Skip to content

Commit

Permalink
fixed(south, template): add validate for tags excel when import tags …
Browse files Browse the repository at this point in the history
…file
  • Loading branch information
orangegzx authored and orangegzx committed Sep 11, 2023
1 parent 72254de commit 44cb63d
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 36 deletions.
4 changes: 3 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<template>
<router-view />
<suspense>
<router-view />
</suspense>
</template>
3 changes: 2 additions & 1 deletion src/composables/config/useAddTagCommon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ export const useTagAttributeTypeSelect = () => {
return Number(total) === value
})
const attrValues = tagAttrValueMap[Number(key) as keyof typeof tagAttrValueMap]
return attrValues.includes(attr)

return attrValues?.includes(attr)
}

return {
Expand Down
16 changes: 5 additions & 11 deletions src/composables/config/useGroupList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,18 @@ import { useStore } from 'vuex'
import { EmqxMessage } from '@emqx/emqx-ui'
import { MessageBoxConfirm } from '@/utils/element'
import { queryGroupList, deleteGroup, queryTagList, addTag } from '@/api/config'
import type { GroupData } from '@/types/config'
import type { GroupData, PluginInfo } from '@/types/config'
import { OmitArrayFields, listOrderByKey } from '@/utils/utils'
import useUploadTagList from '@/composables/config/useUploadTagList'
import useExportTagTable from '@/composables/config/useExportTagTable'
import useAddTag from '@/composables/config/useAddTag'
import useGroupCommon from '@/composables/config/useGroupCommon'
import { groupBy, cloneDeep } from 'lodash'

interface GroupDataInTable extends GroupData {
checked: boolean
}

export default () => {
export default (nodePluginInfo: PluginInfo) => {
const { t } = useI18n()
const route = useRoute()
const router = useRouter()
Expand All @@ -33,12 +32,9 @@ export default () => {
order: '',
})

// for upload tags
const { nodePluginInfo } = useAddTag()

// download | import | export
const { downloadTemplate, getTagsByGroups } = useGroupCommon()
const { readTagListFile, handleTagListInTableFile, batchAddTags } = useUploadTagList(nodePluginInfo.value)
const { readTagListFile, handleTagListInTableFile, batchAddTags } = useUploadTagList(nodePluginInfo)
const { isExporting, exportTable } = useExportTagTable()

const node = computed(() => route.params.node.toString())
Expand Down Expand Up @@ -149,10 +145,8 @@ export default () => {
await batchAddTags(requestList)
getGroupList()
} catch (error) {
// no upload empty content file
if (error) {
getGroupList()
}
// no upload empty content file || excel error
getGroupList()
}

return Promise.reject()
Expand Down
10 changes: 3 additions & 7 deletions src/composables/config/useTemplateGroupList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,28 @@ import { useRoute, useRouter } from 'vue-router'
import { EmqxMessage } from '@emqx/emqx-ui'
import { MessageBoxConfirm } from '@/utils/element'
import { queryGroupList, deleteGroup, addGroup, queryTagList, addTag } from '@/api/template'
import type { GroupData } from '@/types/config'
import type { GroupData, PluginInfo } from '@/types/config'
import { OmitArrayFields } from '@/utils/utils'
import useGroupCommon from '@/composables/config/useGroupCommon'
import useUploadTagList from '@/composables/config/useUploadTagList'
import useExportTagTable from '@/composables/config/useExportTagTable'
import useTemplateAddTag from '@/composables/config/useTemplateAddTag'
import { groupBy } from 'lodash'

interface GroupDataInTable extends GroupData {
checked: boolean
}

export default () => {
export default (pluginInfo: PluginInfo) => {
const { t } = useI18n()
const route = useRoute()
const router = useRouter()

const groupList: Ref<Array<GroupDataInTable>> = ref([])
const isListLoading = ref(false)

// for upload tags
const { pluginInfo } = useTemplateAddTag()

// download | import | export
const { downloadTemplate, getTagsByGroups } = useGroupCommon()
const { readTagListFile, handleTagListInTableFile, batchAddTags } = useUploadTagList(pluginInfo.value)
const { readTagListFile, handleTagListInTableFile, batchAddTags } = useUploadTagList(pluginInfo)
const { isExporting, exportTable } = useExportTagTable()

const template = computed(() => route.params.template.toString())
Expand Down
74 changes: 60 additions & 14 deletions src/composables/config/useUploadTagList.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import useTableFileReader from '@/composables/useTableFileReader'
import type { TagForm, TagData, PluginInfo } from '@/types/config'
import type { TagForm, TagData, PluginInfo, TagRegex } from '@/types/config'
import type { TagType } from '@/types/enums'
import { TagAttributeType } from '@/types/enums'
import { FILLER_IN_TAG_ATTR } from '@/utils/constants'
import { getErrorMsg, matchObjShape, popUpErrorMessage, dataType } from '@/utils/utils'
import { getErrorMsg, matchObjShape, popUpErrorMessage } from '@/utils/utils'
import { EmqxMessage } from '@emqx/emqx-ui'
import { useI18n } from 'vue-i18n'
import { useTagTypeSelect, useTagAttributeTypeSelect, createTagForm } from '@/composables/config/useAddTagCommon'
import useWriteDataCheckNParse from '@/composables/data/useWriteDataCheckNParse'

export default (pluginInfo: PluginInfo) => {
const { fileReader } = useTableFileReader()
const { createRawTagForm } = createTagForm()
const { t } = useI18n()

const { checkWriteData } = useWriteDataCheckNParse()

const { findValueByLabel: findTypeValueByLabel, findLabelByValue: findTypeLabelByValue } = useTagTypeSelect()
const { getTotalValueByStr: getAttrTotalValueByStr, isAttrsIncludeTheValue } = useTagAttributeTypeSelect()

Expand All @@ -29,9 +32,31 @@ export default (pluginInfo: PluginInfo) => {
}

// description, value fields are not required, void uploading failures due to not matching
const { id, description, value, precision, decimal, ...requiredData } = createRawTagForm()
const { name, attribute, type, address, value } = createRawTagForm()
const requireData = {
name,
attribute,
type,
address,
value,
}
let requireFields = {}

if (!data[0]?.attribute) {
EmqxMessage.warning(t('config.errorTableError'))
return false
}
const attr = getAttrTotalValueByStr(String(data[0].attribute), FILLER_IN_TAG_ATTR)
const isAttrIncludeStatic = attr ? checkAttrIncludeStatic(attr) : false
if (isAttrIncludeStatic) {
const { address: addr, ...restData } = requireData
requireFields = restData
} else {
const { value: val, ...restData } = requireData
requireFields = restData
}

if (!matchObjShape(data[0], requiredData)) {
if (!matchObjShape(data[0], requireFields)) {
EmqxMessage.warning(t('config.errorTableError'))
return false
}
Expand All @@ -40,12 +65,19 @@ export default (pluginInfo: PluginInfo) => {

const checkTagType = (type: TagType) => pluginInfo?.tag_type?.some((item) => item === type) || true

const getTagRegex = (type: TagType) => {
const tagRegex = pluginInfo?.tag_regex?.find((item: TagRegex) => item.type === type)
const regex = tagRegex?.regex ? new RegExp(tagRegex.regex) : undefined
return regex
}

// when a filed is added to tag(refer to the `createRawTagForm` in useAddTag.ts), sync here.
const handleTagListInTableFile = async (tagList: Array<Record<string, any>>): Promise<Array<TagForm>> => {
return new Promise((resolve, reject) => {
// eslint-disable-next-line no-async-promise-executor
return new Promise(async (resolve, reject) => {
let startIndex = 2
const ret = []
for (const {
for await (const {
group,
name,
address,
Expand Down Expand Up @@ -74,21 +106,35 @@ export default (pluginInfo: PluginInfo) => {
break
}

// when when `attribute` is includes `Static`, but `value` is empty
// TODO: 校验 value 与 type
if (checkAttrIncludeStatic(attr) && dataType(value) !== 'number') {
EmqxMessage.error(`${t('config.errorStaticWithValue', { rowNum: startIndex, name })}`)
const tagRegex = getTagRegex(type)
const isIncludeStaticAttr = checkAttrIncludeStatic(attr)

// vaild address: `attribute` isnot includes `Static`
if (!isIncludeStaticAttr && tagRegex && !tagRegex.test(address)) {
EmqxMessage.error(`${t('config.errorTableAddress', { rowNum: startIndex, name })}`)
reject()
break
}

// valid value: when when `attribute` is includes `Static`, but `value` is empty
if (checkAttrIncludeStatic(attr)) {
try {
const trueValue = String(value)
await checkWriteData(type, trueValue)
} catch (error) {
EmqxMessage.error(`${t('config.errorStaticWithValue', { rowNum: startIndex, name })}`)
reject()
break
}
}

let tagItem: TagData = {
group,
name: name.toString(),
address: address.toString(),
name: name?.toString() || '',
address: address?.toString() || '',
attribute: attr,
type,
description: description.toString(),
description: description?.toString() || '',
decimal,
precision,
}
Expand Down Expand Up @@ -130,7 +176,7 @@ export default (pluginInfo: PluginInfo) => {
resolve(true)
})
.catch((error: any) => {
const { data = {} } = error
const { data = {} } = error || {}
if (data.index !== undefined && data.error !== undefined) {
handlePartialSuc(data.index, data.error)
}
Expand Down
4 changes: 4 additions & 0 deletions src/i18n/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,10 @@ export default {
zh: '请下载模版,根据模版填充表格数据再尝试上传',
en: 'Please download the template, fill in the form data according to the template and try to upload',
},
errorTableAddress: {
zh: `表格第 {rowNum} 行的点位 {name} 的地址无效,请填入有效的地址后再尝试提交`,
en: `The address of tag {name} in row {rowNum} of the table. Please fill in valid address before attempting to submit`,
},
errorStaticWithValue: {
zh: `表格第 {rowNum} 行的点位 {name} 的属性包含 'Static',请填入有效的值后再尝试提交`,
en: `The attribute of tag {name} in row {rowNum} of the table contains 'Static'. Please fill in valid value before attempting to submit`,
Expand Down
6 changes: 5 additions & 1 deletion src/views/config/southDriver/Group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,13 @@ import AComWithDesc from '@/components/AComWithDesc.vue'
import useGroupList from '@/composables/config/useGroupList'
import type { GroupData, GroupForm } from '@/types/config'
import GroupDialog from './components/GroupDialog.vue'
import { useNodePluginInfo } from '@/composables/config/usePluginInfo'
const router = useRouter()
const { nodePluginInfo, getNodePluginInfo } = useNodePluginInfo()
await getNodePluginInfo()
const {
node,
groupList,
Expand All @@ -139,7 +143,7 @@ const {
importTagsByGroups,
ExportTagsByGroups,
goMonitoringPage,
} = useGroupList()
} = useGroupList(nodePluginInfo.value)
const showGroupDialog = ref(false)
const isEditGroup = ref(false)
Expand Down
6 changes: 5 additions & 1 deletion src/views/config/template/Group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ import AComWithDesc from '@/components/AComWithDesc.vue'
import GroupDialog from '@/views/config/components/GroupDialog.vue'
import useGroupList from '@/composables/config/useTemplateGroupList'
import useTemplateAddGroup from '@/composables/config/useTemplateGroupDialog'
import { useTemplatePluginInfo } from '@/composables/config/usePluginInfo'
const { templatePluginInfo, getTemplatePluginInfo } = useTemplatePluginInfo()
await getTemplatePluginInfo()
const {
template,
isListLoading,
Expand All @@ -129,7 +133,7 @@ const {
ExportTagsByGroups,
goTagPage,
} = useGroupList()
} = useGroupList(templatePluginInfo.value)
const { handleAddGroup, handleEditGroup, isEditGroup, groupDialogVisible, groupForm, isSubmitting, submitForm } =
useTemplateAddGroup()
Expand Down

0 comments on commit 44cb63d

Please sign in to comment.