Skip to content

Commit dc32deb

Browse files
authored
Merge pull request #464 from tapdata/feat/TAP-8725-datahub-mdm
Feat/tap 8725 datahub mdm
2 parents b015453 + e39cc45 commit dc32deb

11 files changed

Lines changed: 171 additions & 50 deletions

File tree

packages/dag/src/components/monitor/LeftSider.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ export default {
8787
hideOverlap: true,
8888
showMaxLabel: true,
8989
formatter: (val) => {
90-
return `${Math.round(val)}%`
90+
return `${Number(val.toFixed(2))}%`
9191
},
9292
},
9393
},

packages/form/src/components/field-select/FieldSelect.tsx

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import i18n from '@tap/i18n'
2+
import { isPlainObject } from 'lodash-es'
23
import {
34
computed,
45
defineComponent,
@@ -8,20 +9,22 @@ import {
89
ref,
910
watch,
1011
} from 'vue'
11-
import type { ElSelectV2 } from 'element-plus'
12+
import type { SelectV2Instance } from 'element-plus'
13+
import './style.scss'
1214

1315
export const FieldSelect = defineComponent({
1416
props: {
1517
options: Array,
1618
enableTooltip: Boolean,
1719
modelValue: String,
20+
loading: Boolean,
1821
},
1922
setup: (props, { attrs, slots }) => {
2023
const labelRef = ref<HTMLElement>()
2124
const showTooltip = ref(false)
2225
const isTextOverflow = ref(false)
2326
const tooltipContent = ref('')
24-
const selectRef = ref<ElSelectV2>()
27+
const selectRef = ref<SelectV2Instance>()
2528

2629
const checkTextOverflow = (element: HTMLElement, text: string) => {
2730
if (!element || !text) return false
@@ -57,6 +60,9 @@ export const FieldSelect = defineComponent({
5760
}
5861

5962
const getIcon = (tapType: string) => {
63+
if (isPlainObject(tapType)) {
64+
return TYPE_ICON[tapType.type] || 'type-unknown'
65+
}
6066
const match = tapType.match(/"type"\s*:\s*(\d+)/)
6167
const value = match?.[1]
6268

@@ -197,8 +203,34 @@ export const FieldSelect = defineComponent({
197203
}, 100)
198204
})
199205

206+
const children: Record<string, any> = {
207+
header: slots.header,
208+
default: ({ item: option }) => (
209+
<div class="flex align-center gap-1">
210+
{option.icon && (
211+
<VIcon size="16" title={option.type}>
212+
{option.icon}
213+
</VIcon>
214+
)}
215+
{option[fieldNames.value.label]}
216+
{renderIcon(option)}
217+
</div>
218+
),
219+
}
220+
221+
const renderLoading = () => {
222+
return (
223+
<el-icon class="el-select-loading__icon is-loading">
224+
<ElIconLoading />
225+
</el-icon>
226+
)
227+
}
228+
200229
return () => {
201230
const newAttrs = { ...attrs }
231+
232+
children.prefix = props.loading ? renderLoading() : undefined
233+
202234
if (
203235
(attrs['allow-create'] || attrs.allowCreate) &&
204236
!('defaultFirstOption' in attrs) &&
@@ -221,29 +253,20 @@ export const FieldSelect = defineComponent({
221253
{...newAttrs}
222254
props={fieldNames.value}
223255
fit-input-width={false}
256+
class="field-select"
224257
popper-class="field-select-popper"
225258
fallback-placements={['bottom-start', 'bottom-end']}
226259
options={fieldOptions.value}
227260
dataSource={fieldOptions.value}
261+
loading={props.loading}
228262
onMouseenter={onMouseEnter}
229263
onMouseleave={() => {
230264
showTooltip.value = false
231265
}}
232266
>
233267
{{
234-
header: slots.header,
268+
...children,
235269
label: ({ label }) => <span ref={labelRef}>{label}</span>,
236-
default: ({ item: option }) => (
237-
<div class="flex align-center gap-1">
238-
{option.icon && (
239-
<VIcon size="16" title={option.type}>
240-
{option.icon}
241-
</VIcon>
242-
)}
243-
{option[fieldNames.value.label]}
244-
{renderIcon(option)}
245-
</div>
246-
),
247270
}}
248271
</ElSelectV2>
249272
</ElTooltip>
@@ -253,24 +276,13 @@ export const FieldSelect = defineComponent({
253276
modelValue={props.modelValue}
254277
{...newAttrs}
255278
props={fieldNames.value}
279+
loading={props.loading}
280+
class="field-select"
256281
popper-class="field-select-popper"
257282
options={fieldOptions.value}
258283
dataSource={fieldOptions.value}
259284
>
260-
{{
261-
header: slots.header,
262-
default: ({ item: option }) => (
263-
<div class="flex align-center gap-1">
264-
{option.icon && (
265-
<VIcon size="16" title={option.type}>
266-
{option.icon}
267-
</VIcon>
268-
)}
269-
{option[fieldNames.value.label]}
270-
{renderIcon(option)}
271-
</div>
272-
),
273-
}}
285+
{children}
274286
</ElSelectV2>
275287
)
276288
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.field-select {
2+
.el-select__prefix .el-select-loading__icon {
3+
position: absolute;
4+
right: 12px;
5+
background-color: var(--el-fill-color-blank);
6+
z-index: 2;
7+
}
8+
.el-select__prefix:has(.el-select-loading__icon) + .el-select__selection {
9+
margin-left: -14px;
10+
}
11+
}

packages/form/src/components/infinite-select/InfiniteSelect.vue

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import { debounce, escapeRegExp, isString, merge } from 'lodash-es'
3-
import { computed, markRaw, nextTick, onMounted, ref, toRaw, watch } from 'vue'
3+
import { computed, nextTick, onMounted, ref, toRaw, watch } from 'vue'
44
import SelectLoading from './SelectLoading.vue'
55
66
const page = ref(0)
@@ -69,7 +69,7 @@ const paramsSerializer = (params: {
6969
7070
if (params.query) {
7171
filter.where = {
72-
[props.itemQuery ||props.itemValue || props.itemLabel]: {
72+
[props.itemQuery || props.itemValue || props.itemLabel]: {
7373
like: escapeRegExp(params.query),
7474
options: 'i',
7575
},
@@ -298,7 +298,7 @@ onMounted(() => {
298298
@visible-change="onVisibleChange"
299299
@change="onChange"
300300
>
301-
<template #prefix>
301+
<template v-if="showLoading || $slots.prefix" #prefix>
302302
<slot name="prefix" />
303303
<el-icon
304304
v-if="showLoading"

packages/i18n/src/locale/lang/en.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,4 +593,5 @@ export default {
593593
public_warningTime: 'Warning Time',
594594
public_warningLog: 'Warning Log',
595595
public_updated_from_now: 'Updated at {time}',
596+
public_crontabExpression: 'Cron Expression',
596597
}

packages/i18n/src/locale/lang/zh-CN.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,5 @@ export default {
584584
public_warningTime: '告警时间',
585585
public_warningLog: '告警日志',
586586
public_updated_from_now: '更新于 {time}',
587+
public_crontabExpression: 'Cron 表达式',
587588
}

packages/i18n/src/locale/lang/zh-TW.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,4 +582,5 @@ export default {
582582
public_warningTime: '告警時間',
583583
public_warningLog: '告警日誌',
584584
public_updated_from_now: '更新于 {time}',
585+
public_crontabExpression: 'Cron 表達式',
585586
}

packages/ldp/src/Dashboard.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,9 +753,11 @@ export default {
753753
background-color: rgba(255, 255, 255, 0.4);
754754
}
755755
756+
:deep(.tree-wrap.is-drop) {
757+
box-shadow: 0px 0px 0px 2px var(--color-primary) inset;
758+
}
756759
:deep(.ldp-tree.is-drop),
757760
:deep(.is-drop .ldp-tree) {
758-
box-shadow: 0px 0px 0px 2px var(--color-primary) inset;
759761
& + .drop-mask {
760762
display: none !important;
761763
}

packages/ldp/src/MDM.vue

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
<script lang="tsx">
2-
import { discoveryApi, ldpApi, metadataDefinitionsApi } from '@tap/api'
2+
import {
3+
discoveryApi,
4+
fetchMetadataInstances,
5+
ldpApi,
6+
metadataDefinitionsApi,
7+
} from '@tap/api'
38
import { makeDragNodeImage, TASK_SETTINGS } from '@tap/business/src/shared'
49
import { IconButton } from '@tap/component/src/icon-button'
5-
10+
import { FieldSelect, mapFieldsData } from '@tap/form'
611
import i18n from '@tap/i18n'
712
import { generateId, uuid } from '@tap/shared'
813
import { debounce } from 'lodash-es'
@@ -11,7 +16,7 @@ import commonMix from './mixins/common'
1116
1217
export default {
1318
name: 'MDM',
14-
components: { IconButton },
19+
components: { IconButton, FieldSelect },
1520
mixins: [commonMix],
1621
props: {
1722
directory: Object,
@@ -43,6 +48,8 @@ export default {
4348
crontabExpression: '',
4449
crontabExpressionType: 'once',
4550
},
51+
fields: [],
52+
updateConditionFields: [],
4653
},
4754
expandedKeys: [],
4855
dialogConfig: {
@@ -256,10 +263,8 @@ export default {
256263
257264
handleDragLeave(ev) {
258265
ev.preventDefault()
259-
console.log('handleDragLeave') // eslint-disable-line
260266
if (!this.allowDrop) return
261267
if (!ev.currentTarget.contains(ev.relatedTarget)) {
262-
console.log('handleDragLeave✌️', ev) // eslint-disable-line
263268
this.removeDropEffect(ev, 'tree-wrap', 'is-drop')
264269
}
265270
},
@@ -315,9 +320,11 @@ export default {
315320
} else {
316321
this.taskDialogConfig.notSupportedCDC = false
317322
}
323+
324+
this.loadFields()
318325
},
319326
320-
async taskDialogSubmit(start, confirmTable) {
327+
taskDialogSubmit(start, confirmTable) {
321328
this.$refs.form.validate(async (valid) => {
322329
if (!valid) return
323330
const {
@@ -354,7 +361,6 @@ export default {
354361
this.setNodeExpand(tagId)
355362
}, 1000)
356363
} catch (error) {
357-
console.log(error) // eslint-disable-line
358364
const code = error?.data?.code
359365
const data = error?.data?.data
360366
if (code === 'Ldp.MdmTargetNoPrimaryKey' && data) {
@@ -407,6 +413,9 @@ export default {
407413
makeTask(from, tableName, newTableName) {
408414
const source = this.getTableNode(from, tableName)
409415
const target = this.getTableNode(this.mdmConnection, newTableName)
416+
417+
target.updateConditionFields = this.taskDialogConfig.updateConditionFields
418+
410419
return {
411420
...TASK_SETTINGS,
412421
syncType: 'sync',
@@ -533,7 +542,6 @@ export default {
533542
this.removeDropEffect(ev, 'tree-wrap', 'is-drop')
534543
535544
this.showTaskDialog(!data.isObject ? data.id : undefined)
536-
console.log('handleTreeDrop') // eslint-disable-line
537545
},
538546
539547
handleSelfDrop(draggingNode, dropNode, dropType, ev) {
@@ -620,6 +628,52 @@ export default {
620628
hideDialog() {
621629
this.dialogConfig.visible = false
622630
},
631+
async loadFields() {
632+
this.taskDialogConfig.loading = true
633+
this.taskDialogConfig.fields = []
634+
this.taskDialogConfig.updateConditionFields = []
635+
636+
const {
637+
items: [schema = {}],
638+
} = await fetchMetadataInstances({
639+
page: 1,
640+
size: 1,
641+
where: {
642+
'source.id': this.taskDialogConfig.from.id,
643+
meta_type: { in: ['collection', 'table', 'view'] },
644+
is_deleted: false,
645+
sourceType: 'SOURCE',
646+
original_name: this.taskDialogConfig.tableName,
647+
},
648+
fields: {
649+
original_name: true,
650+
fields: true,
651+
qualified_name: true,
652+
name: true,
653+
indices: true,
654+
constraints: true,
655+
},
656+
}).finally(() => {
657+
this.taskDialogConfig.loading = false
658+
})
659+
660+
const { fields } = mapFieldsData(schema)
661+
this.taskDialogConfig.fields = fields
662+
663+
let defaultList = fields.filter((item) => item.isPrimaryKey)
664+
665+
if (!defaultList.length) {
666+
defaultList = fields.filter((item) => item.indicesUnique)
667+
}
668+
669+
if (!defaultList.length) {
670+
defaultList = fields.filter((item) => item.source === 'virtual_hash')
671+
}
672+
673+
this.taskDialogConfig.updateConditionFields = defaultList.map(
674+
(item) => item.value,
675+
)
676+
},
623677
async dialogSubmit() {
624678
const config = this.dialogConfig
625679
const value = config.label
@@ -968,10 +1022,10 @@ export default {
9681022
<ElFormItem
9691023
:label="$t('packages_dag_task_setting_crontabExpressionFlag')"
9701024
prop="task.crontabExpressionType"
1025+
class="flex-1"
9711026
>
9721027
<ElSelect
9731028
v-model="taskDialogConfig.task.crontabExpressionType"
974-
class="flex-1"
9751029
@change="handleChangeCronType"
9761030
>
9771031
<ElOption v-for="(opt, i) in cronOptions" v-bind="opt" :key="i" />
@@ -980,11 +1034,24 @@ export default {
9801034
<ElFormItem
9811035
v-if="taskDialogConfig.task.crontabExpressionType === 'custom'"
9821036
prop="task.crontabExpression"
983-
label-width="0"
1037+
class="flex-1"
1038+
label-width="auto"
1039+
:label="$t('public_crontabExpression')"
9841040
>
9851041
<ElInput v-model="taskDialogConfig.task.crontabExpression" />
9861042
</ElFormItem>
9871043
</div>
1044+
<ElFormItem
1045+
:label="$t('packages_dag_nodes_table_gengxintiaojianzi')"
1046+
prop="updateConditionFields"
1047+
>
1048+
<FieldSelect
1049+
v-model="taskDialogConfig.updateConditionFields"
1050+
:options="taskDialogConfig.fields"
1051+
multiple
1052+
:loading="taskDialogConfig.loading"
1053+
/>
1054+
</ElFormItem>
9881055
</ElForm>
9891056
<template #footer>
9901057
<span class="dialog-footer">

0 commit comments

Comments
 (0)