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

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

@ -225,7 +225,8 @@ defineExpose({
/>
<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
v-model:value="filter.logical_op"
:dropdown-match-select-width="false"

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

@ -7,6 +7,7 @@ import {
ColumnInj,
IsFormInj,
IsLockedInj,
IsUnderLookupInj,
ReadonlyInj,
ReloadRowDataHookInj,
RowInj,
@ -36,6 +37,8 @@ const isForm = inject(IsFormInj, ref(false))
const isLocked = inject(IsLockedInj, ref(false))
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const { isUIAllowed } = useUIPermission()
const listItemsDlg = ref(false)
@ -89,7 +92,7 @@ useSelectedCellKeyupListener(active, (e: KeyboardEvent) => {
</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"
>
<GeneralIcon

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

@ -16,6 +16,7 @@ import {
useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow,
useUIPermission,
IsUnderLookupInj
} from '#imports'
const column = inject(ColumnInj)!
@ -32,6 +33,8 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false)
const childListDlg = ref(false)
@ -112,7 +115,7 @@ useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEven
</template>
</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
icon="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,
CellValueInj,
ColumnInj,
IsUnderLookupInj,
MetaInj,
computed,
inject,
@ -70,6 +71,8 @@ const arrValue = computed(() => {
provide(MetaInj, lookupTableMeta)
provide(IsUnderLookupInj, ref(true))
provide(CellUrlDisableOverlayInj, ref(true))
const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activateShowEditNonEditableFieldWarning } =

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

@ -7,6 +7,7 @@ import {
ColumnInj,
IsFormInj,
IsLockedInj,
IsUnderLookupInj,
ReadonlyInj,
ReloadRowDataHookInj,
RowInj,
@ -34,6 +35,8 @@ const readOnly = inject(ReadonlyInj, ref(false))
const isLocked = inject(IsLockedInj)
const isUnderLookup = inject(IsUnderLookupInj, ref(false))
const listItemsDlg = ref(false)
const childListDlg = ref(false)
@ -114,7 +117,7 @@ useSelectedCellKeyupListener(inject(ActiveCellInj, ref(false)), (e: KeyboardEven
</template>
</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
icon="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) => {
await state.signOut()
// todo: handle new user
navigateTo('/signIn')
if (!route.meta.public) navigateTo('/signIn')
return Promise.reject(error)
})

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

@ -7,7 +7,6 @@ import { parseProp } from '#imports'
export default function convertCellData(
args: { from: UITypes; to: UITypes; value: any; column: ColumnType; appInfo: AppInfo },
isMysql = false,
isXcdbBase = false,
) {
const { from, to, value } = args
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 { isMysql, isXcdbBase } = useProject()
const { isMysql } = useProject()
let clipboardContext = $ref<{ value: any; uidt: UITypes } | null>(null)
@ -359,7 +359,6 @@ export function useMultiSelect(
appInfo: unref(appInfo),
},
isMysql(meta.value?.base_id),
isXcdbBase(meta.value?.base_id),
)
e.preventDefault()
@ -394,7 +393,6 @@ export function useMultiSelect(
appInfo: unref(appInfo),
},
isMysql(meta.value?.base_id),
isXcdbBase(meta.value?.base_id),
)
e.preventDefault()
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 SaveRowInj: InjectionKey<(() => void) | undefined> = Symbol('save-row-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'
| 'notempty'
| '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_op?:
| 'daysAgo'
@ -589,7 +621,7 @@ export interface FilterType {
| ('yesterday' & null)
);
/** Foreign Key to Column */
fk_column_id?: IdType;
fk_column_id?: StringOrNullType;
/** Foreign Key to Hook */
fk_hook_id?: StringOrNullType;
/** Foreign Key to Model */
@ -664,7 +696,39 @@ export interface FilterReqType {
| 'notchecked'
| 'notempty'
| '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_op?:
| 'daysAgo'
@ -707,7 +771,7 @@ export interface FilterReqType {
| ('yesterday' & null)
);
/** Foreign Key to Column */
fk_column_id?: IdType;
fk_column_id?: StringOrNullType;
/** Belong to which filter ID */
fk_parent_id?: StringOrNullType;
/** Is this filter grouped? */

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

@ -15197,38 +15197,45 @@
},
"comparison_op": {
"description": "Comparison Operator",
"enum": [
"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"
],
"type": "string"
"anyOf": [
{
"enum": [
"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"
],
"type": "string"
},
{
"type": "null"
}
]
},
"comparison_sub_op": {
"anyOf": [
@ -15262,7 +15269,7 @@
"description": "Comparison Sub-Operator"
},
"fk_column_id": {
"$ref": "#/components/schemas/Id",
"$ref": "#/components/schemas/StringOrNull",
"description": "Foreign Key to Column"
},
"fk_hook_id": {
@ -15518,38 +15525,45 @@
"properties": {
"comparison_op": {
"description": "Comparison Operator",
"enum": [
"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"
],
"type": "string"
"anyOf": [
{
"enum": [
"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"
],
"type": "string"
},
{
"type": "null"
}
]
},
"comparison_sub_op": {
"anyOf": [
@ -15583,7 +15597,7 @@
"description": "Comparison Sub-Operator"
},
"fk_column_id": {
"$ref": "#/components/schemas/Id",
"$ref": "#/components/schemas/StringOrNull",
"description": "Foreign Key to Column"
},
"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 { NcError } from '../helpers/catchError';
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';
@Injectable()
@ -63,23 +63,88 @@ export class PublicMetasService {
// load related table metas
for (const col of view.model.columns) {
if (UITypes.LinkToAnotherRecord === col.uidt) {
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,
});
}
}
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) {
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> {
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) {
ncConfig.dashboardPath = dashboardPath;
} else {
ncConfig.dashboardPath = '/dashboard';
}
try {

Loading…
Cancel
Save