This is an automated email from the ASF dual-hosted git repository. benjobs pushed a commit to branch sync_2.1.3 in repository https://gitbox.apache.org/repos/asf/incubator-streampark.git
commit 1d6049973cdd0c6d3be823888d3d18c3d76ab86b Author: benjobs <[email protected]> AuthorDate: Wed Mar 13 17:39:59 2024 +0800 [Improve] job state style improvements --- .../src/locales/lang/en/flink/app.ts | 52 ++++++++++++-- .../src/locales/lang/zh-CN/flink/app.ts | 39 +++++++++-- .../src/views/flink/app/View.vue | 2 +- .../components/AppView/StartApplicationModal.vue | 80 +++++++++++----------- .../src/views/flink/app/components/State.less | 4 -- .../src/views/flink/app/components/State.tsx | 63 +++++++++-------- 6 files changed, 156 insertions(+), 84 deletions(-) diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts index e9b778af3..ff03d2723 100644 --- a/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts +++ b/streampark-console/streampark-console-webapp/src/locales/lang/en/flink/app.ts @@ -78,6 +78,38 @@ export default { releaseFail: 'release application failed,', releasing: 'Current Application is releasing', }, + runState: { + added: 'ADDED', + initializing: 'INITIALIZING', + created: 'CREATED', + starting: 'STARTING', + restarting: 'RESTARTING', + running: 'RUNNING', + failing: 'FAILING', + failed: 'FAILED', + lost: 'LOST', + cancelling: 'CANCELLING', + canceled: 'CANCELED', + finished: 'FINISHED', + suspended: 'SUSPENDED', + reconciling: 'RECONCILING', + mapping: 'MAPPING', + silent: 'SILENT', + terminated: 'TERMINATED', + }, + releaseState: { + failed: 'FAILED', + success: 'SUCCESS', + waiting: 'WAITING', + releasing: 'RELEASING', + pending: 'PENDING', + }, + clusterState: { + created: 'CREATED', + started: 'STARTED', + canceled: 'SHUTDOWN', + lost: 'LOST', + }, detail: { detailTitle: 'Application Info', flinkWebUi: 'Flink Web UI', @@ -126,19 +158,27 @@ export default { }, }, view: { - buildTitle: 'Application releasing Progress', + buildTitle: 'Job releasing Progress', stepTitle: 'Steps Detail', errorLog: 'Error Log', errorSummary: 'Error Summary', errorStack: 'Error Stack', - logTitle: 'Start Log : Application Name [ {0} ]', + logTitle: 'Start Log : Job Name [ {0} ]', refreshTime: 'last refresh time', refresh: 'refresh', - start: 'Start Application', - stop: 'Stop application', + start: 'Start Job', + stop: 'Stop Job', savepoint: 'Trigger Savepoint', - recheck: 'the associated project has changed and this job need to be rechecked', - changed: 'the application has changed.', + fromSavepoint: 'From savepoint', + savepointTip: 'Restore the job from savepoint or latest checkpoint', + savepointInput: 'Specify the savepoint/checkpoint path', + savepointSwitch: + 'Specify the savepoint/checkpoint path (Double-click to switch between "input" and "select")', + ignoreRestored: 'Ignore failed', + ignoreRestoredTip: + 'ignore savepoint then cannot be restored, Same as:-allowNonRestoredState(-n)', + recheck: 'the associated project has changed and this job need to be release', + changed: 'the job has been updated', }, pod: { choice: 'Choice', diff --git a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts index 17652ec3e..6ffa0806e 100644 --- a/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts +++ b/streampark-console/streampark-console-webapp/src/locales/lang/zh-CN/flink/app.ts @@ -76,6 +76,31 @@ export default { releaseFail: '发布作业失败', releasing: '当前作业正在发布中', }, + runState: { + added: '新增作业', + initializing: '初始化', + created: '创建中', + starting: '启动中', + restarting: '重启中', + running: '运行中', + failing: '失败中', + failed: '作业失败', + lost: '作业失联', + cancelling: '取消中', + canceled: '已取消', + finished: '已完成', + suspended: '已暂停', + reconciling: '调整中', + mapping: '映射中', + silent: '沉默', + terminated: '终止', + }, + clusterState: { + created: '新增', + started: '运行中', + canceled: '停止', + lost: '失联', + }, detail: { detailTitle: '作业详情', flinkWebUi: 'Flink Web UI', @@ -123,7 +148,7 @@ export default { }, }, view: { - buildTitle: '应用程序启动进度', + buildTitle: '作业启动进度', stepTitle: '步骤详情', errorLog: '错误日志', errorSummary: '错误摘要', @@ -131,11 +156,17 @@ export default { logTitle: '启动日志 : 应用名称 [ {0} ]', refreshTime: '上次刷新时间', refresh: '刷新', - start: '开启应用', + start: '启动作业', stop: '停止应用', savepoint: '触发 Savepoint', - recheck: '关联的项目已更改,需要重新检查此作业', - changed: '应用程序已更改。', + recheck: '关联的项目已更新,需要重新发布此作业', + changed: '作业已更新', + fromSavepoint: 'Savepoint 恢复', + savepointTip: '作业从 savepoint 或 checkpoint 恢复状态', + savepointInput: '指定 savepoint/checkpoint 路径', + savepointSwitch: '指定 savepoint/checkpoint 路径 (双击切换"下拉框选择"或"手动输入")', + ignoreRestored: '忽略失败', + ignoreRestoredTip: '当状态恢复失败时跳过错误,作业继续运行, 同参数:-allowNonRestoredState(-n)', }, pod: { choice: '选择', diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue index 9b4a4e8e8..f0795c8a9 100644 --- a/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue +++ b/streampark-console/streampark-console-webapp/src/views/flink/app/View.vue @@ -207,7 +207,7 @@ app['optionState'] === OptionStateEnum.SAVEPOINTING ) { // yarn-per-job|yarn-session|yarn-application - handleView(app, unref(yarn)); + await handleView(app, unref(yarn)); } } diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StartApplicationModal.vue b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StartApplicationModal.vue index 98a0f0188..a78699829 100644 --- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StartApplicationModal.vue +++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/AppView/StartApplicationModal.vue @@ -24,7 +24,7 @@ }); </script> <script setup lang="ts" name="StartApplicationModal"> - import { h } from 'vue'; + import { h, ref } from 'vue'; import { Select, Input, Tag } from 'ant-design-vue'; import { BasicForm, useForm } from '/@/components/Form'; import { SvgIcon, Icon } from '/@/components/Icon'; @@ -32,16 +32,15 @@ import { useMessage } from '/@/hooks/web/useMessage'; import { useRouter } from 'vue-router'; import { fetchCheckStart, fetchForcedStop, fetchStart } from '/@/api/flink/app'; - - import { AppExistsEnum, RestoreModeEnum } from '/@/enums/flinkEnum'; - import { fetchFlinkEnv } from '/@/api/flink/flinkEnv'; - import { renderFlinkAppRestoreMode } from '/@/views/flink/app/hooks/useFlinkRender'; + import { AppExistsEnum } from '/@/enums/flinkEnum'; const SelectOption = Select.Option; const { t } = useI18n(); const { Swal } = useMessage(); const router = useRouter(); + const selectInput = ref<boolean>(false); + const selectValue = ref<string>(null); const emits = defineEmits(['register', 'updateOption']); const receiveData = reactive<Recordable>({}); @@ -56,61 +55,50 @@ } }); + function handleSavePointTip(list) { + if (list != null && list.length > 0) { + return t('flink.app.view.savepointSwitch'); + } + return t('flink.app.view.savepointInput'); + } + const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ name: 'startApplicationModal', labelWidth: 120, schemas: [ { field: 'startSavePointed', - label: 'from savepoint', + label: t('flink.app.view.fromSavepoint'), component: 'Switch', componentProps: { checkedChildren: 'ON', unCheckedChildren: 'OFF', }, defaultValue: true, - afterItem: () => - h( - 'span', - { class: 'tip-info' }, - 'restore the application from savepoint or latest checkpoint', - ), + afterItem: () => h('span', { class: 'conf-switch' }, t('flink.app.view.savepointTip')), }, { field: 'startSavePoint', - label: 'savepoint', + label: 'Savepoint', component: receiveData.historySavePoint && receiveData.historySavePoint.length > 0 ? 'Select' : 'Input', afterItem: () => - h( - 'span', - { class: 'tip-info' }, - 'restore the application from savepoint or latest checkpoint', - ), + h('span', { class: 'conf-switch' }, handleSavePointTip(receiveData.historySavePoint)), slot: 'savepoint', ifShow: ({ values }) => values.startSavePointed, required: true, }, - { - field: 'restoreMode', - label: 'restore mode', - component: 'Select', - defaultValue: RestoreModeEnum.NO_CLAIM, - render: (renderCallbackParams) => renderFlinkAppRestoreMode(renderCallbackParams), - ifShow: ({ values }) => values.startSavePointed && checkFlinkVersion(), - }, { field: 'allowNonRestoredState', - label: 'ignore restored', + label: t('flink.app.view.ignoreRestored'), component: 'Switch', componentProps: { checkedChildren: 'ON', unCheckedChildren: 'OFF', }, - afterItem: () => - h('span', { class: 'tip-info' }, 'ignore savepoint then cannot be restored'), + afterItem: () => h('span', { class: 'conf-switch' }, t('flink.app.view.ignoreRestoredTip')), defaultValue: false, ifShow: ({ values }) => values.startSavePointed, }, @@ -135,16 +123,20 @@ await handleDoSubmit(); } + async function handleReset() { + selectInput.value = false; + selectValue.value = null; + } + /* submit */ async function handleDoSubmit() { try { const formValue = (await validate()) as Recordable; const savePointed = formValue.startSavePointed; const savePointPath = savePointed ? formValue['startSavePoint'] : null; - const restoreMode = savePointed ? formValue['restoreMode'] : null; + handleReset(); const { data } = await fetchStart({ id: receiveData.application.id, - restoreMode, savePointed, savePoint: savePointPath, allowNonRestored: formValue.allowNonRestoredState || false, @@ -152,7 +144,7 @@ if (data.data) { Swal.fire({ icon: 'success', - title: 'The current job is starting', + title: t('flink.app.operation.starting'), showConfirmButton: false, timer: 2000, }); @@ -190,10 +182,14 @@ } } - async function checkFlinkVersion() { - const versionId = receiveData.application.versionId; - const flinkVersion = await fetchFlinkEnv(versionId); - return parseInt(flinkVersion.versionOfMiddle) >= 15; + function handleSavepoint(model, field, input) { + selectInput.value = input; + if (input) { + selectValue.value = model[field]; + model[field] = null; + } else { + model[field] = selectValue.value; + } } </script> <template> @@ -201,6 +197,7 @@ @register="registerModal" :minHeight="100" @ok="handleSubmit" + @cancel="handleReset" :okText="t('common.apply')" :cancelText="t('common.cancelText')" > @@ -211,8 +208,12 @@ <BasicForm @register="registerForm" class="!pt-40px"> <template #savepoint="{ model, field }"> - <template v-if="receiveData.historySavePoint && receiveData.historySavePoint.length > 0"> - <Select allow-clear v-model:value="model[field]"> + <template + v-if=" + !selectInput && receiveData.historySavePoint && receiveData.historySavePoint.length > 0 + " + > + <Select v-model:value="model[field]" @dblclick="handleSavepoint(model, field, true)"> <SelectOption v-for="(k, i) in receiveData.historySavePoint" :key="i" :value="k.path"> <span style="color: darkgrey"> <Icon icon="ant-design:clock-circle-outlined" /> @@ -232,8 +233,9 @@ </template> <Input v-else + @dblclick="handleSavepoint(model, field, false)" type="text" - placeholder="Please enter savepoint manually" + :placeholder="$t('flink.app.view.savepointInput')" v-model:value="model[field]" /> </template> diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.less b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.less index 74c6995d3..895a612a0 100644 --- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.less +++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.less @@ -47,10 +47,6 @@ animation: reconciling-color 800ms ease-out infinite alternate; } -.status-processing-probing { - animation: probing-color 800ms ease-out infinite alternate; -} - @keyframes deploying-color { 0% { border-color: #1abbdc; diff --git a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx index d9b1e26fd..564b32d01 100644 --- a/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx +++ b/streampark-console/streampark-console-webapp/src/views/flink/app/components/State.tsx @@ -19,63 +19,60 @@ import { computed, defineComponent, toRefs, unref } from 'vue'; import { Tag, Tooltip } from 'ant-design-vue'; import './State.less'; import { AppStateEnum, ReleaseStateEnum, OptionStateEnum } from '/@/enums/flinkEnum'; +import { useI18n } from '/@/hooks/web/useI18n'; +const { t } = useI18n(); /* state map*/ export const stateMap = { - [AppStateEnum.ADDED]: { color: '#2f54eb', title: 'ADDED' }, + [AppStateEnum.ADDED]: { color: '#2f54eb', title: t('flink.app.runState.added') }, [AppStateEnum.INITIALIZING]: { color: '#738df8', - title: 'INITIALIZING', + title: t('flink.app.runState.initializing'), class: 'status-processing-initializing', }, - [AppStateEnum.CREATED]: { color: '#2f54eb', title: 'CREATED' }, + [AppStateEnum.CREATED]: { color: '#2f54eb', title: t('flink.app.runState.created') }, [AppStateEnum.STARTING]: { color: '#1AB58E', - title: 'STARTING', + title: t('flink.app.runState.starting'), class: 'status-processing-starting', }, [AppStateEnum.RESTARTING]: { color: '#13c2c2', - title: 'RESTARTING', + title: t('flink.app.runState.restarting'), class: 'status-processing-restarting', }, [AppStateEnum.RUNNING]: { color: '#52c41a', - title: 'RUNNING', + title: t('flink.app.runState.running'), class: 'status-processing-running', }, [AppStateEnum.FAILING]: { color: '#fa541c', - title: 'FAILING', + title: t('flink.app.runState.failing'), class: 'status-processing-failing', }, - [AppStateEnum.FAILED]: { color: '#f5222d', title: 'FAILED' }, - [AppStateEnum.CANCELLING]: { color: '#faad14', title: 'CANCELLING' }, - [AppStateEnum.CANCELED]: { color: '#fa8c16', title: 'CANCELED' }, - [AppStateEnum.FINISHED]: { color: '#1677ff', title: 'FINISHED' }, - [AppStateEnum.SUSPENDED]: { color: '#722ed1', title: 'SUSPENDED' }, + [AppStateEnum.FAILED]: { color: '#f5222d', title: t('flink.app.runState.failed') }, + [AppStateEnum.CANCELLING]: { color: '#faad14', title: t('flink.app.runState.cancelling') }, + [AppStateEnum.CANCELED]: { color: '#fa8c16', title: t('flink.app.runState.canceled') }, + [AppStateEnum.FINISHED]: { color: '#1890ff', title: t('flink.app.runState.finished') }, + [AppStateEnum.SUSPENDED]: { color: '#722ed1', title: t('flink.app.runState.suspended') }, [AppStateEnum.RECONCILING]: { color: '#eb2f96', - title: 'RECONCILING', + title: t('flink.app.runState.reconciling'), class: 'status-processing-reconciling', }, - [AppStateEnum.LOST]: { color: '#000000', title: 'LOST' }, + [AppStateEnum.LOST]: { color: '#333333', title: t('flink.app.runState.lost') }, [AppStateEnum.MAPPING]: { color: '#13c2c2', - title: 'MAPPING', + title: t('flink.app.runState.mapping'), class: 'status-processing-restarting', }, [AppStateEnum.SILENT]: { color: '#738df8', - title: 'SILENT', + title: t('flink.app.runState.silent'), class: 'status-processing-initializing', }, - [AppStateEnum.TERMINATED]: { color: '#8E50FF', title: 'TERMINATED' }, - [AppStateEnum.PROBING]: { - color: '#2febc9', - title: 'PROBING', - class: 'status-processing-probing', - }, + [AppStateEnum.TERMINATED]: { color: '#8E50FF', title: t('flink.app.runState.terminated') }, }; /* option state map*/ export const optionStateMap = { @@ -103,16 +100,19 @@ export const optionStateMap = { /* release state map*/ export const releaseStateMap = { - [ReleaseStateEnum.FAILED]: { color: '#f5222d', title: 'FAILED' }, - [ReleaseStateEnum.DONE]: { color: '#52c41a', title: 'DONE' }, - [ReleaseStateEnum.NEED_RELEASE]: { color: '#fa8c16', title: 'WAITING' }, + [ReleaseStateEnum.FAILED]: { color: '#f5222d', title: t('flink.app.releaseState.failed') }, + [ReleaseStateEnum.DONE]: { color: '#52c41a', title: t('flink.app.releaseState.success') }, + [ReleaseStateEnum.NEED_RELEASE]: { color: '#fa8c16', title: t('flink.app.releaseState.waiting') }, [ReleaseStateEnum.RELEASING]: { color: '#52c41a', - title: 'RELEASING', + title: t('flink.app.releaseState.releasing'), class: 'status-processing-deploying', }, - [ReleaseStateEnum.NEED_RESTART]: { color: '#fa8c16', title: 'PENDING' }, - [ReleaseStateEnum.NEED_ROLLBACK]: { color: '#fa8c16', title: 'WAITING' }, + [ReleaseStateEnum.NEED_RESTART]: { color: '#fa8c16', title: t('flink.app.releaseState.pending') }, + [ReleaseStateEnum.NEED_ROLLBACK]: { + color: '#fa8c16', + title: t('flink.app.releaseState.waiting'), + }, }; /* build state map*/ @@ -127,6 +127,7 @@ export const buildStatusMap = { 3: { color: '#2ECC71', title: 'SUCCESS' }, 4: { color: '#E74C3C', title: 'FAILURE' }, }; + const overviewMap = { running: { color: '#52c41a', title: 'RUNNING' }, canceled: { color: '#fa8c16', title: 'CANCELED' }, @@ -152,14 +153,15 @@ export default defineComponent({ }, setup(props) { const { data, option } = toRefs(props); + const tagWidth = computed(() => { if (props.maxTitle === undefined) return 0; // create a dom to calculate the width of the tag const dom = document.createElement('span'); dom.style.display = 'inline-block'; dom.style.fontSize = '10px'; - dom.style.padding = '0 3px'; - dom.style.borderRadius = '1px'; + dom.style.padding = '0 2px'; + dom.style.borderRadius = '2px'; dom.textContent = props.maxTitle; document.body.appendChild(dom); const width = dom.clientWidth + 2; @@ -177,6 +179,7 @@ export default defineComponent({ </Tag> ); }; + const getStyle = computed(() => { if (tagWidth.value > 0) { return { width: `${tagWidth.value}px`, textAlign: 'center' };
