This is an automated email from the ASF dual-hosted git repository.

imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git

commit 1c2900c62d1c419b0451ede4cca6341a99887730
Author: dark <[email protected]>
AuthorDate: Sat Aug 29 17:23:09 2026 +0800

    fix(hubble): stabilize async task capabilities
    
    - improve task execution feedback
    - gate scoped task actions
    - retry unverified configuration
    - initialize the Computer manager
---
 .../org/apache/hugegraph/driver/HugeClient.java    |   2 +
 .../driver/HugeClientCompatibilityTest.java        |  13 +++
 .../hugegraph/controller/ConfigController.java     |   3 +
 .../controller/algorithm/OlapAlgoController.java   |  13 +++
 .../hugegraph/controller/auth/UserController.java  |   4 +-
 .../service/algorithm/OlapAlgoService.java         |  25 ++++-
 .../apache/hugegraph/service/auth/UserService.java |   3 +-
 .../service/algorithm/OlapAlgoServiceTest.java     |  90 +++++++++++++++++
 .../hugegraph/unit/ConfigControllerTest.java       |   3 +
 .../org/apache/hugegraph/unit/UnitTestSuite.java   |   2 +
 .../unit/UserServiceCompatibilityTest.java         |   6 +-
 hugegraph-hubble/hubble-fe/src/App.js              |  19 +++-
 hugegraph-hubble/hubble-fe/src/App.test.js         |  43 +++++++-
 hugegraph-hubble/hubble-fe/src/api/analysis.js     |   8 ++
 .../src/i18n/resources/en-US/modules/analysis.json |  13 ++-
 .../src/i18n/resources/zh-CN/modules/analysis.json |  13 ++-
 .../algorithmsForm/AlgorithmNameHeader/index.js    |   6 +-
 .../modules/algorithm/algorithmsForm/Home/index.js |   2 +
 .../algorithm/algorithmsForm/MaxDepthItem/index.js |   3 +-
 .../Olap/BetweennessCentrality/index.js            |   2 +
 .../Olap/BetweennessCentralityVermeer/index.js     |   2 +
 .../Olap/ClosenessCentrality/index.js              |   2 +
 .../Olap/ClosenessCentralityVermeer/index.js       |   2 +
 .../Olap/ClusterCoefficient/index.js               |   2 +
 .../algorithmsForm/Olap/DegreeCentrality/index.js  |   2 +
 .../Olap/DegreeCentralityVermeer/index.js          |   2 +
 .../Olap/FilterSubGraphMatching/index.js           |   2 +
 .../Olap/FilteredRingsDetection/index.js           |   2 +
 .../algorithm/algorithmsForm/Olap/KCore/index.js   |   2 +
 .../algorithmsForm/Olap/KCoreVermeer/index.js      |   2 +
 .../Olap/LabelPropagationAlgorithm/index.js        |   2 +
 .../Olap/LabelPropagationAlgorithmVermeer/index.js |   2 +
 .../algorithm/algorithmsForm/Olap/Links/index.js   |   2 +
 .../algorithm/algorithmsForm/Olap/Louvain/index.js |   2 +
 .../algorithmsForm/Olap/PageRank/index.js          |   2 +
 .../algorithmsForm/Olap/PageRankVermeer/index.js   |   2 +
 .../algorithmsForm/Olap/PersonalPageRank/index.js  |   2 +
 .../algorithmsForm/Olap/RingsDetection/index.js    |   2 +
 .../algorithmsForm/Olap/SSSPVermeer/index.js       |   2 +
 .../algorithmsForm/Olap/TriangleCount/index.js     |   2 +
 .../Olap/TriangleCountVermeer/index.js             |   2 +
 .../Olap/WeaklyConnectedComponent/index.js         |   2 +
 .../Olap/WeaklyConnectedComponentVermeer/index.js  |   2 +
 .../algorithm/algorithmsForm/OlapHome/index.js     |  63 ++++++++++--
 .../algorithmsForm/OlapHome/index.test.js          | 111 +++++++++++++++++++++
 .../algorithmsForm/Oltp/AdamicAdar/index.js        |   2 +
 .../algorithmsForm/Oltp/AllPaths/index.js          |   2 +
 .../algorithmsForm/Oltp/Crosspoints/index.js       |   5 +-
 .../Oltp/CustomizedCrosspoints/Home/index.js       |   2 +
 .../Oltp/CustomizedPaths/Home/index.js             |   5 +-
 .../algorithm/algorithmsForm/Oltp/Egonet/index.js  |   5 +-
 .../algorithmsForm/Oltp/FindShortestPath/index.js  |   5 +-
 .../Oltp/FindShortestPathWithWeight/index.js       |   2 +
 .../Oltp/FusiformSimilarity/index.js               |   2 +
 .../Oltp/JaccardSimilarityGet/index.js             |   2 +
 .../Oltp/JaccardSimilarityPost/index.js            |   2 +
 .../algorithmsForm/Oltp/KneighborGet/index.js      |   2 +
 .../algorithmsForm/Oltp/KneighborPost/index.js     |   5 +-
 .../algorithm/algorithmsForm/Oltp/KoutGet/index.js |   2 +
 .../algorithmsForm/Oltp/KoutPost/Home/index.js     |   5 +-
 .../Oltp/MultiNodesShortestPath/index.js           |   5 +-
 .../algorithmsForm/Oltp/NeighborRankApi/index.js   |   2 +
 .../algorithm/algorithmsForm/Oltp/Paths/index.js   |   5 +-
 .../algorithm/algorithmsForm/Oltp/RankApi/index.js |   4 +-
 .../algorithm/algorithmsForm/Oltp/Rays/index.js    |   5 +-
 .../Oltp/ResourceAllocation/index.js               |   2 +
 .../algorithm/algorithmsForm/Oltp/Rings/index.js   |   2 +
 .../algorithmsForm/Oltp/SameNeighbors/index.js     |   2 +
 .../Oltp/SameNeighborsBatch/index.js               |   2 +
 .../algorithmsForm/Oltp/ShortestPath/index.js      |   2 +
 .../Oltp/SingleSourceShortestPath/index.js         |   2 +
 .../Oltp/TemplatePaths/Home/index.js               |   2 +
 .../algorithmsForm/PersistentForm/index.js         |  20 ++++
 .../algorithmsForm/PersistentForm/index.test.js    |  82 ++++++++++++++-
 .../algorithmsForm/algorithm-dom-props.test.js     |  14 +++
 .../src/modules/asyncTasks/Detail/index.js         |  99 +++++++++++++++---
 .../modules/asyncTasks/Detail/index.module.scss    |  12 +++
 .../src/modules/asyncTasks/Detail/index.test.js    | 104 +++++++++++++++++++
 .../src/modules/asyncTasks/Result/index.js         |  90 ++++++++++-------
 .../modules/asyncTasks/Result/index.module.scss    |  12 +++
 .../hubble-fe/src/pages/Account/EditLayer.js       |   3 +-
 .../pages/Account/account-edit-recovery.test.js    |  20 +++-
 82 files changed, 943 insertions(+), 89 deletions(-)

