Browse Source

Merge pull request #6820 from nocodb/nc-feat/fields-follow

Nc feat/fields follow
pull/6761/head
Raju Udava 1 year ago committed by GitHub
parent
commit
df5490ab38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue
  2. 2
      packages/nc-gui/components/smartsheet/column/EditOrAdd.vue
  3. 13
      packages/nc-gui/components/smartsheet/column/SelectOptions.vue
  4. 95
      packages/nc-gui/components/smartsheet/details/Fields.vue
  5. 7
      packages/nc-gui/composables/useTableNew.ts
  6. 21
      tests/playwright/tests/db/general/multiFieldEditor.spec.ts

1
packages/nc-gui/components/dashboard/TreeView/CreateViewBtn.vue

@ -83,6 +83,7 @@ async function onOpenModal({
view, view,
tableId: table.value.id!, tableId: table.value.id!,
baseId: base.value.id!, baseId: base.value.id!,
doNotSwitchTab: true,
}) })
$e('a:view:create', { view: view.type }) $e('a:view:create', { view: view.type })

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

@ -230,7 +230,7 @@ if (props.fromTableExplorer) {
<input <input
ref="antInput" ref="antInput"
v-model="formState.title" v-model="formState.title"
class="flex flex-grow text-lg font-bold outline-none bg-inherit" class="flex flex-grow nc-fields-input text-lg font-bold outline-none bg-inherit"
:contenteditable="true" :contenteditable="true"
/> />
</div> </div>

13
packages/nc-gui/components/smartsheet/column/SelectOptions.vue

@ -120,12 +120,6 @@ onMounted(() => {
} }
}) })
const optionChanged = (changedId: string) => {
if (changedId && changedId === defaultOption.value?.id) {
vModel.value.cdf = defaultOption.value.title
}
}
const getNextColor = () => { const getNextColor = () => {
let tempColor = colors.value[0] let tempColor = colors.value[0]
if (options.value.length && options.value[options.value.length - 1].color) { if (options.value.length && options.value[options.value.length - 1].color) {
@ -191,6 +185,13 @@ const removeRenderedOption = (index: number) => {
} }
} }
const optionChanged = (changedId: string) => {
if (changedId && changedId === defaultOption.value?.id) {
vModel.value.cdf = defaultOption.value.title
}
syncOptions()
}
const undoRemoveRenderedOption = (index: number) => { const undoRemoveRenderedOption = (index: number) => {
renderedOptions.value[index].status = undefined renderedOptions.value[index].status = undefined
syncOptions() syncOptions()

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

@ -3,6 +3,7 @@ import { diff } from 'deep-object-diff'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { UITypes, isSystemColumn } from 'nocodb-sdk' import { UITypes, isSystemColumn } from 'nocodb-sdk'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
import { onKeyDown, useMagicKeys } from '@vueuse/core'
import type { ColumnType, SelectOptionsType } from 'nocodb-sdk' import type { ColumnType, SelectOptionsType } from 'nocodb-sdk'
import { Icon } from '@iconify/vue' import { Icon } from '@iconify/vue'
import { type Field, getUniqueColumnName, ref, useSmartsheetStoreOrThrow } from '#imports' import { type Field, getUniqueColumnName, ref, useSmartsheetStoreOrThrow } from '#imports'
@ -39,6 +40,8 @@ const { getMeta } = useMetas()
const { meta, view } = useSmartsheetStoreOrThrow() const { meta, view } = useSmartsheetStoreOrThrow()
const { openedViewsTab } = storeToRefs(useViewsStore())
const moveOps = ref<moveOp[]>([]) const moveOps = ref<moveOp[]>([])
const visibilityOps = ref<fieldsVisibilityOps[]>([]) const visibilityOps = ref<fieldsVisibilityOps[]>([])
@ -481,7 +484,15 @@ const clearChanges = () => {
changeField() changeField()
} }
const isColumnsValid = computed(() => fields.value.every((f) => isColumnValid(f)))
const saveChanges = async () => { const saveChanges = async () => {
if (!isColumnsValid.value) {
message.error('Please complete the configuration of all fields before saving')
return
} else if (!loading.value && ops.value.length < 1 && moveOps.value.length < 1 && visibilityOps.value.length < 1) {
return
}
try { try {
if (!meta.value?.id) return if (!meta.value?.id) return
@ -569,7 +580,78 @@ const toggleVisibility = async (checked: boolean, field: Field) => {
}) })
} }
const isColumnsValid = computed(() => fields.value.every((f) => isColumnValid(f))) useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey
if (cmdOrCtrl) {
switch (e.key.toLowerCase()) {
case 's':
if (openedViewsTab.value !== 'field') return
e.preventDefault()
break
}
}
})
onKeyDown('ArrowDown', () => {
const index = fields.value.findIndex((f) => compareCols(f, activeField.value))
if (index === -1) changeField(fields.value[0])
else if (index === fields.value.length - 1) changeField(fields.value[0])
else changeField(fields.value[index + 1])
})
onKeyDown('ArrowUp', () => {
const index = fields.value.findIndex((f) => compareCols(f, activeField.value))
if (index === -1) changeField(fields.value[0])
else if (index === 0) changeField(fields.value[fields.value.length - 1])
else changeField(fields.value[index - 1])
})
onKeyDown('Delete', () => {
if (document.activeElement?.tagName === 'INPUT') return
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
onFieldDelete(activeField.value)
}
})
onKeyDown('Backspace', () => {
if (document.activeElement?.tagName === 'INPUT') return
const isDeletedField = fieldStatus(activeField.value) === 'delete'
if (!isDeletedField && activeField.value) {
onFieldDelete(activeField.value)
}
})
onKeyDown('ArrowRight', () => {
if (document.activeElement?.tagName === 'INPUT') return
if (activeField.value) {
const input = document.querySelector('.nc-fields-input')
if (input) {
input.focus()
}
}
})
const keys = useMagicKeys()
whenever(keys.altleft_c, () => {
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') addField()
})
whenever(keys.option_c, () => {
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') addField()
})
whenever(keys.meta_s, () => {
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') saveChanges()
})
whenever(keys.ctrl_s, () => {
if (!meta.value?.id) return
if (openedViewsTab.value === 'field') saveChanges()
})
onMounted(async () => { onMounted(async () => {
if (!meta.value?.id) return if (!meta.value?.id) return
@ -647,7 +729,7 @@ onMounted(async () => {
visibilityOps.find((op) => op.column.fk_column_id === field.id)?.visible ?? viewFieldsMap[field.id].show visibilityOps.find((op) => op.column.fk_column_id === field.id)?.visible ?? viewFieldsMap[field.id].show
" "
@change=" @change="
(event) => { (event: any) => {
toggleVisibility(event.target.checked, viewFieldsMap[field.id]) toggleVisibility(event.target.checked, viewFieldsMap[field.id])
} }
" "
@ -730,7 +812,7 @@ onMounted(async () => {
<a-menu-divider class="my-1" /> <a-menu-divider class="my-1" />
<NcMenuItem key="table-explorer-delete" @click="onFieldDelete(field)"> <NcMenuItem key="table-explorer-delete" class="!hover:bg-red-50" @click="onFieldDelete(field)">
<div class="text-red-500"> <div class="text-red-500">
<GeneralIcon icon="delete" class="group-hover:text-accent" /> <GeneralIcon icon="delete" class="group-hover:text-accent" />
Delete Delete
@ -748,7 +830,12 @@ onMounted(async () => {
</div> </div>
</div> </div>
</template> </template>
<template v-if="displayColumn && displayColumn.title.toLowerCase().includes(searchQuery.toLowerCase())" #header> <template
v-if="
displayColumn && displayColumn.title && displayColumn.title.toLowerCase().includes(searchQuery.toLowerCase())
"
#header
>
<div <div
class="flex px-2 bg-white hover:bg-gray-100 border-b-1 border-gray-200 first:rounded-tl-lg last:border-b-1 pl-5 group" class="flex px-2 bg-white hover:bg-gray-100 border-b-1 border-gray-200 first:rounded-tl-lg last:border-b-1 pl-5 group"
:class="` ${compareCols(displayColumn, activeField) ? 'selected' : ''}`" :class="` ${compareCols(displayColumn, activeField) ? 'selected' : ''}`"

7
packages/nc-gui/composables/useTableNew.ts

@ -49,6 +49,8 @@ export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => v
const { loadTables, baseUrl, isXcdbBase } = useBase() const { loadTables, baseUrl, isXcdbBase } = useBase()
const { loadViews } = useViewsStore()
const { openedViewsTab, viewsByTable } = storeToRefs(useViewsStore()) const { openedViewsTab, viewsByTable } = storeToRefs(useViewsStore())
const workspaceId = computed(() => route.value.params.typeOrId as string) const workspaceId = computed(() => route.value.params.typeOrId as string)
@ -80,10 +82,11 @@ export function useTableNew(param: { onTableCreate?: (tableMeta: TableType) => v
baseIdOrBaseId = route.value.params.baseId as string baseIdOrBaseId = route.value.params.baseId as string
} }
const views = viewsByTable.value.get(table.id as string) ?? [] await getMeta(table.id as string, (route.value.params?.viewId as string) !== table.id)
getMeta(table.id as string, (route.value.params?.viewId as string) !== table.id) await loadViews({ tableId: table.id as string })
const views = viewsByTable.value.get(table.id as string) ?? []
if (openedViewsTab.value !== 'view' && views.length && views[0].id) { if (openedViewsTab.value !== 'view' && views.length && views[0].id) {
await navigateTo({ await navigateTo({
path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}/${views[0].id}/${openedViewsTab.value}`, path: `/${workspaceIdOrType}/${baseIdOrBaseId}/${table?.id}/${views[0].id}/${openedViewsTab.value}`,

21
tests/playwright/tests/db/general/multiFieldEditor.spec.ts

@ -0,0 +1,21 @@
import test from '@playwright/test';
import { DashboardPage } from '../../../pages/Dashboard';
import { GridPage } from '../../../pages/Dashboard/Grid';
import setup from '../../../setup';
test.describe('MultiFieldEditor', () => {
let grid: GridPage, dashboard: DashboardPage;
let context: any;
test.beforeEach(async ({ page }) => {
context = await setup({ page, isEmptyProject: true });
dashboard = new DashboardPage(page, context.base);
grid = dashboard.grid;
await dashboard.treeView.createTable({ title: 'sheet1', baseTitle: context.base.title });
});
test.skip('Hide Columns', async () => {
//
});
});
Loading…
Cancel
Save