From 44ef0dc485a83db73f020ce00fccf19e449a9c70 Mon Sep 17 00:00:00 2001 From: Anbarasu Date: Sat, 17 Aug 2024 19:07:22 +0530 Subject: [PATCH] feat: field, table and view descriptions (#9256) * feat: table description wip * fix: swagger update * fix: wip descriptions view * feat: field, view, table descriptions * fix: failing tests * fix: allow description edit for schema read-only sources * fix: add missing condition * fix: ux changes fix: duplicate service didn't copy descriptions * fix: long text default value update * fix: add new line for long text * fix: include labels for table and view description update * fix: workaround without breaking all tests * fix: update swagger types and tests fix * fix: source restriction tests * fix: pr review changes * fix: updated icons * fix: updated tooltip positions fix: minor corrections * fix: invalid description length * fix: update focus on tables * fix: add shared view descriptions * fix: title is missing --- .../nc-gui/assets/nc-icons/align-left.svg | 6 + packages/nc-gui/assets/nc-icons/calendar.svg | 11 + packages/nc-gui/assets/nc-icons/form.svg | 8 + packages/nc-gui/assets/nc-icons/gallery.svg | 5 + packages/nc-gui/assets/nc-icons/grid.svg | 6 + packages/nc-gui/assets/nc-icons/kanban.svg | 6 + .../dashboard/TreeView/TableNode.vue | 272 +++++++++++------- .../dashboard/TreeView/ViewsNode.vue | 18 ++ .../components/dashboard/TreeView/index.vue | 44 ++- .../nc-gui/components/dlg/TableCreate.vue | 108 +++++-- .../components/dlg/TableDescriptionUpdate.vue | 182 ++++++++++++ packages/nc-gui/components/dlg/ViewCreate.vue | 91 +++++- .../components/dlg/ViewDescriptionUpdate.vue | 170 +++++++++++ packages/nc-gui/components/nc/Button.vue | 2 +- packages/nc-gui/components/nc/Tooltip.vue | 73 +++-- .../smartsheet/column/DefaultValue.vue | 4 +- .../smartsheet/column/EditOrAdd.vue | 147 +++++++--- .../smartsheet/column/EditOrAddProvider.vue | 4 +- .../column/RichLongTextDefaultValue.vue | 4 +- .../components/smartsheet/header/Cell.vue | 24 +- .../components/smartsheet/header/Menu.vue | 123 ++++++-- .../smartsheet/header/VirtualCell.vue | 17 +- .../smartsheet/toolbar/OpenedViewAction.vue | 25 +- .../smartsheet/toolbar/ViewActionMenu.vue | 14 +- .../composables/useColumnCreateStore.ts | 1 + packages/nc-gui/composables/useTableNew.ts | 3 +- .../nc-gui/composables/useViewAggregate.ts | 2 + packages/nc-gui/context/index.ts | 2 + packages/nc-gui/lang/en.json | 6 + packages/nc-gui/layouts/shared-view.vue | 17 +- packages/nc-gui/lib/acl.ts | 1 + packages/nc-gui/utils/iconUtils.ts | 22 +- .../meta/migrations/XcMigrationSourcev2.ts | 4 + .../meta/migrations/v2/nc_060_descriptions.ts | 28 ++ packages/nocodb/src/models/Column.ts | 4 + packages/nocodb/src/models/Model.ts | 16 +- packages/nocodb/src/models/View.ts | 4 + .../jobs/jobs/export-import/export.service.ts | 3 + packages/nocodb/src/schema/swagger.json | 29 ++ .../nocodb/src/services/columns.service.ts | 31 +- .../nocodb/src/services/tables.service.ts | 6 +- .../tests/unit/rest/tests/typeCasts.test.ts | 10 +- .../db/general/sourceRestrictions.spec.ts | 4 +- 43 files changed, 1276 insertions(+), 281 deletions(-) create mode 100644 packages/nc-gui/assets/nc-icons/align-left.svg create mode 100644 packages/nc-gui/assets/nc-icons/calendar.svg create mode 100644 packages/nc-gui/assets/nc-icons/form.svg create mode 100644 packages/nc-gui/assets/nc-icons/gallery.svg create mode 100644 packages/nc-gui/assets/nc-icons/grid.svg create mode 100644 packages/nc-gui/assets/nc-icons/kanban.svg create mode 100644 packages/nc-gui/components/dlg/TableDescriptionUpdate.vue create mode 100644 packages/nc-gui/components/dlg/ViewDescriptionUpdate.vue create mode 100644 packages/nocodb/src/meta/migrations/v2/nc_060_descriptions.ts diff --git a/packages/nc-gui/assets/nc-icons/align-left.svg b/packages/nc-gui/assets/nc-icons/align-left.svg new file mode 100644 index 0000000000..93e9813fff --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/align-left.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/calendar.svg b/packages/nc-gui/assets/nc-icons/calendar.svg new file mode 100644 index 0000000000..7e3a4df73a --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/calendar.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/form.svg b/packages/nc-gui/assets/nc-icons/form.svg new file mode 100644 index 0000000000..2e2c8d8c36 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/form.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/gallery.svg b/packages/nc-gui/assets/nc-icons/gallery.svg new file mode 100644 index 0000000000..8ff51296a7 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/gallery.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/nc-gui/assets/nc-icons/grid.svg b/packages/nc-gui/assets/nc-icons/grid.svg new file mode 100644 index 0000000000..95a842664e --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/grid.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/nc-gui/assets/nc-icons/kanban.svg b/packages/nc-gui/assets/nc-icons/kanban.svg new file mode 100644 index 0000000000..aae9418923 --- /dev/null +++ b/packages/nc-gui/assets/nc-icons/kanban.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages/nc-gui/components/dashboard/TreeView/TableNode.vue b/packages/nc-gui/components/dashboard/TreeView/TableNode.vue index 653d7d72b7..bff3ac0dd3 100644 --- a/packages/nc-gui/components/dashboard/TreeView/TableNode.vue +++ b/packages/nc-gui/components/dashboard/TreeView/TableNode.vue @@ -45,7 +45,12 @@ const { copy } = useCopy() const baseRole = inject(ProjectRoleInj) provide(SidebarTableInj, table) -const { setMenuContext, openRenameTableDialog: _openRenameTableDialog, duplicateTable: _duplicateTable } = inject(TreeViewInj)! +const { + setMenuContext, + openRenameTableDialog: _openRenameTableDialog, + openTableDescriptionDialog: _openTableDescriptionDialog, + duplicateTable: _duplicateTable, +} = inject(TreeViewInj)! const { loadViews: _loadViews, navigateToView } = useViewsStore() const { activeView, activeViewTitleOrId, viewsByTable } = storeToRefs(useViewsStore()) @@ -204,6 +209,11 @@ const openRenameTableDialog = (table: SidebarTableNode, sourceId: string) => { _openRenameTableDialog(table, !!sourceId) } +const openTableDescriptionDialog = (table: SidebarTableNode) => { + isOptionsOpen.value = false + _openTableDescriptionDialog(table) +} + const deleteTable = () => { isOptionsOpen.value = false isTableDeleteDialogVisible.value = true @@ -343,124 +353,164 @@ const source = computed(() => { {{ table.title }} - - - - - - - + + + + + + + + { } .nc-tree-item svg { - @apply text-primary text-opacity-60; + &:not(.nc-info-icon) { + @apply text-primary text-opacity-60; + } } diff --git a/packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue b/packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue index bcd6fda025..5dc062272d 100644 --- a/packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue +++ b/packages/nc-gui/components/dashboard/TreeView/ViewsNode.vue @@ -63,6 +63,8 @@ const isDefaultBase = computed(() => { return _isDefaultBase(source) }) +const { openViewDescriptionDialog: _openViewDescriptionDialog } = inject(TreeViewInj)! + const input = ref() const isDropdownOpen = ref(false) @@ -193,6 +195,12 @@ async function onRename() { onStopEdit() } +const openViewDescriptionDialog = (view: ViewType) => { + isDropdownOpen.value = false + + _openViewDescriptionDialog(view) +} + /** Cancel renaming view */ function onCancel() { if (!isEditing.value) return @@ -281,6 +289,15 @@ watch(isDropdownOpen, async () => { diff --git a/packages/nc-gui/components/dashboard/TreeView/index.vue b/packages/nc-gui/components/dashboard/TreeView/index.vue index 3d760f98c2..fc22eeb885 100644 --- a/packages/nc-gui/components/dashboard/TreeView/index.vue +++ b/packages/nc-gui/components/dashboard/TreeView/index.vue @@ -1,6 +1,6 @@ + + + + diff --git a/packages/nc-gui/components/dlg/ViewCreate.vue b/packages/nc-gui/components/dlg/ViewCreate.vue index 4a1886031e..87581a44b6 100644 --- a/packages/nc-gui/components/dlg/ViewCreate.vue +++ b/packages/nc-gui/components/dlg/ViewCreate.vue @@ -23,6 +23,7 @@ interface Props { selectedViewId?: string groupingFieldColumnId?: string geoDataFieldColumnId?: string + description?: string tableId: string calendarRange?: Array<{ fk_from_column_id: string @@ -40,6 +41,7 @@ interface Emits { interface Form { title: string type: ViewTypes + description?: string copy_from_id: string | null // for kanban view only fk_grp_col_id: string | null @@ -103,6 +105,7 @@ const form = reactive
({ fk_geo_data_col_id: null, calendar_range: props.calendarRange || [], fk_cover_image_col_id: null, + description: props.description || '', }) const viewSelectFieldOptions = ref([]) @@ -243,14 +246,35 @@ const addCalendarRange = async () => { } */ +const enableDescription = ref(false) + +const removeDescription = () => { + form.description = '' + enableDescription.value = false +} + +const toggleDescription = () => { + if (enableDescription.value) { + enableDescription.value = false + } else { + enableDescription.value = true + setTimeout(() => { + inputEl.value?.focus() + }, 100) + } +} + const isMetaLoading = ref(false) onMounted(async () => { + if (form.copy_from_id) { + enableDescription.value = true + } + if ([ViewTypes.GALLERY, ViewTypes.KANBAN, ViewTypes.MAP, ViewTypes.CALENDAR].includes(props.type)) { isMetaLoading.value = true try { meta.value = (await getMeta(tableId.value))! - if (props.type === ViewTypes.MAP) { viewSelectFieldOptions.value = meta .value!.columns!.filter((el) => el.uidt === UITypes.GeoData) @@ -708,28 +732,65 @@ onMounted(async () => { -
- - {{ $t('general.cancel') }} - + +
+ + {{ $t('labels.description') }} + - - {{ $t('labels.createView') }} - + + + +
+ + +
+ +
+ +
+ + + + {{ $t('labels.addDescription') }} + +
+
+
+ + {{ $t('general.cancel') }} + + + + {{ $t('labels.createView') }} + + +
diff --git a/packages/nc-gui/components/nc/Button.vue b/packages/nc-gui/components/nc/Button.vue index 9c191ad2cf..f07efc6ef8 100644 --- a/packages/nc-gui/components/nc/Button.vue +++ b/packages/nc-gui/components/nc/Button.vue @@ -97,7 +97,7 @@ useEventListener(NcButton, 'mousedown', () => { 'justify-center': props.centered, 'justify-start': !props.centered, }" - class="flex flex-row gap-x-2.5 w-full" + class="flex flex-row gap-x-2.5 nc-btn-inner w-full" > + +
+ + {{ $t('labels.description') }} + + + + + +
+ + +
+ @@ -635,6 +713,11 @@ const isFullUpdateAllowed = computed(() => {