Browse Source

Merge branch 'develop' into fix/refresh-token

pull/5764/head
Pranav C 1 year ago committed by GitHub
parent
commit
a057db14c0
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. 3
      packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue
  4. 5
      packages/nc-gui/components/virtual-cell/BelongsTo.vue
  5. 5
      packages/nc-gui/components/virtual-cell/HasMany.vue
  6. 3
      packages/nc-gui/components/virtual-cell/Lookup.vue
  7. 5
      packages/nc-gui/components/virtual-cell/ManyToMany.vue
  8. 3
      packages/nc-gui/composables/useApi/interceptors.ts
  9. 1
      packages/nc-gui/composables/useMultiSelect/convertCellData.ts
  10. 4
      packages/nc-gui/composables/useMultiSelect/index.ts
  11. 1
      packages/nc-gui/context/index.ts
  12. 72
      packages/nocodb-sdk/src/lib/Api.ts
  13. 146
      packages/nocodb/src/schema/swagger.json
  14. 89
      packages/nocodb/src/services/public-metas.service.ts
  15. 2
      packages/nocodb/src/utils/nc-config/NcConfig.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"

3
packages/nc-gui/components/smartsheet/toolbar/ColumnFilter.vue

@ -225,7 +225,8 @@ defineExpose({
/> />
<span v-else :key="`${i}dummy`" /> <span v-else :key="`${i}dummy`" />
<div :key="`${i}nested`" class="flex"> <span v-if="!i" class="flex items-center">{{ $t('labels.where') }}</span>
<div v-else :key="`${i}nested`" class="flex bob">
<a-select <a-select
v-model:value="filter.logical_op" v-model:value="filter.logical_op"
:dropdown-match-select-width="false" :dropdown-match-select-width="false"

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

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

1
packages/nc-gui/composables/useMultiSelect/convertCellData.ts

@ -7,7 +7,6 @@ import { parseProp } from '#imports'
export default function convertCellData( export default function convertCellData(
args: { from: UITypes; to: UITypes; value: any; column: ColumnType; appInfo: AppInfo }, args: { from: UITypes; to: UITypes; value: any; column: ColumnType; appInfo: AppInfo },
isMysql = false, isMysql = false,
isXcdbBase = false,
) { ) {
const { from, to, value } = args const { from, to, value } = args
if (from === to && ![UITypes.Attachment, UITypes.Date, UITypes.DateTime, UITypes.Time, UITypes.Year].includes(to)) { if (from === to && ![UITypes.Attachment, UITypes.Date, UITypes.DateTime, UITypes.Time, UITypes.Year].includes(to)) {

4
packages/nc-gui/composables/useMultiSelect/index.ts

@ -55,7 +55,7 @@ export function useMultiSelect(
const { appInfo } = useGlobal() const { appInfo } = useGlobal()
const { isMysql, isXcdbBase } = useProject() const { isMysql } = useProject()
let clipboardContext = $ref<{ value: any; uidt: UITypes } | null>(null) let clipboardContext = $ref<{ value: any; uidt: UITypes } | null>(null)
@ -359,7 +359,6 @@ export function useMultiSelect(
appInfo: unref(appInfo), appInfo: unref(appInfo),
}, },
isMysql(meta.value?.base_id), isMysql(meta.value?.base_id),
isXcdbBase(meta.value?.base_id),
) )
e.preventDefault() e.preventDefault()
@ -394,7 +393,6 @@ export function useMultiSelect(
appInfo: unref(appInfo), appInfo: unref(appInfo),
}, },
isMysql(meta.value?.base_id), isMysql(meta.value?.base_id),
isXcdbBase(meta.value?.base_id),
) )
e.preventDefault() e.preventDefault()
syncCellData?.(activeCell) syncCellData?.(activeCell)

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')

72
packages/nocodb-sdk/src/lib/Api.ts

@ -546,7 +546,39 @@ export interface FilterType {
| 'notchecked' | 'notchecked'
| 'notempty' | 'notempty'
| 'notnull' | 'notnull'
| 'null'; | 'null'
| null
| (
| 'allof'
| 'anyof'
| 'blank'
| 'btw'
| 'checked'
| 'empty'
| 'eq'
| 'ge'
| 'gt'
| 'gte'
| 'in'
| 'is'
| 'isWithin'
| 'isnot'
| 'le'
| 'like'
| 'lt'
| 'lte'
| 'nallof'
| 'nanyof'
| 'nbtw'
| 'neq'
| 'nlike'
| 'not'
| 'notblank'
| 'notchecked'
| 'notempty'
| 'notnull'
| ('null' & null)
);
/** Comparison Sub-Operator */ /** Comparison Sub-Operator */
comparison_sub_op?: comparison_sub_op?:
| 'daysAgo' | 'daysAgo'
@ -589,7 +621,7 @@ export interface FilterType {
| ('yesterday' & null) | ('yesterday' & null)
); );
/** Foreign Key to Column */ /** Foreign Key to Column */
fk_column_id?: IdType; fk_column_id?: StringOrNullType;
/** Foreign Key to Hook */ /** Foreign Key to Hook */
fk_hook_id?: StringOrNullType; fk_hook_id?: StringOrNullType;
/** Foreign Key to Model */ /** Foreign Key to Model */
@ -664,7 +696,39 @@ export interface FilterReqType {
| 'notchecked' | 'notchecked'
| 'notempty' | 'notempty'
| 'notnull' | 'notnull'
| 'null'; | 'null'
| null
| (
| 'allof'
| 'anyof'
| 'blank'
| 'btw'
| 'checked'
| 'empty'
| 'eq'
| 'ge'
| 'gt'
| 'gte'
| 'in'
| 'is'
| 'isWithin'
| 'isnot'
| 'le'
| 'like'
| 'lt'
| 'lte'
| 'nallof'
| 'nanyof'
| 'nbtw'
| 'neq'
| 'nlike'
| 'not'
| 'notblank'
| 'notchecked'
| 'notempty'
| 'notnull'
| ('null' & null)
);
/** Comparison Sub-Operator */ /** Comparison Sub-Operator */
comparison_sub_op?: comparison_sub_op?:
| 'daysAgo' | 'daysAgo'
@ -707,7 +771,7 @@ export interface FilterReqType {
| ('yesterday' & null) | ('yesterday' & null)
); );
/** Foreign Key to Column */ /** Foreign Key to Column */
fk_column_id?: IdType; fk_column_id?: StringOrNullType;
/** Belong to which filter ID */ /** Belong to which filter ID */
fk_parent_id?: StringOrNullType; fk_parent_id?: StringOrNullType;
/** Is this filter grouped? */ /** Is this filter grouped? */

146
packages/nocodb/src/schema/swagger.json

@ -15197,38 +15197,45 @@
}, },
"comparison_op": { "comparison_op": {
"description": "Comparison Operator", "description": "Comparison Operator",
"enum": [ "anyOf": [
"allof", {
"anyof", "enum": [
"blank", "allof",
"btw", "anyof",
"checked", "blank",
"empty", "btw",
"eq", "checked",
"ge", "empty",
"gt", "eq",
"gte", "ge",
"in", "gt",
"is", "gte",
"isWithin", "in",
"isnot", "is",
"le", "isWithin",
"like", "isnot",
"lt", "le",
"lte", "like",
"nallof", "lt",
"nanyof", "lte",
"nbtw", "nallof",
"neq", "nanyof",
"nlike", "nbtw",
"not", "neq",
"notblank", "nlike",
"notchecked", "not",
"notempty", "notblank",
"notnull", "notchecked",
"null" "notempty",
], "notnull",
"type": "string" "null"
],
"type": "string"
},
{
"type": "null"
}
]
}, },
"comparison_sub_op": { "comparison_sub_op": {
"anyOf": [ "anyOf": [
@ -15262,7 +15269,7 @@
"description": "Comparison Sub-Operator" "description": "Comparison Sub-Operator"
}, },
"fk_column_id": { "fk_column_id": {
"$ref": "#/components/schemas/Id", "$ref": "#/components/schemas/StringOrNull",
"description": "Foreign Key to Column" "description": "Foreign Key to Column"
}, },
"fk_hook_id": { "fk_hook_id": {
@ -15518,38 +15525,45 @@
"properties": { "properties": {
"comparison_op": { "comparison_op": {
"description": "Comparison Operator", "description": "Comparison Operator",
"enum": [ "anyOf": [
"allof", {
"anyof", "enum": [
"blank", "allof",
"btw", "anyof",
"checked", "blank",
"empty", "btw",
"eq", "checked",
"ge", "empty",
"gt", "eq",
"gte", "ge",
"in", "gt",
"is", "gte",
"isWithin", "in",
"isnot", "is",
"le", "isWithin",
"like", "isnot",
"lt", "le",
"lte", "like",
"nallof", "lt",
"nanyof", "lte",
"nbtw", "nallof",
"neq", "nanyof",
"nlike", "nbtw",
"not", "neq",
"notblank", "nlike",
"notchecked", "not",
"notempty", "notblank",
"notnull", "notchecked",
"null" "notempty",
], "notnull",
"type": "string" "null"
],
"type": "string"
},
{
"type": "null"
}
]
}, },
"comparison_sub_op": { "comparison_sub_op": {
"anyOf": [ "anyOf": [
@ -15583,7 +15597,7 @@
"description": "Comparison Sub-Operator" "description": "Comparison Sub-Operator"
}, },
"fk_column_id": { "fk_column_id": {
"$ref": "#/components/schemas/Id", "$ref": "#/components/schemas/StringOrNull",
"description": "Foreign Key to Column" "description": "Foreign Key to Column"
}, },
"fk_parent_id": { "fk_parent_id": {

89
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) {
if (UITypes.LinkToAnotherRecord === col.uidt) { await this.extractRelatedMetas({ col, relatedMetas });
const colOpt = await col.getColOptions<LinkToAnotherRecordType>();
relatedMetas[colOpt.fk_related_model_id] = await Model.getWithInfo({
id: colOpt.fk_related_model_id,
});
if (colOpt.type === 'mm') {
relatedMetas[colOpt.fk_mm_model_id] = await Model.getWithInfo({
id: colOpt.fk_mm_model_id,
});
}
}
} }
view.relatedMetas = relatedMetas; view.relatedMetas = relatedMetas;
return view; return view;
} }
private async extractRelatedMetas({
col,
relatedMetas = {},
}: {
col: Column<any>;
relatedMetas: Record<string, Model>;
}) {
if (UITypes.LinkToAnotherRecord === col.uidt) {
await this.extractLTARRelatedMetas({
ltarColOption: await col.getColOptions<LinkToAnotherRecordColumn>(),
relatedMetas,
});
} else if (UITypes.Lookup === col.uidt) {
await this.extractLookupRelatedMetas({
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,
});
}
}
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,
});
// 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);

2
packages/nocodb/src/utils/nc-config/NcConfig.ts

@ -126,6 +126,8 @@ export class NcConfig {
if (dashboardPath) { if (dashboardPath) {
ncConfig.dashboardPath = dashboardPath; ncConfig.dashboardPath = dashboardPath;
} else {
ncConfig.dashboardPath = '/dashboard';
} }
try { try {

Loading…
Cancel
Save