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

benjobs pushed a commit to branch submit
in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git


The following commit(s) were added to refs/heads/submit by this push:
     new e17041162 [Improve] check job on yarn exists improvement
e17041162 is described below

commit e170411621e205cf664aa24c60c07960f27db7f8
Author: benjobs <[email protected]>
AuthorDate: Fri Dec 22 15:09:22 2023 +0800

    [Improve] check job on yarn exists improvement
---
 .../core/controller/ApplicationController.java     |  8 ++++
 .../application/ApplicationActionService.java      |  3 ++
 .../impl/ApplicationActionServiceImpl.java         | 15 +++++++
 .../streampark-console-webapp/src/api/flink/app.ts |  9 ++--
 .../Application/src/AppDarkModeToggle.vue          |  4 +-
 .../src/components/ContextMenu/src/ContextMenu.vue |  4 +-
 .../src/components/Form/src/BasicForm.vue          |  2 +-
 .../components/Form/src/components/FormItem.vue    |  8 ++--
 .../Modal/src/components/ModalWrapper.vue          |  4 +-
 .../src/components/Page/src/PageFooter.vue         |  4 +-
 .../components/Table/src/components/HeaderCell.vue |  2 +-
 .../src/enums/flinkEnum.ts                         |  8 ++++
 .../src/hooks/setting/useMenuSetting.ts            | 10 ++---
 .../src/hooks/web/useLockPage.ts                   |  9 ++--
 .../streampark-console-webapp/src/utils/props.ts   | 48 +++++++++++-----------
 .../src/views/base/error-log/data.tsx              | 12 +++---
 .../src/views/flink/app/hooks/useApp.tsx           | 36 ++++++++++++++--
 17 files changed, 121 insertions(+), 65 deletions(-)

diff --git 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
index 3d178ac64..db2d1f8df 100644
--- 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
+++ 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/controller/ApplicationController.java
@@ -214,6 +214,14 @@ public class ApplicationController {
     }
   }
 
+  @PermissionAction(id = "#app.id", type = PermissionTypeEnum.APP)
+  @PostMapping(value = "check_start")
+  @RequiresPermissions("app:start")
+  public RestResponse checkStart(Long id) {
+    AppExistsStateEnum stateEnum = applicationActionService.checkStart(id);
+    return RestResponse.success(stateEnum.get());
+  }
+
   @Operation(
       summary = "Cancel application",
       tags = {ApiDocConstant.FLINK_APP_OP_TAG})
diff --git 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/ApplicationActionService.java
 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/ApplicationActionService.java
index e2936cb73..d180154a6 100644
--- 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/ApplicationActionService.java
+++ 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/ApplicationActionService.java
@@ -19,6 +19,7 @@ package 
org.apache.streampark.console.core.service.application;
 
 import org.apache.streampark.console.base.exception.ApplicationException;
 import org.apache.streampark.console.core.entity.Application;
+import org.apache.streampark.console.core.enums.AppExistsStateEnum;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 
@@ -67,4 +68,6 @@ public interface ApplicationActionService extends 
IService<Application> {
    * @param appParam the application to be stopped
    */
   void forcedStop(Application appParam);
+
+  AppExistsStateEnum checkStart(Long id);
 }
diff --git 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
index a7447cb0c..46b570c24 100644
--- 
a/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
+++ 
b/streampark-console/streampark-console-service/src/main/java/org/apache/streampark/console/core/service/application/impl/ApplicationActionServiceImpl.java
@@ -43,6 +43,7 @@ import org.apache.streampark.console.core.entity.FlinkEnv;
 import org.apache.streampark.console.core.entity.FlinkSql;
 import org.apache.streampark.console.core.entity.Resource;
 import org.apache.streampark.console.core.entity.SavePoint;
+import org.apache.streampark.console.core.enums.AppExistsStateEnum;
 import org.apache.streampark.console.core.enums.CheckPointTypeEnum;
 import org.apache.streampark.console.core.enums.ConfigFileTypeEnum;
 import org.apache.streampark.console.core.enums.FlinkAppStateEnum;
@@ -232,6 +233,20 @@ public class ApplicationActionServiceImpl extends 
ServiceImpl<ApplicationMapper,
     }
   }
 
