Browse Source

Merge pull request #5767 from nocodb/fix/5766-shared-grid-gallery-missing-lookup-meta

fix: include lookup related metas in shared view meta api
pull/5774/head
Raju Udava 2 years ago committed by GitHub
parent
commit
a3e00761da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      packages/nc-gui/components/smartsheet/Gallery.vue
  2. 2
      packages/nc-gui/components/smartsheet/header/Cell.vue
  3. 5
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  4. 5
      packages/nc-gui/components/virtual-cell/HasMany.vue
  5. 3
      packages/nc-gui/components/virtual-cell/Lookup.vue
  6. 5
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  7. 3
      packages/nc-gui/composables/useApi/interceptors.ts
  8. 1
      packages/nc-gui/context/index.ts
  9. 83
      packages/nocodb/src/services/public-metas.service.ts

8
packages/nc-gui/components/smartsheet/Gallery.vue

@ -7,6 +7,7 @@ import {
IsFormInj, IsFormInj,
IsGalleryInj, IsGalleryInj,
IsGridInj, IsGridInj,
IsPublicInj,
MetaInj, MetaInj,
NavigateDir, NavigateDir,
OpenNewRecordFormHookInj, OpenNewRecordFormHookInj,
@ -62,6 +63,8 @@ provide(IsGridInj, ref(false))
provide(PaginationDataInj, paginationData) provide(PaginationDataInj, paginationData)
provide(ChangePageInj, changePage) provide(ChangePageInj, changePage)
const isPublic = inject(IsPublicInj, ref(false))
const fields = inject(FieldsInj, ref([])) const fields = inject(FieldsInj, ref([]))
const route = useRoute() const route = useRoute()
@ -125,6 +128,10 @@ const attachments = (record: any): Attachment[] => {
} }
const expandForm = (row: RowType, state?: Record<string, any>) => { const expandForm = (row: RowType, state?: Record<string, any>) => {
if (isPublic.value) {
return
}
const rowId = extractPkFromRow(row.row, meta.value!.columns!) const rowId = extractPkFromRow(row.row, meta.value!.columns!)
if (rowId) { if (rowId) {
@ -234,6 +241,7 @@ watch(view, async (nextView) => {
:data-testid="`nc-gallery-card-${record.row.id}`" :data-testid="`nc-gallery-card-${record.row.id}`"
@click="expandFormClick($event, record)" @click="expandFormClick($event, record)"
@contextmenu="showContextMenu($event, { row: rowIndex })" @contextmenu="showContextMenu($event, { row: rowIndex })"
:style="isPublic ? { cursor: 'default' } : { cursor: 'pointer' }"
> >
<template v-if="galleryData?.fk_cover_image_col_id" #cover> <template v-if="galleryData?.fk_cover_image_col_id" #cover>
<a-carousel v-if="!reloadAttachments && attachments(record).length" autoplay class="gallery-carousel" arrows> <a-carousel v-if="!reloadAttachments && attachments(record).length" autoplay class="gallery-carousel" arrows>

2
packages/nc-gui/components/smartsheet/header/Cell.vue

@ -52,7 +52,7 @@ const openHeaderMenu = () => {
<span <span
v-if="column" v-if="column"
class="name" class="name"
:class="{ 'cursor-pointer': !isForm && isUIAllowed('edit-column') }" :class="{ 'cursor-pointer': !isForm && isUIAllowed('edit-column') && !hideMenu }"
style="white-space: nowrap" style="white-space: nowrap"
:title="column.title" :title="column.title"
@dblclick="openHeaderMenu" @dblclick="openHeaderMenu"

5
packages/nc-gui/components/virtual-cell/BelongsTo.vue

@ -7,6 +7,7 @@ import {
ColumnInj, ColumnInj,
IsFormInj, IsFormInj,
IsLockedInj, IsLockedInj,
IsUnderLookupInj,
ReadonlyInj, ReadonlyInj,
ReloadRowDataHookInj, ReloadRowDataHookInj,
RowInj, RowInj,
@ -36,6 +37,8 @@ const isForm = inject(IsFormInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false)) const isLocked = inject(IsLockedInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
@ -89,7 +92,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
</div> </div>
<div <div
v-if="!readOnly && !isLocked && (isUIAllowed('xcDatatableEditable') || isForm)" v-if="!readOnly && !isLocked && (isUIAllowed('xcDatatableEditable') || isForm) && !isUnderLookup"
class="flex justify-end gap-1 min-h-[30px] items-center" class="flex justify-end gap-1 min-h-[30px] items-center"
> >
<GeneralIcon <GeneralIcon

5
packages/nc-gui/components/virtual-cell/HasMany.vue

@ -16,6 +16,7 @@ import {
useSelectedCellKeyupListener, useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow, useSmartsheetRowStoreOrThrow,
useUIPermission, useUIPermission,
IsUnderLookupInj
} from '#imports' } from '#imports'
const column = inject(ColumnInj)! const column = inject(ColumnInj)!
@ -32,6 +33,8 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj) const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
@ -112,7 +115,7 @@ useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEven
</template> </template>
</div> </div>
<div v-if="!isLocked" class="flex justify-end gap-1 min-h-[30px] items-center"> <div v-if="!isLocked && !isUnderLookup" class="flex justify-end gap-1 min-h-[30px] items-center">
<GeneralIcon <GeneralIcon
icon="expand" icon="expand"
class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand" class="select-none transform text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand"

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

@ -5,6 +5,7 @@ import {
CellUrlDisableOverlayInj, CellUrlDisableOverlayInj,
CellValueInj, CellValueInj,
ColumnInj, ColumnInj,
IsUnderLookupInj,
MetaInj, MetaInj,
computed, computed,
inject, inject,
@ -70,6 +71,8 @@ const arrValue = computed(() => {
provide(MetaInj, lookupTableMeta) provide(MetaInj, lookupTableMeta)
provide(IsUnderLookupInj, ref(true))
provide(CellUrlDisableOverlayInj, ref(true)) provide(CellUrlDisableOverlayInj, ref(true))
const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activateShowEditNonEditableFieldWarning } = const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activateShowEditNonEditableFieldWarning } =

5
packages/nc-gui/components/virtual-cell/ManyToMany.vue

@ -7,6 +7,7 @@ import {
ColumnInj, ColumnInj,
IsFormInj, IsFormInj,
IsLockedInj, IsLockedInj,
IsUnderLookupInj,
ReadonlyInj, ReadonlyInj,
ReloadRowDataHookInj, ReloadRowDataHookInj,
RowInj, RowInj,
@ -34,6 +35,8 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj) const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false) const listItemsDlg = ref(false)
const childListDlg = ref(false) const childListDlg = ref(false)
@ -114,7 +117,7 @@ useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEven
</template> </template>
</div> </div>
<div v-if="!isLocked" class="flex justify-end gap-1 min-h-[30px] items-center"> <div v-if="!isLocked && !isUnderLookup" class="flex justify-end gap-1 min-h-[30px] items-center">
<GeneralIcon <GeneralIcon
icon="expand" icon="expand"
class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand" class="text-sm nc-action-icon text-gray-500/50 hover:text-gray-500 nc-arrow-expand"

3
packages/nc-gui/composables/useApi/interceptors.ts

@ -67,9 +67,8 @@ export function addAxiosInterceptors(api: Api<any>) {
}) })
.catch(async (error) => { .catch(async (error) => {
await state.signOut() await state.signOut()
// todo: handle new user
navigateTo('/signIn') if (!route.meta.public) navigateTo('/signIn')
return Promise.reject(error) return Promise.reject(error)
}) })

1
packages/nc-gui/context/index.ts

@ -38,3 +38,4 @@ export const ToggleDialogInj: InjectionKey<Function> = Symbol('toggle-dialog-inj
export const CellClickHookInj: InjectionKey<EventHook<MouseEvent> | undefined> = Symbol('cell-click-injection') export const CellClickHookInj: InjectionKey<EventHook<MouseEvent> | undefined> = Symbol('cell-click-injection')
export const SaveRowInj: InjectionKey<(() => void) | undefined> = Symbol('save-row-injection') export const SaveRowInj: InjectionKey<(() => void) | undefined> = Symbol('save-row-injection')
export const CurrentCellInj: InjectionKey<Ref<Element | undefined>> = Symbol('current-cell-injection') export const CurrentCellInj: InjectionKey<Ref<Element | undefined>> = Symbol('current-cell-injection')
export const IsUnderLookupInj: InjectionKey<Ref<boolean>> = Symbol('is-under-lookup-injection')

83
packages/nocodb/src/services/public-metas.service.ts

@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
import { ErrorMessages, RelationTypes, UITypes } from 'nocodb-sdk'; import { ErrorMessages, RelationTypes, UITypes } from 'nocodb-sdk';
import { NcError } from '../helpers/catchError'; import { NcError } from '../helpers/catchError';
import { Base, Column, Model, Project, View } from '../models'; import { Base, Column, Model, Project, View } from '../models';
import type { LinkToAnotherRecordColumn } from '../models'; import type { LinkToAnotherRecordColumn, LookupColumn } from '../models';
import type { LinkToAnotherRecordType } from 'nocodb-sdk'; import type { LinkToAnotherRecordType } from 'nocodb-sdk';
@Injectable() @Injectable()
@ -63,23 +63,88 @@ export class PublicMetasService {
// load related table metas // load related table metas
for (const col of view.model.columns) { for (const col of view.model.columns) {
await this.extractRelatedMetas({ col, relatedMetas });
}
view.relatedMetas = relatedMetas;
return view;
}
private async extractRelatedMetas({
col,
relatedMetas = {},
}: {
col: Column<any>;
relatedMetas: Record<string, Model>;
}) {
if (UITypes.LinkToAnotherRecord === col.uidt) { if (UITypes.LinkToAnotherRecord === col.uidt) {
const colOpt = await col.getColOptions<LinkToAnotherRecordType>(); await this.extractLTARRelatedMetas({
relatedMetas[colOpt.fk_related_model_id] = await Model.getWithInfo({ ltarColOption: await col.getColOptions<LinkToAnotherRecordColumn>(),
id: colOpt.fk_related_model_id, relatedMetas,
}); });
if (colOpt.type === 'mm') { } else if (UITypes.Lookup === col.uidt) {
relatedMetas[colOpt.fk_mm_model_id] = await Model.getWithInfo({ await this.extractLookupRelatedMetas({
id: colOpt.fk_mm_model_id, lookupColOption: await col.getColOptions<LookupColumn>(),
relatedMetas,
}); });
} }
} }
private async extractLTARRelatedMetas({
ltarColOption,
relatedMetas = {},
}: {
ltarColOption: LinkToAnotherRecordColumn;
relatedMetas: { [key: string]: Model };
}) {
relatedMetas[ltarColOption.fk_related_model_id] = await Model.getWithInfo({
id: ltarColOption.fk_related_model_id,
});
if (ltarColOption.type === 'mm') {
relatedMetas[ltarColOption.fk_mm_model_id] = await Model.getWithInfo({
id: ltarColOption.fk_mm_model_id,
});
}
} }
view.relatedMetas = relatedMetas; private async extractLookupRelatedMetas({
lookupColOption,
relatedMetas = {},
}: {
lookupColOption: LookupColumn;
relatedMetas: { [key: string]: Model };
}) {
const relationCol = await Column.get({
colId: lookupColOption.fk_relation_column_id,
});
const lookedUpCol = await Column.get({
colId: lookupColOption.fk_lookup_column_id,
});
return view; // extract meta for table which belongs the relation column
// if not already extracted
if (!relatedMetas[relationCol.fk_model_id]) {
relatedMetas[relationCol.fk_model_id] = await Model.getWithInfo({
id: relationCol.fk_model_id,
});
} }
// extract meta for table in which looked up column belongs
// if not already extracted
if (!relatedMetas[lookedUpCol.fk_model_id]) {
relatedMetas[lookedUpCol.fk_model_id] = await Model.getWithInfo({
id: lookedUpCol.fk_model_id,
});
}
// extract metas related to the looked up column
await this.extractRelatedMetas({
col: lookedUpCol,
relatedMetas,
});
}
async publicSharedBaseGet(param: { sharedBaseUuid: string }): Promise<any> { async publicSharedBaseGet(param: { sharedBaseUuid: string }): Promise<any> {
const project = await Project.getByUuid(param.sharedBaseUuid); const project = await Project.getByUuid(param.sharedBaseUuid);

Loading…
Cancel
Save