@@ -351,12 +344,6 @@ const selectedOpt = computed(() => {
@apply !px-0;
}
-:deep(.ant-select-selection-search) {
- // following a-select with mode = multiple | tags
- // initial width will block @mouseover in Grid.vue
- @apply !w-[5px];
-}
-
:deep(.ant-select-selection-search-input) {
@apply !text-xs;
}
diff --git a/packages/nc-gui/components/dashboard/TreeView.vue b/packages/nc-gui/components/dashboard/TreeView.vue
index 2f5f97ee4b..5940b634c5 100644
--- a/packages/nc-gui/components/dashboard/TreeView.vue
+++ b/packages/nc-gui/components/dashboard/TreeView.vue
@@ -399,8 +399,8 @@ const duplicateTable = async (table: TableType) => {
const { close } = useDialog(resolveComponent('DlgTableDuplicate'), {
'modelValue': isOpen,
'table': table,
- 'onOk': async (jobData: { name: string; id: string }) => {
- $jobs.subscribe({ name: jobData.name, id: jobData.id }, undefined, async (status: string, data?: any) => {
+ 'onOk': async (jobData: { id: string }) => {
+ $jobs.subscribe({ id: jobData.id }, undefined, async (status: string, data?: any) => {
if (status === JobStatus.COMPLETED) {
await loadTables()
const newTable = tables.value.find((el) => el.id === data?.result?.id)
diff --git a/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue b/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
index bb4f6d56d8..296f0bced1 100644
--- a/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
+++ b/packages/nc-gui/components/dashboard/settings/data-sources/CreateBase.vue
@@ -495,7 +495,7 @@ watch(
-
+
{{ $t('activity.useConnectionUrl') }}
@@ -611,7 +611,7 @@ watch(
-
+
{{ $t('activity.testDbConn') }}
diff --git a/packages/nc-gui/components/dlg/ProjectDuplicate.vue b/packages/nc-gui/components/dlg/ProjectDuplicate.vue
index ca1fcc939a..4c2e7c530c 100644
--- a/packages/nc-gui/components/dlg/ProjectDuplicate.vue
+++ b/packages/nc-gui/components/dlg/ProjectDuplicate.vue
@@ -34,7 +34,12 @@ const isLoading = ref(false)
const _duplicate = async () => {
isLoading.value = true
try {
- const jobData = await api.project.duplicate(props.project.id as string, optionsToExclude.value)
+ const jobData = await api.project.duplicate(props.project.id as string, {
+ options: optionsToExclude.value,
+ project: {
+ meta: props.project.meta,
+ },
+ })
props.onOk(jobData as any)
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
diff --git a/packages/nc-gui/components/dlg/TableDuplicate.vue b/packages/nc-gui/components/dlg/TableDuplicate.vue
index dc4ca1b407..6393d9f48e 100644
--- a/packages/nc-gui/components/dlg/TableDuplicate.vue
+++ b/packages/nc-gui/components/dlg/TableDuplicate.vue
@@ -34,7 +34,7 @@ const isLoading = ref(false)
const _duplicate = async () => {
isLoading.value = true
try {
- const jobData = await api.dbTable.duplicate(props.table.project_id!, props.table.id!, optionsToExclude.value)
+ const jobData = await api.dbTable.duplicate(props.table.project_id!, props.table.id!, { options: optionsToExclude.value })
props.onOk(jobData as any)
} catch (e: any) {
message.error(await extractSdkResponseErrorMsg(e))
diff --git a/packages/nc-gui/components/smartsheet/Cell.vue b/packages/nc-gui/components/smartsheet/Cell.vue
index 2023ec9604..2bdaf83de4 100644
--- a/packages/nc-gui/components/smartsheet/Cell.vue
+++ b/packages/nc-gui/components/smartsheet/Cell.vue
@@ -209,7 +209,12 @@ onUnmounted(() => {
-
+
diff --git a/packages/nc-gui/components/smartsheet/Gallery.vue b/packages/nc-gui/components/smartsheet/Gallery.vue
index f4f4a160f4..5b0a2f5088 100644
--- a/packages/nc-gui/components/smartsheet/Gallery.vue
+++ b/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) => {
+ 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' }"
>
diff --git a/packages/nc-gui/components/smartsheet/Grid.vue b/packages/nc-gui/components/smartsheet/Grid.vue
index 85b008fdda..134edc59d9 100644
--- a/packages/nc-gui/components/smartsheet/Grid.vue
+++ b/packages/nc-gui/components/smartsheet/Grid.vue
@@ -316,6 +316,12 @@ const {
return
}
+ // See DateTimePicker.vue for details
+ data.value[ctx.row].rowMeta.isUpdatedFromCopyNPaste = {
+ ...data.value[ctx.row].rowMeta.isUpdatedFromCopyNPaste,
+ [ctx.updatedColumnTitle || columnObj.title]: true,
+ }
+
// update/save cell value
await updateOrSaveRow(rowObj, ctx.updatedColumnTitle || columnObj.title)
},
diff --git a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
index beb16b58be..6889cfae2e 100644
--- a/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
+++ b/packages/nc-gui/components/smartsheet/column/FormulaOptions.vue
@@ -149,28 +149,29 @@ function parseAndValidateFormula(formula: string) {
function validateAgainstMeta(parsedTree: any, errors = new Set(), typeErrors = new Set()) {
if (parsedTree.type === JSEPNode.CALL_EXP) {
+ const calleeName = parsedTree.callee.name.toUpperCase()
// validate function name
- if (!availableFunctions.includes(parsedTree.callee.name)) {
- errors.add(`'${parsedTree.callee.name}' function is not available`)
+ if (!availableFunctions.includes(calleeName)) {
+ errors.add(`'${calleeName}' function is not available`)
}
// validate arguments
- const validation = formulas[parsedTree.callee.name] && formulas[parsedTree.callee.name].validation
+ const validation = formulas[calleeName] && formulas[calleeName].validation
if (validation && validation.args) {
if (validation.args.rqd !== undefined && validation.args.rqd !== parsedTree.arguments.length) {
- errors.add(`'${parsedTree.callee.name}' required ${validation.args.rqd} arguments`)
+ errors.add(`'${calleeName}' required ${validation.args.rqd} arguments`)
} else if (validation.args.min !== undefined && validation.args.min > parsedTree.arguments.length) {
- errors.add(`'${parsedTree.callee.name}' required minimum ${validation.args.min} arguments`)
+ errors.add(`'${calleeName}' required minimum ${validation.args.min} arguments`)
} else if (validation.args.max !== undefined && validation.args.max < parsedTree.arguments.length) {
- errors.add(`'${parsedTree.callee.name}' required maximum ${validation.args.max} arguments`)
+ errors.add(`'${calleeName}' required maximum ${validation.args.max} arguments`)
}
}
parsedTree.arguments.map((arg: Record) => validateAgainstMeta(arg, errors))
// validate data type
if (parsedTree.callee.type === JSEPNode.IDENTIFIER) {
- const expectedType = formulas[parsedTree.callee.name].type
+ const expectedType = formulas[calleeName.toUpperCase()].type
if (expectedType === formulaTypes.NUMERIC) {
- if (parsedTree.callee.name === 'WEEKDAY') {
+ if (calleeName === 'WEEKDAY') {
// parsedTree.arguments[0] = date
validateAgainstType(
parsedTree.arguments[0],
@@ -202,7 +203,7 @@ function validateAgainstMeta(parsedTree: any, errors = new Set(), typeErrors = n
parsedTree.arguments.map((arg: Record) => validateAgainstType(arg, expectedType, null, typeErrors))
}
} else if (expectedType === formulaTypes.DATE) {
- if (parsedTree.callee.name === 'DATEADD') {
+ if (calleeName === 'DATEADD') {
// parsedTree.arguments[0] = date
validateAgainstType(
parsedTree.arguments[0],
@@ -236,7 +237,7 @@ function validateAgainstMeta(parsedTree: any, errors = new Set(), typeErrors = n
},
typeErrors,
)
- } else if (parsedTree.callee.name === 'DATETIME_DIFF') {
+ } else if (calleeName === 'DATETIME_DIFF') {
// parsedTree.arguments[0] = date
validateAgainstType(
parsedTree.arguments[0],
@@ -504,8 +505,9 @@ function validateAgainstType(parsedTree: any, expectedType: string, func: any, t
typeErrors.add(`${formulaTypes.NUMERIC} type is found but ${expectedType} type is expected`)
}
} else if (parsedTree.type === JSEPNode.CALL_EXP) {
- if (formulas[parsedTree.callee.name]?.type && expectedType !== formulas[parsedTree.callee.name].type) {
- typeErrors.add(`${expectedType} not matched with ${formulas[parsedTree.callee.name].type}`)
+ const calleeName = parsedTree.callee.name.toUpperCase()
+ if (formulas[calleeName]?.type && expectedType !== formulas[calleeName].type) {
+ typeErrors.add(`${expectedType} not matched with ${formulas[calleeName].type}`)
}
}
return typeErrors
@@ -514,7 +516,7 @@ function validateAgainstType(parsedTree: any, expectedType: string, func: any, t
function getRootDataType(parsedTree: any): any {
// given a parse tree, return the data type of it
if (parsedTree.type === JSEPNode.CALL_EXP) {
- return formulas[parsedTree.callee.name].type
+ return formulas[parsedTree.callee.name.toUpperCase()].type
} else if (parsedTree.type === JSEPNode.IDENTIFIER) {
const col = supportedColumns.value.find((c) => c.title === parsedTree.name) as Record
if (col?.uidt === UITypes.Formula) {
diff --git a/packages/nc-gui/components/smartsheet/header/Cell.vue b/packages/nc-gui/components/smartsheet/header/Cell.vue
index ecafbd9f32..819b25fc09 100644
--- a/packages/nc-gui/components/smartsheet/header/Cell.vue
+++ b/packages/nc-gui/components/smartsheet/header/Cell.vue
@@ -52,7 +52,7 @@ const openHeaderMenu = () => {
-
+
{{ $t('labels.where') }}
+
import type { ColumnType } from 'nocodb-sdk'
import type { Ref } from 'vue'
-import { CellValueInj, ColumnInj, computed, handleTZ, inject, replaceUrlsWithLink, useProject } from '#imports'
+import { CellValueInj, ColumnInj, computed, handleTZ, inject, renderValue, replaceUrlsWithLink, useProject } from '#imports'
// todo: column type doesn't have required property `error` - throws in typecheck
const column = inject(ColumnInj) as Ref
@@ -10,7 +10,9 @@ const cellValue = inject(CellValueInj)
const { isPg } = useProject()
-const result = computed(() => (isPg(column.value.base_id) ? handleTZ(cellValue?.value) : cellValue?.value))
+const result = computed(() =>
+ isPg(column.value.base_id) ? renderValue(handleTZ(cellValue?.value)) : renderValue(cellValue?.value),
+)
const urls = computed(() => replaceUrlsWithLink(result.value))
diff --git a/packages/nc-gui/components/virtual-cell/HasMany.vue b/packages/nc-gui/components/virtual-cell/HasMany.vue
index fe43c2b03f..4397fa190f 100644
--- a/packages/nc-gui/components/virtual-cell/HasMany.vue
+++ b/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
-
+
{
provide(MetaInj, lookupTableMeta)
+provide(IsUnderLookupInj, ref(true))
+
provide(CellUrlDisableOverlayInj, ref(true))
const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning, activateShowEditNonEditableFieldWarning } =
diff --git a/packages/nc-gui/components/virtual-cell/ManyToMany.vue b/packages/nc-gui/components/virtual-cell/ManyToMany.vue
index b1ae3d9f76..4af1ab7005 100644
--- a/packages/nc-gui/components/virtual-cell/ManyToMany.vue
+++ b/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
-
+
- {{ value }}
+ {{ renderValue(value) }}
()
@@ -148,7 +148,7 @@ const onClick = (row: Row) => {
>
- {{ row[relatedTableDisplayValueProp] }}
+ {{ renderValue(row[relatedTableDisplayValueProp]) }}
(Primary key : {{ getRelatedTableRowId(row) }})
diff --git a/packages/nc-gui/components/virtual-cell/components/ListItems.vue b/packages/nc-gui/components/virtual-cell/components/ListItems.vue
index 5059cc39a5..0b5f90e63d 100644
--- a/packages/nc-gui/components/virtual-cell/components/ListItems.vue
+++ b/packages/nc-gui/components/virtual-cell/components/ListItems.vue
@@ -12,11 +12,11 @@ import {
inject,
isDrawerExist,
ref,
+ renderValue,
useLTARStoreOrThrow,
useSelectedCellKeyupListener,
useSmartsheetRowStoreOrThrow,
useVModel,
- watch,
} from '#imports'
const props = defineProps<{ modelValue: boolean }>()
@@ -213,7 +213,7 @@ watch(vModel, (nextVal) => {
-
+
{{ $t('activity.addNewRecord') }}
@@ -229,7 +229,7 @@ watch(vModel, (nextVal) => {
:class="{ 'nc-selected-row': selectedRowIndex === i }"
@click="linkRow(refRow)"
>
- {{ refRow[relatedTableDisplayValueProp] }}
+ {{ renderValue(refRow[relatedTableDisplayValueProp]) }}
({{ $t('labels.primaryKey') }} : {{ getRelatedTableRowId(refRow) }})
diff --git a/packages/nc-gui/composables/useApi/interceptors.ts b/packages/nc-gui/composables/useApi/interceptors.ts
index 4c12bc083c..ca95a62243 100644
--- a/packages/nc-gui/composables/useApi/interceptors.ts
+++ b/packages/nc-gui/composables/useApi/interceptors.ts
@@ -67,9 +67,8 @@ export function addAxiosInterceptors(api: Api
) {
})
.catch(async (error) => {
await state.signOut()
- // todo: handle new user
- navigateTo('/signIn')
+ if (!route.meta.public) navigateTo('/signIn')
return Promise.reject(error)
})
diff --git a/packages/nc-gui/composables/useGridViewColumnWidth.ts b/packages/nc-gui/composables/useGridViewColumnWidth.ts
index 4e7786c250..66b180c3ae 100644
--- a/packages/nc-gui/composables/useGridViewColumnWidth.ts
+++ b/packages/nc-gui/composables/useGridViewColumnWidth.ts
@@ -13,7 +13,7 @@ import {
watch,
} from '#imports'
-export function useGridViewColumnWidth(view: Ref) {
+export function useGridViewColumnWidth(view: Ref<(ViewType & { columns?: GridColumnType[] }) | undefined>) {
const { css, load: loadCss, unload: unloadCss } = useStyleTag('')
const { isUIAllowed } = useUIPermission()
@@ -52,7 +52,9 @@ export function useGridViewColumnWidth(view: Ref) {
const loadGridViewColumns = async () => {
if (!view.value?.id && !isPublic.value) return
- const colsData: GridColumnType[] = (isPublic.value ? columns.value : await $api.dbView.gridColumnsList(view.value!.id!)) ?? []
+ const colsData: GridColumnType[] =
+ (isPublic.value ? view.value?.columns : await $api.dbView.gridColumnsList(view.value!.id!)) ?? []
+
gridViewCols.value = colsData.reduce>(
(o, col) => ({
...o,
diff --git a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts
index 33cce2db2a..a6bb90685a 100644
--- a/packages/nc-gui/composables/useMultiSelect/convertCellData.ts
+++ b/packages/nc-gui/composables/useMultiSelect/convertCellData.ts
@@ -42,7 +42,7 @@ export default function convertCellData(
if (!parsedDateTime.isValid()) {
throw new Error('Not a valid datetime value')
}
- return parsedDateTime.format(dateFormat)
+ return parsedDateTime.utc().format('YYYY-MM-DD HH:mm:ssZ')
}
case UITypes.Time: {
let parsedTime = dayjs(value)
diff --git a/packages/nc-gui/composables/useMultiSelect/index.ts b/packages/nc-gui/composables/useMultiSelect/index.ts
index 507cd81f63..b5d5fb4226 100644
--- a/packages/nc-gui/composables/useMultiSelect/index.ts
+++ b/packages/nc-gui/composables/useMultiSelect/index.ts
@@ -1,3 +1,4 @@
+import dayjs from 'dayjs'
import type { MaybeRef } from '@vueuse/core'
import type { ColumnType, LinkToAnotherRecordType, TableType } from 'nocodb-sdk'
import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
@@ -7,6 +8,7 @@ import convertCellData from './convertCellData'
import type { Nullable, Row } from '~/lib'
import {
copyTable,
+ dateFormats,
extractPkFromRow,
extractSdkResponseErrorMsg,
isMac,
@@ -14,6 +16,7 @@ import {
message,
reactive,
ref,
+ timeFormats,
unref,
useCopy,
useEventListener,
@@ -79,6 +82,20 @@ export function useMultiSelect(
activeCell.col = col
}
+ function constructDateTimeFormat(column: ColumnType) {
+ const dateFormat = constructDateFormat(column)
+ const timeFormat = constructTimeFormat(column)
+ return `${dateFormat} ${timeFormat}`
+ }
+
+ function constructDateFormat(column: ColumnType) {
+ return parseProp(column?.meta)?.date_format ?? dateFormats[0]
+ }
+
+ function constructTimeFormat(column: ColumnType) {
+ return parseProp(column?.meta)?.time_format ?? timeFormats[0]
+ }
+
async function copyValue(ctx?: Cell) {
try {
if (selectedRange.start !== null && selectedRange.end !== null && !selectedRange.isSingleCell()) {
@@ -106,6 +123,43 @@ export function useMultiSelect(
if (typeof textToCopy === 'object') {
textToCopy = JSON.stringify(textToCopy)
}
+
+ if (columnObj.uidt === UITypes.Formula) {
+ textToCopy = textToCopy.replace(/\b(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}[+-]\d{2}:\d{2})\b/g, (d: string) => {
+ // TODO(timezone): retrieve the format from the corresponding column meta
+ // assume hh:mm at this moment
+ return dayjs(d).utc().local().format('YYYY-MM-DD HH:mm')
+ })
+ }
+
+ if (columnObj.uidt === UITypes.DateTime || columnObj.uidt === UITypes.Time) {
+ // remove `"`
+ // e.g. "2023-05-12T08:03:53.000Z" -> 2023-05-12T08:03:53.000Z
+ textToCopy = textToCopy.replace(/["']/g, '')
+
+ const isMySQL = isMysql(columnObj.base_id)
+
+ let d = dayjs(textToCopy)
+
+ if (!d.isValid()) {
+ // insert a datetime value, copy the value without refreshing
+ // e.g. textToCopy = 2023-05-12T03:49:25.000Z
+ // feed custom parse format
+ d = dayjs(textToCopy, isMySQL ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ssZ')
+ }
+
+ // users can change the datetime format in UI
+ // `textToCopy` would be always in YYYY-MM-DD HH:mm:ss(Z / +xx:yy) format
+ // therefore, here we reformat to the correct datetime format based on the meta
+ textToCopy = d.format(
+ columnObj.uidt === UITypes.DateTime ? constructDateTimeFormat(columnObj) : constructTimeFormat(columnObj),
+ )
+
+ if (columnObj.uidt === UITypes.DateTime && !dayjs(textToCopy).isValid()) {
+ throw new Error('Invalid DateTime')
+ }
+ }
+
await copy(textToCopy)
message.success(t('msg.info.copiedToClipboard'))
}
diff --git a/packages/nc-gui/composables/useSharedFormViewStore.ts b/packages/nc-gui/composables/useSharedFormViewStore.ts
index 8cb6ae2d9a..db93cf4b39 100644
--- a/packages/nc-gui/composables/useSharedFormViewStore.ts
+++ b/packages/nc-gui/composables/useSharedFormViewStore.ts
@@ -1,7 +1,16 @@
import useVuelidate from '@vuelidate/core'
import { helpers, minLength, required } from '@vuelidate/validators'
import type { Ref } from 'vue'
-import type { BoolType, ColumnType, FormType, LinkToAnotherRecordType, StringOrNullType, TableType, ViewType, FormColumnType } from 'nocodb-sdk'
+import type {
+ BoolType,
+ ColumnType,
+ FormColumnType,
+ FormType,
+ LinkToAnotherRecordType,
+ StringOrNullType,
+ TableType,
+ ViewType,
+} from 'nocodb-sdk'
import { ErrorMessages, RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
import { isString } from '@vueuse/core'
import {
@@ -92,18 +101,10 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
{} as Record,
)
- let order = 1
-
- columns.value = meta?.value?.columns
- ?.map((c: Record) => ({
- ...c,
- fk_column_id: c.id,
- fk_view_id: viewMeta.id,
- ...(fieldById[c.id] ? fieldById[c.id] : {}),
- order: (fieldById[c.id] && fieldById[c.id].order) || order++,
- id: fieldById[c.id] && fieldById[c.id].id,
- }))
- .sort((a: Record, b: Record) => a.order - b.order) as Record[]
+ columns.value = viewMeta.model?.columns?.map((c) => ({
+ ...c,
+ description: fieldById[c.id].description,
+ }))
const _sharedViewMeta = (viewMeta as any).meta
sharedViewMeta.value = isString(_sharedViewMeta) ? JSON.parse(_sharedViewMeta) : _sharedViewMeta
diff --git a/packages/nc-gui/context/index.ts b/packages/nc-gui/context/index.ts
index 0ea07a931e..1b8e84baa0 100644
--- a/packages/nc-gui/context/index.ts
+++ b/packages/nc-gui/context/index.ts
@@ -38,3 +38,4 @@ export const ToggleDialogInj: InjectionKey = Symbol('toggle-dialog-inj
export const CellClickHookInj: InjectionKey | undefined> = Symbol('cell-click-injection')
export const SaveRowInj: InjectionKey<(() => void) | undefined> = Symbol('save-row-injection')
export const CurrentCellInj: InjectionKey[> = Symbol('current-cell-injection')
+export const IsUnderLookupInj: InjectionKey][> = Symbol('is-under-lookup-injection')
diff --git a/packages/nc-gui/lang/fr.json b/packages/nc-gui/lang/fr.json
index 28d5266003..d5a9b10471 100644
--- a/packages/nc-gui/lang/fr.json
+++ b/packages/nc-gui/lang/fr.json
@@ -260,7 +260,7 @@
"barcodeFormat": "Format du code-barres",
"qrCodeValueTooLong": "Trop de caractères pour un code QR",
"barcodeValueTooLong": "Trop de caractères pour un code-barres",
- "currentLocation": "Current Location",
+ "currentLocation": "Emplacement actuel",
"lng": "Lng",
"lat": "Lat",
"aggregateFunction": "Fonction agrégée",
@@ -385,12 +385,12 @@
"nextRecord": "Ligne suivante",
"previousRecord": "Ligne précédente",
"copyApiURL": "Copier l'URL de l'API",
- "createTable": "Create New Table",
+ "createTable": "Créer une nouvelle table",
"refreshTable": "Actualiser le tableau",
- "renameTable": "Rename Table",
- "deleteTable": "Delete Table",
+ "renameTable": "Renommer la table",
+ "deleteTable": "Supprimer la table",
"addField": "Ajouter un nouveau champ à ce tableau",
- "setDisplay": "Set as Display value",
+ "setDisplay": "Définir comme valeur d'affichage",
"addRow": "Ajouter une nouvelle ligne",
"saveRow": "Enregistrer la ligne",
"saveAndExit": "Enregistrer et quitter",
@@ -580,7 +580,7 @@
"afterEnablePwd": "L’accès est restreint par un mot de passe",
"privateLink": "Cette vue est partagée avec un lien privé",
"privateLinkAdditionalInfo": "Les personnes ayant le lien privé peuvent voir uniquement les cellules visibles de cette vue",
- "afterFormSubmitted": "Après que le formulaire ait été soumis",
+ "afterFormSubmitted": "Après que le formulaire a été soumis",
"apiOptions": "Accéder au projet via",
"submitAnotherForm": "Afficher le bouton \"Soumettre un autre formulaire\"",
"showBlankForm": "Montrer un formulaire vierge après 5 secondes",
diff --git a/packages/nc-gui/lang/ru.json b/packages/nc-gui/lang/ru.json
index 394045cc3e..b5f43aae0c 100644
--- a/packages/nc-gui/lang/ru.json
+++ b/packages/nc-gui/lang/ru.json
@@ -354,7 +354,7 @@
"account": {
"authToken": "Скопировать токен авторизации",
"swagger": "Swagger: REST APIs",
- "projInfo": "Скопировать информацию о проекте",
+ "projInfo": "Информация о проекте",
"themes": "Темы"
},
"sort": "Сортировать",
@@ -385,10 +385,10 @@
"nextRecord": "Следующая запись",
"previousRecord": "Предыдущая запись",
"copyApiURL": "Скопируйте URL API",
- "createTable": "Create New Table",
+ "createTable": "Создать новую таблицу",
"refreshTable": "Обновление таблицы",
- "renameTable": "Rename Table",
- "deleteTable": "Delete Table",
+ "renameTable": "Переименовать таблицу",
+ "deleteTable": "Удалить таблицу",
"addField": "Добавить новое поле в эту таблицу",
"setDisplay": "Установить как значение отображения",
"addRow": "Добавить новую строку",
diff --git a/packages/nc-gui/lang/zh-Hans.json b/packages/nc-gui/lang/zh-Hans.json
index 7ccd56f0d7..55a5255e04 100644
--- a/packages/nc-gui/lang/zh-Hans.json
+++ b/packages/nc-gui/lang/zh-Hans.json
@@ -68,7 +68,7 @@
"questions": "问题",
"reachOut": "联系我们",
"betaNote": "此功能仍在测试中。",
- "moreInfo": "这里可以找到更多信息",
+ "moreInfo": "点击此处了解更多信息。",
"logs": "日志",
"groupingField": "分组字段",
"insertAfter": "在右侧插入列",
@@ -385,10 +385,10 @@
"nextRecord": "下一条记录",
"previousRecord": "上一条纪录",
"copyApiURL": "复制 API 链接",
- "createTable": "Create New Table",
+ "createTable": "创建新的表格",
"refreshTable": "刷新表格",
- "renameTable": "Rename Table",
- "deleteTable": "Delete Table",
+ "renameTable": "重命名表格",
+ "deleteTable": "删除表格",
"addField": "添加新字段",
"setDisplay": "设置为显示值",
"addRow": "添加新行",
diff --git a/packages/nc-gui/lib/types.ts b/packages/nc-gui/lib/types.ts
index d2c06f44d1..5f158dbe3e 100644
--- a/packages/nc-gui/lib/types.ts
+++ b/packages/nc-gui/lib/types.ts
@@ -60,6 +60,8 @@ export interface Row {
commentCount?: number
changed?: boolean
saving?: boolean
+ // use in datetime picker component
+ isUpdatedFromCopyNPaste?: Record
}
}
diff --git a/packages/nc-gui/nuxt-shim.d.ts b/packages/nc-gui/nuxt-shim.d.ts
index dec8a6e113..4dc4ac605a 100644
--- a/packages/nc-gui/nuxt-shim.d.ts
+++ b/packages/nc-gui/nuxt-shim.d.ts
@@ -18,7 +18,6 @@ declare module '#app/nuxt' {
job:
| {
id: string
- name: string
}
| any,
subscribedCb?: () => void,
diff --git a/packages/nc-gui/package-lock.json b/packages/nc-gui/package-lock.json
index 71d4cce849..57c16ce20f 100644
--- a/packages/nc-gui/package-lock.json
+++ b/packages/nc-gui/package-lock.json
@@ -110,7 +110,7 @@
}
},
"../nocodb-sdk": {
- "version": "0.107.0-beta.1",
+ "version": "0.108.0",
"license": "AGPL-3.0-or-later",
"dependencies": {
"axios": "^0.21.1",
@@ -15245,9 +15245,9 @@
}
},
"node_modules/socket.io-parser": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
- "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
+ "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
@@ -29548,9 +29548,9 @@
}
},
"socket.io-parser": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.1.tgz",
- "integrity": "sha512-V4GrkLy+HeF1F/en3SpUaM+7XxYXpuMUWLGde1kSSh5nQMN4hLrbPIkD+otwh6q9R6NOQBN4AMaOZ2zVjui82g==",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.3.tgz",
+ "integrity": "sha512-JMafRntWVO2DCJimKsRTh/wnqVvO4hrfwOqtO7f+uzwsQMuxO6VwImtYxaQ+ieoyshWOTJyV0fA21lccEXRPpQ==",
"requires": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
diff --git a/packages/nc-gui/pages/index/index/index.vue b/packages/nc-gui/pages/index/index/index.vue
index bc22e036b3..8aeedb8bc6 100644
--- a/packages/nc-gui/pages/index/index/index.vue
+++ b/packages/nc-gui/pages/index/index/index.vue
@@ -90,10 +90,10 @@ const duplicateProject = (project: ProjectType) => {
const { close } = useDialog(resolveComponent('DlgProjectDuplicate'), {
'modelValue': isOpen,
'project': project,
- 'onOk': async (jobData: { name: string; id: string }) => {
+ 'onOk': async (jobData: { id: string }) => {
await loadProjects()
- $jobs.subscribe({ name: jobData.name, id: jobData.id }, undefined, async (status: string) => {
+ $jobs.subscribe({ id: jobData.id }, undefined, async (status: string) => {
if (status === JobStatus.COMPLETED) {
await loadProjects()
} else if (status === JobStatus.FAILED) {
@@ -308,6 +308,7 @@ const copyProjectMeta = async () => {
]