+  @Override
+  public AppExistsStateEnum checkStart(Long id) {
+    Application application = getById(id);
+    if (application == null) {
+      return AppExistsStateEnum.INVALID;
+    }
+    if (FlinkExecutionMode.isYarnMode(application.getFlinkExecutionMode())) {
+      boolean exists = 
!getApplicationReports(application.getJobName()).isEmpty();
+      return exists ? AppExistsStateEnum.IN_YARN : AppExistsStateEnum.NO;
+    }
+    // todo on k8s check...
+    return AppExistsStateEnum.NO;
+  }
+
   @Override
   public void cancel(Application appParam) throws Exception {
     FlinkAppHttpWatcher.setOptionState(appParam.getId(), 
OptionStateEnum.CANCELLING);
diff --git a/streampark-console/streampark-console-webapp/src/api/flink/app.ts 
b/streampark-console/streampark-console-webapp/src/api/flink/app.ts
index 13110db38..61008b782 100644
--- a/streampark-console/streampark-console-webapp/src/api/flink/app.ts
+++ b/streampark-console/streampark-console-webapp/src/api/flink/app.ts
@@ -26,7 +26,6 @@ enum APP_API {
   COPY = '/flink/app/copy',
   UPLOAD = '/flink/app/upload',
   K8S_START_LOG = '/flink/app/k8sStartLog',
-  DEPLOY = '/flink/app/deploy',
   MAPPING = '/flink/app/mapping',
   YARN = '/flink/app/yarn',
   LIST = '/flink/app/list',
@@ -41,14 +40,12 @@ enum APP_API {
   DELETE_BAK = '/flink/app/deletebak',
   CREATE = '/flink/app/create',
   START = '/flink/app/start',
-  CLEAN = '/flink/app/clean',
+  CHECK_START = '/flink/app/check_start',
   BACKUPS = '/flink/app/backups',
   ROLLBACK = '/flink/app/rollback',
   REVOKE = '/flink/app/revoke',
   OPTION_LOG = '/flink/app/optionlog',
   DELETE_OPERATION_LOG = '/flink/app/deleteOperationLog',
-  CHECK_JAR = '/flink/app/checkjar',
-  VERIFY_SCHEMA = '/flink/app/verifySchema',
   CHECK_SAVEPOINT_PATH = '/flink/app/checkSavepointPath',
 }
 
@@ -174,6 +171,10 @@ export function fetchForcedStop(data: { id: string }): 
Promise<boolean> {
   return defHttp.post({ url: APP_API.FORCED_STOP, data });
 }
 
+export function fetchCheckStart(data): Promise<AxiosResponse<number>> {
+  return defHttp.post({ url: APP_API.CHECK_START, data }, { 
isReturnNativeResponse: true });
+}
+
 export function fetchStart(data): Promise<AxiosResponse<Result>> {
   return defHttp.post({ url: APP_API.START, data }, { isReturnNativeResponse: 
true });
 }
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
 
b/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
index d4e0ce164..19ba3b151 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Application/src/AppDarkModeToggle.vue
@@ -63,9 +63,7 @@
       height: 18px;
       background-color: #fff;
       border-radius: 50%;
-      transition:
-        transform 0.5s,
-        background-color 0.5s;
+      transition: transform 0.5s, background-color 0.5s;
       will-change: transform;
     }
 
diff --git 
a/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
 
b/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
index 78cac5c5b..e08c25f36 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/ContextMenu/src/ContextMenu.vue
@@ -179,9 +179,7 @@
     background-color: @component-background;
     border: 1px solid rgb(0 0 0 / 8%);
     border-radius: 0.25rem;
-    box-shadow:
-      0 2px 2px 0 rgb(0 0 0 / 14%),
-      0 3px 1px -2px rgb(0 0 0 / 10%),
+    box-shadow: 0 2px 2px 0 rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 10%),
       0 1px 5px 0 rgb(0 0 0 / 6%);
     background-clip: padding-box;
     user-select: none;
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
 