diff --git 
a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java 
b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java
index 64e19f48f..171801c0f 100644
--- a/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java
+++ b/hugegraph-client/src/main/java/org/apache/hugegraph/driver/HugeClient.java
@@ -192,6 +192,7 @@ public class HugeClient implements Closeable {
             this.traverser = new TraverserManager(client, this.graph);
             this.variable = new VariablesManager(client, graphSpace, graph);
             this.job = new JobManager(client, graphSpace, graph);
+            this.computer = new ComputerManager(client, graphSpace, graph);
             this.task = new TaskManager(client, graphSpace, graph);
         } else {
             /*
@@ -205,6 +206,7 @@ public class HugeClient implements Closeable {
             this.traverser = null;
             this.variable = null;
             this.job = null;
+            this.computer = null;
             this.task = null;
         }
     }
diff --git 
a/hugegraph-client/src/test/java/org/apache/hugegraph/driver/HugeClientCompatibilityTest.java
 
b/hugegraph-client/src/test/java/org/apache/hugegraph/driver/HugeClientCompatibilityTest.java
index 049c542ae..3bef153ff 100644
--- 
a/hugegraph-client/src/test/java/org/apache/hugegraph/driver/HugeClientCompatibilityTest.java
+++ 
b/hugegraph-client/src/test/java/org/apache/hugegraph/driver/HugeClientCompatibilityTest.java
@@ -19,6 +19,7 @@ package org.apache.hugegraph.driver;
 
 import java.util.Arrays;
 
+import org.apache.hugegraph.client.RestClient;
 import org.apache.hugegraph.exception.ServerException;
 import org.apache.hugegraph.structure.auth.TokenPayload;
 import org.apache.hugegraph.structure.auth.User;
@@ -81,6 +82,18 @@ public class HugeClientCompatibilityTest {
         Assert.assertFalse(this.client.requiresBasicGremlinAuth());
     }
 
+    @Test
+    public void shouldInitializeAndResetComputerWithGraphScope() {
+        RestClient restClient = Mockito.mock(RestClient.class);
+        Whitebox.setInternalState(this.client, "apiVersionChecked", true);
+
+        this.client.initManagers(restClient, "DEFAULT", "hugegraph");
+        Assert.assertNotNull(this.client.computer());
+
+        this.client.initManagers(restClient, "DEFAULT", null);
+        Assert.assertNull(this.client.computer());
+    }
+
     @Test
     public void shouldFindCurrentUserFromVerifiedTokenIdentity() {
         TokenPayload payload = Mockito.mock(TokenPayload.class);
diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/ConfigController.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/ConfigController.java
index 8ee22aa1c..a908100e0 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/ConfigController.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/ConfigController.java
@@ -59,11 +59,13 @@ public class ConfigController {
         Map<String, Object> capabilities = new HashMap<>();
         boolean pdEnabled = config.get(HubbleOptions.PD_ENABLED);
         if (pdEnabled) {
+            capabilities.put("server_capabilities_verified", true);
             capabilities.put("auth_enabled", this.authModeService.enabled());
             capabilities.put("graph_create_enabled", true);
             capabilities.put("cypher_enabled", true);
             return capabilities;
         }
+        capabilities.put("server_capabilities_verified", false);
         capabilities.put("auth_enabled", true);
         capabilities.put("graph_create_enabled", false);
         capabilities.put("cypher_enabled", false);
@@ -78,6 +80,7 @@ public class ConfigController {
             capabilities.put("graph_create_enabled",
                              client.supportsGraphCreate());
             capabilities.put("cypher_enabled", client.supportsCypher());
+            capabilities.put("server_capabilities_verified", true);
             return capabilities;
         } catch (RuntimeException ignored) {
             // Keep bootstrap resilient when the Server is temporarily 
unavailable.
diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/algorithm/OlapAlgoController.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/algorithm/OlapAlgoController.java
index e20e716f9..b20c3cf00 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/algorithm/OlapAlgoController.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/algorithm/OlapAlgoController.java
@@ -18,6 +18,9 @@
 
 package org.apache.hugegraph.controller.algorithm;
 
+import java.util.Collections;
+import java.util.Map;
+
 import lombok.extern.log4j.Log4j2;
 import org.apache.hugegraph.common.Constant;
 import org.apache.hugegraph.controller.BaseController;
@@ -26,6 +29,7 @@ import org.apache.hugegraph.entity.algorithm.OlapEntity;
 import org.apache.hugegraph.entity.query.OlapView;
 import org.apache.hugegraph.service.algorithm.OlapAlgoService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -40,6 +44,15 @@ public class OlapAlgoController extends BaseController {
     @Autowired
     private OlapAlgoService service;
 
+    @GetMapping("capability")
+    public Map<String, Boolean> capability(
+            @PathVariable("graphspace") String graphspace,
+            @PathVariable("graph") String graph) {
+        HugeClient client = this.authClient(graphspace, graph);
+        return Collections.singletonMap(
+                "available", this.service.computerAvailable(client));
+    }
+
     @PostMapping
     public OlapView olapView(@PathVariable("graphspace") String graphspace,
                              @PathVariable("graph") String graph,
diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/UserController.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/UserController.java
index a0c9d2495..fd4d7b1b7 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/UserController.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/controller/auth/UserController.java
@@ -72,10 +72,10 @@ public class UserController extends BaseController {
     }
 
     @PostMapping
-    public void create(@RequestBody UserEntity userEntity) {
+    public UserEntity create(@RequestBody UserEntity userEntity) {
         HugeClient client = this.requireAccountManager();
         this.checkAccountGrantScope(client, null, userEntity);
-        userService.add(client, userEntity);
+        return userService.add(client, userEntity);
     }
 
     @PostMapping("batch")
diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/algorithm/OlapAlgoService.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/algorithm/OlapAlgoService.java
index be3b8abcc..ed14c3095 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/algorithm/OlapAlgoService.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/algorithm/OlapAlgoService.java
@@ -22,6 +22,7 @@ import org.apache.hugegraph.config.HugeConfig;
 import org.apache.hugegraph.driver.HugeClient;
 import org.apache.hugegraph.entity.algorithm.OlapEntity;
 import org.apache.hugegraph.entity.query.OlapView;
+import org.apache.hugegraph.exception.ServerCapabilityUnavailableException;
 import org.apache.hugegraph.service.query.ExecuteHistoryService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -37,6 +38,16 @@ public class OlapAlgoService {
     @Autowired
     private ExecuteHistoryService historyService;
 
+    public boolean computerAvailable(HugeClient client) {
+        try {
+            client.computer().list(1L);
+            return true;
+        } catch (RuntimeException e) {
+            log.debug("HugeGraph Computer is unavailable: {}", e.getMessage());
+            return false;
+        }
+    }
+
     public OlapView olapView(HugeClient client, String graphspace, OlapEntity 
body) {
         Map<String, Object> params = body.getParams();
         if (!"DEFAULT".equals(graphspace)) {
@@ -48,7 +59,19 @@ public class OlapAlgoService {
             params.put("k8s.worker_memory", "5Gi");
             params.putAll(body.getParams());
         }
-        long taskid = client.computer().create(body.getAlgorithm(), 
body.getWorker(), params);
+        long taskid;
+        try {
+            taskid = client.computer().create(body.getAlgorithm(),
+                                              body.getWorker(), params);
+        } catch (RuntimeException e) {
+            String detail = e.getMessage();
+            if (detail == null || detail.trim().isEmpty() ||
+                "request_failure".equals(detail)) {
+                throw new ServerCapabilityUnavailableException(
+                        "server.capability.computer.unavailable", e);
+            }
+            throw e;
+        }
         return OlapView.builder().taskId(taskid).build();
     }
 }
diff --git 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/auth/UserService.java
 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/auth/UserService.java
index 058ce1949..18676daff 100644
--- 
a/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/auth/UserService.java
+++ 
b/hugegraph-hubble/hubble-be/src/main/java/org/apache/hugegraph/service/auth/UserService.java
@@ -219,7 +219,7 @@ public class UserService extends AuthService {
         return userEntity;
     }
 
-    public void add(HugeClient client, UserEntity ue) {
+    public UserEntity add(HugeClient client, UserEntity ue) {
         boolean permissionPresets = isPdEnabled() &&
                                     client.supportsDefaultRole();
         this.validatePermissionMutation(client, ue, true,
@@ -254,6 +254,7 @@ public class UserService extends AuthService {
                                     superAdminAttempted, error);
             throw error;
         }
+        return this.convert(client, newUser);
     }
 
     private void rollbackNewAccount(HugeClient client, User user,
diff --git 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/service/algorithm/OlapAlgoServiceTest.java
 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/service/algorithm/OlapAlgoServiceTest.java
new file mode 100644
index 000000000..1bd15a570
--- /dev/null
+++ 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/service/algorithm/OlapAlgoServiceTest.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hugegraph.service.algorithm;
+
+import java.util.Collections;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import org.apache.hugegraph.driver.ComputerManager;
+import org.apache.hugegraph.driver.HugeClient;
+import org.apache.hugegraph.entity.algorithm.OlapEntity;
+import org.apache.hugegraph.exception.ServerCapabilityUnavailableException;
+import org.apache.hugegraph.testutil.Assert;
+
+public class OlapAlgoServiceTest {
+
+    @Test
+    public void testComputerAvailabilityUsesTaskEndpoint() {
+        HugeClient client = Mockito.mock(HugeClient.class);
+        ComputerManager computer = Mockito.mock(ComputerManager.class);
+        Mockito.when(client.computer()).thenReturn(computer);
+        Mockito.when(computer.list(1L)).thenReturn(Collections.emptyList());
+
+        Assert.assertTrue(new OlapAlgoService().computerAvailable(client));
+
+        Mockito.when(computer.list(1L))
+               .thenThrow(new RuntimeException("request_failure"));
+        Assert.assertFalse(new OlapAlgoService().computerAvailable(client));
+    }
+
+    @Test
+    public void testMissingComputerErrorExplainsRequiredEnvironment() {
+        HugeClient client = Mockito.mock(HugeClient.class);
+        ComputerManager computer = Mockito.mock(ComputerManager.class);
+        Mockito.when(client.computer()).thenReturn(computer);
+        Mockito.when(computer.create(
+                Mockito.anyString(), Mockito.anyLong(), Mockito.anyMap()))
+               .thenThrow(new RuntimeException((String) null));
+
+        Throwable error = Assert.assertThrows(
+                ServerCapabilityUnavailableException.class,
+                () -> new OlapAlgoService().olapView(
+                        client, "DEFAULT", entity()));
+
+        Assert.assertEquals("server.capability.computer.unavailable",
+                            error.getMessage());
+    }
+
+    @Test
+    public void testMeaningfulComputerErrorRemainsVisible() {
+        HugeClient client = Mockito.mock(HugeClient.class);
+        ComputerManager computer = Mockito.mock(ComputerManager.class);
+        Mockito.when(client.computer()).thenReturn(computer);
+        RuntimeException failure = new RuntimeException("invalid worker");
+        Mockito.when(computer.create(
+                Mockito.anyString(), Mockito.anyLong(), Mockito.anyMap()))
+               .thenThrow(failure);
+
+        Throwable error = Assert.assertThrows(
+                RuntimeException.class,
+                () -> new OlapAlgoService().olapView(
+                        client, "DEFAULT", entity()));
+
+        Assert.assertSame(failure, error);
+    }
+
+    private static OlapEntity entity() {
+        return OlapEntity.builder()
+                         .algorithm("page-rank")
+                         .worker(2L)
+                         .params(Collections.emptyMap())
+                         .build();
+    }
+}
diff --git 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/ConfigControllerTest.java
 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/ConfigControllerTest.java
index e99ed7393..630e44add 100644
--- 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/ConfigControllerTest.java
+++ 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/ConfigControllerTest.java
@@ -57,6 +57,7 @@ public class ConfigControllerTest {
         Map<String, Object> result = controller.getConfig();
 
         Assert.assertEquals(Map.of("pd_enabled", false,
+                                   "server_capabilities_verified", true,
                                    "auth_enabled", false,
                                    "graph_create_enabled", false,
                                    "cypher_enabled", false), result);
@@ -89,6 +90,7 @@ public class ConfigControllerTest {
         Map<String, Object> result = controller.getConfig();
 
         Assert.assertEquals(Map.of("pd_enabled", false,
+                                   "server_capabilities_verified", true,
                                    "auth_enabled", true,
                                    "graph_create_enabled", true,
                                    "cypher_enabled", false), result);
@@ -114,6 +116,7 @@ public class ConfigControllerTest {
         Map<String, Object> result = controller.getConfig();
 
         Assert.assertEquals(Map.of("pd_enabled", false,
+                                   "server_capabilities_verified", false,
                                    "auth_enabled", true,
                                    "graph_create_enabled", false,
                                    "cypher_enabled", false), result);
diff --git 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
index 9ce4fe4e5..c7ed4f658 100644
--- 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
+++ 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UnitTestSuite.java
@@ -27,6 +27,7 @@ import 
org.apache.hugegraph.controller.schema.SchemaControllerSecurityTest;
 import org.apache.hugegraph.controller.space.GraphSpaceControllerTest;
 import 
org.apache.hugegraph.controller.space.SchemaTemplateControllerSecurityTest;
 import org.apache.hugegraph.handler.ResponseAdvisorStatusTest;
+import org.apache.hugegraph.service.algorithm.OlapAlgoServiceTest;
 import org.apache.hugegraph.service.load.IngestTransactionIntegrationTest;
 import org.apache.hugegraph.service.auth.AuthContextServiceTest;
 import org.apache.hugegraph.service.auth.AuthModeServiceTest;
@@ -74,6 +75,7 @@ import org.junit.runners.Suite;
     LangChainControllerSecurityTest.class,
     LegacyFacadeRemovalTest.class,
     MessageSourceHandlerTest.class,
+    OlapAlgoServiceTest.class,
     SchemaControllerSecurityTest.class,
     SchemaTemplateControllerSecurityTest.class,
     GroovySchemaCompatibilityTest.class,
diff --git 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UserServiceCompatibilityTest.java
 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UserServiceCompatibilityTest.java
index 3075790d8..600fe3728 100644
--- 
a/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UserServiceCompatibilityTest.java
+++ 
b/hugegraph-hubble/hubble-be/src/test/java/org/apache/hugegraph/unit/UserServiceCompatibilityTest.java
@@ -67,7 +67,7 @@ public class UserServiceCompatibilityTest {
         Mockito.when(this.client.graphSpace()).thenReturn(this.graphSpace);
         Mockito.when(this.client.graphs()).thenReturn(this.graphs);
         Mockito.when(this.auth.createUser(Mockito.any(User.class)))
-               .thenReturn(new User());
+               .thenReturn(user("created-id"));
         Mockito.when(this.auth.listSuperAdmin())
                .thenReturn(java.util.Collections.emptyList());
         this.service = new UserService();
@@ -80,11 +80,13 @@ public class UserServiceCompatibilityTest {
     public void testStandaloneUserCreationOmitsPdOnlyNickname() {
         
Mockito.when(this.config.get(HubbleOptions.PD_ENABLED)).thenReturn(false);
 
-        this.service.add(this.client, userEntity("display-name"));
+        UserEntity created =
+                this.service.add(this.client, userEntity("display-name"));
 
         ArgumentCaptor<User> request = ArgumentCaptor.forClass(User.class);
         Mockito.verify(this.auth).createUser(request.capture());
         Assert.assertNull(request.getValue().nickname());
+        Assert.assertEquals("created-id", created.getId());
     }
 
     @Test
diff --git a/hugegraph-hubble/hubble-fe/src/App.js 
b/hugegraph-hubble/hubble-fe/src/App.js
index ec6ee6aa8..5b6b951c0 100644
--- a/hugegraph-hubble/hubble-fe/src/App.js
+++ b/hugegraph-hubble/hubble-fe/src/App.js
@@ -27,29 +27,40 @@ import * as api from './api';
 import {setConfig} from './utils/config';
 import {useEffect, useState} from 'react';
 
+const CONFIG_RETRY_DELAY_MS = 2000;
+
 function App() {
     const [configReady, setConfigReady] = useState(false);
     const [configError, setConfigError] = useState(false);
 
     useEffect(() => {
         let active = true;
-        api.config.getConfig()
-            .then(response => {
+        let retryTimer;
+        const loadConfig = () => {
+            api.config.getConfig().then(response => {
                 if (response?.status !== 200 || !response.data) {
                     throw new Error('invalid_hubble_config');
                 }
                 if (active) {
                     setConfig(response.data);
                     setConfigReady(true);
+                    setConfigError(false);
+                    if (response.data.server_capabilities_verified === false) {
+                        retryTimer = window.setTimeout(
+                            loadConfig, CONFIG_RETRY_DELAY_MS
+                        );
+                    }
                 }
-            })
-            .catch(() => {
+            }).catch(() => {
                 if (active) {
                     setConfigError(true);
                 }
             });
+        };
+        loadConfig();
         return () => {
             active = false;
+            window.clearTimeout(retryTimer);
         };
     }, []);
 
diff --git a/hugegraph-hubble/hubble-fe/src/App.test.js 
b/hugegraph-hubble/hubble-fe/src/App.test.js
index a3ed5534d..20eb51794 100644
--- a/hugegraph-hubble/hubble-fe/src/App.test.js
+++ b/hugegraph-hubble/hubble-fe/src/App.test.js
@@ -16,7 +16,7 @@
  * under the License.
  */
 
-import {render, screen} from '@testing-library/react';
+import {act, render, screen, waitFor} from '@testing-library/react';
 import {MemoryRouter} from 'react-router-dom';
 import App from './App';
 import * as api from './api';
@@ -70,3 +70,44 @@ test('shows a retry surface when configuration bootstrap 
fails', async () => {
     );
     expect(screen.getByRole('button', {name: 'Retry'})).toBeInTheDocument();
 });
