Parcourir la source

[Improvement-14456][UI] When making the process online the system should remind user to take care of its offline timing. (#14460)

calvin il y a 1 an
Parent
commit
92d2b8e33f

+ 10 - 8
dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/cases/WorkflowE2ETest.java

@@ -49,6 +49,8 @@ import static org.awaitility.Awaitility.await;
 class WorkflowE2ETest {
     private static final String project = "test-workflow-1";
 
+    private static final String workflow = "test-workflow-1";
+
     private static final String user = "admin";
 
     private static final String password = "dolphinscheduler123";
@@ -86,22 +88,23 @@ class WorkflowE2ETest {
             .goToNav(ProjectPage.class)
             .goTo(project)
             .goToTab(WorkflowDefinitionTab.class)
-            .cancelPublishAll()
-            .deleteAll()
-        ;
+            .delete(workflow);
+
         new NavBarPage(browser)
             .goToNav(ProjectPage.class)
-            .delete(project)
+            .delete(project);
+
+        browser.navigate().refresh();
+
+        new NavBarPage(browser)
             .goToNav(SecurityPage.class)
             .goToTab(TenantPage.class)
-            .delete(tenant)
-        ;
+            .delete(tenant);
     }
 
     @Test
     @Order(1)
     void testCreateWorkflow() {
-        final String workflow = "test-workflow-1";
         WorkflowDefinitionTab workflowDefinitionPage =
             new ProjectPage(browser)
                 .goTo(project)
@@ -163,7 +166,6 @@ class WorkflowE2ETest {
     @Test
     @Order(30)
     void testRunWorkflow() {
-        final String workflow = "test-workflow-1";
         final ProjectDetailPage projectPage =
                 new ProjectPage(browser)
                         .goToNav(ProjectPage.class)

+ 2 - 2
dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/LoginPage.java

@@ -58,7 +58,7 @@ public final class LoginPage extends NavBarPage {
 
     @SneakyThrows
     public NavBarPage login(String username, String password) {
-        new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(buttonSwitchLanguage));
+        new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(buttonSwitchLanguage));
 
         buttonSwitchLanguage().click();
 
@@ -66,7 +66,7 @@ public final class LoginPage extends NavBarPage {
         inputPassword().sendKeys(password);
         buttonLogin().click();
 
-        new WebDriverWait(driver, 10)
+        new WebDriverWait(driver, 20)
             .until(ExpectedConditions.urlContains("/home"));
 
         return new NavBarPage(driver);

+ 33 - 1
dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/project/workflow/WorkflowDefinitionTab.java

@@ -19,6 +19,9 @@
  */
 package org.apache.dolphinscheduler.e2e.pages.project.workflow;
 
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Awaitility.await;
+
 import lombok.Getter;
 import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
 import org.apache.dolphinscheduler.e2e.pages.project.ProjectDetailPage;
@@ -30,7 +33,6 @@ import org.openqa.selenium.support.FindBy;
 import org.openqa.selenium.support.FindBys;
 
 import java.util.List;
-import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
 @Getter
@@ -56,6 +58,12 @@ public final class WorkflowDefinitionTab extends NavBarPage implements ProjectDe
     })
     private WebElement buttonConfirm;
 
+    @FindBys({
+        @FindBy(className = "n-dialog__action"),
+        @FindBy(className = "n-button--default-type"),
+    })
+    private WebElement publishSuccessButtonCancel;
+
     @FindBy(className = "items")
     private List<WebElement> workflowList;
 
@@ -89,6 +97,10 @@ public final class WorkflowDefinitionTab extends NavBarPage implements ProjectDe
             .orElseThrow(() -> new RuntimeException("Can not find publish button in workflow definition"))
             .click();
 
+        ((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
+
+        ((JavascriptExecutor) driver).executeScript("arguments[0].click();", publishSuccessButtonCancel());
+
         return this;
     }
 
@@ -114,11 +126,31 @@ public final class WorkflowDefinitionTab extends NavBarPage implements ProjectDe
 
         for (WebElement cancelButton : cancelButtons) {
             cancelButton.click();
+            ((JavascriptExecutor) driver).executeScript("arguments[0].click();", buttonConfirm());
         }
 
         return this;
     }
 
+    public WorkflowDefinitionTab delete(String workflow) {
+        await().untilAsserted(() -> assertThat(workflowList())
+            .as("Workflow list should contain newly-created workflow")
+            .anyMatch(
+                it -> it.getText().contains(workflow)
+            ));
+
+        workflowList()
+            .stream()
+            .filter(it -> it.findElement(By.className("workflow-name")).getAttribute("innerText").equals(workflow))
+            .flatMap(it -> it.findElements(By.className("btn-delete")).stream())
+            .filter(WebElement::isDisplayed)
+            .findFirst()
+            .orElseThrow(() -> new RuntimeException("Can not find delete button in workflow definition"))
+            .click();
+
+        return this;
+    }
+
     public WorkflowDefinitionTab deleteAll() {
         if (workflowList().isEmpty()) {
             return this;

+ 6 - 1
dolphinscheduler-ui/src/locales/en_US/project.ts

@@ -75,6 +75,8 @@ export default {
     modify_user: 'Modify User',
     operation: 'Operation',
     edit: 'Edit',
+    confirm: 'Confirm',
+    cancel: 'Cancel',
     start: 'Start',
     timing: 'Timing',
     timezone: 'Timezone',
@@ -226,7 +228,10 @@ export default {
     workflow_relation_no_data_result_desc:
       'There is not any workflows. Please create a workflow, and then visit this page again.',
     ready_to_block: 'Ready to block',
-    block: 'Block'
+    block: 'Block',
+    want_to_set_timing: 'Would you like to set the workflow timing?',
+    confirm_to_online: 'Confirm to make the workflow online?',
+    confirm_to_offline: 'Confirm to make the workflow offline?',
   },
   task: {
     on_line: 'Online',

+ 4 - 1
dolphinscheduler-ui/src/locales/zh_CN/project.ts

@@ -226,7 +226,10 @@ export default {
     workflow_relation_no_data_result_desc:
       '目前没有任何工作流,请先创建工作流,再访问该页面',
     ready_to_block: '准备锁定',
-    block: '锁定'
+    block: '锁定',
+    want_to_set_timing: '现在想去配置该工作流定时?',
+    confirm_to_online: '是否确定上线该工作流?',
+    confirm_to_offline: '是否确定下线该工作流?',
   },
   task: {
     on_line: '线上',

+ 17 - 8
dolphinscheduler-ui/src/views/projects/workflow/definition/components/table-action.tsx

@@ -189,16 +189,25 @@ export default defineComponent({
                 type={releaseState === 'ONLINE' ? 'warning' : 'error'}
                 tag='div'
                 circle
-                onClick={this.handleReleaseWorkflow}
                 class='btn-publish'
               >
-                <NIcon>
-                  {releaseState === 'ONLINE' ? (
-                    <DownloadOutlined />
-                  ) : (
-                    <UploadOutlined />
-                  )}
-                </NIcon>
+                <NPopconfirm onPositiveClick={this.handleReleaseWorkflow}>
+                  {{
+                    default: () =>
+                      releaseState === 'ONLINE'
+                        ? t('project.workflow.confirm_to_offline')
+                        : t('project.workflow.confirm_to_online'),
+                    trigger: () => (
+                      <NIcon>
+                        {releaseState === 'ONLINE' ? (
+                          <DownloadOutlined />
+                        ) : (
+                          <UploadOutlined />
+                        )}
+                      </NIcon>
+                    )
+                  }}
+                </NPopconfirm>
               </NButton>
             )
           }}

+ 19 - 2
dolphinscheduler-ui/src/views/projects/workflow/definition/index.tsx

@@ -23,7 +23,8 @@ import {
   NPagination,
   NSpace,
   NTooltip,
-  NPopconfirm
+  NPopconfirm,
+  NModal
 } from 'naive-ui'
 import {
   defineComponent,
@@ -59,7 +60,8 @@ export default defineComponent({
       getTableData,
       batchDeleteWorkflow,
       batchExportWorkflow,
-      batchCopyWorkflow
+      batchCopyWorkflow,
+      gotoTimingManage
     } = useTable()
 
     const requestData = () => {
@@ -79,6 +81,10 @@ export default defineComponent({
       requestData()
     }
 
+    const confirmToSetWorkflowTiming = () => {
+      gotoTimingManage(variables.row)
+    }
+
     const handleSearch = () => {
       variables.page = 1
       requestData()
@@ -136,6 +142,7 @@ export default defineComponent({
       batchExportWorkflow,
       batchCopyWorkflow,
       handleCopyUpdateList,
+      confirmToSetWorkflowTiming,
       ...toRefs(variables),
       uiSettingStore,
       trim
@@ -300,6 +307,16 @@ export default defineComponent({
           v-model:show={this.copyShowRef}
           onUpdateList={this.handleCopyUpdateList}
         />
+        <NModal
+          v-model:show={this.setTimingDialogShowRef}
+          preset={'dialog'}
+          title={t('project.workflow.success')}
+          content={t('project.workflow.want_to_set_timing')}
+          positiveText={t('project.workflow.confirm')}
+          negativeText={t('project.workflow.cancel')}
+          maskClosable={false}
+          onPositiveClick={this.confirmToSetWorkflowTiming}
+        />
       </NSpace>
     )
   }

+ 99 - 0
dolphinscheduler-ui/src/views/projects/workflow/definition/timing/use-table.ts

@@ -75,6 +75,104 @@ export function useTable() {
     ])
   }
 
+  const createTimingListTableColumns = (variables: any) => {
+    variables.columns = [
+      {
+        title: '#',
+        key: 'id',
+        ...COLUMN_WIDTH_CONFIG['index'],
+        render: (row: any, index: number) => index + 1
+      },
+      {
+        title: t('project.workflow.start_time'),
+        key: 'startTime',
+        ...COLUMN_WIDTH_CONFIG['timeZone'],
+        render: (row: any) => renderTime(row.startTime, row.timezoneId)
+      },
+      {
+        title: t('project.workflow.end_time'),
+        key: 'endTime',
+        ...COLUMN_WIDTH_CONFIG['timeZone'],
+        render: (row: any) => renderTime(row.endTime, row.timezoneId)
+      },
+      {
+        title: t('project.workflow.crontab'),
+        key: 'crontab',
+        width: 140
+      },
+      {
+        title: t('project.workflow.status'),
+        key: 'releaseState',
+        ...COLUMN_WIDTH_CONFIG['state'],
+        render: (row: any) => {
+          if (row.releaseState === 'ONLINE') {
+            return h(
+                NTag,
+                { type: 'success', size: 'small' },
+                {
+                  default: () => t('project.workflow.up_line')
+                }
+            )
+          } else {
+            return h(
+                NTag,
+                { type: 'warning', size: 'small' },
+                {
+                  default: () => t('project.workflow.down_line')
+                }
+            )
+          }
+        }
+      },
+      {
+        title: t('project.workflow.operation'),
+        key: 'operation',
+        ...COLUMN_WIDTH_CONFIG['operation'](3),
+        render: (row: any) => {
+          return h(NSpace, null, {
+            default: () => [
+              h(
+                  NTooltip,
+                  {},
+                  {
+                    trigger: () =>
+                        h(
+                            NButton,
+                            {
+                              circle: true,
+                              type:
+                                  row.releaseState === 'ONLINE' ? 'error' : 'warning',
+                              size: 'small',
+                              onClick: () => {
+                                handleReleaseState(row)
+                              }
+                            },
+                            {
+                              icon: () =>
+                                  h(
+                                      row.releaseState === 'ONLINE'
+                                          ? ArrowDownOutlined
+                                          : ArrowUpOutlined
+                                  )
+                            }
+                        ),
+                    default: () =>
+                        row.releaseState === 'ONLINE'
+                            ? t('project.workflow.down_line')
+                            : t('project.workflow.up_line')
+                  }
+              ),
+            ]
+          })
+        }
+      }
+    ]
+    if (variables.tableWidth) {
+      variables.tableWidth = calculateTableWidth(variables.columns)
+    }
+  }
+
+
   const createColumns = (variables: any) => {
     variables.columns = [
       {
@@ -326,6 +424,7 @@ export function useTable() {
   return {
     variables,
     createColumns,
+    createTimingListTableColumns,
     getTableData
   }
 }

+ 11 - 3
dolphinscheduler-ui/src/views/projects/workflow/definition/use-table.ts

@@ -63,7 +63,8 @@ export function useTable() {
     timingShowRef: ref(false),
     versionShowRef: ref(false),
     copyShowRef: ref(false),
-    loadingRef: ref(false)
+    loadingRef: ref(false),
+    setTimingDialogShowRef: ref(false)
   })
 
   const createColumns = (variables: any) => {
@@ -351,8 +352,14 @@ export function useTable() {
         | 'OFFLINE'
         | 'ONLINE'
     }
+
     release(data, variables.projectCode, row.code).then(() => {
-      window.$message.success(t('project.workflow.success'))
+      if (data.releaseState === 'ONLINE') {
+        variables.setTimingDialogShowRef = true
+        variables.row = row
+      } else {
+        window.$message.success(t('project.workflow.success'))
+      }
       getTableData({
         pageSize: variables.pageSize,
         pageNo: variables.page,
@@ -448,6 +455,7 @@ export function useTable() {
     getTableData,
     batchDeleteWorkflow,
     batchExportWorkflow,
-    batchCopyWorkflow
+    batchCopyWorkflow,
+    gotoTimingManage
   }
 }