b/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
index e5a9dacf6..1cd7e3809 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Form/src/BasicForm.vue
@@ -113,7 +113,7 @@
       });
 
       const getBindValue = computed(
-        () => ({ ...attrs, ...props, ...unref(getProps) }) as Recordable,
+        () => ({ ...attrs, ...props, ...unref(getProps) } as Recordable),
       );
 
       const getSchema = computed((): FormSchema[] => {
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
 
b/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
index 9bbb5023f..137ae94d6 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Form/src/components/FormItem.vue
@@ -333,8 +333,8 @@
             return slot
               ? getSlot(slots, slot, unref(getValues))
               : render
-                ? render(unref(getValues))
-                : renderComponent();
+              ? render(unref(getValues))
+              : renderComponent();
           };
 
           const showSuffix = !!suffix;
@@ -382,8 +382,8 @@
           return colSlot
             ? getSlot(slots, colSlot, values)
             : renderColContent
-              ? renderColContent(values)
-              : renderItem();
+            ? renderColContent(values)
+            : renderItem();
         };
 
         return (
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
 
b/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
index 52c8b5eb8..1b1b9a613 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Modal/src/components/ModalWrapper.vue
@@ -153,8 +153,8 @@
             realHeightRef.value = props.height
               ? props.height
               : realHeight > maxHeight
-                ? maxHeight
-                : realHeight;
+              ? maxHeight
+              : realHeight;
           }
           emit('height-change', unref(realHeightRef));
         } catch (error) {
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
 
b/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
index 8fdbc8f41..e89a6ce97 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Page/src/PageFooter.vue
@@ -39,9 +39,7 @@
     line-height: 44px;
     background-color: @component-background;
     border-top: 1px solid @border-color-base;
-    box-shadow:
-      0 -6px 16px -8px rgb(0 0 0 / 8%),
-      0 -9px 28px 0 rgb(0 0 0 / 5%),
+    box-shadow: 0 -6px 16px -8px rgb(0 0 0 / 8%), 0 -9px 28px 0 rgb(0 0 0 / 
5%),
       0 -12px 48px 16px rgb(0 0 0 / 3%);
     transition: width 0.2s;
 
diff --git 
a/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
 
b/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
index 36ab854c5..35c080269 100644
--- 
a/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
+++ 
b/streampark-console/streampark-console-webapp/src/components/Table/src/components/HeaderCell.vue
@@ -22,7 +22,7 @@
     props: {
       column: {
         type: Object as PropType<BasicColumn>,
-        default: () => ({}) as BasicColumn,
+        default: () => ({} as BasicColumn),
       },
     },
     setup(props) {
diff --git 
a/streampark-console/streampark-console-webapp/src/enums/flinkEnum.ts 
b/streampark-console/streampark-console-webapp/src/enums/flinkEnum.ts
index ef463403b..b0b2f83ed 100644
--- a/streampark-console/streampark-console-webapp/src/enums/flinkEnum.ts
+++ b/streampark-console/streampark-console-webapp/src/enums/flinkEnum.ts
@@ -226,3 +226,11 @@ export enum RestoreModeEnum {
   CLAIM = 2,
   LEGACY = 3,
 }
+
+export enum AppExistsEnum {
+  NO = 0,
+  IN_DB = 1,
+  IN_YARN = 2,
+  IN_KUBERNETES = 3,
+  INVALID = 4,
+}
diff --git 
a/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
 
b/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
index f501c6e80..3566bfd27 100644
--- 
a/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
+++ 
b/streampark-console/streampark-console-webapp/src/hooks/setting/useMenuSetting.ts
@@ -105,8 +105,8 @@ export function useMenuSetting() {
     return siderHidden
       ? 0
       : collapsedShowTitle
-        ? SIDE_BAR_SHOW_TIT_MINI_WIDTH
-        : SIDE_BAR_MINI_WIDTH;
+      ? SIDE_BAR_SHOW_TIT_MINI_WIDTH
+      : SIDE_BAR_MINI_WIDTH;
   });
 
   const getCalcContentWidth = computed(() => {
@@ -114,9 +114,9 @@ export function useMenuSetting() {
       unref(getIsTopMenu) || !unref(getShowMenu) || (unref(getSplit) && 
unref(getMenuHidden))
         ? 0
         : unref(getIsMixSidebar)
-          ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : 
SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
-            (unref(getMixSideFixed) && unref(mixSideHasChildren) ? 
unref(getRealWidth) : 0)
-          : unref(getRealWidth);
+        ? (unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : 
SIDE_BAR_SHOW_TIT_MINI_WIDTH) +
+          (unref(getMixSideFixed) && unref(mixSideHasChildren) ? 
unref(getRealWidth) : 0)
+        : unref(getRealWidth);
 
     return `calc(100% - ${unref(width)}px)`;
   });
diff --git 
a/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts 
b/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
index 9a6607421..c543be954 100644
--- a/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
+++ b/streampark-console/streampark-console-webapp/src/hooks/web/useLockPage.ts
@@ -32,12 +32,9 @@ export function useLockPage() {
     }
     clear();
 
-    timeId = setTimeout(
-      () => {
-        lockPage();
-      },
-      lockTime * 60 * 1000,
-    );
+    timeId = setTimeout(() => {
+      lockPage();
+    }, lockTime * 60 * 1000);
   }
 
   function lockPage(): void {
diff --git a/streampark-console/streampark-console-webapp/src/utils/props.ts 
b/streampark-console/streampark-console-webapp/src/utils/props.ts
index 4a5491b27..4a15ec465 100644
--- a/streampark-console/streampark-console-webapp/src/utils/props.ts
+++ b/streampark-console/streampark-console-webapp/src/utils/props.ts
@@ -28,8 +28,8 @@ export type BuildPropOption<T, D extends BuildPropType<T, V, 
C>, R, V, C> = {
   default?: R extends true
     ? never
     : D extends Record<string, unknown> | Array<any>
-      ? () => D
-      : (() => D) | D;
+    ? () => D
+    : (() => D) | D;
   validator?: ((val: any) => val is C) | ((val: any) => boolean);
 };
 
@@ -37,8 +37,8 @@ type _BuildPropType<T, V, C> =
   | (T extends PropWrapper<unknown>
       ? T[typeof wrapperKey]
       : [V] extends [never]
-        ? ResolvePropTypeWithReadonly<T>
-        : never)
+      ? ResolvePropTypeWithReadonly<T>
+      : never)
   | V
   | C;
 export type BuildPropType<T, V, C> = _BuildPropType<
@@ -53,8 +53,8 @@ type _BuildPropDefault<T, D> = [T] extends [
 ]
   ? D
   : D extends () => T
-    ? ReturnType<D>
-    : D;
+  ? ReturnType<D>
+  : D;
 
 export type BuildPropDefault<T, D, R> = R extends true
   ? { readonly default?: undefined }
@@ -146,12 +146,12 @@ export const buildProps = <
     [K in keyof O]: O[K] extends BuildPropReturn<any, any, any, any, any>
       ? O[K]
       : [O[K]] extends NativePropType
-        ? O[K]
-        : O[K] extends BuildPropOption<infer T, infer D, infer R, infer V, 
infer C>
-          ? D extends BuildPropType<T, V, C>
-            ? BuildPropOption<T, D, R, V, C>
-            : never
-          : never;
+      ? O[K]
+      : O[K] extends BuildPropOption<infer T, infer D, infer R, infer V, infer 
C>
+      ? D extends BuildPropType<T, V, C>
+        ? BuildPropOption<T, D, R, V, C>
+        : never
+      : never;
   },
 >(
   props: O,
@@ -162,20 +162,20 @@ export const buildProps = <
     [K in keyof O]: O[K] extends { [propKey]: boolean }
       ? O[K]
       : [O[K]] extends NativePropType
-        ? O[K]
-        : O[K] extends BuildPropOption<
-              infer T,
-              // eslint-disable-next-line @typescript-eslint/no-unused-vars
-              infer _D,
-              infer R,
-              infer V,
-              infer C
-            >
-          ? BuildPropReturn<T, O[K]['default'], R, V, C>
-          : never;
+      ? O[K]
+      : O[K] extends BuildPropOption<
+          infer T,
+          // eslint-disable-next-line @typescript-eslint/no-unused-vars
+          infer _D,
+          infer R,
+          infer V,
+          infer C
+        >
+      ? BuildPropReturn<T, O[K]['default'], R, V, C>
+      : never;
   };
 
