From 0f5bb23d43a8a67f34fca52252d76f00b9d1ed88 Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 10 Aug 2022 18:50:50 +0300 Subject: [PATCH 1/8] fix: use column_name instead of title for queries Signed-off-by: mertmit --- .../nocodb/src/lib/meta/api/columnApis.ts | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index cc441c0cb4..c76406a04b 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -748,13 +748,13 @@ export async function columnUpdate(req: Request, res: Response) { // MultiSelect to SingleSelect if (column.uidt === UITypes.MultiSelect && colBody.uidt === UITypes.SingleSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { - await dbDriver.raw(`UPDATE ?? SET ?? = SUBSTRING_INDEX(??, ',', 1) WHERE ?? LIKE '%,%';`, [table.table_name, column.title, column.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = SUBSTRING_INDEX(??, ',', 1) WHERE ?? LIKE '%,%';`, [table.table_name, column.column_name, column.column_name, column.column_name]); } else if (driverType === 'pg') { - await dbDriver.raw(`UPDATE ?? SET ?? = split_part(??, ',', 1);`, [table.table_name, column.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = split_part(??, ',', 1);`, [table.table_name, column.column_name, column.column_name]); } else if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = LEFT(cast(?? as varchar(max)), CHARINDEX(',', ??) - 1) WHERE CHARINDEX(',', ??) > 0;`, [table.table_name, column.title, column.title, column.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = LEFT(cast(?? as varchar(max)), CHARINDEX(',', ??) - 1) WHERE CHARINDEX(',', ??) > 0;`, [table.table_name, column.column_name, column.column_name, column.column_name, column.column_name]); } else if (driverType === 'sqlite3') { - await dbDriver.raw(`UPDATE ?? SET ?? = substr(??, 1, instr(??, ',') - 1) WHERE ?? LIKE '%,%';`, [table.table_name, column.title, column.title, column.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = substr(??, 1, instr(??, ',') - 1) WHERE ?? LIKE '%,%';`, [table.table_name, column.column_name, column.column_name, column.column_name, column.column_name]); } } @@ -811,19 +811,19 @@ export async function columnUpdate(req: Request, res: Response) { } if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [table.table_name, column.title, column.title, option.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = NULL WHERE ?? LIKE ?`, [table.table_name, column.column_name, column.column_name, option.title]); } else { - await baseModel.bulkUpdateAll({ where: `(${column.title},eq,${option.title})` }, { [column.title]: null }); + await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: null }); } } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ',')) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.title, column.title, option.title, option.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), ',')) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, option.title, column.column_name]); } else if (driverType === 'pg') { - await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_remove(string_to_array(??, ','), ?), ',')`, [table.table_name, column.title, column.title, option.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_remove(string_to_array(??, ','), ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title]); } else if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), ','), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), ',')) - 2)`, [table.table_name, column.title, column.title, option.title, column.title, option.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), ','), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), ',')) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, column.column_name, option.title]); } else if (driverType === 'sqlite3') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ','), ',')`, [table.table_name, column.title, column.title, option.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title]); } } } @@ -909,19 +909,19 @@ export async function columnUpdate(req: Request, res: Response) { if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.title, newOp.title, column.title, option.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.column_name, newOp.title, column.column_name, option.title]); } else { - await baseModel.bulkUpdateAll({ where: `(${column.title},eq,${option.title})` }, { [column.title]: newOp.title }); + await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${option.title})` }, { [column.column_name]: newOp.title }); } } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.title, column.title, option.title, newOp.title, option.title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, option.title, column.column_name]); } else if (driverType === 'pg') { - await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.title, column.title, option.title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]); } else if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.title, column.title, option.title, newOp.title, column.title, option.title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title, column.column_name, option.title, newOp.title]); } else if (driverType === 'sqlite3') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.title, column.title, option.title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.column_name, column.column_name, option.title, newOp.title]); } } } @@ -930,19 +930,19 @@ export async function columnUpdate(req: Request, res: Response) { let newOp = ch.def_option; if (column.uidt === UITypes.SingleSelect) { if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.title, newOp.title, column.title, ch.temp_title]); + await dbDriver.raw(`UPDATE ?? SET ?? = ? WHERE ?? LIKE ?`, [table.table_name, column.column_name, newOp.title, column.column_name, ch.temp_title]); } else { - await baseModel.bulkUpdateAll({ where: `(${column.title},eq,${ch.temp_title})` }, { [column.title]: newOp.title }); + await baseModel.bulkUpdateAll({ where: `(${column.column_name},eq,${ch.temp_title})` }, { [column.column_name]: newOp.title }); } } else if (column.uidt === UITypes.MultiSelect) { if (driverType === 'mysql' || driverType === 'mysql2') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.title, column.title, ch.temp_title, newOp.title, ch.temp_title, column.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(BOTH ',' FROM REPLACE(CONCAT(',', ??, ','), CONCAT(',', ?, ','), CONCAT(',', ?, ','))) WHERE FIND_IN_SET(?, ??)`, [table.table_name, column.column_name, column.column_name, ch.temp_title, newOp.title, ch.temp_title, column.column_name]); } else if (driverType === 'pg') { - await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.title, column.title, ch.temp_title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = array_to_string(array_replace(string_to_array(??, ','), ?, ?), ',')`, [table.table_name, column.column_name, column.column_name, ch.temp_title, newOp.title]); } else if (driverType === 'mssql') { - await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.title, column.title, ch.temp_title, newOp.title, column.title, ch.temp_title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = substring(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ',')), 2, len(replace(concat(',', ??, ','), concat(',', ?, ','), concat(',', ?, ','))) - 2)`, [table.table_name, column.column_name, column.column_name, ch.temp_title, newOp.title, column.column_name, ch.temp_title, newOp.title]); } else if (driverType === 'sqlite3') { - await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.title, column.title, ch.temp_title, newOp.title]); + await dbDriver.raw(`UPDATE ?? SET ?? = TRIM(REPLACE(',' || ?? || ',', ',' || ? || ',', ',' || ? || ','), ',')`, [table.table_name, column.column_name, column.column_name, ch.temp_title, newOp.title]); } } } From ca50f7d3964ff7c0ff61696c3d256272c86d993d Mon Sep 17 00:00:00 2001 From: mertmit Date: Fri, 12 Aug 2022 11:28:21 +0300 Subject: [PATCH 2/8] fix: add missing default value handler for select types Signed-off-by: mertmit --- .../nocodb/src/lib/meta/api/columnApis.ts | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/packages/nocodb/src/lib/meta/api/columnApis.ts b/packages/nocodb/src/lib/meta/api/columnApis.ts index c76406a04b..82cd920b63 100644 --- a/packages/nocodb/src/lib/meta/api/columnApis.ts +++ b/packages/nocodb/src/lib/meta/api/columnApis.ts @@ -764,16 +764,21 @@ export async function columnUpdate(req: Request, res: Response) { } // Handle default values + const optionTitles = colBody.colOptions.options.map(el => el.title); if (colBody.cdf) { - - if (driverType === 'mysql' || driverType === 'mysql2') { - - } else if (driverType === 'pg') { - - } else if (driverType === 'mssql') { - - } else if (driverType === 'sqlite3') { - + if (colBody.uidt === UITypes.SingleSelect) { + if (!optionTitles.includes(colBody.cdf)) { + NcError.badRequest(`Default value '${colBody.cdf}' is not a select option.`); + } + } else { + for (const cdf of colBody.cdf.split(',')) { + if (!optionTitles.includes(cdf)) { + NcError.badRequest(`Default value '${cdf}' is not a select option.`); + } + } + } + if (driverType === 'pg') { + colBody.cdf = `'${colBody.cdf}'`; } } From fbec61ebbfda9db5dc40797d9760998594a3163f Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 10 Aug 2022 19:02:57 +0300 Subject: [PATCH 3/8] fix(gui-v2): empty select option Signed-off-by: mertmit --- packages/nc-gui-v2/components/cell/MultiSelect.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui-v2/components/cell/MultiSelect.vue b/packages/nc-gui-v2/components/cell/MultiSelect.vue index b8d7f78dc2..512ba97d9d 100644 --- a/packages/nc-gui-v2/components/cell/MultiSelect.vue +++ b/packages/nc-gui-v2/components/cell/MultiSelect.vue @@ -38,7 +38,7 @@ const options = computed(() => { }) const vModel = computed({ - get: () => selectedIds.value.map((el) => options.value.find((op: SelectOptionType) => op.id === el).title), + get: () => selectedIds.value.map((el) => options.value.find((op: SelectOptionType) => op.id === el)?.title), set: (val) => emit('update:modelValue', val.length === 0 ? null : val.join(',')), }) From 139820e0168a661cc89e265251da8c56291f20c2 Mon Sep 17 00:00:00 2001 From: mertmit Date: Wed, 10 Aug 2022 20:21:59 +0300 Subject: [PATCH 4/8] fix(gui-v2): add missing value prop Signed-off-by: mertmit --- packages/nc-gui-v2/components/cell/SingleSelect.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nc-gui-v2/components/cell/SingleSelect.vue b/packages/nc-gui-v2/components/cell/SingleSelect.vue index 598b1f584e..a40870bdd4 100644 --- a/packages/nc-gui-v2/components/cell/SingleSelect.vue +++ b/packages/nc-gui-v2/components/cell/SingleSelect.vue @@ -76,7 +76,7 @@ watch(isOpen, (n, _o) => { @keydown="handleKeys" @click="isOpen = !isOpen" > - + {{ op.title }} From 15b42939a1175f11bbfb0f97443b185a78fb9800 Mon Sep 17 00:00:00 2001 From: mertmit Date: Thu, 11 Aug 2022 20:16:26 +0300 Subject: [PATCH 5/8] feat(gui-v2): hide arrow if selected from single select Signed-off-by: mertmit --- packages/nc-gui-v2/components/cell/SingleSelect.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nc-gui-v2/components/cell/SingleSelect.vue b/packages/nc-gui-v2/components/cell/SingleSelect.vue index a40870bdd4..6439b061f0 100644 --- a/packages/nc-gui-v2/components/cell/SingleSelect.vue +++ b/packages/nc-gui-v2/components/cell/SingleSelect.vue @@ -72,6 +72,7 @@ watch(isOpen, (n, _o) => { placeholder="Select an option" :bordered="false" :open="isOpen" + :show-arrow="active || vModel === null" @select="isOpen = false" @keydown="handleKeys" @click="isOpen = !isOpen" From b17dfdaeaa1fc86e4a6c601ca13c4f9d9136fa6a Mon Sep 17 00:00:00 2001 From: mertmit Date: Thu, 11 Aug 2022 21:04:18 +0300 Subject: [PATCH 6/8] fix(gui-v2): modelValue prop type warning Signed-off-by: mertmit --- packages/nc-gui-v2/components/cell/MultiSelect.vue | 2 +- packages/nc-gui-v2/components/cell/SingleSelect.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nc-gui-v2/components/cell/MultiSelect.vue b/packages/nc-gui-v2/components/cell/MultiSelect.vue index 512ba97d9d..1941137130 100644 --- a/packages/nc-gui-v2/components/cell/MultiSelect.vue +++ b/packages/nc-gui-v2/components/cell/MultiSelect.vue @@ -6,7 +6,7 @@ import { ActiveCellInj, ColumnInj } from '~/context' import MdiCloseCircle from '~icons/mdi/close-circle' interface Props { - modelValue: string | string[] | undefined + modelValue?: string | string[] } const { modelValue } = defineProps() diff --git a/packages/nc-gui-v2/components/cell/SingleSelect.vue b/packages/nc-gui-v2/components/cell/SingleSelect.vue index 6439b061f0..0df8af6b1e 100644 --- a/packages/nc-gui-v2/components/cell/SingleSelect.vue +++ b/packages/nc-gui-v2/components/cell/SingleSelect.vue @@ -5,7 +5,7 @@ import { computed, inject } from '#imports' import { ActiveCellInj, ColumnInj } from '~/context' interface Props { - modelValue: string | undefined + modelValue?: string } const { modelValue } = defineProps() From ab1fcde39ae528ecface5143e515436c452dbb24 Mon Sep 17 00:00:00 2001 From: mertmit Date: Fri, 12 Aug 2022 13:37:45 +0300 Subject: [PATCH 7/8] fix(gui-v2): multiselect cell overflow Signed-off-by: mertmit --- packages/nc-gui-v2/components/cell/MultiSelect.vue | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/nc-gui-v2/components/cell/MultiSelect.vue b/packages/nc-gui-v2/components/cell/MultiSelect.vue index 1941137130..d1f93c5a2d 100644 --- a/packages/nc-gui-v2/components/cell/MultiSelect.vue +++ b/packages/nc-gui-v2/components/cell/MultiSelect.vue @@ -130,7 +130,7 @@ watch(isOpen, (n, _o) => { :close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })" @close="onClose" > - {{ val }} + {{ val }} @@ -169,6 +169,10 @@ watch(isOpen, (n, _o) => { :deep(.ant-tag-close-icon) { @apply "text-slate-500"; } + +:deep(.ant-select-selection-overflow-item) { + @apply "flex overflow-hidden"; +}