+
+test('revalidates fail-closed server capabilities until verified', async () => 
{
+    jest.useFakeTimers();
+    api.config.getConfig
+        .mockResolvedValueOnce({
+            status: 200,
+            data: {
+                pd_enabled: false,
+                auth_enabled: true,
+                server_capabilities_verified: false,
+            },
+        })
+        .mockResolvedValueOnce({
+            status: 200,
+            data: {
+                pd_enabled: false,
+                auth_enabled: false,
+                server_capabilities_verified: true,
+            },
+        });
+
+    render(
+        <MemoryRouter
+            future={{v7_startTransition: true, v7_relativeSplatPath: true}}
+        >
+            <App />
+        </MemoryRouter>
+    );
+    expect(await screen.findByTestId('app-route')).toBeInTheDocument();
+
+    await act(async () => {
+        jest.advanceTimersByTime(2000);
+    });
+    await waitFor(() => expect(api.config.getConfig).toHaveBeenCalledTimes(2));
+    expect(JSON.parse(sessionStorage.getItem('hubble_config_')))
+        .toMatchObject({
+            auth_enabled: false,
+            server_capabilities_verified: true,
+        });
+    jest.useRealTimers();
+});
diff --git a/hugegraph-hubble/hubble-fe/src/api/analysis.js 
b/hugegraph-hubble/hubble-fe/src/api/analysis.js
index eddbf1abf..835614c75 100644
--- a/hugegraph-hubble/hubble-fe/src/api/analysis.js
+++ b/hugegraph-hubble/hubble-fe/src/api/analysis.js
@@ -170,6 +170,13 @@ const postOlapInfo =  (graphspace, graph, data) => {
     });
 };
 