-export const definePropType = <T>(val: any) => ({ [wrapperKey]: val }) as 
PropWrapper<T>;
+export const definePropType = <T>(val: any) => ({ [wrapperKey]: val } as 
PropWrapper<T>);
 
 export const keyOf = <T extends Object>(arr: T) => Object.keys(arr) as 
Array<keyof T>;
 export const mutable = <T extends readonly any[] | Record<string, 
unknown>>(val: T) =>
diff --git 
a/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
 
b/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
index 73120a425..3ffc2f453 100644
--- 
a/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
+++ 
b/streampark-console/streampark-console-webapp/src/views/base/error-log/data.tsx
@@ -16,12 +16,12 @@ export function getColumns(): BasicColumn[] {
           text === ErrorTypeEnum.VUE
             ? 'green'
             : text === ErrorTypeEnum.RESOURCE
-              ? 'cyan'
-              : text === ErrorTypeEnum.PROMISE
-                ? 'blue'
-                : ErrorTypeEnum.AJAX
-                  ? 'red'
-                  : 'purple';
+            ? 'cyan'
+            : text === ErrorTypeEnum.PROMISE
+            ? 'blue'
+            : ErrorTypeEnum.AJAX
+            ? 'red'
+            : 'purple';
         return <Tag color={color}>{() => text}</Tag>;
       },
     },
