Browse Source

fix: avoid marking updated on select (#8741)

* fix: avoid marking updated on select

* fix: handle null/undefined meta

* fix: use local meta for field details

* fix: avoid creating options on update

* fix: improve readability
pull/8749/head
Mert E 6 months ago committed by GitHub
parent
commit
da706f4252
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      packages/nc-gui/components/smartsheet/column/AttachmentOptions.vue
  2. 20
      packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue
  3. 10
      packages/nc-gui/components/smartsheet/column/CheckboxOptions.vue
  4. 7
      packages/nc-gui/components/smartsheet/column/CurrencyOptions.vue
  5. 9
      packages/nc-gui/components/smartsheet/column/DateOptions.vue
  6. 18
      packages/nc-gui/components/smartsheet/column/DateTimeOptions.vue
  7. 5
      packages/nc-gui/components/smartsheet/column/DecimalOptions.vue
  8. 6
      packages/nc-gui/components/smartsheet/column/DurationOptions.vue
  9. 2
      packages/nc-gui/components/smartsheet/column/LinkOptions.vue
  10. 4
      packages/nc-gui/components/smartsheet/column/NumberOptions.vue
  11. 6
      packages/nc-gui/components/smartsheet/column/PercentOptions.vue
  12. 36
      packages/nc-gui/components/smartsheet/column/RatingOptions.vue
  13. 4
      packages/nc-gui/components/smartsheet/column/TimeOptions.vue
  14. 7
      packages/nc-gui/components/smartsheet/column/UserOptions.vue
  15. 45
      packages/nc-gui/components/smartsheet/details/Fields.vue
  16. 2
      packages/nc-gui/composables/useViewGroupBy.ts
  17. 119
      packages/nc-gui/helpers/columnDefaultMeta.ts
  18. 2
      packages/nocodb/src/services/columns.service.ts

2
packages/nc-gui/components/smartsheet/column/AttachmentOptions.vue

@ -33,7 +33,7 @@ vModel.value.meta = {
// allow all mime types by default // allow all mime types by default
supportedAttachmentMimeTypes: ['*'], supportedAttachmentMimeTypes: ['*'],
}), }),
...vModel.value.meta, ...(vModel.value.meta || {}),
} }
const expandedKeys = ref<(string | number)[]>([]) const expandedKeys = ref<(string | number)[]>([])

20
packages/nc-gui/components/smartsheet/column/BarcodeOptions.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType, UITypes } from 'nocodb-sdk' import { type ColumnType, UITypes } from 'nocodb-sdk'
import { AllowedColumnTypesForQrAndBarcodes, isVirtualCol } from 'nocodb-sdk' import { AllowedColumnTypesForQrAndBarcodes, isVirtualCol } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
@ -29,25 +29,11 @@ const columnsAllowedAsBarcodeValue = computed<ColumnType[]>(() => {
) )
}) })
const supportedBarcodeFormats = [
{ value: 'CODE128', label: 'CODE128' },
{ value: 'upc', label: 'UPC' },
{ value: 'EAN13', label: 'EAN-13' },
{ value: 'EAN8', label: 'EAN-8' },
{ value: 'EAN5', label: 'EAN-5' },
{ value: 'EAN2', label: 'EAN-2' },
{ value: 'CODE39', label: 'CODE39' },
{ value: 'ITF14', label: 'ITF-14' },
{ value: 'MSI', label: 'MSI' },
{ value: 'PHARMACODE', label: 'PHARMACODE' },
{ value: 'CODABAR', label: 'CODABAR' },
]
onMounted(() => { onMounted(() => {
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
barcodeFormat: supportedBarcodeFormats[0].value, ...columnDefaultMeta[UITypes.Barcode],
...vModel.value.meta, ...(vModel.value.meta || {}),
} }
vModel.value.fk_barcode_value_column_id = vModel.value.fk_barcode_value_column_id =
(column?.value?.colOptions as Record<string, any>)?.fk_barcode_value_column_id || columnsAllowedAsBarcodeValue.value?.[0]?.id (column?.value?.colOptions as Record<string, any>)?.fk_barcode_value_column_id || columnsAllowedAsBarcodeValue.value?.[0]?.id

10
packages/nc-gui/components/smartsheet/column/CheckboxOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -50,12 +52,8 @@ const isOpenColorPicker = ref(false)
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
icon: { ...columnDefaultMeta[UITypes.Checkbox],
checked: 'mdi-check-bold', ...(vModel.value.meta || {}),
unchecked: 'mdi-crop-square',
},
color: '#777',
...vModel.value.meta,
} }
// antdv doesn't support object as value // antdv doesn't support object as value

