diff --git a/dolphinscheduler-ui/pnpm-lock.yaml b/dolphinscheduler-ui/pnpm-lock.yaml index 3030cc3ac9..67abc01cf1 100644 --- a/dolphinscheduler-ui/pnpm-lock.yaml +++ b/dolphinscheduler-ui/pnpm-lock.yaml @@ -15,7 +15,7 @@ # limitations under the License. # -lockfileVersion: 5.3 +lockfileVersion: 5.4 specifiers: '@antv/layout': 0.1.31 diff --git a/dolphinscheduler-ui/src/layouts/content/components/timezone/index.tsx b/dolphinscheduler-ui/src/layouts/content/components/timezone/index.tsx index 7935974ae3..f22814fbf6 100644 --- a/dolphinscheduler-ui/src/layouts/content/components/timezone/index.tsx +++ b/dolphinscheduler-ui/src/layouts/content/components/timezone/index.tsx @@ -33,6 +33,7 @@ const Timezone = defineComponent({ } }, setup(props) { + // console.log(prosp.timezoneOptions); const { t } = useI18n() const reload: any = inject('reload') const timezoneStore = useTimezoneStore() diff --git a/dolphinscheduler-ui/src/layouts/content/use-dataList.ts b/dolphinscheduler-ui/src/layouts/content/use-dataList.ts index 0d8fb17731..a2610e7a4f 100644 --- a/dolphinscheduler-ui/src/layouts/content/use-dataList.ts +++ b/dolphinscheduler-ui/src/layouts/content/use-dataList.ts @@ -314,7 +314,15 @@ export function useDataList() { icon: renderIcon(SafetyOutlined) } ] - } + }, + // add UI setting to the banner + { + label: () => + h(NEllipsis, null, { default: () => t('menu.ui_setting') }), + key: 'ui-setting', + icon: renderIcon(SettingOutlined), + children: [] + }, ] } diff --git a/dolphinscheduler-ui/src/locales/en_US/index.ts b/dolphinscheduler-ui/src/locales/en_US/index.ts index d04b7efcc2..ed28fe0d4a 100644 --- a/dolphinscheduler-ui/src/locales/en_US/index.ts +++ b/dolphinscheduler-ui/src/locales/en_US/index.ts @@ -30,6 +30,7 @@ import resource from '@/locales/en_US/resource' import security from '@/locales/en_US/security' import theme from '@/locales/en_US/theme' import user_dropdown from '@/locales/en_US/user-dropdown' +import ui_setting from '@/locales/en_US/ui_setting' export default { login, @@ -46,5 +47,6 @@ export default { security, datasource, data_quality, - crontab + crontab, + ui_setting } diff --git a/dolphinscheduler-ui/src/locales/en_US/menu.ts b/dolphinscheduler-ui/src/locales/en_US/menu.ts index c605257384..af788e86c9 100644 --- a/dolphinscheduler-ui/src/locales/en_US/menu.ts +++ b/dolphinscheduler-ui/src/locales/en_US/menu.ts @@ -56,5 +56,6 @@ export default { task_group_queue: 'Task Group Queue', data_quality: 'Data Quality', task_result: 'Task Result', - rule: 'Rule management' + rule: 'Rule management', + ui_setting: 'Setting', } diff --git a/dolphinscheduler-ui/src/locales/en_US/ui_setting.ts b/dolphinscheduler-ui/src/locales/en_US/ui_setting.ts new file mode 100644 index 0000000000..7ab6413353 --- /dev/null +++ b/dolphinscheduler-ui/src/locales/en_US/ui_setting.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export default { + log: { + refresh_time: 'Log Auto Refresh Time', + } + } + \ No newline at end of file diff --git a/dolphinscheduler-ui/src/locales/zh_CN/index.ts b/dolphinscheduler-ui/src/locales/zh_CN/index.ts index 132fd14f75..aee6d13151 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/index.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/index.ts @@ -30,6 +30,7 @@ import resource from '@/locales/zh_CN/resource' import security from '@/locales/zh_CN/security' import theme from '@/locales/zh_CN/theme' import user_dropdown from '@/locales/zh_CN/user-dropdown' +import ui_setting from '@/locales/zh_CN/ui_setting' export default { login, @@ -46,5 +47,6 @@ export default { security, datasource, data_quality, - crontab + crontab, + ui_setting } diff --git a/dolphinscheduler-ui/src/locales/zh_CN/menu.ts b/dolphinscheduler-ui/src/locales/zh_CN/menu.ts index b90bf7510f..174ff54774 100644 --- a/dolphinscheduler-ui/src/locales/zh_CN/menu.ts +++ b/dolphinscheduler-ui/src/locales/zh_CN/menu.ts @@ -22,6 +22,7 @@ export default { datasource: '数据源中心', monitor: '监控中心', security: '安全中心', + ui_setting: '界面设置', project_overview: '项目概览', workflow_relation: '工作流关系', workflow: '工作流', diff --git a/dolphinscheduler-ui/src/locales/zh_CN/ui_setting.ts b/dolphinscheduler-ui/src/locales/zh_CN/ui_setting.ts new file mode 100644 index 0000000000..14c556d369 --- /dev/null +++ b/dolphinscheduler-ui/src/locales/zh_CN/ui_setting.ts @@ -0,0 +1,23 @@ +/* + * 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. + */ + +export default { + log: { + refresh_time: '自动刷新时间', + } + } + \ No newline at end of file diff --git a/dolphinscheduler-ui/src/router/modules/ui-setting.ts b/dolphinscheduler-ui/src/router/modules/ui-setting.ts new file mode 100644 index 0000000000..5f759e1926 --- /dev/null +++ b/dolphinscheduler-ui/src/router/modules/ui-setting.ts @@ -0,0 +1,43 @@ +/* + * 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 type { Component } from 'vue' +import utils from '@/utils' + +// All TSX files under the views folder automatically generate mapping relationship +const modules = import.meta.glob('/src/views/**/**.tsx') +const components: { [key: string]: Component } = utils.mapping(modules) + +export default { + path: '/ui-setting', + name: 'ui-setting', + meta: { title: '设置' }, + component: () => import('@/layouts/content'), + children: [ + { + path: '', + name: 'ui-setting', + component: components['ui-setting'], + meta: { + title: '设置', + activeMenu: 'ui-setting', + showSide: false, + auth: [] + } + } + ] +} diff --git a/dolphinscheduler-ui/src/router/routes.ts b/dolphinscheduler-ui/src/router/routes.ts index 7a36ac82fe..9d91c74afa 100644 --- a/dolphinscheduler-ui/src/router/routes.ts +++ b/dolphinscheduler-ui/src/router/routes.ts @@ -24,6 +24,8 @@ import datasourcePage from './modules/datasource' import monitorPage from './modules/monitor' import securityPage from './modules/security' import dataQualityPage from './modules/data-quality' +// todo: why is it throwing cannot find module and its corresponding type, but the render is working? +import uiSettingPage from './modules/ui-setting' // All TSX files under the views folder automatically generate mapping relationship const modules = import.meta.glob('/src/views/**/**.tsx') @@ -74,7 +76,8 @@ const basePage: RouteRecordRaw[] = [ datasourcePage, monitorPage, securityPage, - dataQualityPage + dataQualityPage, + uiSettingPage ] /** diff --git a/dolphinscheduler-ui/src/store/logTimer/logTimer.ts b/dolphinscheduler-ui/src/store/logTimer/logTimer.ts new file mode 100644 index 0000000000..f7d47e02ae --- /dev/null +++ b/dolphinscheduler-ui/src/store/logTimer/logTimer.ts @@ -0,0 +1,38 @@ +/* + * 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 { defineStore } from 'pinia' +import { LogTimerStore } from './types' + +export const useLogTimerStore = defineStore({ + id: 'logTimer', + state: (): LogTimerStore => ({ + logTimer: 0, + }), + persist: true, + getters: { + getLogTimer(): number { + return this.logTimer + } + }, + actions: { + setLogTimer(timer: number): void { + this.logTimer = timer + } + } +}) + diff --git a/dolphinscheduler-ui/src/store/logTimer/types.ts b/dolphinscheduler-ui/src/store/logTimer/types.ts new file mode 100644 index 0000000000..c2d105e96d --- /dev/null +++ b/dolphinscheduler-ui/src/store/logTimer/types.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ +interface LogTimerStore { + logTimer: number +} + +export { LogTimerStore } \ No newline at end of file diff --git a/dolphinscheduler-ui/src/views/profile/use-form.ts b/dolphinscheduler-ui/src/views/profile/use-form.ts index 388d6a93f9..6f0dd2c0f6 100644 --- a/dolphinscheduler-ui/src/views/profile/use-form.ts +++ b/dolphinscheduler-ui/src/views/profile/use-form.ts @@ -23,6 +23,7 @@ import type { FormRules } from 'naive-ui' import type { UserInfoRes } from '@/service/modules/users/types' export function useForm() { + // todo: is "t": some kind of function to internationalize text? const { t, locale } = useI18n() const userInfo = useUserStore().userInfo as UserInfoRes @@ -31,7 +32,7 @@ export function useForm() { profileForm: { username: userInfo.userName, email: userInfo.email, - phone: userInfo.phone + phone: userInfo.phone, }, saving: false, rules: { @@ -62,7 +63,7 @@ export function useForm() { state.profileForm = { username: userInfo.userName, email: userInfo.email, - phone: userInfo.phone + phone: userInfo.phone, } }) diff --git a/dolphinscheduler-ui/src/views/projects/task/instance/batch-task.tsx b/dolphinscheduler-ui/src/views/projects/task/instance/batch-task.tsx index 548e9c500d..3dd77786f1 100644 --- a/dolphinscheduler-ui/src/views/projects/task/instance/batch-task.tsx +++ b/dolphinscheduler-ui/src/views/projects/task/instance/batch-task.tsx @@ -38,12 +38,15 @@ import { useI18n } from 'vue-i18n' import { useAsyncState } from '@vueuse/core' import { queryLog } from '@/service/modules/log' import { stateType } from '@/common/common' +import { useLogTimerStore } from '@/store/logTimer/logTimer' import Card from '@/components/card' import LogModal from '@/components/log-modal' const BatchTaskInstance = defineComponent({ name: 'task-instance', setup() { + const logTimerStore = useLogTimerStore() + const logTimer = logTimerStore.getLogTimer const { t, variables, getTableData, createColumns } = useTable() const requestTableData = () => { @@ -74,20 +77,34 @@ const BatchTaskInstance = defineComponent({ variables.showModalRef = false } - const getLogs = (row: any) => { + var getLogsID: number + + const getLogs = (row: any, logTimer: number) => { const { state } = useAsyncState( queryLog({ taskInstanceId: Number(row.id), limit: variables.limit, skipLineNum: variables.skipLineNum }).then((res: any) => { - if (res?.message) { - variables.logRef += res.message + variables.logRef += res.message || '' + if (res && res.message !== '') { variables.limit += 1000 variables.skipLineNum += res.lineNum - getLogs(row) + getLogs(row, logTimer) } else { variables.logLoadingRef = false + if (logTimer !== 0) { + if (typeof getLogsID === 'number') { + clearTimeout(getLogsID) + } + getLogsID = setTimeout(() => { + variables.logRef = '' + variables.limit = 1000 + variables.skipLineNum = 0 + variables.logLoadingRef = true + getLogs(row, logTimer) + }, logTimer * 1000) + } } }), {} @@ -100,7 +117,7 @@ const BatchTaskInstance = defineComponent({ variables.logRef = '' variables.limit = 1000 variables.skipLineNum = 0 - getLogs(row) + getLogs(row, logTimer) } const trim = getCurrentInstance()?.appContext.config.globalProperties.trim @@ -118,7 +135,7 @@ const BatchTaskInstance = defineComponent({ () => variables.showModalRef, () => { if (variables.showModalRef) { - getLogs(variables.row) + getLogs(variables.row, logTimer) } else { variables.row = {} variables.logRef = '' diff --git a/dolphinscheduler-ui/src/views/projects/task/instance/index.tsx b/dolphinscheduler-ui/src/views/projects/task/instance/index.tsx index de9e7f690b..f0212a50ba 100644 --- a/dolphinscheduler-ui/src/views/projects/task/instance/index.tsx +++ b/dolphinscheduler-ui/src/views/projects/task/instance/index.tsx @@ -21,6 +21,7 @@ import { NTabPane, NTabs } from 'naive-ui' import BatchTaskInstance from './batch-task' import StreamTaskInstance from './stream-task' + const TaskDefinition = defineComponent({ name: 'task-instance', setup() { @@ -38,4 +39,4 @@ const TaskDefinition = defineComponent({ } }) -export default TaskDefinition +export default TaskDefinition \ No newline at end of file diff --git a/dolphinscheduler-ui/src/views/projects/task/instance/stream-task.tsx b/dolphinscheduler-ui/src/views/projects/task/instance/stream-task.tsx index 5a6493af09..c67462b3ec 100644 --- a/dolphinscheduler-ui/src/views/projects/task/instance/stream-task.tsx +++ b/dolphinscheduler-ui/src/views/projects/task/instance/stream-task.tsx @@ -39,6 +39,7 @@ import { useI18n } from 'vue-i18n' import { useAsyncState } from '@vueuse/core' import { queryLog } from '@/service/modules/log' import { streamStateType } from '@/common/common' +import { useLogTimerStore } from '@/store/logTimer/logTimer' import Card from '@/components/card' import LogModal from '@/components/log-modal' @@ -46,6 +47,8 @@ const BatchTaskInstance = defineComponent({ name: 'task-instance', setup() { let setIntervalP: number + const logTimerStore = useLogTimerStore() + const logTimer = logTimerStore.getLogTimer const { t, variables, getTableData, createColumns } = useTable() const onUpdatePageSize = () => { @@ -62,20 +65,27 @@ const BatchTaskInstance = defineComponent({ variables.showModalRef = false } - const getLogs = (row: any) => { + const getLogs = (row: any, logTimer: number) => { const { state } = useAsyncState( queryLog({ taskInstanceId: Number(row.id), limit: variables.limit, skipLineNum: variables.skipLineNum }).then((res: any) => { - if (res?.message) { - variables.logRef += res.message + variables.logRef += res.message || '' + if (res && res.message !== '') { variables.limit += 1000 variables.skipLineNum += res.lineNum - getLogs(row) + getLogs(row, logTimer) } else { variables.logLoadingRef = false + setTimeout(() => { + variables.logRef = '' + variables.limit = 1000 + variables.skipLineNum = 0 + variables.logLoadingRef = true + getLogs(row, logTimer) + }, logTimer * 1000) } }), {} @@ -88,7 +98,7 @@ const BatchTaskInstance = defineComponent({ variables.logRef = '' variables.limit = 1000 variables.skipLineNum = 0 - getLogs(row) + getLogs(row, logTimer) } const trim = getCurrentInstance()?.appContext.config.globalProperties.trim @@ -113,7 +123,7 @@ const BatchTaskInstance = defineComponent({ () => variables.showModalRef, () => { if (variables.showModalRef) { - getLogs(variables.row) + getLogs(variables.row, logTimer) } else { variables.row = {} variables.logRef = '' diff --git a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/index.tsx b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/index.tsx index b573ed3f38..a255f22a54 100644 --- a/dolphinscheduler-ui/src/views/projects/workflow/components/dag/index.tsx +++ b/dolphinscheduler-ui/src/views/projects/workflow/components/dag/index.tsx @@ -54,6 +54,7 @@ import './x6-style.scss' import { queryLog } from '@/service/modules/log' import { useAsyncState } from '@vueuse/core' import utils from '@/utils' +import { useLogTimerStore } from '@/store/logTimer/logTimer' const props = { // If this prop is passed, it means from definition detail @@ -84,6 +85,9 @@ export default defineComponent({ const route = useRoute() const theme = useThemeStore() + const logTimerStore = useLogTimerStore() + const logTimer = logTimerStore.getLogTimer + // Whether the graph can be operated provide('readonly', toRef(props, 'readonly')) @@ -233,23 +237,37 @@ export default defineComponent({ const handleViewLog = (taskId: number, taskType: string) => { taskModalVisible.value = false viewLog(taskId, taskType) - getLogs() + + getLogs(logTimer) } - const getLogs = () => { + var getLogsID: number + + const getLogs = (logTimer: number) => { const { state } = useAsyncState( queryLog({ taskInstanceId: nodeVariables.logTaskId, limit: nodeVariables.limit, skipLineNum: nodeVariables.skipLineNum }).then((res: any) => { - if (res.message) { - nodeVariables.logRef += res.message + + nodeVariables.logRef += res.message || '' + if (res && res.message !== '') { nodeVariables.limit += 1000 nodeVariables.skipLineNum += res.lineNum - getLogs() + getLogs(logTimer) } else { nodeVariables.logLoadingRef = false + if (logTimer !== 0) { + if (typeof getLogsID === 'number') { + clearTimeout(getLogsID) + } + getLogsID = setTimeout(() => { + nodeVariables.limit += 1000 + nodeVariables.skipLineNum += 1000 + getLogs(logTimer) + }, logTimer * 1000) + } } }), {} @@ -258,11 +276,11 @@ export default defineComponent({ return state } - const refreshLogs = () => { + const refreshLogs = (logTimer: number) => { nodeVariables.logRef = '' nodeVariables.limit = 1000 nodeVariables.skipLineNum = 0 - getLogs() + getLogs(logTimer) } const downloadLogs = () => { diff --git a/dolphinscheduler-ui/src/views/ui-setting/index.tsx b/dolphinscheduler-ui/src/views/ui-setting/index.tsx new file mode 100644 index 0000000000..bee87f7bc7 --- /dev/null +++ b/dolphinscheduler-ui/src/views/ui-setting/index.tsx @@ -0,0 +1,91 @@ +/* + * 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 { useI18n } from 'vue-i18n' +import { NForm, NFormItem, NSelect } from "naive-ui"; +import { defineComponent } from "vue"; +import { useLogTimerStore } from '@/store/logTimer/logTimer' + +// Update LogTimer store when select value is updated +const handleUpdateValue = (logTimer: number) => { + const logTimerStore = useLogTimerStore() + logTimerStore.setLogTimer(logTimer) +} + +const setting = defineComponent({ + name: 'ui-setting', + setup() { + const logTimerStore = useLogTimerStore() + const defaultLogTimer = logTimerStore.getLogTimer; + + const logTimerMap = { + 0: "Off", + 10: '10 Seconds', + 30: '30 Seconds', + 60: '1 Minute', + 300: '5 Minutes', + 1800: '30 Minutes' + } as any + + const logTimerOptions = [ + { + label: "Off", + value: 0, + }, + { + label: "10 Seconds", + value: 10, + }, + { + label: "30 Seconds", + value: 30, + }, + { + label: "1 Minute", + value: 60, + }, + { + label: "5 Minutes", + value: 300, + }, + { + label: "30 Minutes", + value: 1800, + }, + ] + return {defaultLogTimer, logTimerMap, logTimerOptions} + }, + render() { + const { t } = useI18n() + + return ( + <> + + + + + + + ) + } +}) + +export default setting \ No newline at end of file