From d2a28ee27a565a6e14440992e40521bf3a6e1a9c Mon Sep 17 00:00:00 2001 From: mertmit Date: Sat, 1 Oct 2022 14:32:05 +0300 Subject: [PATCH] fix: select options default value Signed-off-by: mertmit --- .../smartsheet/column/SelectOptions.vue | 68 +++++++++++++------ .../nocodb/src/lib/meta/api/columnApis.ts | 24 +++++-- 2 files changed, 68 insertions(+), 24 deletions(-) diff --git a/packages/nc-gui/components/smartsheet/column/SelectOptions.vue b/packages/nc-gui/components/smartsheet/column/SelectOptions.vue index 1a523d3511..ac71de7b2f 100644 --- a/packages/nc-gui/components/smartsheet/column/SelectOptions.vue +++ b/packages/nc-gui/components/smartsheet/column/SelectOptions.vue @@ -11,7 +11,7 @@ const emit = defineEmits(['update:value']) const vModel = useVModel(props, 'value', emit) -const { isPg } = useProject() +const { isPg, isMysql } = useProject() const { setAdditionalValidations, validateInfos } = useColumnCreateStoreOrThrow() @@ -19,6 +19,7 @@ let options = $ref([]) const colorMenus = $ref({}) const colors = $ref(enumColor.light) const inputs = ref() +const defaultOption = ref() const validators = { 'colOptions.options': [ @@ -47,6 +48,49 @@ setAdditionalValidations({ ...validators, }) +onMounted(() => { + if (!vModel.value.colOptions?.options) { + vModel.value.colOptions = { + options: [], + } + } + options = vModel.value.colOptions.options + // Support for older options + for (const op of options.filter((el) => el.order === null)) { + op.title = op.title.replace(/^'/, '').replace(/'$/, '') + } + + if (vModel.value.cdf) { + // Postgres returns default value wrapped with single quotes & casted with type so we have to get value between single quotes to keep it unified for all databases + if (isPg.value) { + vModel.value.cdf = vModel.value.cdf.substring(vModel.value.cdf.indexOf(`'`) + 1, vModel.value.cdf.lastIndexOf(`'`)) + } + + // Mysql escapes single quotes with backslash so we keep quotes but others have to unescaped + if (!isMysql.value) { + vModel.value.cdf = vModel.value.cdf.replace(/''/g, "'") + } + } + + const fndDefaultOption = options.find((el) => el.title === vModel.value.cdf) + if (fndDefaultOption) { + defaultOption.value = fndDefaultOption + } +}) + +const optionChanged = (changedId: string) => { + if (changedId === defaultOption.value?.id) { + vModel.value.cdf = defaultOption.value.title + } +} + +const optionDropped = (changedId: string) => { + if (changedId === defaultOption.value?.id) { + vModel.value.cdf = null + defaultOption.value = null + } +} + const getNextColor = () => { let tempColor = colors[0] if (options.length && options[options.length - 1].color) { @@ -65,27 +109,11 @@ const addNewOption = () => { } const removeOption = (index: number) => { + const optionId = options[index]?.id options.splice(index, 1) + optionDropped(optionId) } -onMounted(() => { - if (!vModel.value.colOptions?.options) { - vModel.value.colOptions = { - options: [], - } - } - options = vModel.value.colOptions.options - // Support for older options - for (const op of options.filter((el) => el.order === null)) { - op.title = op.title.replace(/^'/, '').replace(/'$/, '') - } - - // Postgres returns default value wrapped with single quotes & casted with type so we have to get value between single quotes to keep it unified for all databases - if (isPg.value && vModel.value.cdf) { - vModel.value.cdf = vModel.value.cdf.substring(vModel.value.cdf.indexOf(`'`) + 1, vModel.value.cdf.lastIndexOf(`'`)) - } -}) - // focus last created input watch(inputs, () => { if (inputs.value?.$el) { @@ -116,7 +144,7 @@ watch(inputs, () => { - + diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index 705a810d14..386eb02c5f 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -524,20 +524,28 @@ export async function columnAdd(req: Request, res: Response) { // Handle default values if (colBody.cdf) { if (colBody.uidt === UITypes.SingleSelect) { - if (!optionTitles.includes(colBody.cdf)) { + if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) { NcError.badRequest( `Default value '${colBody.cdf}' is not a select option.` ); } } else { for (const cdf of colBody.cdf.split(',')) { - if (!optionTitles.includes(cdf)) { + if (!optionTitles.includes(cdf.replace(/'/g, "''"))) { NcError.badRequest( `Default value '${cdf}' is not a select option.` ); } } } + + // handle single quote for default value + if (driverType === 'mysql' || driverType === 'mysql2') { + colBody.cdf = colBody.cdf.replace(/'/g, "\'"); + } else { + colBody.cdf = colBody.cdf.replace(/'/g, "''"); + } + if (driverType === 'pg') { colBody.cdf = `'${colBody.cdf}'`; } @@ -812,20 +820,28 @@ export async function columnUpdate(req: Request, res: Response) { ); if (colBody.cdf) { if (colBody.uidt === UITypes.SingleSelect) { - if (!optionTitles.includes(colBody.cdf)) { + if (!optionTitles.includes(colBody.cdf.replace(/'/g, "''"))) { NcError.badRequest( `Default value '${colBody.cdf}' is not a select option.` ); } } else { for (const cdf of colBody.cdf.split(',')) { - if (!optionTitles.includes(cdf)) { + if (!optionTitles.includes(cdf.replace(/'/g, "''"))) { NcError.badRequest( `Default value '${cdf}' is not a select option.` ); } } } + + // handle single quote for default value + if (driverType === 'mysql' || driverType === 'mysql2') { + colBody.cdf = colBody.cdf.replace(/'/g, "\'"); + } else { + colBody.cdf = colBody.cdf.replace(/'/g, "''"); + } + if (driverType === 'pg') { colBody.cdf = `'${colBody.cdf}'`; }