mirror of
https://gitee.com/devlive-community/datacap.git
synced 2024-12-03 04:27:56 +08:00
[Core] [Refactor] [UI] [Source] Add history
This commit is contained in:
parent
d8a6a0fb8b
commit
77fc3c8de5
@ -18,6 +18,7 @@ export default {
|
|||||||
create: 'Create Source',
|
create: 'Create Source',
|
||||||
delete: 'Delete Source [ $NAME ]',
|
delete: 'Delete Source [ $NAME ]',
|
||||||
syncMetadata: 'Sync Metadata',
|
syncMetadata: 'Sync Metadata',
|
||||||
|
syncHistory: 'Sync History',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
selectSource: 'Please select a source',
|
selectSource: 'Please select a source',
|
||||||
|
@ -18,6 +18,7 @@ export default {
|
|||||||
create: '创建数据源',
|
create: '创建数据源',
|
||||||
delete: '删除数据源 [ $NAME ]',
|
delete: '删除数据源 [ $NAME ]',
|
||||||
syncMetadata: '同步元数据',
|
syncMetadata: '同步元数据',
|
||||||
|
syncHistory: '同步历史',
|
||||||
},
|
},
|
||||||
tip: {
|
tip: {
|
||||||
selectSource: '请选择数据源',
|
selectSource: '请选择数据源',
|
||||||
|
@ -3,6 +3,7 @@ import { BaseService } from '@/services/base'
|
|||||||
import { HttpUtils } from '@/utils/http'
|
import { HttpUtils } from '@/utils/http'
|
||||||
import { SourceModel } from '@/model/source.ts'
|
import { SourceModel } from '@/model/source.ts'
|
||||||
import { isEmpty } from 'lodash'
|
import { isEmpty } from 'lodash'
|
||||||
|
import { FilterModel } from '@/model/filter.ts'
|
||||||
|
|
||||||
const DEFAULT_PATH_V1 = '/api/v1/source'
|
const DEFAULT_PATH_V1 = '/api/v1/source'
|
||||||
const DEFAULT_PATH_V2 = '/api/v2/source'
|
const DEFAULT_PATH_V2 = '/api/v2/source'
|
||||||
@ -50,6 +51,11 @@ class SourceService
|
|||||||
{
|
{
|
||||||
return new HttpUtils().put(`${ DEFAULT_PATH_V2 }/syncMetadata/${ id }`)
|
return new HttpUtils().put(`${ DEFAULT_PATH_V2 }/syncMetadata/${ id }`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getHistory(id: number, configure: FilterModel): Promise<ResponseModel>
|
||||||
|
{
|
||||||
|
return new HttpUtils().post(`${ DEFAULT_PATH_V2 }/getHistory/${ id }`, configure)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new SourceService()
|
export default new SourceService()
|
||||||
|
157
core/datacap-ui/src/views/pages/admin/source/SourceHistory.vue
Normal file
157
core/datacap-ui/src/views/pages/admin/source/SourceHistory.vue
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<template>
|
||||||
|
<Dialog :is-visible="visible" :title="$t('source.common.syncHistory')" :width="'60%'">
|
||||||
|
<TableCommon :loading="loading" :columns="headers" :data="data" :pagination="pagination" @changePage="handlerChangePage">
|
||||||
|
<template #elapsed="{row}">
|
||||||
|
{{ (getTime(row.updateTime) - getTime(row.createTime)) / 1000 }}
|
||||||
|
</template>
|
||||||
|
<template #state="{row}">
|
||||||
|
<Badge :style="{backgroundColor: Common.getColor(row?.state)}">
|
||||||
|
<HoverCard v-if="row?.state === 'FAILURE'">
|
||||||
|
<HoverCardTrigger as-child>
|
||||||
|
<Button variant="link">
|
||||||
|
{{ getStateText(row?.state) }}
|
||||||
|
</Button>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<HoverCardContent class="w-full">
|
||||||
|
{{ row?.message }}
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCard>
|
||||||
|
<span v-else>{{ getStateText(row?.state) }}</span>
|
||||||
|
</Badge>
|
||||||
|
</template>
|
||||||
|
<template #result="{row}">
|
||||||
|
<HoverCard>
|
||||||
|
<HoverCardTrigger as-child>
|
||||||
|
<Eye class="cursor-pointer"/>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<HoverCardContent class="w-full">
|
||||||
|
<MdPreview :modelValue="toMarkdown(row.info)" style="padding: 0"/>
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCard>
|
||||||
|
</template>
|
||||||
|
</TableCommon>
|
||||||
|
<template #footer>
|
||||||
|
<div class="space-x-5">
|
||||||
|
<Button variant="outline" size="sm" @click="handlerCancel">
|
||||||
|
{{ $t('common.cancel') }}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
import Dialog from '@/views/ui/dialog'
|
||||||
|
import { SourceModel } from '@/model/source'
|
||||||
|
import SourceService from '@/services/source'
|
||||||
|
import Button from '@/views/ui/button'
|
||||||
|
import { FilterModel } from '@/model/filter'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { createHistoryHeaders } from '@/views/pages/admin/source/SourceUtils'
|
||||||
|
import { PaginationModel, PaginationRequest } from '@/model/pagination'
|
||||||
|
import TableCommon from '@/views/components/table/TableCommon.vue'
|
||||||
|
import { Badge } from '@/components/ui/badge'
|
||||||
|
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card'
|
||||||
|
import Common from '@/utils/common'
|
||||||
|
import { Eye } from 'lucide-vue-next'
|
||||||
|
import { MdPreview } from 'md-editor-v3'
|
||||||
|
import 'md-editor-v3/lib/style.css'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'SourceHistory',
|
||||||
|
components: {
|
||||||
|
Badge,
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
TableCommon,
|
||||||
|
HoverCard, HoverCardContent, HoverCardTrigger,
|
||||||
|
Eye,
|
||||||
|
MdPreview
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
visible: {
|
||||||
|
get(): boolean
|
||||||
|
{
|
||||||
|
return this.isVisible
|
||||||
|
},
|
||||||
|
set(value: boolean)
|
||||||
|
{
|
||||||
|
this.$emit('close', value)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Common()
|
||||||
|
{
|
||||||
|
return Common
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
isVisible: {
|
||||||
|
type: Boolean
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: Object as () => SourceModel | null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup()
|
||||||
|
{
|
||||||
|
const i18n = useI18n()
|
||||||
|
const filter: FilterModel = new FilterModel()
|
||||||
|
const headers = createHistoryHeaders(i18n)
|
||||||
|
|
||||||
|
return {
|
||||||
|
filter,
|
||||||
|
headers,
|
||||||
|
i18n
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
data: [],
|
||||||
|
pagination: {} as PaginationModel
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created()
|
||||||
|
{
|
||||||
|
this.handlerInitialize()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handlerInitialize()
|
||||||
|
{
|
||||||
|
this.loading = true
|
||||||
|
SourceService.getHistory(this.info?.id as number, this.filter)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status) {
|
||||||
|
this.data = response.data.content
|
||||||
|
this.pagination = PaginationRequest.of(response.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => this.loading = false)
|
||||||
|
},
|
||||||
|
handlerChangePage(value: PaginationModel)
|
||||||
|
{
|
||||||
|
this.filter.page = value.currentPage
|
||||||
|
this.filter.size = value.pageSize
|
||||||
|
this.handlerInitialize()
|
||||||
|
},
|
||||||
|
handlerCancel()
|
||||||
|
{
|
||||||
|
this.visible = false
|
||||||
|
},
|
||||||
|
getTime(time: any)
|
||||||
|
{
|
||||||
|
return time ? new Date(time).getTime() : 0
|
||||||
|
},
|
||||||
|
getStateText(origin: string): string
|
||||||
|
{
|
||||||
|
return Common.getText(this.i18n, origin)
|
||||||
|
},
|
||||||
|
toMarkdown(content: string)
|
||||||
|
{
|
||||||
|
return '```json\n' + JSON.stringify(content, null, 4) + '\n```'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
@ -45,6 +45,10 @@
|
|||||||
<Trash class="mr-2 h-4 w-4"/>
|
<Trash class="mr-2 h-4 w-4"/>
|
||||||
<span>{{ $t('common.deleteData') }}</span>
|
<span>{{ $t('common.deleteData') }}</span>
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem :disabled="(loginUserId !== row.user.id)" class="cursor-pointer" @click="handlerHistory(true, row)">
|
||||||
|
<History class="mr-2 h-4 w-4"/>
|
||||||
|
{{ $t('source.common.syncHistory') }}
|
||||||
|
</DropdownMenuItem>
|
||||||
<DropdownMenuItem :disabled="(loginUserId !== row.user.id) || !row.available" class="cursor-pointer" @click="handlerSyncMetadata(true, row)">
|
<DropdownMenuItem :disabled="(loginUserId !== row.user.id) || !row.available" class="cursor-pointer" @click="handlerSyncMetadata(true, row)">
|
||||||
<RefreshCcwDot class="mr-2 h-4 w-4"/>
|
<RefreshCcwDot class="mr-2 h-4 w-4"/>
|
||||||
{{ $t('source.common.syncMetadata') }}
|
{{ $t('source.common.syncMetadata') }}
|
||||||
@ -59,6 +63,7 @@
|
|||||||
<SourceInfo v-if="dataInfoVisible" :is-visible="dataInfoVisible" :info="dataInfo" @close="handlerInfo(false, null)"/>
|
<SourceInfo v-if="dataInfoVisible" :is-visible="dataInfoVisible" :info="dataInfo" @close="handlerInfo(false, null)"/>
|
||||||
<SourceDelete v-if="dataDeleteVisible" :is-visible="dataDeleteVisible" :info="dataInfo" @close="handlerDelete(false, null)"/>
|
<SourceDelete v-if="dataDeleteVisible" :is-visible="dataDeleteVisible" :info="dataInfo" @close="handlerDelete(false, null)"/>
|
||||||
<SourceMetadata v-if="dataSyncMetadataVisible" :is-visible="dataSyncMetadataVisible" :info="dataInfo" @close="handlerSyncMetadata(false, null)"/>
|
<SourceMetadata v-if="dataSyncMetadataVisible" :is-visible="dataSyncMetadataVisible" :info="dataInfo" @close="handlerSyncMetadata(false, null)"/>
|
||||||
|
<SourceHistory v-if="dataHistoryVisible" :is-visible="dataHistoryVisible" :info="dataInfo" @close="handlerHistory(false, null)"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -66,7 +71,7 @@
|
|||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
import Card from '@/views/ui/card'
|
import Card from '@/views/ui/card'
|
||||||
import Button from '@/views/ui/button'
|
import Button from '@/views/ui/button'
|
||||||
import { CirclePlay, CircleX, Cog, Pencil, Plus, RefreshCcwDot, Trash } from 'lucide-vue-next'
|
import { CirclePlay, CircleX, Cog, History, Pencil, Plus, RefreshCcwDot, Trash } from 'lucide-vue-next'
|
||||||
import TableCommon from '@/views/components/table/TableCommon.vue'
|
import TableCommon from '@/views/components/table/TableCommon.vue'
|
||||||
import { FilterModel } from '@/model/filter'
|
import { FilterModel } from '@/model/filter'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
@ -91,10 +96,12 @@ import {
|
|||||||
} from '@/components/ui/dropdown-menu'
|
} from '@/components/ui/dropdown-menu'
|
||||||
import SourceDelete from '@/views/pages/admin/source/SourceDelete.vue'
|
import SourceDelete from '@/views/pages/admin/source/SourceDelete.vue'
|
||||||
import SourceMetadata from '@/views/pages/admin/source/SourceMetadata.vue'
|
import SourceMetadata from '@/views/pages/admin/source/SourceMetadata.vue'
|
||||||
|
import SourceHistory from '@/views/pages/admin/source/SourceHistory.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SourceHome',
|
name: 'SourceHome',
|
||||||
components: {
|
components: {
|
||||||
|
SourceHistory,
|
||||||
SourceMetadata,
|
SourceMetadata,
|
||||||
SourceDelete,
|
SourceDelete,
|
||||||
DropdownMenuItem, DropdownMenuGroup, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuContent, DropdownMenuTrigger, DropdownMenu,
|
DropdownMenuItem, DropdownMenuGroup, DropdownMenuSeparator, DropdownMenuLabel, DropdownMenuContent, DropdownMenuTrigger, DropdownMenu,
|
||||||
@ -104,7 +111,7 @@ export default defineComponent({
|
|||||||
Switch,
|
Switch,
|
||||||
Avatar,
|
Avatar,
|
||||||
TableCommon,
|
TableCommon,
|
||||||
Pencil, CircleX, CirclePlay, Cog, Trash, Plus, RefreshCcwDot,
|
Pencil, CircleX, CirclePlay, Cog, Trash, Plus, RefreshCcwDot, History,
|
||||||
Button,
|
Button,
|
||||||
Card
|
Card
|
||||||
},
|
},
|
||||||
@ -129,7 +136,8 @@ export default defineComponent({
|
|||||||
dataInfoVisible: false,
|
dataInfoVisible: false,
|
||||||
dataInfo: null as SourceModel | null,
|
dataInfo: null as SourceModel | null,
|
||||||
dataDeleteVisible: false,
|
dataDeleteVisible: false,
|
||||||
dataSyncMetadataVisible: false
|
dataSyncMetadataVisible: false,
|
||||||
|
dataHistoryVisible: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created()
|
created()
|
||||||
@ -175,6 +183,11 @@ export default defineComponent({
|
|||||||
{
|
{
|
||||||
this.dataSyncMetadataVisible = opened
|
this.dataSyncMetadataVisible = opened
|
||||||
this.dataInfo = value
|
this.dataInfo = value
|
||||||
|
},
|
||||||
|
handlerHistory(opened: boolean, value: null | SourceModel)
|
||||||
|
{
|
||||||
|
this.dataHistoryVisible = opened
|
||||||
|
this.dataInfo = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -15,6 +15,19 @@ const createHeaders = (i18n: any) => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
const createHistoryHeaders = (i18n: any) => {
|
||||||
createHeaders
|
return [
|
||||||
|
{ key: 'id', hidden: true, header: i18n.t('common.id'), width: 80 },
|
||||||
|
{ key: 'name', hidden: true, header: i18n.t('common.name') },
|
||||||
|
{ key: 'createTime', hidden: true, header: i18n.t('common.createTime') },
|
||||||
|
{ key: 'updateTime', hidden: true, header: i18n.t('common.updateTime') },
|
||||||
|
{ key: 'elapsed', hidden: true, header: i18n.t('common.elapsed'), slot: 'elapsed', class: 'text-center' },
|
||||||
|
{ key: 'state', hidden: true, header: i18n.t('common.state'), slot: 'state', class: 'text-center' },
|
||||||
|
{ key: 'result', hidden: true, header: i18n.t('common.result'), slot: 'result' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
createHeaders,
|
||||||
|
createHistoryHeaders
|
||||||
}
|
}
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<Modal v-model="visible"
|
|
||||||
:title="$t('common.syncMetadata') + ' [ ' + data.name + ' ]'"
|
|
||||||
:mask-closable="false"
|
|
||||||
@cancel="handlerCancel()">
|
|
||||||
<Alert type="warning"
|
|
||||||
show-icon>
|
|
||||||
{{ $t('source.manager.sourceSyncMetadataTip1') }}
|
|
||||||
</Alert>
|
|
||||||
<Alert type="error"
|
|
||||||
show-icon>
|
|
||||||
{{ $t('source.manager.sourceSyncMetadataTip2') }}
|
|
||||||
</Alert>
|
|
||||||
<p>{{ $t('source.manager.sourceSyncMetadataTip3').replace('REPLACE_NAME', data.name) }}</p>
|
|
||||||
<Input v-model="inputValue"/>
|
|
||||||
<template #footer>
|
|
||||||
<Button type="primary"
|
|
||||||
:disabled="inputValue !== data.name"
|
|
||||||
:loading="loading"
|
|
||||||
@click="handlerSubmit()">
|
|
||||||
<FontAwesomeIcon icon="rotate"/>
|
|
||||||
{{ $t('common.syncMetadata') }}
|
|
||||||
</Button>
|
|
||||||
</template>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script lang="ts">
|
|
||||||
import {defineComponent} from "vue";
|
|
||||||
import SourceV2Service from "@/services/SourceV2Service";
|
|
||||||
|
|
||||||
export class DataItem
|
|
||||||
{
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
name: "SourceMetadata",
|
|
||||||
props: {
|
|
||||||
isVisible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: () => false
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
type: DataItem
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data()
|
|
||||||
{
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
inputValue: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handlerSubmit()
|
|
||||||
{
|
|
||||||
this.loading = true;
|
|
||||||
SourceV2Service
|
|
||||||
.syncMetadata(this.data.id)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status) {
|
|
||||||
this.$Message.success(`${this.$t('source.manager.sourceSyncMetadataTip4').replace('REPLACE_NAME', this.data.name)}`);
|
|
||||||
this.handlerCancel();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.finally(() => this.loading = false);
|
|
||||||
},
|
|
||||||
handlerCancel()
|
|
||||||
{
|
|
||||||
this.visible = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
visible: {
|
|
||||||
get(): boolean
|
|
||||||
{
|
|
||||||
return this.isVisible;
|
|
||||||
},
|
|
||||||
set(value: boolean)
|
|
||||||
{
|
|
||||||
this.$emit('close', value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
Loading…
Reference in New Issue
Block a user