From eaeb3b57b70affee99dfeea0b886042ebdd95cfd Mon Sep 17 00:00:00 2001 From: Ramesh Mane <101566080+rameshmane7218@users.noreply.github.com> Date: Sat, 9 Mar 2024 11:51:10 +0000 Subject: [PATCH] feat(nc-gui): add prefill support for rating, url, checkbox, year, data & dateTime fields --- .../composables/useSharedFormViewStore.ts | 225 ++++++++++++------ 1 file changed, 156 insertions(+), 69 deletions(-) diff --git a/packages/nc-gui/composables/useSharedFormViewStore.ts b/packages/nc-gui/composables/useSharedFormViewStore.ts index 87fea962cf..cd23ad7e06 100644 --- a/packages/nc-gui/composables/useSharedFormViewStore.ts +++ b/packages/nc-gui/composables/useSharedFormViewStore.ts @@ -1,5 +1,6 @@ import useVuelidate from '@vuelidate/core' import { helpers, minLength, required } from '@vuelidate/validators' +import dayjs from 'dayjs' import type { Ref } from 'vue' import type { BoolType, @@ -11,7 +12,16 @@ import type { StringOrNullType, TableType, } from 'nocodb-sdk' -import { ErrorMessages, RelationTypes, UITypes, isLinksOrLTAR, isSystemColumn, isVirtualCol } from 'nocodb-sdk' +import { + ErrorMessages, + RelationTypes, + UITypes, + getDateFormat, + getDateTimeFormat, + isLinksOrLTAR, + isSystemColumn, + isVirtualCol, +} from 'nocodb-sdk' import { isString } from '@vue/shared' import { filterNullOrUndefinedObjectProperties } from '~/helpers/parsers/parserHelpers' import { @@ -258,9 +268,17 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share if (Object.keys(route.query).length && sharedViewMeta.value.preFilledMode !== PreFilledMode.Disabled) { console.log('router', route.query) columns.value = columns.value?.map((c) => { - if (!c.title || !route.query?.[c.title] || isSystemColumn(c) || (isVirtualCol(c) && !isLinksOrLTAR(c)) || isAttachment(c)) + if ( + !c.title || + !route.query?.[c.title] || + isSystemColumn(c) || + (isVirtualCol(c) && !isLinksOrLTAR(c)) || + isAttachment(c) + ) { return c + } + // Update column switch (sharedViewMeta.value.preFilledMode) { case PreFilledMode.Hidden: { c.show = false @@ -272,77 +290,15 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share } } - switch (c.uidt) { - case UITypes.SingleSelect: - case UITypes.MultiSelect: - case UITypes.User: { - const limitOptions = (parseProp(c.meta).limitOptions || []).reduce((ac, op) => { - if (op?.id) { - ac[op.id] = op - } - return ac - }, {}) - - const queryOptions = (route.query?.[c.title] as string)?.split(',') - - let options: string[] = [] - - if ([UITypes.SingleSelect, UITypes.MultiSelect].includes(c.uidt as UITypes)) { - options = ((c.colOptions as SelectOptionsType)?.options || []) - .filter((op) => { - if ( - op?.id && - op?.title && - queryOptions.includes(op.title) && - (limitOptions[op.id] ? limitOptions[op.id]?.show : !(parseProp(c.meta).limitOptions || []).length) - ) { - return true - } - return false - }) - .map((op) => op.title as string) - - if (options.length) { - formState.value[c.title] = c.uidt === UITypes.SingleSelect ? options[0] : options.join(',') - } - } else { - options = (meta.value?.base_id ? basesUser.value.get(meta.value.base_id) || [] : []) - .filter((user) => { - if ( - user?.id && - user?.email && - queryOptions.includes(user.email) && - (limitOptions[user.id] ? limitOptions[user.id]?.show : !(parseProp(c.meta).limitOptions || []).length) - ) { - return true - } - return false - }) - .map((user) => user.email) - - if (options.length) { - formState.value[c.title] = !parseProp(c.meta)?.is_multi ? options[0] : options.join(',') - } - } - break - } - default: { - if (isNumericFieldType(c, getColAbstractType(c))) { - if (!isNaN(parseInt(route.query?.[c.title] as string))) { - formState.value[c.title] = parseInt(route.query?.[c.title] as string) - } - } else { - formState.value[c.title] = route.query?.[c.title] - } - } + // Prefill form state + const preFillValue = getPreFillValue(c, (route.query?.[c.title] as string).trim()) + if (preFillValue !== undefined) { + formState.value[c.title] = preFillValue } - console.log('c', c) - - console.log('form state', formState.value) return c }) - + console.log('form state', formState.value) console.log('column', columns.value) } } @@ -351,6 +307,137 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share return (c?.source_id ? sqlUis.value[c?.source_id] : Object.values(sqlUis.value)[0]).getAbstractType(c) } + function getPreFillValue(c: ColumnType, value: string) { + let preFillValue: any = '' + switch (c.uidt) { + case UITypes.SingleSelect: + case UITypes.MultiSelect: + case UITypes.User: { + const limitOptions = (parseProp(c.meta).limitOptions || []).reduce((ac, op) => { + if (op?.id) { + ac[op.id] = op + } + return ac + }, {}) + + const queryOptions = value.split(',') + + let options: string[] = [] + + if ([UITypes.SingleSelect, UITypes.MultiSelect].includes(c.uidt as UITypes)) { + options = ((c.colOptions as SelectOptionsType)?.options || []) + .filter((op) => { + if ( + op?.id && + op?.title && + queryOptions.includes(op.title) && + (limitOptions[op.id] ? limitOptions[op.id]?.show : !(parseProp(c.meta).limitOptions || []).length) + ) { + return true + } + return false + }) + .map((op) => op.title as string) + + if (options.length) { + preFillValue = c.uidt === UITypes.SingleSelect ? options[0] : options.join(',') + } + } else { + options = (meta.value?.base_id ? basesUser.value.get(meta.value.base_id) || [] : []) + .filter((user) => { + if ( + user?.id && + user?.email && + queryOptions.includes(user.email) && + (limitOptions[user.id] ? limitOptions[user.id]?.show : !(parseProp(c.meta).limitOptions || []).length) + ) { + return true + } + return false + }) + .map((user) => user.email) + + if (options.length) { + preFillValue = !parseProp(c.meta)?.is_multi ? options[0] : options.join(',') + } + } + break + } + case UITypes.Checkbox: { + if (['true', '1'].includes(value.toLowerCase())) { + preFillValue = true + } else if (['false', '0'].includes(value.toLowerCase())) { + preFillValue = false + } + break + } + case UITypes.Rating: { + if (!isNaN(Number(value))) { + preFillValue = Number(value) > parseProp(c.meta).max ? parseProp(c.meta).max : Number(preFillValue) + } + break + } + case UITypes.URL: { + if (parseProp(c.meta).validate) { + if (isValidURL(value)) { + preFillValue = value + } + } else { + preFillValue = value + } + break + } + case UITypes.Year: { + if (/^\d+$/.test(preFillValue)) { + preFillValue = Number(value) + } + break + } + case UITypes.Date: + case UITypes.DateTime: { + let parsedDateOrDateTime = dayjs(value, getDateTimeFormat(value)) + + if (!parsedDateOrDateTime.isValid()) { + parsedDateOrDateTime = dayjs(value, getDateFormat(value)) + } + + if (parsedDateOrDateTime.isValid()) { + preFillValue = + c.uidt === UITypes.Date + ? parsedDateOrDateTime.format('YYYY-MM-DD') + : parsedDateOrDateTime.utc().format('YYYY-MM-DD HH:mm:ssZ') + } + break + } + case UITypes.Time: { + let parsedTime = dayjs(value) + + if (!parsedTime.isValid()) { + parsedTime = dayjs(value, 'HH:mm:ss') + } + if (!parsedTime.isValid()) { + parsedTime = dayjs(`1999-01-01 ${value}`) + } + if (parsedTime.isValid()) { + preFillValue = parsedTime.format(baseStore.isMysql(c.source_id) ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ') + } + } + case UITypes.LinkToAnotherRecord: { + break + } + default: { + if (isNumericFieldType(c, getColAbstractType(c))) { + if (!isNaN(Number(value))) { + preFillValue = Number(value) + } + } else { + preFillValue = value + } + } + } + return preFillValue + } + /** reset form if show_blank_form is true */ watch(submitted, (nextVal) => { if (nextVal && sharedFormView.value?.show_blank_form) {