+const getOlapCapability = (graphspace, graph, config = {}) => {
+    return request.get(
+        
`/graphspaces/${graphspace}/graphs/${graph}/algorithms/olap/capability`,
+        config
+    );
+};
+
 const runOltpInfo =  (graphspace, graph, data) => {
     return runAlgorithmRequest(() => {
         return request.post(
@@ -226,6 +233,7 @@ export {
     fetchManageTaskList,
     addFavoriate,
     postOlapInfo,
+    getOlapCapability,
     runOltpInfo,
     runOlapVermeer,
     fetchAsyncTaskResult,
diff --git 
a/hugegraph-hubble/hubble-fe/src/i18n/resources/en-US/modules/analysis.json 
b/hugegraph-hubble/hubble-fe/src/i18n/resources/en-US/modules/analysis.json
index eefd7cfaf..03640f187 100644
--- a/hugegraph-hubble/hubble-fe/src/i18n/resources/en-US/modules/analysis.json
+++ b/hugegraph-hubble/hubble-fe/src/i18n/resources/en-US/modules/analysis.json
@@ -477,6 +477,13 @@
       },
       "placeholder": "Algorithm Query",
       "run": "Run",
+      "run_shortcut": "Run (⌘/Ctrl + Enter)",
+      "computer_environment_title": "HugeGraph Computer environment required",
+      "computer_environment_description": "These whole-graph algorithms run 
asynchronously through HugeGraph Computer. Configure its compute environment, 
including Kubernetes when required by the deployment, before submitting a task",
+      "computer_unavailable_title": "HugeGraph Computer unavailable",
+      "computer_unavailable_description": "This graph cannot reach HugeGraph 
Computer. Configure Computer and its Kubernetes environment before running 
batch algorithms",
+      "vermeer_unavailable_title": "Vermeer computation is unavailable",
+      "vermeer_unavailable_description": "This Hubble version cannot securely 
submit Vermeer compute tasks. Configure HugeGraph Computer or upgrade the 
Vermeer integration before running batch algorithms",
       "task_submit_success": "{{name}} task submitted successfully",
       "common": {
         "instance_num": "Instance Count",
@@ -560,7 +567,7 @@
       },
       "mode": {
         "OLTP": "Interactive exploration",
-        "OLAP": "Batch analysis (async)"
+        "OLAP": "Cluster batch computation"
       },
       "capacity_item": {
         "tooltip": "Maximum number of vertices visited during traversal"
@@ -879,6 +886,7 @@
       "result_title": "Task result",
       "result_context": "{{graphspace}} / {{graph}} / Task {{taskId}}",
       "result_back": "Back to async tasks",
+      "result_open_full": "Open full result",
       "delete_failed": "Delete failed",
       "abort_failed": "Abort failed",
       "delete_confirm_title": "Delete Task",
@@ -930,7 +938,8 @@
         "aborting": "Aborting",
         "delete": "Delete",
         "check_result": "View Result",
-        "check_reason": "View Reason"
+        "check_reason": "View Reason",
+        "collapse_result": "Hide Result"
       }
     },
     "topbar": {
diff --git 
a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json 
b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
index 8d681f628..fa91e30fd 100644
--- a/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
+++ b/hugegraph-hubble/hubble-fe/src/i18n/resources/zh-CN/modules/analysis.json
@@ -477,6 +477,13 @@
       },
       "placeholder": "算法查询",
       "run": "运行",
+      "run_shortcut": "运行(⌘/Ctrl + Enter)",
+      "computer_environment_title": "需要 HugeGraph Computer 计算环境",
+      "computer_environment_description": "这些全图算法通过 HugeGraph Computer 
异步执行。提交任务前需先配置计算环境;部署要求 Kubernetes 时还需完成对应集群配置",
+      "computer_unavailable_title": "HugeGraph Computer 暂不可用",
+      "computer_unavailable_description": "当前图无法连接 HugeGraph Computer。请完成 
Computer 与 Kubernetes 环境配置后再运行批量算法",
+      "vermeer_unavailable_title": "当前无法运行 Vermeer 计算",
+      "vermeer_unavailable_description": "当前 Hubble 版本无法安全提交 Vermeer 
计算任务。请改用已配置的 HugeGraph Computer,或升级 Vermeer 集成后再运行批量算法",
       "task_submit_success": "{{name}} 算法任务提交成功",
       "common": {
         "instance_num": "实例数",
@@ -560,7 +567,7 @@
       },
       "mode": {
         "OLTP": "交互式探索",
-        "OLAP": "异步批量分析"
+        "OLAP": "集群批量计算"
       },
       "capacity_item": {
         "tooltip": "遍历过程中最大的访问的顶点数目"
@@ -879,6 +886,7 @@
       "result_title": "任务结果",
       "result_context": "{{graphspace}} / {{graph}} / 任务 {{taskId}}",
       "result_back": "返回异步任务",
+      "result_open_full": "查看完整结果",
       "delete_failed": "删除失败",
       "abort_failed": "终止失败",
       "delete_confirm_title": "删除任务",
@@ -930,7 +938,8 @@
         "aborting": "终止中",
         "delete": "删除",
         "check_result": "查看结果",
-        "check_reason": "查看原因"
+        "check_reason": "查看原因",
+        "collapse_result": "收起结果"
       }
     },
     "topbar": {
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/AlgorithmNameHeader/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/AlgorithmNameHeader/index.js
index ae95ae77d..a44c34416 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/AlgorithmNameHeader/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/AlgorithmNameHeader/index.js
@@ -120,7 +120,11 @@ const AlgorithmNameHeader = props => {
             return (
                 <Tooltip
                     placement="rightTop"
-                    title={<span style={{color: 
'#000'}}>{t('analysis.algorithm.run')}</span>}
+                    title={(
+                        <span style={{color: '#000'}}>
+                            {t('analysis.algorithm.run_shortcut')}
+                        </span>
+                    )}
                     color={'#fff'}
                 >
                     <Button
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Home/index.js 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Home/index.js
index ba2721929..6425770be 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Home/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Home/index.js
@@ -104,6 +104,8 @@ const AlgorithmFormHome = props => {
                 currentAlgorithm={currentAlgorithm}
                 updateCurrentAlgorithm={updateCurrentAlgorithm}
                 canRunLouvain={canRunLouvain}
+                graphSpace={graphSpace}
+                graph={graph}
             />
         </div>
     );
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/MaxDepthItem/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/MaxDepthItem/index.js
index c596faad7..9cd54e788 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/MaxDepthItem/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/MaxDepthItem/index.js
@@ -33,7 +33,8 @@ const MaxDepthItem = props => {
         <Form.Item
             label='max_depth'
             name='max_depth'
-            rules={[{required: true}, {validator: validator}]}
+            initialValue={3}
+            rules={[{validator: validator}]}
             tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
         >
             <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentrality/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentrality/index.js
index c39acc55b..3bac1ef8b 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentrality/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentrality/index.js
@@ -134,6 +134,8 @@ const BetweennessCentrality = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentralityVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentralityVermeer/index.js
index 6d25a3a3e..d40e4f95c 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentralityVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/BetweennessCentralityVermeer/index.js
@@ -138,6 +138,8 @@ const BetweennessCentralityVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 disabled={graphStatus !== LOADED}
                 form={form}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentrality/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentrality/index.js
index 8882d13f9..54ba426e4 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentrality/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentrality/index.js
@@ -132,6 +132,8 @@ const ClosenessCentrality = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentralityVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentralityVermeer/index.js
index 7aa39be4a..8f1f42af0 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentralityVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClosenessCentralityVermeer/index.js
@@ -142,6 +142,8 @@ const ClosenessCentralityVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClusterCoefficient/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClusterCoefficient/index.js
index ff98e1951..fa132afda 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClusterCoefficient/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/ClusterCoefficient/index.js
@@ -132,6 +132,8 @@ const ClusterCoefficient = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentrality/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentrality/index.js
index 6e3e23203..f01663fd3 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentrality/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentrality/index.js
@@ -131,6 +131,8 @@ const DegreeCentrality = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentralityVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentralityVermeer/index.js
index 16350b2fb..47d3f69b3 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentralityVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/DegreeCentralityVermeer/index.js
@@ -144,6 +144,8 @@ const DegreeCentralityVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilterSubGraphMatching/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilterSubGraphMatching/index.js
index faaeb4c5c..bc1e0d2cc 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilterSubGraphMatching/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilterSubGraphMatching/index.js
@@ -137,6 +137,8 @@ const FilterSubGraphMatching = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilteredRingsDetection/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilteredRingsDetection/index.js
index c498681b8..198675a62 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilteredRingsDetection/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/FilteredRingsDetection/index.js
@@ -137,6 +137,8 @@ const FilteredRingsDetection = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCore/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCore/index.js
index bd60438fb..c1baeaf15 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCore/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCore/index.js
@@ -133,6 +133,8 @@ const KCore = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCoreVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCoreVermeer/index.js
index 7d043562c..7f151a3ff 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCoreVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/KCoreVermeer/index.js
@@ -142,6 +142,8 @@ const KCoreVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithm/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithm/index.js
index a0cc74aa9..d62852628 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithm/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithm/index.js
@@ -130,6 +130,8 @@ const LabelPropagationAlgorithm = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithmVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithmVermeer/index.js
index b3b710162..e0f81a70f 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithmVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/LabelPropagationAlgorithmVermeer/index.js
@@ -143,6 +143,8 @@ const LabelPropagationAlgorithmVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Links/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Links/index.js
index 2110d92bf..c533b89ae 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Links/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Links/index.js
@@ -135,6 +135,8 @@ const Links = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Louvain/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Louvain/index.js
index c69e51f96..9df26c8c5 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Louvain/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/Louvain/index.js
@@ -172,6 +172,8 @@ const Louvain = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={debouncedRunAvailability}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRank/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRank/index.js
index 99e613419..0e125894d 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRank/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRank/index.js
@@ -131,6 +131,8 @@ const PageRank = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRankVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRankVermeer/index.js
index 40af1a3c9..6100e3fcb 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRankVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PageRankVermeer/index.js
@@ -131,6 +131,8 @@ const PageRankVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PersonalPageRank/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PersonalPageRank/index.js
index b84462eee..1ede08edd 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PersonalPageRank/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/PersonalPageRank/index.js
@@ -134,6 +134,8 @@ const PersonalPageRank = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/RingsDetection/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/RingsDetection/index.js
index 67aae215c..f59bce8b7 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/RingsDetection/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/RingsDetection/index.js
@@ -129,6 +129,8 @@ const RingsDetection = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/SSSPVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/SSSPVermeer/index.js
index 7b96ed620..7206406b5 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/SSSPVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/SSSPVermeer/index.js
@@ -134,6 +134,8 @@ const SSSPVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCount/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCount/index.js
index d824f23d6..116f552fe 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCount/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCount/index.js
@@ -133,6 +133,8 @@ const TriangleCount = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCountVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCountVermeer/index.js
index a8678c300..72a6e0004 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCountVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/TriangleCountVermeer/index.js
@@ -133,6 +133,8 @@ const TriangleCountVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponent/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponent/index.js
index 064dba69f..0b7958feb 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponent/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponent/index.js
@@ -129,6 +129,8 @@ const WeaklyConnectedComponent = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponentVermeer/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponentVermeer/index.js
index 2d0159ac6..859df8a26 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponentVermeer/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Olap/WeaklyConnectedComponentVermeer/index.js
@@ -135,6 +135,8 @@ const WeaklyConnectedComponentVermeer = props => {
             forceRender
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 disabled={graphStatus !== LOADED}
                 onFinish={onFormFinish}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.js
index cc153a057..38d415633 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.js
@@ -20,8 +20,9 @@
  * @file Olap图算法表单列表
  */
 
-import React, {useContext} from 'react';
-import {Collapse, Tooltip} from 'antd';
+import React, {useContext, useEffect, useState} from 'react';
+import {Alert, Collapse, Tooltip} from 'antd';
+import * as api from '../../../../api';
 import GraphAnalysisContext from '../../../Context';
 import _ from 'lodash';
 import {
@@ -44,6 +45,8 @@ const OlapFormHome = props => {
         currentAlgorithm,
         updateCurrentAlgorithm,
         canRunLouvain,
+        graphSpace,
+        graph,
     } =  props;
     const {ALGORITHM_NAME, ALGORITHM_MODE} = useTranslatedConstants();
     const {t} = useTranslation();
@@ -99,6 +102,32 @@ const OlapFormHome = props => {
 
     const {OLAP} = ALGORITHM_MODE;
     const {isVermeer, graphStatus} = useContext(GraphAnalysisContext);
+    const [computerAvailable, setComputerAvailable] = useState(null);
+
+    useEffect(() => {
+        let cancelled = false;
+        if (isVermeer || !graphSpace || !graph) {
+            setComputerAvailable(null);
+            return undefined;
+        }
+        setComputerAvailable(null);
+        api.analysis.getOlapCapability(graphSpace, graph, {
+            suppressBusinessErrorToast: true,
+        }).then(response => {
+            if (!cancelled) {
+                setComputerAvailable(
+                    response?.status === 200 && response?.data?.available === 
true
+                );
+            }
+        }).catch(() => {
+            if (!cancelled) {
+                setComputerAvailable(false);
+            }
+        });
+        return () => {
+            cancelled = true;
+        };
+    }, [graph, graphSpace, isVermeer]);
 
     const getSearchedList = (arr, value) => {
         return arr.filter(item => isAlgorithmNameMatched(item, value, t));
@@ -131,16 +160,36 @@ const OlapFormHome = props => {
         ),
     })).filter(group => !_.isEmpty(group.items));
     const isEmptyBasicOlap = _.isEmpty(visibleGroups);
-    const shouldDisableForm = isVermeer && graphStatus !== 
GRAPH_LOAD_STATUS.LOADED;
+    const shouldDisableForm = isVermeer
+        ? graphStatus !== GRAPH_LOAD_STATUS.LOADED
+        : computerAvailable !== true;
+    const capabilityTitle = isVermeer
+        ? 'analysis.algorithm.vermeer_unavailable_title'
+        : computerAvailable === false
+            ? 'analysis.algorithm.computer_unavailable_title'
+            : 'analysis.algorithm.computer_environment_title';
+    const capabilityDescription = isVermeer
+        ? 'analysis.algorithm.vermeer_unavailable_description'
+        : computerAvailable === false
+            ? 'analysis.algorithm.computer_unavailable_description'
+            : 'analysis.algorithm.computer_environment_description';
 
     return (
         <div>
             {!isEmptyBasicOlap && (
-                <Tooltip title={shouldDisableForm ? 
t(TEXT_PATH.ALGORITHM_COMMON + '.query_tooltip') : ''}>
-                    <div className={c.algorithmCatagery}>{OLAP}</div>
-                </Tooltip>
+                <>
+                    <Tooltip title={shouldDisableForm ? 
t(TEXT_PATH.ALGORITHM_COMMON + '.query_tooltip') : ''}>
+                        <div className={c.algorithmCatagery}>{OLAP}</div>
+                    </Tooltip>
+                    <Alert
+                        showIcon
+                        type={shouldDisableForm ? 'warning' : 'info'}
+                        message={t(capabilityTitle)}
+                        description={t(capabilityDescription)}
+                    />
+                </>
             )}
-            {visibleGroups.map(group => (
+            {!isVermeer && computerAvailable === true && 
visibleGroups.map(group => (
                 <div key={group.key}>
                     <div className={c.algorithmGoal}>
                         {t(`analysis.algorithm.group.${group.key}`)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.test.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.test.js
new file mode 100644
index 000000000..e60c3a5fd
--- /dev/null
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/OlapHome/index.test.js
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {render, screen, waitFor} from '@testing-library/react';
+import GraphAnalysisContext from '../../../Context';
+import OlapFormHome from '.';
+import * as api from '../../../../api';
+
+jest.mock('../../../../api', () => ({
+    analysis: {
+        getOlapCapability: jest.fn(),
+    },
+}));
+
+jest.mock('../Olap/OlapItem', () => ({algorithmName}) => (
+    <div data-testid="olap-item">{algorithmName}</div>
+));
+
+jest.mock('../../../../utils/constants', () => ({
+    GRAPH_LOAD_STATUS: {LOADED: 'LOADED'},
+    isAlgorithmNameMatched: () => true,
+    TEXT_PATH: {ALGORITHM_COMMON: 'analysis.algorithm.common'},
+    useTranslatedConstants: () => ({
+        ALGORITHM_MODE: {OLAP: 'OLAP'},
+        ALGORITHM_NAME: {
+            PAGE_RANK: 'PageRank',
+            WEAKLY_CONNECTED_COMPONENT: 'WCC',
+            DEGREE_CENTRALIT: 'Degree',
+            CLOSENESS_CENTRALITY: 'Closeness',
+            TRIANGLE_COUNT: 'Triangle',
+            RINGS_DETECTION: 'Rings',
+            FILTERED_RINGS_DETECTION: 'FilteredRings',
+            LINKS: 'Links',
+            CLUSTER_COEFFICIENT: 'Cluster',
+            BETWEENNESS_CENTRALITY: 'Betweenness',
+            LABEL_PROPAGATION_ALGORITHM: 'LabelPropagation',
+            LOUVAIN: 'Louvain',
+            FILTER_SUBGRAPH_MATCHING: 'Subgraph',
+            K_CORE: 'KCore',
+            PERSONAL_PAGE_RANK: 'PersonalPageRank',
+            SSSP: 'SSSP',
+        },
+    }),
+}));
+
+jest.mock('react-i18next', () => ({
+    useTranslation: () => ({t: key => key}),
+}));
+
+const renderHome = () => render(
+    <GraphAnalysisContext.Provider
+        value={{isVermeer: false, graphStatus: 'LOADED'}}
+    >
+        <OlapFormHome
+            graphSpace="DEFAULT"
+            graph="hugegraph"
+            search=""
+            currentAlgorithm=""
+            updateCurrentAlgorithm={jest.fn()}
+            onOlapFormSubmit={jest.fn()}
+            canRunLouvain
+        />
+    </GraphAnalysisContext.Provider>
+);
+
+test('does not render runnable Computer algorithms when capability is 
unavailable',
+    async () => {
+        api.analysis.getOlapCapability.mockResolvedValue({
+            status: 200,
+            data: {available: false},
+        });
+
+        renderHome();
+
+        expect(await screen.findByText(
+            'analysis.algorithm.computer_unavailable_title'
+        )).toBeInTheDocument();
+        expect(screen.queryByTestId('olap-item')).not.toBeInTheDocument();
+    });
+
+test('renders Computer algorithms only after capability succeeds', async () => 
{
+    api.analysis.getOlapCapability.mockResolvedValue({
+        status: 200,
+        data: {available: true},
+    });
+
+    renderHome();
+
+    await waitFor(() => {
+        expect(screen.getAllByTestId('olap-item').length).toBeGreaterThan(0);
+    });
+    expect(api.analysis.getOlapCapability).toHaveBeenCalledWith(
+        'DEFAULT',
+        'hugegraph',
+        {suppressBusinessErrorToast: true}
+    );
+});
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AdamicAdar/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AdamicAdar/index.js
index 09b16d87d..f309a1a0e 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AdamicAdar/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AdamicAdar/index.js
@@ -137,6 +137,8 @@ const AdamicAdar = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AllPaths/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AllPaths/index.js
index 3fd351ac7..06a5f5a50 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AllPaths/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/AllPaths/index.js
@@ -225,6 +225,8 @@ const AllPaths = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Crosspoints/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Crosspoints/index.js
index 0cfdc3ff8..44aada75c 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Crosspoints/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Crosspoints/index.js
@@ -124,6 +124,8 @@ const Crosspoints = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -167,7 +169,8 @@ const Crosspoints = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: maxDepthValidator}]}
+                    initialValue={3}
+                    rules={[{validator: maxDepthValidator}]}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
                 >
                     <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedCrosspoints/Home/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedCrosspoints/Home/index.js
index 12d97aaa7..1b0bb27a5 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedCrosspoints/Home/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedCrosspoints/Home/index.js
@@ -138,6 +138,8 @@ const CustomizedCrosspoints = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedPaths/Home/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedPaths/Home/index.js
index f0e2b9c56..ce944d935 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedPaths/Home/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/CustomizedPaths/Home/index.js
@@ -146,6 +146,8 @@ const CustomizedPaths = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 className={s.oltpForms}
@@ -157,7 +159,8 @@ const CustomizedPaths = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: integerValidator}]}
+                    initialValue={3}
+                    rules={[{validator: integerValidator}]}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
                 >
                     <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Egonet/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Egonet/index.js
index b0425b9ef..4910e2828 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Egonet/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Egonet/index.js
@@ -229,6 +229,8 @@ const Egonet = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={egonetForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -261,7 +263,8 @@ const Egonet = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    initialValue={3}
+                    rules={[{validator: positiveIntegerValidator}]}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
                 >
                     <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPath/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPath/index.js
index e1228c658..85fc9c4e9 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPath/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPath/index.js
@@ -130,6 +130,8 @@ const FindShortestPath = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -162,8 +164,9 @@ const FindShortestPath = props => {
                 <Form.Item
                     name='max_depth'
                     label="max_depth"
+                    initialValue={3}
                     tooltip={t('analysis.algorithm.oltp.common.max_steps')}
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    rules={[{validator: positiveIntegerValidator}]}
                 >
                     <InputNumber />
                 </Form.Item>
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPathWithWeight/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPathWithWeight/index.js
index acb51059e..0e44b1167 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPathWithWeight/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FindShortestPathWithWeight/index.js
@@ -130,6 +130,8 @@ const FindShortestPathWithWeight = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FusiformSimilarity/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FusiformSimilarity/index.js
index 387ce1477..d5f65beb8 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FusiformSimilarity/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/FusiformSimilarity/index.js
@@ -129,6 +129,8 @@ const FusiformSimilarity = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityGet/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityGet/index.js
index 0aea8f084..11ebb59a7 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityGet/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityGet/index.js
@@ -123,6 +123,8 @@ const JaccardSimilarityGet = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityPost/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityPost/index.js
index 61532b41a..64625f20d 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityPost/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/JaccardSimilarityPost/index.js
@@ -245,6 +245,8 @@ const JaccardSimilarityPost = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborGet/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborGet/index.js
index 9ed5efee1..5aabd1a0f 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborGet/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborGet/index.js
@@ -125,6 +125,8 @@ const KneighborGet = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborPost/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborPost/index.js
index 00a04ffdd..d002b8de8 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborPost/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KneighborPost/index.js
@@ -257,6 +257,8 @@ const KneighborPost = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -274,7 +276,8 @@ const KneighborPost = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    initialValue={3}
+                    rules={[{validator: positiveIntegerValidator}]}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
                 >
                     <Input />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutGet/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutGet/index.js
index 49e99b8b8..c9d19e258 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutGet/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutGet/index.js
@@ -131,6 +131,8 @@ const KoutGet = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutPost/Home/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutPost/Home/index.js
index 450ca9f15..0c29c4153 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutPost/Home/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/KoutPost/Home/index.js
@@ -155,6 +155,8 @@ const KoutPost = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -172,7 +174,8 @@ const KoutPost = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    initialValue={3}
+                    rules={[{validator: positiveIntegerValidator}]}
                     tooltip={t('analysis.algorithm.form.step.max_depth')}
                 >
                     <Input />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/MultiNodesShortestPath/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/MultiNodesShortestPath/index.js
index d3bd13c6a..ed986d229 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/MultiNodesShortestPath/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/MultiNodesShortestPath/index.js
@@ -229,6 +229,8 @@ const MultiNodesShortestPath = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -241,8 +243,9 @@ const MultiNodesShortestPath = props => {
                 <Form.Item
                     name='max_depth'
                     label="max_depth"
+                    initialValue={3}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    rules={[{validator: positiveIntegerValidator}]}
                 >
                     <InputNumber />
                 </Form.Item>
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/NeighborRankApi/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/NeighborRankApi/index.js
index b9fa572d2..9ebe98cc9 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/NeighborRankApi/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/NeighborRankApi/index.js
@@ -269,6 +269,8 @@ const NeighborRankApi = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Paths/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Paths/index.js
index dd57b14d3..50e6de567 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Paths/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Paths/index.js
@@ -121,6 +121,8 @@ const Paths = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={pathsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -148,7 +150,8 @@ const Paths = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: maxDepthValidator}]}
+                    initialValue={3}
+                    rules={[{validator: maxDepthValidator}]}
                     tooltip={t('analysis.algorithm.oltp.common.max_steps')}
                 >
                     <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/RankApi/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/RankApi/index.js
index aa5e8cc1a..081ee6c8d 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/RankApi/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/RankApi/index.js
@@ -41,7 +41,7 @@ const {RANK_API} = ALGORITHM_NAME;
 const initialValue = {
     alpha: 0.85,
     max_degree: 10000,
-    max_depth: 5,
+    max_depth: 3,
     limit: 100,
     max_diff: 0.0001,
     sorted: true,
@@ -137,6 +137,8 @@ const RankApi = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rays/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rays/index.js
index 28c7928af..2402d4ea7 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rays/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rays/index.js
@@ -125,6 +125,8 @@ const Rays = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
@@ -160,7 +162,8 @@ const Rays = props => {
                 <Form.Item
                     label='max_depth'
                     name='max_depth'
-                    rules={[{required: true}, {validator: 
positiveIntegerValidator}]}
+                    initialValue={3}
+                    rules={[{validator: positiveIntegerValidator}]}
                     tooltip={t('analysis.algorithm.max_depth_item.tooltip')}
                 >
                     <InputNumber />
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ResourceAllocation/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ResourceAllocation/index.js
index 474354359..9a36de580 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ResourceAllocation/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ResourceAllocation/index.js
@@ -120,6 +120,8 @@ const ResourceAllocation = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={resourceAllocationForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rings/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rings/index.js
index 07eaf1b79..98f1014e3 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rings/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/Rings/index.js
@@ -126,6 +126,8 @@ const Rings = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighbors/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighbors/index.js
index e48fa0242..f8557a80d 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighbors/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighbors/index.js
@@ -125,6 +125,8 @@ const SameNeighbors = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighborsBatch/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighborsBatch/index.js
index f77c45c41..88710d7a9 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighborsBatch/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SameNeighborsBatch/index.js
@@ -125,6 +125,8 @@ const SameNeighborsBatch = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ShortestPath/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ShortestPath/index.js
index 2007c9f7b..b775c8c66 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ShortestPath/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/ShortestPath/index.js
@@ -126,6 +126,8 @@ const ShortestPath = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={crosspointsForm}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SingleSourceShortestPath/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SingleSourceShortestPath/index.js
index fb19a58df..27089399b 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SingleSourceShortestPath/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/SingleSourceShortestPath/index.js
@@ -131,6 +131,8 @@ const SingleSourceShortestPath = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 onValuesChange={_.debounce(onFormValuesChange, 300)}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/TemplatePaths/Home/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/TemplatePaths/Home/index.js
index a93f9f83b..de3dfe7b9 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/TemplatePaths/Home/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/Oltp/TemplatePaths/Home/index.js
@@ -147,6 +147,8 @@ const TemplatePaths = props => {
             }
         >
             <Form
+                isDisabled={!isEnableRun}
+                isRunning={isRequiring}
                 form={form}
                 onFinish={onFormFinish}
                 className={s.oltpForms}
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.js
index f52569612..42c3a6fe0 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.js
@@ -140,6 +140,9 @@ const PersistentForm = props => {
     const [fallbackForm] = AntForm.useForm();
     const {
         form = fallbackForm,
+        isDisabled = false,
+        isRunning = false,
+        onKeyDown,
         onValuesChange,
         ...formProps
     } = props;
@@ -166,10 +169,27 @@ const PersistentForm = props => {
         [onValuesChange, storageKey]
     );
 
+    const handleKeyDown = useCallback(
+        event => {
+            onKeyDown?.(event);
+            if (event.defaultPrevented || event.key !== 'Enter'
+                || (!event.metaKey && !event.ctrlKey)
+                || event.altKey || event.shiftKey
+                || event.nativeEvent?.isComposing || event.repeat
+                || isDisabled || isRunning) {
+                return;
+            }
+            event.preventDefault();
+            form.submit();
+        },
+        [form, isDisabled, isRunning, onKeyDown]
+    );
+
     return (
         <AntForm
             {...formProps}
             form={form}
+            onKeyDown={handleKeyDown}
             onValuesChange={handleValuesChange}
         />
     );
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.test.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.test.js
index 5cc0f91ea..658db2af1 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.test.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/PersistentForm/index.test.js
@@ -87,6 +87,56 @@ test('persists and restores parameters per graph and 
algorithm', async () => {
     await waitFor(() => 
expect(screen.getByLabelText('source')).toHaveValue('1:alice'));
 });
 
+test('submits with Cmd/Ctrl+Enter', async () => {
+    const onFinish = jest.fn();
+    const {container} = render(
+        <Form onFinish={onFinish}>
+            <Form.Item name='source' initialValue='1:marko'>
+                <Input />
+            </Form.Item>
+        </Form>
+    );
+    const form = container.querySelector('form');
+
+    fireEvent.keyDown(form, {key: 'Enter', metaKey: true});
+    await waitFor(() => expect(onFinish).toHaveBeenCalledTimes(1));
+
+    fireEvent.keyDown(form, {key: 'Enter', ctrlKey: true});
+    await waitFor(() => expect(onFinish).toHaveBeenCalledTimes(2));
+});
+
+test.each([
+    ['plain Enter', {key: 'Enter'}],
+    ['Alt modifier', {key: 'Enter', metaKey: true, altKey: true}],
+    ['Shift modifier', {key: 'Enter', metaKey: true, shiftKey: true}],
+    ['composition', {key: 'Enter', metaKey: true, isComposing: true}],
+    ['repeat', {key: 'Enter', metaKey: true, repeat: true}],
+])('ignores shortcut during %s', async (name, event) => {
+    const onFinish = jest.fn();
+    const {container} = render(<Form onFinish={onFinish} />);
+
+    fireEvent.keyDown(container.querySelector('form'), event);
+
+    await Promise.resolve();
+    expect(onFinish).not.toHaveBeenCalled();
+});
+
+test.each([
+    ['disabled', {isDisabled: true}],
+    ['loading', {isRunning: true}],
+])('does not submit while the run action is %s', async (name, state) => {
+    const onFinish = jest.fn();
+    const {container} = render(<Form {...state} onFinish={onFinish} />);
+
+    fireEvent.keyDown(container.querySelector('form'), {
+        key: 'Enter',
+        metaKey: true,
+    });
+
+    await Promise.resolve();
+    expect(onFinish).not.toHaveBeenCalled();
+});
+
 const algorithmSourceFiles = directory => fs.readdirSync(directory, 
{withFileTypes: true})
     .flatMap(entry => {
         const entryPath = path.join(directory, entry.name);
@@ -182,14 +232,42 @@ test('renders examples through real shared and OLAP 
resource field components',
         </GraphAnalysisContext.Provider>
     );
 
-    expect(screen.getByLabelText('max_depth'))
-        .toHaveAttribute('placeholder', 'For example: 10');
+    expect(screen.getByLabelText('max_depth')).toHaveValue('3');
     expect(screen.getByLabelText('k8s.computer_cpu'))
         .toHaveAttribute('placeholder', 'For example: 2');
     expect(screen.getByLabelText('k8s.worker_request_memory'))
         .toHaveAttribute('placeholder', 'For example: 1Gi');
 });
 
+test('defaults optional max_depth parameters to 3', () => {
+    const algorithmRoot = path.resolve(__dirname, '..');
+    const requiredFields = [];
+    const fieldsWithoutDefault = [];
+
+    algorithmSourceFiles(algorithmRoot).forEach(file => {
+        const source = fs.readFileSync(file, 'utf8');
+        const itemBlocks = 
source.match(/<Form\.Item\b[\s\S]*?<\/Form\.Item>/g) || [];
+
+        itemBlocks.forEach(block => {
+            if (!/name\s*=\s*['"]max_depth['"]/.test(block)) {
+                return;
+            }
+            const isRequired = /required\s*:\s*true/.test(block);
+            const hasDefault = /initialValue\s*=\s*\{3\}/.test(block)
+                || /max_depth\s*:\s*3/.test(source);
+            if (isRequired) {
+                requiredFields.push(path.relative(algorithmRoot, file));
+            }
+            if (!hasDefault) {
+                fieldsWithoutDefault.push(path.relative(algorithmRoot, file));
+            }
+        });
+    });
+
+    expect(requiredFields).toEqual([]);
+    expect(fieldsWithoutDefault).toEqual([]);
+});
+
 test('resets an existing form when the next graph has no saved draft', async 
() => {
     const view = renderForm();
     fireEvent.change(screen.getByLabelText('source'), {target: {value: 
'1:alice'}});
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/algorithm-dom-props.test.js
 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/algorithm-dom-props.test.js
index 0edf395ad..89f7f682b 100644
--- 
a/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/algorithm-dom-props.test.js
+++ 
b/hugegraph-hubble/hubble-fe/src/modules/algorithm/algorithmsForm/algorithm-dom-props.test.js
@@ -52,3 +52,17 @@ test('algorithm panels forward only the collapse control 
contract', () => {
 
     expect(offenders).toEqual([]);
 });
+
+test('max_depth defaults stay optional', () => {
+    const offenders = collectJavaScript(__dirname).flatMap(file => {
+        const source = fs.readFileSync(file, 'utf8');
+        const fields = source.match(
+            /name=['"]max_depth['"][\s\S]*?<\/Form\.Item>/gu
+        ) ?? [];
+        return fields.some(field => field.includes('required: true'))
+            ? [path.relative(__dirname, file)]
+            : [];
+    });
+
+    expect(offenders).toEqual([]);
+});
diff --git a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.js 
b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.js
index dbe631a5b..21ad80d9d 100644
--- a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.js
+++ b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.js
@@ -20,7 +20,8 @@
  * @file 任务管理 table页面
  */
 
-import React, {useState, useCallback, useContext} from 'react';
+import React, {useState, useCallback, useContext, useEffect} from 'react';
+import {Link} from 'react-router-dom';
 import {Table, Tag, Spin, message, Button, Typography, Modal} from 'antd';
 import GraphAnalysisContext from '../../Context';
 import {CloseOutlined} from '@ant-design/icons';
@@ -36,16 +37,22 @@ import {
 import {intersection, size} from 'lodash-es';
 import {format} from 'date-fns';
 import {useTranslation} from 'react-i18next';
+import {AsyncTaskResultContent} from '../Result';
 import c from './index.module.scss';
 const {Text} = Typography;
 
 const {FAILED, SUCCESS, DELETING, CANCELLING} = Async_Taskt_Status;
 
-const TaskAction = ({onAction, args, children}) => {
+const TaskAction = ({onAction, args, children, ...buttonProps}) => {
     const handleClick = useCallback(() => onAction(...args), [args, onAction]);
 
     return (
-        <Button type='link' style={{margin: '10px'}} onClick={handleClick}>
+        <Button
+            type='link'
+            style={{margin: '10px'}}
+            onClick={handleClick}
+            {...buttonProps}
+        >
             {children}
         </Button>
     );
@@ -65,6 +72,7 @@ const AsyncTaskDetail = props => {
     const {graphSpace: currentGraphSpace, graph: currentGraph, isVermeer} = 
useContext(GraphAnalysisContext);
     const {records: asyncManageTaskDataRecords, total: 
asyncManageTaskDataTotal} = asyncManageTaskData || {};
     const [selectedRowKeys, setSelectedRowKeys] = useState([]);
+    const [expandedTaskId, setExpandedTaskId] = useState();
     const {
         taskTypeNames,
         taskStatusNames,
@@ -123,10 +131,27 @@ const AsyncTaskDetail = props => {
         return res;
     };
 
-    const viewResult = useCallback(
-        (text, rowData, index) => {
-            
window.open(`/asyncTasks/result/${currentGraphSpace}/${currentGraph}/${rowData.id}`);
-        }, [currentGraph, currentGraphSpace]);
+    const toggleResult = useCallback(taskId => {
+        setExpandedTaskId(current => (
+            current === taskId ? undefined : taskId
+        ));
+    }, []);
+
+    useEffect(() => {
+        setExpandedTaskId(undefined);
+    }, [currentGraph, currentGraphSpace, page, pageSize]);
+
+    useEffect(() => {
+        if (expandedTaskId === undefined) {
+            return;
+        }
+        const stillVisible = asyncManageTaskDataRecords?.some(
+            task => task.id === expandedTaskId
+        );
+        if (!stillVisible) {
+            setExpandedTaskId(undefined);
+        }
+    }, [asyncManageTaskDataRecords, expandedTaskId]);
 
     const deleteTaskByIds = useCallback(
         taskIdArr => {
@@ -248,6 +273,7 @@ const AsyncTaskDetail = props => {
                 const {'task_status': status, 'task_type': type, id: taskId}  
= rowData;
                 const allowCheckResTypeArr = ['gremlin', 'computer-dis', 
'cypher'];
                 const isAllowCheckRes = status === SUCCESS && 
allowCheckResTypeArr.includes(type);
+                const isResultExpanded = expandedTaskId === taskId;
                 const allowAbortStatusArr = ['scheduling', 'scheduled', 
'queued', 'running', 'restoring'];
                 const isAllowAbort = allowAbortStatusArr.includes(status);
                 const {
@@ -260,17 +286,26 @@ const AsyncTaskDetail = props => {
                 return (
                     <div style={{whiteSpace: 'nowrap'}}>
                         {status === FAILED && (
-                            <a
-                                style={{margin: '10px'}}
-                                
href={`/asyncTasks/result/${currentGraphSpace}/${currentGraph}/${taskId}`}
+                            <TaskAction
+                                onAction={toggleResult}
+                                args={[taskId]}
+                                aria-expanded={isResultExpanded}
+                                aria-controls={`async-task-result-${taskId}`}
                             >
                                 {reason}
-                            </a>
+                            </TaskAction>
 
                         )}
                         {isAllowCheckRes && (
-                            <TaskAction onAction={viewResult} args={[result, 
rowData, index]}>
-                                {resultText}
+                            <TaskAction
+                                onAction={toggleResult}
+                                args={[taskId]}
+                                aria-expanded={isResultExpanded}
+                                aria-controls={`async-task-result-${taskId}`}
+                            >
+                                {isResultExpanded
+                                    ? 
t('analysis.async_task.action.collapse_result')
+                                    : resultText}
                             </TaskAction>
                         )}
                         {!isAllowAbort && (
@@ -325,6 +360,44 @@ const AsyncTaskDetail = props => {
                 columns={columns}
                 dataSource={asyncManageTaskDataRecords}
                 onChange={onPageChange}
+                expandable={{
+                    expandedRowKeys: expandedTaskId === undefined
+                        ? [] : [expandedTaskId],
+                    onExpand: (expanded, rowData) => {
+                        setExpandedTaskId(expanded ? rowData.id : undefined);
+                    },
+                    rowExpandable: rowData => {
+                        const resultTypes = [
+                            'gremlin',
+                            'computer-dis',
+                            'cypher',
+                        ];
+                        return rowData.task_status === FAILED
+                               || (rowData.task_status === SUCCESS
+                                   && resultTypes.includes(rowData.task_type));
+                    },
+                    expandedRowRender: rowData => (
+                        <div
+                            id={`async-task-result-${rowData.id}`}
+                            className={c.inlineResult}
+                        >
+                            <div className={c.inlineResultHeader}>
+                                <strong>
+                                    {t('analysis.async_task.result_title')}
+                                </strong>
+                                <Link 
to={`/asyncTasks/result/${currentGraphSpace}/${currentGraph}/${rowData.id}`}>
+                                    {t('analysis.async_task.result_open_full')}
+                                </Link>
+                            </div>
+                            <AsyncTaskResultContent
+                                compact
+                                graphspace={currentGraphSpace}
+                                graph={currentGraph}
+                                taskId={rowData.id}
+                            />
+                        </div>
+                    ),
+                }}
                 pagination={{
                     position: ['bottomRight'],
                     total: asyncManageTaskDataTotal,
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.module.scss 
b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.module.scss
index 7c5f64fa7..42e2f9d9c 100644
--- a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.module.scss
+++ b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.module.scss
@@ -45,4 +45,16 @@
     .clearSelection {
         color: inherit;
     }
+
+    .inlineResult {
+        padding: var(--workbench-space-3) var(--workbench-space-4);
+    }
+
+    .inlineResultHeader {
+        display: flex;
+        align-items: center;
+        justify-content: space-between;
+        gap: var(--workbench-space-3);
+        margin-bottom: var(--workbench-space-2);
+    }
 }
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.test.js 
b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.test.js
new file mode 100644
index 000000000..3be9a4df0
--- /dev/null
+++ b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Detail/index.test.js
@@ -0,0 +1,104 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import {fireEvent, render, screen} from '@testing-library/react';
+import {MemoryRouter} from 'react-router-dom';
+import GraphAnalysisContext from '../../Context';
+import AsyncTaskDetail from './index';
+
+jest.mock('../../../api/index', () => ({
+    analysis: {
+        deleteAsyncTask: jest.fn(),
+        abortAsyncTask: jest.fn(),
+    },
+}));
+jest.mock('lodash-es', () => ({
+    intersection: (left, right) => left.filter(value => right.includes(value)),
+    size: value => value.length,
+}));
+jest.mock('../Result', () => ({
+    AsyncTaskResultContent: ({taskId}) => (
+        <div data-testid="inline-result">result {taskId}</div>
+    ),
+}));
+jest.mock('react-i18next', () => ({
+    useTranslation: () => ({t: key => key}),
+}));
+
+beforeAll(() => {
+    window.matchMedia = window.matchMedia || (() => ({
+        matches: false,
+        addListener: jest.fn(),
+        removeListener: jest.fn(),
+    }));
+});
+
+const renderDetail = () => render(
+    <MemoryRouter future={{v7_startTransition: true, v7_relativeSplatPath: 
true}}>
+        <GraphAnalysisContext.Provider
+            value={{
+                graphSpace: 'DEFAULT',
+                graph: 'hugegraph',
+                isVermeer: false,
+            }}
+        >
+            <AsyncTaskDetail
+                page={1}
+                pageSize={10}
+                onPageChange={jest.fn()}
+                getAsynTaskList={jest.fn()}
+                asyncManageTaskData={{
+                    records: [{
+                        id: 4,
+                        task_name: 'g.V().count()',
+                        task_type: 'gremlin',
+                        task_status: 'success',
+                        task_create: 1787991956000,
+                        task_update: 1787991957000,
+                    }],
+                    total: 1,
+                }}
+                loading={false}
+            />
+        </GraphAnalysisContext.Provider>
+    </MemoryRouter>
+);
+
+it('controls row expansion without opening a new browser tab', () => {
+    window.open = jest.fn();
+    renderDetail();
+
+    const view = screen.getByRole('button', {
+        name: 'analysis.async_task.action.check_result',
+    });
+    expect(view).toHaveAttribute('aria-expanded', 'false');
+    fireEvent.click(view);
+
+    expect(screen.getByRole('button', {
+        name: 'analysis.async_task.action.collapse_result',
+    })).toHaveAttribute('aria-expanded', 'true');
+    expect(document.querySelector('.ant-table-row-expand-icon'))
+        .toHaveClass('ant-table-row-expand-icon-expanded');
+    expect(window.open).not.toHaveBeenCalled();
+
+    fireEvent.click(screen.getByRole('button', {
+        name: 'analysis.async_task.action.collapse_result',
+    }));
+    expect(document.querySelector('.ant-table-row-expand-icon'))
+        .not.toHaveClass('ant-table-row-expand-icon-expanded');
+});
diff --git a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.js 
b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.js
index 8976a133b..458c4da00 100644
--- a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.js
+++ b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.js
@@ -29,14 +29,13 @@ import ReactJsonView from 'react-json-view';
 import convertStringToJSON from '../../../utils/convertStringToJSON';
 import c from './index.module.scss';
 
-const AsyncTaskResult = () => {
+export const AsyncTaskResultContent = ({
+    graphspace,
+    graph,
+    taskId,
+    compact = false,
+}) => {
     const {t} = useTranslation();
-    const {
-        graphspace,
-        graph,
-        taskId,
-    } = useParams();
-
     const [asyncTaskResultJson, setAsyncTaskResultJson] = useState();
     const [loading, setLoading] = useState(true);
     const [error, setError] = useState(false);
@@ -89,6 +88,48 @@ const AsyncTaskResult = () => {
                       && asyncTaskResultJson !== null
                       && asyncTaskResultJson !== 'null';
 
+    return (
+        <div className={compact ? c.inlineResultBody : c.resultBody}>
+            {error && (
+                <Alert
+                    showIcon
+                    type='error'
+                    message={t('analysis.async_task.result_load_failed')}
+                    action={(
+                        <Button size='small' onClick={getResult}>
+                            {t('analysis.async_task.retry_result')}
+                        </Button>
+                    )}
+                />
+            )}
+            {loading && <Spin tip={t('analysis.async_task.result_loading')} />}
+            {!loading && !error && (
+                !hasResult ? (
+                    <Empty description={t('analysis.async_task.no_result')} />
+                ) : resultForJSON === null ? (
+                    asyncTaskResultJson
+                ) : (
+                    <ReactJsonView
+                        src={resultForJSON}
+                        name={false}
+                        displayObjectSize={false}
+                        displayDataTypes={false}
+                        groupArraysAfterLength={50}
+                    />
+                )
+            )}
+        </div>
+    );
+};
+
+const AsyncTaskResult = () => {
+    const {t} = useTranslation();
+    const {
+        graphspace,
+        graph,
+        taskId,
+    } = useParams();
+
     return (
         <div className={c.pageCanvas}>
             <section className={c.asyncTaskResult}>
@@ -107,36 +148,11 @@ const AsyncTaskResult = () => {
                         {t('analysis.async_task.result_back')}
                     </Link>
                 </header>
-                <div className={c.resultBody}>
-                    {error && (
-                        <Alert
-                            showIcon
-                            type='error'
-                            
message={t('analysis.async_task.result_load_failed')}
-                            action={(
-                                <Button size='small' onClick={getResult}>
-                                    {t('analysis.async_task.retry_result')}
-                                </Button>
-                            )}
-                        />
-                    )}
-                    {loading && <Spin 
tip={t('analysis.async_task.result_loading')} />}
-                    {!loading && !error && (
-                        !hasResult ? (
-                            <Empty 
description={t('analysis.async_task.no_result')} />
-                        ) : resultForJSON === null ? (
-                            asyncTaskResultJson
-                        ) : (
-                            <ReactJsonView
-                                src={resultForJSON}
-                                name={false}
-                                displayObjectSize={false}
-                                displayDataTypes={false}
-                                groupArraysAfterLength={50}
-                            />
-                        )
-                    )}
-                </div>
+                <AsyncTaskResultContent
+                    graphspace={graphspace}
+                    graph={graph}
+                    taskId={taskId}
+                />
             </section>
         </div>
     );
diff --git 
a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.module.scss 
b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.module.scss
index 59d40ac52..f98bb0cf3 100644
--- a/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.module.scss
+++ b/hugegraph-hubble/hubble-fe/src/modules/asyncTasks/Result/index.module.scss
@@ -68,6 +68,18 @@
     overflow-wrap: anywhere;
 }
 
+.inlineResultBody {
+    max-height: 420px;
+    min-height: 112px;
+    padding: var(--workbench-space-4);
+    overflow: auto;
+    border: 1px solid var(--workbench-color-border);
+    border-radius: var(--workbench-radius-lg);
+    background: var(--workbench-color-surface);
+    white-space: pre-wrap;
+    overflow-wrap: anywhere;
+}
+
 @media (max-width: 900px) {
     .resultHeader {
         flex-direction: column;
diff --git a/hugegraph-hubble/hubble-fe/src/pages/Account/EditLayer.js 
b/hugegraph-hubble/hubble-fe/src/pages/Account/EditLayer.js
index 13616c29e..b22718677 100644
--- a/hugegraph-hubble/hubble-fe/src/pages/Account/EditLayer.js
+++ b/hugegraph-hubble/hubble-fe/src/pages/Account/EditLayer.js
@@ -88,8 +88,9 @@ const EditLayer = ({
                 onCancel();
                 refresh();
                 onCreated?.({
+                    user_id: res.data?.id,
                     user_name: values.user_name,
-                    is_superadmin: values.is_superadmin,
+                    is_superadmin: Boolean(values.is_superadmin),
                 });
                 return;
             }
diff --git 
a/hugegraph-hubble/hubble-fe/src/pages/Account/account-edit-recovery.test.js 
b/hugegraph-hubble/hubble-fe/src/pages/Account/account-edit-recovery.test.js
index c5ecf6510..530c7465c 100644
--- a/hugegraph-hubble/hubble-fe/src/pages/Account/account-edit-recovery.test.js
+++ b/hugegraph-hubble/hubble-fe/src/pages/Account/account-edit-recovery.test.js
@@ -85,8 +85,19 @@ beforeEach(() => {
 test('creates a non-elevated account when preset API is unavailable',
     async () => {
         mockAuthContext = {capabilities: ['accounts_manage']};
-        api.auth.addUser.mockResolvedValue({status: 200});
-        render(<EditLayer {...props} data={{}} op='create' />);
+        const onCreated = jest.fn();
+        api.auth.addUser.mockResolvedValue({
+            status: 200,
+            data: {id: 'user-42'},
+        });
+        render(
+            <EditLayer
+                {...props}
+                data={{}}
+                op='create'
+                onCreated={onCreated}
+            />
+        );
         await act(async () => undefined);
 
         expect(screen.queryByText('account.form.permission_preset'))
@@ -111,6 +122,11 @@ test('creates a non-elevated account when preset API is 
unavailable',
         expect(payload).not.toHaveProperty('graphspace_permissions');
         expect(payload).not.toHaveProperty('adminSpaces');
         expect(payload).not.toHaveProperty('is_superadmin');
+        expect(onCreated).toHaveBeenCalledWith({
+            user_id: 'user-42',
+            user_name: 'alice',
+            is_superadmin: false,
+        });
     });
 
 test('keeps global super administrator identity in account creation', async () 
=> {

Reply via email to