7
packages/nc-gui/components/smartsheet/column/CurrencyOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
interface Option { interface Option {
label: string label: string
value: string value: string
@ -64,9 +66,8 @@ function filterOption(input: string, option: Option) {
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
currency_locale: 'en-US', ...columnDefaultMeta[UITypes.Currency],
currency_code: 'USD', ...(vModel.value.meta || {}),
...vModel.value.meta,
} }
currencyLocales().then((locales) => { currencyLocales().then((locales) => {

9
packages/nc-gui/components/smartsheet/column/DateOptions.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { dateFormats, dateMonthFormats } from 'nocodb-sdk' import { UITypes, dateFormats, dateMonthFormats } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
@ -9,9 +9,10 @@ const emit = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
if (!vModel.value.meta?.date_format) { // set default value
if (!vModel.value.meta) vModel.value.meta = {} vModel.value.meta = {
vModel.value.meta.date_format = dateFormats[0] ...columnDefaultMeta[UITypes.Date],
...(vModel.value.meta || {}),
} }
</script> </script>

18
packages/nc-gui/components/smartsheet/column/DateTimeOptions.vue

@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { dateFormats, timeFormats } from 'nocodb-sdk' import { UITypes, dateFormats, timeFormats } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
@ -9,18 +9,10 @@ const emit = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
if (!vModel.value.meta?.date_format) { // set default value
if (!vModel.value.meta) vModel.value.meta = {} vModel.value.meta = {
vModel.value.meta.date_format = dateFormats[0] ...columnDefaultMeta[UITypes.DateTime],
} ...(vModel.value.meta || {}),
if (!vModel.value.meta?.time_format) {
if (!vModel.value.meta) vModel.value.meta = {}
vModel.value.meta.time_format = timeFormats[0]
}
if (vModel.value.meta?.is12hrFormat === undefined) {
if (!vModel.value.meta) vModel.value.meta = {}
vModel.value.meta.is12hrFormat = false
} }
</script> </script>

5
packages/nc-gui/components/smartsheet/column/DecimalOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -24,8 +26,7 @@ const vModel = useVModel(props, 'value', emit)
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
precision: precisionFormats[0], ...columnDefaultMeta[UITypes.Decimal],
isLocaleString: false,
...(vModel.value.meta || {}), ...(vModel.value.meta || {}),
} }

6
packages/nc-gui/components/smartsheet/column/DurationOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -16,8 +18,8 @@ const durationOptionList =
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
duration: 0, ...columnDefaultMeta[UITypes.Duration],
...vModel.value.meta, ...(vModel.value.meta || {}),
} }
</script> </script>

2
packages/nc-gui/components/smartsheet/column/LinkOptions.vue

@ -44,7 +44,7 @@ setAdditionalValidations({
vModel.value.meta = { vModel.value.meta = {
singular: '', singular: '',
plural: '', plural: '',
...vModel.value.meta, ...(vModel.value.meta || {}),
} }
</script> </script>

4
packages/nc-gui/components/smartsheet/column/NumberOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -9,7 +11,7 @@ const vModel = useVModel(props, 'value', emit)
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
isLocaleString: false, ...columnDefaultMeta[UITypes.Number],
...(vModel.value.meta || {}), ...(vModel.value.meta || {}),
} }
</script> </script>

6
packages/nc-gui/components/smartsheet/column/PercentOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
isEdit?: boolean isEdit?: boolean
@ -18,8 +20,8 @@ setAdditionalValidations({
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
is_progress: false, ...columnDefaultMeta[UITypes.Percent],
...vModel.value.meta, ...(vModel.value.meta || {}),
} }
</script> </script>

36
packages/nc-gui/components/smartsheet/column/RatingOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -7,30 +9,6 @@ const emit = defineEmits(['update:value'])
const vModel = useVModel(props, 'value', emit) const vModel = useVModel(props, 'value', emit)
// cater existing v1 cases
const iconList = [
{
full: 'mdi-star',
empty: 'mdi-star-outline',
},
{
full: 'mdi-heart',
empty: 'mdi-heart-outline',
},
{
full: 'mdi-moon-full',
empty: 'mdi-moon-new',
},
{
full: 'mdi-thumb-up',
empty: 'mdi-thumb-up-outline',
},
{
full: 'mdi-flag',
empty: 'mdi-flag-outline',
},
]
const picked = computed({ const picked = computed({
get: () => vModel.value.meta.color, get: () => vModel.value.meta.color,
set: (val) => { set: (val) => {
@ -42,14 +20,8 @@ const isOpenColorPicker = ref(false)
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
iconIdx: 0, ...columnDefaultMeta[UITypes.Rating],
icon: { ...(vModel.value.meta || {}),
full: 'mdi-star',
empty: 'mdi-star-outline',
},
color: '#fcb401',
max: 5,
...vModel.value.meta,
} }
// antdv doesn't support object as value // antdv doesn't support object as value

4
packages/nc-gui/components/smartsheet/column/TimeOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
}>() }>()
@ -9,7 +11,7 @@ const vModel = useVModel(props, 'value', emit)
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
is12hrFormat: false, ...columnDefaultMeta[UITypes.Time],
...(vModel.value.meta ?? {}), ...(vModel.value.meta ?? {}),
} }
</script> </script>

7
packages/nc-gui/components/smartsheet/column/UserOptions.vue

@ -1,4 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { UITypes } from 'nocodb-sdk'
const props = defineProps<{ const props = defineProps<{
value: any value: any
isEdit: boolean isEdit: boolean
@ -22,9 +24,8 @@ setAdditionalValidations({
// set default value // set default value
vModel.value.meta = { vModel.value.meta = {
is_multi: false, ...columnDefaultMeta[UITypes.User],
notify: false, ...(vModel.value.meta || {}),
...vModel.value.meta,
} }
onMounted(() => { onMounted(() => {

45
packages/nc-gui/components/smartsheet/details/Fields.vue

@ -46,6 +46,8 @@ const isLocked = inject(IsLockedInj, ref(false))
const { openedViewsTab } = storeToRefs(useViewsStore()) const { openedViewsTab } = storeToRefs(useViewsStore())
const localMetaColumns = ref<ColumnType[] | undefined>([])
const moveOps = ref<moveOp[]>([]) const moveOps = ref<moveOp[]>([])
const visibilityOps = ref<fieldsVisibilityOps[]>([]) const visibilityOps = ref<fieldsVisibilityOps[]>([])
@ -99,7 +101,7 @@ const getFieldOrder = (field?: TableExplorerColumn) => {
const fields = computed<TableExplorerColumn[]>({ const fields = computed<TableExplorerColumn[]>({
get: () => { get: () => {
const x = ((meta.value?.columns as ColumnType[]) ?? []) const x = ((localMetaColumns.value as ColumnType[]) ?? [])
.filter((field) => !field.fk_column_id && !isSystemColumn(field)) .filter((field) => !field.fk_column_id && !isSystemColumn(field))
.concat(newFields.value) .concat(newFields.value)
.map((field) => updateDefaultColumnValues(field)) .map((field) => updateDefaultColumnValues(field))
@ -109,7 +111,7 @@ const fields = computed<TableExplorerColumn[]>({
return x return x
}, },
set: (val) => { set: (val) => {
meta.value!.columns = meta.value?.columns?.map((col) => { localMetaColumns.value = localMetaColumns.value?.map((col) => {
const field = val.find((f) => compareCols(f, col)) const field = val.find((f) => compareCols(f, col))
if (field) { if (field) {
return field return field
@ -217,15 +219,15 @@ const addField = (field?: TableExplorerColumn, before = false) => {
} }
const displayColumn = computed(() => { const displayColumn = computed(() => {
if (!meta.value?.columns) return if (!localMetaColumns.value) return
return meta.value?.columns.find((col) => col.pv) return localMetaColumns.value.find((col) => col.pv)
}) })
const duplicateField = async (field: TableExplorerColumn) => { const duplicateField = async (field: TableExplorerColumn) => {
if (!meta.value?.columns) return if (!localMetaColumns.value) return
// generate duplicate column name // generate duplicate column name
const duplicateColumnName = getUniqueColumnName(`${field.title}_copy`, meta.value?.columns) const duplicateColumnName = getUniqueColumnName(`${field.title}_copy`, localMetaColumns.value)
let fieldPayload = {} let fieldPayload = {}
@ -306,7 +308,12 @@ const onFieldUpdate = (state: TableExplorerColumn, skipLinkChecks = false) => {
} }
} }
const diffs = diff(col, state) as Partial<TableExplorerColumn> const pdiffs: Record<string, any> = diff(col, state)
// remove undefined values
const diffs = Object.fromEntries(
Object.entries(pdiffs).filter(([_, value]) => value !== undefined),
) as Partial<TableExplorerColumn>
if (Object.keys(diffs).length === 0 || (Object.keys(diffs).length === 1 && 'altered' in diffs)) { if (Object.keys(diffs).length === 0 || (Object.keys(diffs).length === 1 && 'altered' in diffs)) {
ops.value = ops.value.filter((op) => op.op === 'add' || !compareCols(op.column, state)) ops.value = ops.value.filter((op) => op.op === 'add' || !compareCols(op.column, state))
@ -604,6 +611,21 @@ const clearChanges = () => {
const isColumnsValid = computed(() => fields.value.every((f) => isColumnValid(f))) const isColumnsValid = computed(() => fields.value.every((f) => isColumnValid(f)))
const metaToLocal = () => {
localMetaColumns.value = meta.value?.columns?.map((c: ColumnType) => {
if (c.uidt && c.uidt in columnDefaultMeta) {
if (!c.meta) c.meta = {}
c.meta = {
...columnDefaultMeta[c.uidt],
...(c.meta || {}),
}
}
return {
...c,
}
})
}
const saveChanges = async () => { const saveChanges = async () => {
if (!isColumnsValid.value) { if (!isColumnsValid.value) {
message.error(t('msg.error.multiFieldSaveValidation')) message.error(t('msg.error.multiFieldSaveValidation'))
@ -692,6 +714,9 @@ const saveChanges = async () => {
} }
await getMeta(meta.value.id, true) await getMeta(meta.value.id, true)
metaToLocal()
columnsHash.value = (await $api.dbTableColumn.hash(meta.value?.id)).hash columnsHash.value = (await $api.dbTableColumn.hash(meta.value?.id)).hash
visibilityOps.value = [] visibilityOps.value = []
@ -841,6 +866,10 @@ onMounted(async () => {
if (meta.value && meta.value.id) { if (meta.value && meta.value.id) {
columnsHash.value = (await $api.dbTableColumn.hash(meta.value.id)).hash columnsHash.value = (await $api.dbTableColumn.hash(meta.value.id)).hash
} }
await until(() => meta.value?.columns)
metaToLocal()
}) })
const onFieldOptionUpdate = () => { const onFieldOptionUpdate = () => {
@ -874,7 +903,7 @@ watch(
const defaultColumnName = generateUniqueColumnName({ const defaultColumnName = generateUniqueColumnName({
formState: oldField, formState: oldField,
tableExplorerColumns: fields.value || [], tableExplorerColumns: fields.value || [],
metaColumns: meta.value?.columns || [], metaColumns: localMetaColumns.value || [],
newFieldTitles, newFieldTitles,
}) })

2
packages/nc-gui/composables/useViewGroupBy.ts

@ -532,6 +532,8 @@ const [useProvideViewGroupBy, useViewGroupBy] = useInjectionState(
(c) => c.id === (nextCol?.colOptions as LookupType).fk_relation_column_id, (c) => c.id === (nextCol?.colOptions as LookupType).fk_relation_column_id,
) )
if (!lookupRelation?.colOptions) break
const relatedTableMeta = await getMeta( const relatedTableMeta = await getMeta(
(lookupRelation?.colOptions as LinkToAnotherRecordType).fk_related_model_id as string, (lookupRelation?.colOptions as LinkToAnotherRecordType).fk_related_model_id as string,
) )

119
packages/nc-gui/helpers/columnDefaultMeta.ts

@ -0,0 +1,119 @@
import { UITypes, dateFormats, timeFormats } from 'nocodb-sdk'
export const precisionFormats = [1, 2, 3, 4, 5, 6, 7, 8]
export const iconList = [
{
full: 'mdi-star',
empty: 'mdi-star-outline',
},
{
full: 'mdi-heart',
empty: 'mdi-heart-outline',
},
{
full: 'mdi-moon-full',
empty: 'mdi-moon-new',
},
{
full: 'mdi-thumb-up',
empty: 'mdi-thumb-up-outline',
},
{
full: 'mdi-flag',
empty: 'mdi-flag-outline',
},
]
export const supportedBarcodeFormats = [
{ value: 'CODE128', label: 'CODE128' },
{ value: 'upc', label: 'UPC' },
{ value: 'EAN13', label: 'EAN-13' },
{ value: 'EAN8', label: 'EAN-8' },
{ value: 'EAN5', label: 'EAN-5' },
{ value: 'EAN2', label: 'EAN-2' },
{ value: 'CODE39', label: 'CODE39' },
{ value: 'ITF14', label: 'ITF-14' },
{ value: 'MSI', label: 'MSI' },
{ value: 'PHARMACODE', label: 'PHARMACODE' },
{ value: 'CODABAR', label: 'CODABAR' },
]
const barcodeDefaultMeta = {
barcodeFormat: supportedBarcodeFormats[0].value,
}
const checkboxDefaultMeta = {
iconIdx: 0,
icon: {
checked: 'mdi-check-bold',
unchecked: 'mdi-crop-square',
},
color: '#777',
}
const currencyDefaultMeta = {
currency_locale: 'en-US',
currency_code: 'USD',
}
const dateDefaultMeta = {
date_format: dateFormats[0],
}
const dateTimeDefaultMeta = {
date_format: dateFormats[0],
time_format: timeFormats[0],
is12hrFormat: false,
}
const decimalDefaultMeta = {
precision: precisionFormats[0],
isLocaleString: false,
}
const durationDefaultMeta = {
duration: 0,
}
const numberDefaultMeta = {
isLocaleString: false,
}
const percentDefaultMeta = {
is_progress: false,
}
const ratingDefaultMeta = {
iconIdx: 0,
icon: {
full: 'mdi-star',
empty: 'mdi-star-outline',
},
color: '#fcb401',
max: 5,
}
const timeDefaultMeta = {
is12hrFormat: false,
}
const userDefaultMeta = {
is_multi: false,
notify: false,
}
export const columnDefaultMeta = {
[UITypes.Checkbox]: checkboxDefaultMeta,
[UITypes.Currency]: currencyDefaultMeta,
[UITypes.Date]: dateDefaultMeta,
[UITypes.DateTime]: dateTimeDefaultMeta,
[UITypes.Decimal]: decimalDefaultMeta,
[UITypes.Duration]: durationDefaultMeta,
[UITypes.Number]: numberDefaultMeta,
[UITypes.Percent]: percentDefaultMeta,
[UITypes.Rating]: ratingDefaultMeta,
[UITypes.Time]: timeDefaultMeta,
[UITypes.User]: userDefaultMeta,
[UITypes.Barcode]: barcodeDefaultMeta,
}

2
packages/nocodb/src/services/columns.service.ts

@ -542,7 +542,7 @@ export class ColumnsService {
}, },
); );
if (data.length) { if (data.length && column.uidt !== colBody.uidt) {
const existingOptions = colBody.colOptions.options.map( const existingOptions = colBody.colOptions.options.map(
(el) => el.title, (el) => el.title,
); );

Loading…
Cancel
Save