Browse Source

Merge pull request #7376 from nocodb/nc-fix/multifield-editor-issues

Multifield editor bug fixes ( Sync EE to OSS )
pull/7394/head
Raju Udava 12 months ago committed by GitHub
parent
commit
977cceb271
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/nc-gui/components/smartsheet/VirtualCell.vue
  2. 147
      packages/nc-gui/components/smartsheet/details/Fields.vue
  3. 2
      packages/nc-gui/components/smartsheet/grid/GroupByLabel.vue
  4. 2
      packages/nc-gui/components/tabs/Smartsheet.vue
  5. 3
      packages/nc-gui/components/virtual-cell/components/ListChildItems.vue
  6. 2
      packages/nc-gui/components/virtual-cell/components/ListItems.vue
  7. 10
      packages/nc-gui/composables/useLTARStore.ts
  8. 26
      packages/nocodb/src/services/columns.service.ts

2
packages/nc-gui/components/smartsheet/VirtualCell.vue

@ -20,11 +20,11 @@ import {
isLink,
isLookup,
isMm,
isPrimary,
isQrCode,
isRollup,
provide,
toRef,
isPrimary,
} from '#imports'
import type { Row } from '#imports'

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

@ -100,6 +100,7 @@ const fields = computed<TableExplorerColumn[]>({
const x = ((meta.value?.columns as ColumnType[]) ?? [])
.filter((field) => !field.fk_column_id && !isSystemColumn(field))
.concat(newFields.value)
.map((field) => updateDefaultColumnValues(field))
.sort((a, b) => {
return getFieldOrder(a) - getFieldOrder(b)
})
@ -268,8 +269,30 @@ const duplicateField = async (field: TableExplorerColumn) => {
const onFieldUpdate = (state: TableExplorerColumn) => {
const col = fields.value.find((col) => compareCols(col, state))
if (!col) return
const diffs = diff(col, state)
if (Object.keys(diffs).length === 0 || (Object.keys(diffs).length === 1 && 'altered' in diffs)) {
// hack to prevent update status `Updated Field` when clicking on field first time
let isUpdated = true
if (
[UITypes.SingleSelect, UITypes.MultiSelect].includes(col.uidt) &&
Object.keys(diffs).length === 1 &&
diffs?.colOptions?.options &&
(diffs?.colOptions?.options?.length === 0 ||
(diffs?.colOptions?.options[0]?.index !== undefined && Object.keys(diffs?.colOptions?.options[0] || {}).length === 1))
) {
isUpdated = false
}
if (!isUpdated) {
let field = fields.value.find((field) => compareCols(field, state))
if (field) {
field = state
}
}
if (Object.keys(diffs).length === 0 || (Object.keys(diffs).length === 1 && 'altered' in diffs) || !isUpdated) {
ops.value = ops.value.filter((op) => op.op === 'add' || !compareCols(op.column, state))
} else {
const field = ops.value.find((op) => compareCols(op.column, state))
@ -291,7 +314,7 @@ const onFieldUpdate = (state: TableExplorerColumn) => {
return
}
if (field && !moveField) {
if (field || (field && moveField)) {
field.column = state
} else {
ops.value.push({
@ -376,6 +399,19 @@ const onMove = (_event: { moved: { newIndex: number; oldIndex: number } }) => {
return
}
const mop = moveOps.value.find((op) => compareCols(op.column, fields.value[_event.moved.oldIndex]))
if (mop) {
mop.index = _event.moved.newIndex
mop.order = order
} else {
moveOps.value.push({
op: 'move',
column: fields.value[_event.moved.oldIndex],
index: _event.moved.newIndex,
order,
})
}
if (op) {
onFieldUpdate({
...op.column,
@ -393,19 +429,6 @@ const onMove = (_event: { moved: { newIndex: number; oldIndex: number } }) => {
},
})
}
const mop = moveOps.value.find((op) => compareCols(op.column, fields.value[_event.moved.oldIndex]))
if (mop) {
mop.index = _event.moved.newIndex
mop.order = order
} else {
moveOps.value.push({
op: 'move',
column: fields.value[_event.moved.oldIndex],
index: _event.moved.newIndex,
order,
})
}
}
const isColumnValid = (column: TableExplorerColumn) => {
@ -438,6 +461,52 @@ const isColumnValid = (column: TableExplorerColumn) => {
return true
}
function updateDefaultColumnValues(column: TableExplorerColumn) {
if (column.uidt === UITypes.QrCode && column.colOptions?.fk_qr_value_column_id) {
if (!column?.fk_qr_value_column_id) {
column.fk_qr_value_column_id = column.colOptions.fk_qr_value_column_id
}
}
if (column.uidt === UITypes.Barcode && column.colOptions?.fk_barcode_value_column_id) {
if (!column?.fk_barcode_value_column_id) {
column.fk_barcode_value_column_id = column.colOptions.fk_barcode_value_column_id
}
}
if (column.uidt === UITypes.Lookup && column?.colOptions?.fk_lookup_column_id && column?.colOptions?.fk_relation_column_id) {
if (!column?.fk_lookup_column_id) {
column.fk_lookup_column_id = column.colOptions.fk_lookup_column_id
}
if (!column?.fk_relation_column_id) {
column.fk_relation_column_id = column.colOptions.fk_relation_column_id
}
}
if (
column.uidt === UITypes.Rollup &&
column?.colOptions?.fk_relation_column_id &&
column?.colOptions?.fk_rollup_column_id &&
column?.colOptions?.rollup_function
) {
if (!column?.fk_relation_column_id) {
column.fk_relation_column_id = column.colOptions.fk_relation_column_id
}
if (!column?.fk_rollup_column_id) {
column.fk_rollup_column_id = column.colOptions.fk_rollup_column_id
}
if (!column?.rollup_function) {
column.rollup_function = column.colOptions.rollup_function
}
}
if (column.uidt === UITypes.Formula && column.colOptions?.formula_raw && !column?.formula_raw) {
column.formula_raw = column.colOptions?.formula_raw
}
return column
}
const recoverField = (state: TableExplorerColumn) => {
const field = ops.value.find((op) => compareCols(op.column, state))
if (field) {
@ -512,10 +581,13 @@ const saveChanges = async () => {
view_id: view.value?.id as string,
}
}
}
for (const f of fields.value) {
console.log(f.title, getFieldOrder(f))
if (op && op.op === 'update') {
op.column.column_order = {
order: mop.order,
view_id: view.value?.id as string,
}
}
}
for (const op of ops.value) {
@ -545,7 +617,10 @@ const saveChanges = async () => {
await loadViewColumns()
if (res) {
ops.value = (res.failedOps as op[]) || []
ops.value =
res.failedOps && res.failedOps?.length
? (res.failedOps as (op & { error: unknown })[]).map(({ error: _, ...rest }) => rest)
: []
newFields.value = newFields.value.filter((col) => {
if (res.failedOps) {
const op = res.failedOps.find((fop) => {
@ -631,8 +706,14 @@ onKeyDown('ArrowUp', () => {
onKeyDown('Delete', () => {
if (isLocked.value) return
if (document.activeElement?.tagName === 'INPUT') return
if (document.activeElement?.tagName === 'TEXTAREA') return
if (
document.activeElement?.tagName === 'INPUT' ||
document.activeElement?.tagName === 'TEXTAREA' ||
// A rich text editor is a div with the contenteditable attribute set to true.
document.activeElement?.getAttribute('contenteditable')
) {
return
}
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
@ -643,8 +724,14 @@ onKeyDown('Delete', () => {
onKeyDown('Backspace', () => {
if (isLocked.value) return
if (document.activeElement?.tagName === 'INPUT') return
if (document.activeElement?.tagName === 'TEXTAREA') return
if (
document.activeElement?.tagName === 'INPUT' ||
document.activeElement?.tagName === 'TEXTAREA' ||
// A rich text editor is a div with the contenteditable attribute set to true.
document.activeElement?.getAttribute('contenteditable')
) {
return
}
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
@ -705,6 +792,16 @@ const onFieldOptionUpdate = () => {
isFieldIdCopied.value = false
}, 200)
}
watch(
fields,
() => {
if (activeField.value) {
activeField.value = fields.value.find((field) => field.id === activeField.value.id) || activeField.value
}
},
{ deep: true },
)
</script>
<template>
@ -771,7 +868,7 @@ const onFieldOptionUpdate = () => {
</div>
<div class="flex flex-row rounded-lg border-1 overflow-clip border-gray-200">
<div ref="fieldsListWrapperDomRef" class="nc-scrollbar-md !overflow-auto flex-1 flex-grow-1 nc-fields-height">
<Draggable v-model="fields" :disabled="isLocked" item-key="id" @change="onMove($event)">
<Draggable :model-value="fields" :disabled="isLocked" item-key="id" @change="onMove($event)">
<template #item="{ element: field }">
<div
v-if="field.title.toLowerCase().includes(searchQuery.toLowerCase()) && !field.pv"
@ -1080,7 +1177,7 @@ const onFieldOptionUpdate = () => {
</template>
</Draggable>
</div>
<Transition v-if="!changingField" name="slide-fade">
<Transition name="slide-fade">
<div v-if="!changingField" class="border-gray-200 border-l-1 nc-scrollbar-md nc-fields-height !overflow-y-auto">
<SmartsheetColumnEditOrAddProvider
v-if="activeField"

2
packages/nc-gui/components/smartsheet/grid/GroupByLabel.vue

@ -1,7 +1,7 @@
<script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk'
import { isVirtualCol } from 'nocodb-sdk'
import { ReadonlyInj, IsGroupByLabelInj } from '#imports'
import { IsGroupByLabelInj, ReadonlyInj } from '#imports'
defineProps<{
column: ColumnType

2
packages/nc-gui/components/tabs/Smartsheet.vue

@ -87,7 +87,7 @@ const onDrop = async (event: DragEvent) => {
event.preventDefault()
try {
// Access the dropped data
const data = JSON.parse(event.dataTransfer!.getData('text/json'))
const data = JSON.parse(event.dataTransfer!.getData('text/json') || '{}')
// Do something with the received data
// if dragged item is not from the same source, return

3
packages/nc-gui/components/virtual-cell/components/ListChildItems.vue

@ -55,10 +55,9 @@ const {
isChildrenListLinked,
isChildrenLoading,
relatedTableMeta,
row,
link,
meta,
headerDisplayValue
headerDisplayValue,
} = useLTARStoreOrThrow()
const { isNew, state, removeLTARRef, addLTARRef } = useSmartsheetRowStoreOrThrow()

2
packages/nc-gui/components/virtual-cell/components/ListItems.vue

@ -49,7 +49,7 @@ const {
meta,
unlink,
row,
headerDisplayValue
headerDisplayValue,
} = useLTARStoreOrThrow()
const { addLTARRef, isNew, removeLTARRef, state: rowState } = useSmartsheetRowStoreOrThrow()

10
packages/nc-gui/composables/useLTARStore.ts

@ -1,13 +1,13 @@
import {
UITypes,
type ColumnType,
type LinkToAnotherRecordType,
type PaginatedType,
type RequestParams,
type TableType,
UITypes,
dateFormats,
timeFormats,
parseStringDateTime,
timeFormats,
} from 'nocodb-sdk'
import type { ComputedRef, Ref } from 'vue'
import {
@ -19,6 +19,7 @@ import {
extractSdkResponseErrorMsg,
inject,
message,
parseProp,
reactive,
ref,
storeToRefs,
@ -30,7 +31,6 @@ import {
useRouter,
useSharedView,
watch,
parseProp,
} from '#imports'
import type { Row } from '#imports'
@ -145,7 +145,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
type: '',
format: '',
}
let currentColumn = relatedTableMeta.value?.columns?.find((c) => c.pv) || relatedTableMeta?.value?.columns?.[0]
const currentColumn = relatedTableMeta.value?.columns?.find((c) => c.pv) || relatedTableMeta?.value?.columns?.[0]
if (currentColumn) {
if (currentColumn?.uidt === UITypes.DateTime) {
@ -545,7 +545,7 @@ const [useProvideLTARStore, useLTARStore] = useInjectionState(
isChildrenExcludedLoading,
deleteRelatedRow,
getRelatedTableRowId,
headerDisplayValue
headerDisplayValue,
}
},
'ltar-store',

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

@ -52,6 +52,7 @@ import {
KanbanView,
Model,
Source,
View,
} from '~/models';
import Noco from '~/Noco';
import NcConnectionMgrv2 from '~/utils/common/NcConnectionMgrv2';
@ -195,7 +196,8 @@ export class ColumnsService {
formula?: string;
formula_raw?: string;
parsed_tree?: any;
};
} & Partial<Pick<ColumnReqType, 'column_order'>>;
if (
isCreatedOrLastModifiedTimeCol(column) ||
[
@ -274,7 +276,29 @@ export class ColumnsService {
meta: colBody.meta,
});
}
// handle reorder column for Links and LinkToAnotherRecord
if (
[UITypes.Links, UITypes.LinkToAnotherRecord].includes(
column.uidt,
) &&
colBody?.column_order &&
colBody.column_order?.order &&
colBody.column_order?.view_id
) {
const viewColumn = (
await View.getColumns(colBody.column_order.view_id)
).find((col) => col.fk_column_id === column.id);
await View.updateColumn(
colBody.column_order.view_id,
viewColumn.id,
{
order: colBody.column_order.order,
},
);
}
}
await this.updateRollupOrLookup(colBody, column);
} else {
NcError.notImplemented(

Loading…
Cancel
Save