diff --git 
a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
 
b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
index 82f616765..04fb6a7ef 100644
--- 
a/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
+++ 
b/streampark-console/streampark-console-webapp/src/views/flink/app/hooks/useApp.tsx
@@ -17,12 +17,18 @@
 import { Alert, Form, Input, Tag } from 'ant-design-vue';
 import { h, onMounted, reactive, ref, unref, VNode } from 'vue';
 import { handleAppBuildStatueText } from '../utils';
-import { fetchCheckName, fetchCopy, fetchForcedStop, fetchMapping } from 
'/@/api/flink/app';
+import {
+  fetchCheckName,
+  fetchCopy,
+  fetchForcedStop,
+  fetchCheckStart,
+  fetchMapping,
+} from '/@/api/flink/app';
 import { fetchBuild, fetchBuildDetail } from '/@/api/flink/flinkBuild';
 import { fetchSavePonitHistory } from '/@/api/flink/savepoint';
 import { fetchAppOwners } from '/@/api/system/user';
 import { SvgIcon } from '/@/components/Icon';
-import { AppStateEnum, ExecModeEnum, OptionStateEnum } from 
'/@/enums/flinkEnum';
+import { AppExistsEnum, AppStateEnum, ExecModeEnum, OptionStateEnum } from 
'/@/enums/flinkEnum';
 import { useI18n } from '/@/hooks/web/useI18n';
 import { useMessage } from '/@/hooks/web/useMessage';
 
@@ -79,8 +85,32 @@ export const useFlinkApplication = (openStartModal: Fn) => {
   }
 
   /* start application */
-  function handleAppCheckStart(app: Recordable) {
+  async function handleAppCheckStart(app: Recordable) {
     // when then app is building, show forced starting modal
+    const resp = await fetchCheckStart({
+      id: app.id,
+    });
+    if (resp.data === AppExistsEnum.IN_YARN) {
+      Swal.fire({
+        title: 'Are you sure?',
+        text: `current job already exists on yarn, are you sure restart the 
job and managed by StreamPark?`,
+        icon: 'warning',
+        showCancelButton: true,
+        confirmButtonText: 'Yes, restart!',
+        denyButtonText: `close`,
+        confirmButtonColor: '#d33',
+        cancelButtonColor: '#3085d6',
+      }).then(async (result) => {
+        if (result.isConfirmed) {
+          await fetchForcedStop({
+            id: app.id,
+          });
+          await handleStart(app);
+          return Promise.resolve(true);
+        }
+      });
+    }
+
     if (app['appControl']['allowStart'] === false) {
       handleFetchBuildDetail(app);
       createWarningModal({

Reply via email to