From dc7a704c5598859a16147958b9a693e82d7f4cae Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Sat, 29 Jun 2024 22:29:20 +0800 Subject: [PATCH] feat: finalized git progress for clone, pull, push https://github.com/crawlab-team/crawlab/issues/1485 --- src/components/box/Box.vue | 130 ++++++++++++++++++ src/components/file/FileEditorNavMenu.vue | 1 + src/components/git/GitLogsBox.vue | 37 +++++ src/components/git/GitLogsDialog.vue | 55 ++++++++ src/components/git/GitPath.vue | 20 +++ src/components/index.ts | 8 ++ src/components/tag/Tag.vue | 2 +- src/i18n/lang/en/components/git.ts | 7 + src/i18n/lang/en/components/spider.ts | 1 + src/i18n/lang/zh/components/git.ts | 7 + src/i18n/lang/zh/components/spider.ts | 1 + src/interfaces/components/dialog/Dialog.d.ts | 2 +- src/interfaces/i18n/components/git.d.ts | 7 + src/interfaces/i18n/components/spider.d.ts | 1 + src/interfaces/models/git.d.ts | 1 + src/interfaces/models/spider.d.ts | 1 + src/store/modules/git.ts | 26 +++- src/views/deps/task/LogsView.vue | 53 ++++--- src/views/git/detail/GitDetail.vue | 27 +++- src/views/git/detail/useGitDetail.ts | 82 ++++++----- src/views/git/list/GitList.vue | 16 ++- src/views/git/list/useGitList.ts | 46 +++++-- .../actions/SpiderDetailActionsCommon.vue | 53 ++++--- 23 files changed, 490 insertions(+), 94 deletions(-) create mode 100644 src/components/box/Box.vue create mode 100644 src/components/git/GitLogsBox.vue create mode 100644 src/components/git/GitLogsDialog.vue create mode 100644 src/components/git/GitPath.vue diff --git a/src/components/box/Box.vue b/src/components/box/Box.vue new file mode 100644 index 0000000000000..6ee4cb1180014 --- /dev/null +++ b/src/components/box/Box.vue @@ -0,0 +1,130 @@ + + + + + + diff --git a/src/components/file/FileEditorNavMenu.vue b/src/components/file/FileEditorNavMenu.vue index a4af6b481f52a..46676337be8fa 100644 --- a/src/components/file/FileEditorNavMenu.vue +++ b/src/components/file/FileEditorNavMenu.vue @@ -430,6 +430,7 @@ const fileSearchString = ref(''); @node-drag-end="onNodeDragEnd" @node-drop="onNodeDrop" @node-click="onNodeClick" + @node-contextmenu="onNodeContextMenuShow" @node-expand="onNodeExpand" @node-collapse="onNodeCollapse" > diff --git a/src/components/git/GitLogsBox.vue b/src/components/git/GitLogsBox.vue new file mode 100644 index 0000000000000..8860e7e9b33c5 --- /dev/null +++ b/src/components/git/GitLogsBox.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/src/components/git/GitLogsDialog.vue b/src/components/git/GitLogsDialog.vue new file mode 100644 index 0000000000000..6f7818cb81ad1 --- /dev/null +++ b/src/components/git/GitLogsDialog.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/src/components/git/GitPath.vue b/src/components/git/GitPath.vue new file mode 100644 index 0000000000000..be7701ac24a8c --- /dev/null +++ b/src/components/git/GitPath.vue @@ -0,0 +1,20 @@ + + + + + diff --git a/src/components/index.ts b/src/components/index.ts index 27055f1b1454e..d25270ae4cdfd 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,3 +1,4 @@ +import Box from './box/Box.vue'; import Button from './button/Button.vue'; import FaIconButton from './button/FaIconButton.vue'; import IconButton from './button/IconButton.vue'; @@ -59,6 +60,9 @@ import CreateGitSpiderDialog from './git/CreateGitSpiderDialog.vue'; import GitBranchSelect from './git/GitBranchSelect.vue'; import GitFileStatus from './git/GitFileStatus.vue'; import GitForm from './git/GitForm.vue'; +import GitLogsBox from './git/GitLogsBox.vue'; +import GitLogsDialog from './git/GitLogsDialog.vue'; +import GitPath from './git/GitPath.vue'; import GitRepo from './git/GitRepo.vue'; import GitStatus from './git/GitStatus.vue'; import UploadGitFilesDialog from './git/UploadGitFilesDialog.vue'; @@ -149,6 +153,7 @@ import UserRole from './user/UserRole.vue'; import useUser from './user/useUser'; export { + Box as ClBox, Button as ClButton, FaIconButton as ClFaIconButton, IconButton as ClIconButton, @@ -210,6 +215,9 @@ export { GitBranchSelect as ClGitBranchSelect, GitFileStatus as ClGitFileStatus, GitForm as ClGitForm, + GitLogsBox as ClGitLogsBox, + GitLogsDialog as ClGitLogsDialog, + GitPath as ClGitPath, GitRepo as ClGitRepo, GitStatus as ClGitStatus, UploadGitFilesDialog as ClUploadGitFilesDialog, diff --git a/src/components/tag/Tag.vue b/src/components/tag/Tag.vue index 6c690eabb0510..7afc298a45a92 100644 --- a/src/components/tag/Tag.vue +++ b/src/components/tag/Tag.vue @@ -153,7 +153,7 @@ onMounted(() => { margin-right: 5px; } -.tag:deep(.suffix-icon) { +.tag:not(.no-label):deep(.suffix-icon) { margin-left: 5px; } diff --git a/src/i18n/lang/en/components/git.ts b/src/i18n/lang/en/components/git.ts index dfd60e5d72de9..49abb7c5f120a 100644 --- a/src/i18n/lang/en/components/git.ts +++ b/src/i18n/lang/en/components/git.ts @@ -12,6 +12,7 @@ const git: LComponentsGit = { autoPull: 'Auto Pull', urlInvalid: 'Invalid URL', spider: 'Spider', + cloneLogs: 'Clone Logs', }, common: { currentBranch: 'Current Branch', @@ -59,6 +60,12 @@ const git: LComponentsGit = { tooltip: 'Loading Git data from remote, please wait...', }, }, + box: { + title: { + pull: 'Git Pull', + push: 'Git Push', + }, + }, }, branches: { select: 'Select Branch', diff --git a/src/i18n/lang/en/components/spider.ts b/src/i18n/lang/en/components/spider.ts index cbd1413de2f24..e0102f8682c23 100644 --- a/src/i18n/lang/en/components/spider.ts +++ b/src/i18n/lang/en/components/spider.ts @@ -13,6 +13,7 @@ const spider: LComponentsSpider = { incrementalSync: 'Incremental Sync', autoInstall: 'Auto Install', autoInstallDisabled: 'Auto Install (available in Crawlab Pro)', + git: 'Git Repo', gitRootPath: 'Git Path', }, actions: { diff --git a/src/i18n/lang/zh/components/git.ts b/src/i18n/lang/zh/components/git.ts index 762ebf7b6fb26..b0e7b5476e3dd 100644 --- a/src/i18n/lang/zh/components/git.ts +++ b/src/i18n/lang/zh/components/git.ts @@ -12,6 +12,7 @@ const git: LComponentsGit = { autoPull: '自动拉取', urlInvalid: '无效 URL', spider: '爬虫', + cloneLogs: '克隆日志', }, common: { currentBranch: '当前分支', @@ -49,6 +50,12 @@ const git: LComponentsGit = { }, }, }, + box: { + title: { + pull: '拉取代码', + push: '推送代码', + }, + }, actions: { pull: '拉取代码', commit: '提交代码', diff --git a/src/i18n/lang/zh/components/spider.ts b/src/i18n/lang/zh/components/spider.ts index 413aef852ea2a..b407879c8e948 100644 --- a/src/i18n/lang/zh/components/spider.ts +++ b/src/i18n/lang/zh/components/spider.ts @@ -13,6 +13,7 @@ const spider: LComponentsSpider = { incrementalSync: '增量同步文件', autoInstall: '自动安装依赖', autoInstallDisabled: '自动安装依赖 (仅限 Crawlab Pro)', + git: 'Git 仓库', gitRootPath: 'Git 仓库路径', }, actions: { diff --git a/src/interfaces/components/dialog/Dialog.d.ts b/src/interfaces/components/dialog/Dialog.d.ts index 338bc94d990b3..04e63386a143a 100644 --- a/src/interfaces/components/dialog/Dialog.d.ts +++ b/src/interfaces/components/dialog/Dialog.d.ts @@ -1,4 +1,4 @@ -type DialogKey = 'create' | 'edit' | 'run' | 'uploadFiles'; +type DialogKey = 'create' | 'edit' | 'run' | 'uploadFiles' | 'logs'; interface DialogVisible { createEdit: boolean; diff --git a/src/interfaces/i18n/components/git.d.ts b/src/interfaces/i18n/components/git.d.ts index 05f5f60afdee4..1cfecb9888ae8 100644 --- a/src/interfaces/i18n/components/git.d.ts +++ b/src/interfaces/i18n/components/git.d.ts @@ -12,6 +12,7 @@ interface LComponentsGit { autoPull: string; urlInvalid: string; spider: string; + cloneLogs: string; }; common: { currentBranch: string; @@ -49,6 +50,12 @@ interface LComponentsGit { }; }; }; + box: { + title: { + pull: string; + push: string; + }; + }; actions: { pull: string; commit: string; diff --git a/src/interfaces/i18n/components/spider.d.ts b/src/interfaces/i18n/components/spider.d.ts index f4aafebc7d85d..1d47434cf128f 100644 --- a/src/interfaces/i18n/components/spider.d.ts +++ b/src/interfaces/i18n/components/spider.d.ts @@ -13,6 +13,7 @@ interface LComponentsSpider { incrementalSync: string; autoInstall: string; autoInstallDisabled: string; + git: string; gitRootPath: string; }; actions: { diff --git a/src/interfaces/models/git.d.ts b/src/interfaces/models/git.d.ts index fe63d6db33246..1c578653f453f 100644 --- a/src/interfaces/models/git.d.ts +++ b/src/interfaces/models/git.d.ts @@ -49,5 +49,6 @@ export declare global { error?: string; auto_pull?: boolean; spiders?: Spider[]; + clone_logs?: string[]; } } diff --git a/src/interfaces/models/spider.d.ts b/src/interfaces/models/spider.d.ts index 9553fc8c7de7d..c613d9227bbd6 100644 --- a/src/interfaces/models/spider.d.ts +++ b/src/interfaces/models/spider.d.ts @@ -23,6 +23,7 @@ export declare global { auto_install?: boolean; git_id?: string; git_root_path?: string; + git?: Git; } interface SpiderStat { diff --git a/src/store/modules/git.ts b/src/store/modules/git.ts index d16d1274736e6..acbd171ed788e 100644 --- a/src/store/modules/git.ts +++ b/src/store/modules/git.ts @@ -135,34 +135,43 @@ const actions = { return await post(`${endpoint}/${id}/clone`); }, getGitRemoteRefs: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/git/remote-refs`); + if (JSON.stringify(state.gitRemoteRefs) === JSON.stringify(res?.data)) { + return; + } commit('setGitRemoteRefs', res?.data || []); return res; }, getCurrentBranch: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/branches/current`); + if (JSON.stringify(state.currentBranch) === JSON.stringify(res?.data)) + return; commit('setCurrentBranch', res?.data); return res; }, getBranches: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/branches`); + if (JSON.stringify(state.gitBranches) === JSON.stringify(res?.data)) return; commit('setGitBranches', res?.data || []); return res; }, getRemoteBranches: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/branches/remote`); + if (JSON.stringify(state.gitRemoteBranches) === JSON.stringify(res?.data)) { + return; + } commit('setGitRemoteBranches', res?.data || []); return res; }, @@ -204,10 +213,11 @@ const actions = { }); }, getChanges: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/changes`); + if (JSON.stringify(state.gitChanges) === JSON.stringify(res?.data)) return; commit('setGitChanges', res?.data || []); return res; }, @@ -253,18 +263,20 @@ const actions = { return await post(`${endpoint}/${id}/push`, {}); }, getLogs: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/logs`); + if (JSON.stringify(state.gitLogs) === JSON.stringify(res?.data)) return; commit('setGitLogs', res?.data || []); return res; }, getGitTags: async ( - { commit }: StoreActionContext, + { state, commit }: StoreActionContext, { id }: { id: string } ) => { const res = await get(`${endpoint}/${id}/git/tags`); + if (JSON.stringify(state.gitTags) === JSON.stringify(res?.data)) return; commit('setGitTags', res?.data || []); return res; }, diff --git a/src/views/deps/task/LogsView.vue b/src/views/deps/task/LogsView.vue index 6de4bd10c8ccb..d1cc442effa37 100644 --- a/src/views/deps/task/LogsView.vue +++ b/src/views/deps/task/LogsView.vue @@ -1,30 +1,39 @@ - \ No newline at end of file + diff --git a/src/views/git/detail/GitDetail.vue b/src/views/git/detail/GitDetail.vue index 1bb01ae0ae78e..4d1aa80b6f496 100644 --- a/src/views/git/detail/GitDetail.vue +++ b/src/views/git/detail/GitDetail.vue @@ -24,7 +24,17 @@ const ns = 'git'; const store = useStore(); const { git: state } = store.state; -const { activeId, activeTabName, tabs } = useGitDetail(); +const { + activeId, + activeTabName, + tabs, + pullLoading, + pullBoxVisible, + pullBoxLogs, + pushLoading, + pushBoxVisible, + pushBoxLogs, +} = useGitDetail(); // update tab disabled keys const { form } = useGit(store); @@ -134,6 +144,21 @@ provide<{ (item: FileNavItem): void }>( + + + + + diff --git a/src/views/git/detail/useGitDetail.ts b/src/views/git/detail/useGitDetail.ts index 9b563552494b3..c070045fe9f21 100644 --- a/src/views/git/detail/useGitDetail.ts +++ b/src/views/git/detail/useGitDetail.ts @@ -1,21 +1,11 @@ -import { computed, ref, onBeforeMount, onBeforeUnmount, watch } from 'vue'; +import { computed, ref, watch } from 'vue'; import { useStore } from 'vuex'; import { useRoute, useRouter } from 'vue-router'; -import useGitService from '@/services/git/gitService'; import { getTabName } from '@/utils/route'; import { ElMessage, ElMessageBox } from 'element-plus'; -import { sendEvent } from '@/admin/umeng'; import { translate } from '@/utils/i18n'; -import Form from '@/components/form/Form.vue'; -import { - GIT_REF_TYPE_BRANCH, - GIT_STATUS_CLONING, - GIT_STATUS_ERROR, - GIT_STATUS_PENDING, - GIT_STATUS_READY, -} from '@/constants/git'; +import { GIT_STATUS_READY } from '@/constants/git'; import useDetail from '@/layouts/content/detail/useDetail'; -import useGit from '@/components/git/useGit'; import { TAB_NAME_CHANGES, TAB_NAME_FILES, @@ -28,9 +18,13 @@ import { getRequestBaseUrlWs } from '@/utils'; const t = translate; const pullLoading = ref(false); +const pullBoxVisible = ref(false); +const pullBoxLogs = ref([]); const commitLoading = ref(false); const rollbackLoading = ref(false); const pushLoading = ref(false); +const pushBoxLogs = ref([]); +const pushBoxVisible = ref(false); const useGitDetail = () => { const ns = 'git'; @@ -166,16 +160,21 @@ const useGitDetail = () => { ); ws.onopen = () => { pullLoading.value = true; + pullBoxVisible.value = true; }; ws.onmessage = event => { - console.debug(event.data); + if (event.data) pullBoxLogs.value.push(event.data); }; ws.onerror = error => { pullLoading.value = false; - ElMessage.error(error); + pullBoxVisible.value = false; + pullBoxLogs.value = []; + ElMessage.error(error.toString()); }; ws.onclose = event => { pullLoading.value = false; + pullBoxVisible.value = false; + pullBoxLogs.value = []; if (event.code === 1000) { if (event.reason) { ElMessage.info(event.reason); @@ -194,27 +193,40 @@ const useGitDetail = () => { }; const onPush = async () => { - pushLoading.value = true; - try { - const res = await store.dispatch(`${ns}/push`, { - id: id.value, - }); - if (res.data) { - ElMessage.info(res.data); + const ws = new WebSocket( + getRequestBaseUrlWs() + `/gits/${id.value}/push/ws` + ); + ws.onopen = () => { + pushLoading.value = true; + pushBoxVisible.value = true; + }; + ws.onmessage = event => { + if (event.data) pushBoxLogs.value.push(event.data); + }; + ws.onerror = error => { + pushLoading.value = false; + pushBoxVisible.value = false; + pushBoxLogs.value = []; + ElMessage.error(error.toString()); + }; + ws.onclose = event => { + pushLoading.value = false; + pushBoxVisible.value = false; + pushBoxLogs.value = []; + if (event.code === 1000) { + if (event.reason) { + ElMessage.info(event.reason); + } else { + ElMessage.success(t('components.git.common.message.success.push')); + if (activeTabName.value === TAB_NAME_LOGS) { + store.dispatch(`${ns}/getLogs`, { id: id.value }); + store.dispatch(`${ns}/getRemoteBranches`, { id: id.value }); + } + } } else { - ElMessage.success(t('components.git.common.message.success.push')); - } - if (activeTabName.value === TAB_NAME_LOGS) { - await Promise.all([ - store.dispatch(`${ns}/getLogs`, { id: id.value }), - store.dispatch(`${ns}/getRemoteBranches`, { id: id.value }), - ]); + ElMessage.error(event.reason); } - } catch (e: any) { - ElMessage.error(e.message); - } finally { - pushLoading.value = false; - } + }; }; return { @@ -231,8 +243,12 @@ const useGitDetail = () => { rollbackLoading, onRollback, pullLoading, + pullBoxVisible, + pullBoxLogs, onPull, pushLoading, + pushBoxVisible, + pushBoxLogs, onPush, }; }; diff --git a/src/views/git/list/GitList.vue b/src/views/git/list/GitList.vue index c7d56badc3379..4574646a7330b 100644 --- a/src/views/git/list/GitList.vue +++ b/src/views/git/list/GitList.vue @@ -16,8 +16,14 @@ const { + + diff --git a/src/views/git/list/useGitList.ts b/src/views/git/list/useGitList.ts index b43918f9916fa..ae2188997e96f 100644 --- a/src/views/git/list/useGitList.ts +++ b/src/views/git/list/useGitList.ts @@ -1,6 +1,7 @@ import { computed, h } from 'vue'; import { useStore } from 'vuex'; import { useRouter } from 'vue-router'; +import { ElPopover } from 'element-plus'; import { ACTION_ADD, ACTION_DELETE, @@ -8,6 +9,7 @@ import { ACTION_FILTER_SEARCH, ACTION_VIEW, FILTER_OP_CONTAINS, + GIT_STATUS_READY, TABLE_COLUMN_NAME_ACTIONS, } from '@/constants'; import { sendEvent } from '@/admin/umeng'; @@ -19,6 +21,7 @@ import { } from '@/utils'; import NavLink from '@/components/nav/NavLink.vue'; import GitStatus from '@/components/git/GitStatus.vue'; +import ClTag from '@/components/tag/Tag.vue'; const useGitList = () => { // router @@ -102,16 +105,41 @@ const useGitList = () => { key: 'status', label: t('views.gits.table.columns.status'), icon: ['fa', 'heartbeat'], - width: '150', + width: '160', value: (row: Git) => { - const { _id, status, error } = row; - return h(GitStatus, { - id: _id, - status, - error, - onClick: () => router.push(`/gits/${_id}`), - onRetry: () => store.dispatch(`${ns}/getList`), - }); + const { _id, status, error, clone_logs } = row; + return h( + 'div', + { + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'start', + }, + }, + [ + h(GitStatus, { + id: _id, + status, + error, + onClick: () => { + router.push(`/gits/${_id}`); + }, + onRetry: () => store.dispatch(`${ns}/getList`), + }), + clone_logs?.length + ? h(ClTag, { + type: 'info', + icon: ['fa', 'file-alt'], + clickable: true, + onClick: () => { + store.commit(`${ns}/showDialog`, 'logs'); + store.commit(`${ns}/setForm`, row); + }, + }) + : null, + ] + ); }, hasSort: true, hasFilter: true, diff --git a/src/views/spider/detail/actions/SpiderDetailActionsCommon.vue b/src/views/spider/detail/actions/SpiderDetailActionsCommon.vue index fc58220b20e94..50eaee580a4ae 100644 --- a/src/views/spider/detail/actions/SpiderDetailActionsCommon.vue +++ b/src/views/spider/detail/actions/SpiderDetailActionsCommon.vue @@ -1,9 +1,15 @@