langs.find((lang) => lang.name === selectedLa
const code = $computed(() => {
if (activeLang?.name === 'nocodb-sdk') {
- return `${selectedClient === 'node' ? 'const { Api } require("nocodb-sdk");' : 'import { Api } from "nocodb-sdk";'}
+ return `${selectedClient === 'node' ? 'const { Api } = require("nocodb-sdk");' : 'import { Api } from "nocodb-sdk";'}
const api = new Api({
- baseURL: ${JSON.stringify(apiUrl)},
+ baseURL: "${(appInfo && appInfo.ncSiteUrl) || '/'}",
headers: {
"xc-auth": ${JSON.stringify(token as string)}
}
diff --git a/packages/nc-gui/components/smartsheet/Cell.vue b/packages/nc-gui/components/smartsheet/Cell.vue
index 12636665a8..dfab72b7fa 100644
--- a/packages/nc-gui/components/smartsheet/Cell.vue
+++ b/packages/nc-gui/components/smartsheet/Cell.vue
@@ -10,11 +10,36 @@ import {
ReadonlyInj,
computed,
inject,
+ isAttachment,
+ isAutoSaved,
+ isBoolean,
+ isCurrency,
+ isDate,
+ isDateTime,
+ isDecimal,
+ isDuration,
+ isEmail,
+ isFloat,
+ isInt,
+ isJSON,
+ isManualSaved,
+ isMultiSelect,
+ isPercent,
+ isPhoneNumber,
+ isPrimary,
+ isPrimaryKey,
+ isRating,
+ isSingleSelect,
+ isString,
+ isTextArea,
+ isTime,
+ isURL,
+ isYear,
provide,
ref,
toRef,
- useColumn,
useDebounceFn,
+ useProject,
useSmartsheetRowStoreOrThrow,
useVModel,
} from '#imports'
@@ -46,9 +71,7 @@ provide(EditModeInj, useVModel(props, 'editEnabled', emit))
provide(ActiveCellInj, active)
-if (readOnly?.value) {
- provide(ReadonlyInj, readOnly)
-}
+provide(ReadonlyInj, readOnly)
const isForm = inject(IsFormInj, ref(false))
@@ -58,6 +81,10 @@ const isLocked = inject(IsLockedInj, ref(false))
const { currentRow } = useSmartsheetRowStoreOrThrow()
+const { sqlUi } = useProject()
+
+const abstractType = computed(() => column.value && sqlUi.value.getAbstractType(column.value))
+
const syncValue = useDebounceFn(
() => {
currentRow.value.rowMeta.changed = false
@@ -66,33 +93,6 @@ const syncValue = useDebounceFn(
500,
{ maxWait: 2000 },
)
-const {
- isPrimary,
- isURL,
- isEmail,
- isJSON,
- isDate,
- isYear,
- isDateTime,
- isTime,
- isBoolean,
- isDuration,
- isRating,
- isCurrency,
- isAttachment,
- isTextArea,
- isString,
- isInt,
- isFloat,
- isDecimal,
- isSingleSelect,
- isMultiSelect,
- isPercent,
- isPhoneNumber,
- isAutoSaved,
- isManualSaved,
- isPrimaryKey,
-} = useColumn(column)
const vModel = computed({
get: () => props.modelValue,
@@ -100,9 +100,9 @@ const vModel = computed({
if (val !== props.modelValue) {
currentRow.value.rowMeta.changed = true
emit('update:modelValue', val)
- if (isAutoSaved.value) {
+ if (isAutoSaved(column.value)) {
syncValue()
- } else if (!isManualSaved.value) {
+ } else if (!isManualSaved(column.value)) {
emit('save')
currentRow.value.rowMeta.changed = true
}
@@ -112,7 +112,7 @@ const vModel = computed({
const syncAndNavigate = (dir: NavigateDir, e: KeyboardEvent) => {
console.log('syncAndNavigate', e.target)
- if (isJSON.value) return
+ if (isJSON(column.value)) return
if (currentRow.value.rowMeta.changed || currentRow.value.rowMeta.new) {
emit('save')
@@ -127,32 +127,41 @@ const syncAndNavigate = (dir: NavigateDir, e: KeyboardEvent) => {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/nc-gui/components/smartsheet/Grid.vue b/packages/nc-gui/components/smartsheet/Grid.vue
index 7ce1602d06..fcaa154b32 100644
--- a/packages/nc-gui/components/smartsheet/Grid.vue
+++ b/packages/nc-gui/components/smartsheet/Grid.vue
@@ -524,19 +524,23 @@ provide(ReloadRowDataHookInj, reloadViewDataHook)
watch(
view,
async (next, old) => {
- if (next && next.id !== old?.id) {
- // whenever tab changes or view changes save any unsaved data
- if (old?.id) {
- const oldMeta = await getMeta(old.fk_model_id!)
- if (oldMeta) {
- await saveOrUpdateRecords({
- viewMetaValue: old,
- metaValue: oldMeta as TableType,
- data: data.value,
- })
+ try {
+ if (next && next.id !== old?.id) {
+ // whenever tab changes or view changes save any unsaved data
+ if (old?.id) {
+ const oldMeta = await getMeta(old.fk_model_id!)
+ if (oldMeta) {
+ await saveOrUpdateRecords({
+ viewMetaValue: old,
+ metaValue: oldMeta as TableType,
+ data: data.value,
+ })
+ }
}
+ await loadData()
}
- await loadData()
+ } catch (e) {
+ console.log(e)
}
},
{ immediate: true },
diff --git a/packages/nc-gui/components/smartsheet/VirtualCell.vue b/packages/nc-gui/components/smartsheet/VirtualCell.vue
index 9e935f9550..4ab569fbce 100644
--- a/packages/nc-gui/components/smartsheet/VirtualCell.vue
+++ b/packages/nc-gui/components/smartsheet/VirtualCell.vue
@@ -1,6 +1,22 @@
-
-
-
-
diff --git a/packages/nc-gui/components/smartsheet/header/VirtualCell.vue b/packages/nc-gui/components/smartsheet/header/VirtualCell.vue
index f0dc511883..329ccac8a5 100644
--- a/packages/nc-gui/components/smartsheet/header/VirtualCell.vue
+++ b/packages/nc-gui/components/smartsheet/header/VirtualCell.vue
@@ -7,6 +7,12 @@ import {
MetaInj,
computed,
inject,
+ isBt,
+ isFormula,
+ isHm,
+ isLookup,
+ isMm,
+ isRollup,
isVirtualColRequired,
provide,
ref,
@@ -14,7 +20,6 @@ import {
useI18n,
useMetas,
useUIPermission,
- useVirtualCell,
} from '#imports'
const props = defineProps<{ column: ColumnType; hideMenu?: boolean; required?: boolean | number }>()
@@ -37,14 +42,12 @@ const meta = inject(MetaInj, ref())
const isForm = inject(IsFormInj, ref(false))
-const { isLookup, isBt, isRollup, isMm, isHm, isFormula } = useVirtualCell(column)
-
const colOptions = $computed(() => column.value?.colOptions)
const tableTile = $computed(() => meta?.value?.title)
const relationColumnOptions = $computed(() => {
- if (isMm.value || isHm.value || isBt.value) {
+ if (isMm(column.value) || isHm(column.value) || isBt(column.value)) {
return column.value?.colOptions as LinkToAnotherRecordType
} else if ((column?.value?.colOptions as LookupType | RollupType)?.fk_relation_column_id) {
return meta?.value?.columns?.find(
@@ -62,10 +65,10 @@ const relatedTableTitle = $computed(() => relatedTableMeta?.title)
const childColumn = $computed(() => {
if (relatedTableMeta?.columns) {
- if (isRollup.value) {
+ if (isRollup(column.value)) {
return relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as RollupType).fk_rollup_column_id)
}
- if (isLookup.value) {
+ if (isLookup(column.value)) {
return relatedTableMeta?.columns.find((c: ColumnType) => c.id === (colOptions as LookupType).fk_lookup_column_id)
}
}
@@ -76,22 +79,22 @@ const tooltipMsg = computed(() => {
if (!column.value) {
return ''
}
- if (isHm.value) {
+ if (isHm(column.value)) {
return `'${tableTile}' ${t('labels.hasMany')} '${relatedTableTitle}'`
- } else if (isMm.value) {
+ } else if (isMm(column.value)) {
return `'${tableTile}' & '${relatedTableTitle}' ${t('labels.manyToMany')}`
- } else if (isBt.value) {
+ } else if (isBt(column.value)) {
return `'${column?.value?.title}' ${t('labels.belongsTo')} '${relatedTableTitle}'`
- } else if (isLookup.value) {
+ } else if (isLookup(column.value)) {
return `'${childColumn.title}' from '${relatedTableTitle}' (${childColumn.uidt})`
- } else if (isFormula.value) {
+ } else if (isFormula(column.value)) {
const formula = substituteColumnIdWithAliasInFormula(
(column.value?.colOptions as FormulaType)?.formula,
meta?.value?.columns as ColumnType[],
(column.value?.colOptions as any)?.formula_raw,
)
return `Formula - ${formula}`
- } else if (isRollup.value) {
+ } else if (isRollup(column.value)) {
return `'${childColumn.title}' of '${relatedTableTitle}' (${childColumn.uidt})`
}
return ''
diff --git a/packages/nc-gui/components/smartsheet/header/VirtualCellIcon.vue b/packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
similarity index 62%
rename from packages/nc-gui/components/smartsheet/header/VirtualCellIcon.vue
rename to packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
index 5ad8dee881..029543fb48 100644
--- a/packages/nc-gui/components/smartsheet/header/VirtualCellIcon.vue
+++ b/packages/nc-gui/components/smartsheet/header/VirtualCellIcon.ts
@@ -1,8 +1,8 @@
-
+}
+
+export default defineComponent({
+ name: 'VirtualCellIcon',
+ props: {
+ columnMeta: {
+ type: Object as PropType,
+ required: false,
+ },
+ },
+ setup(props) {
+ const columnMeta = toRef(props, 'columnMeta')
+
+ const column = inject(ColumnInj, columnMeta) as Ref
+
+ let relationColumn: ColumnType & { colOptions: LookupType }
+
+ return () => {
+ if (!column.value) return null
-
-
-
+ if (column && column.value) {
+ if (isMm(column.value) || isHm(column.value) || isBt(column.value) || isLookup(column.value) || isRollup(column.value)) {
+ const meta = inject(MetaInj, ref())
+
+ relationColumn = meta.value?.columns?.find(
+ (c) => c.id === column.value?.colOptions?.fk_relation_column_id,
+ ) as ColumnType & {
+ colOptions: LinkToAnotherRecordType
+ }
+ }
+ }
+
+ const { icon: Icon, color } = renderIcon(column.value, relationColumn)
+
+ return h(Icon, { class: `${color} mx-1 !text-xs` })
+ }
+ },
+})
diff --git a/packages/nc-gui/components/tabs/auth/UserManagement.vue b/packages/nc-gui/components/tabs/auth/UserManagement.vue
index e86dd444c0..05941c2470 100644
--- a/packages/nc-gui/components/tabs/auth/UserManagement.vue
+++ b/packages/nc-gui/components/tabs/auth/UserManagement.vue
@@ -1,4 +1,5 @@
@@ -252,6 +257,13 @@ watchDebounced(searchText, () => loadUsers(), { debounce: 300, maxWait: 600 })
+
+ Super Admin
+
loadUsers(), { debounce: 300, maxWait: 600 })
-
-
- {{ $t('activity.editUser') }}
-
-
-
-
-
+
+
+
+ {{ $t('activity.editUser') }}
-
-
-
-
-
-
- {{ $t('activity.addUserToProject') }}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('activity.addUserToProject') }}
-
-
-
-
-
-
- {{ $t('activity.deleteUser') }}
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('activity.deleteUser') }}
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ $t('activity.resendInvite') }}
-
-
-
-
-
-
{{ $t('activity.copyInviteURL') }}
+
+
+
+
+
+
+
+
+
+
+
+
{{ $t('activity.resendInvite') }}
+
+
+
+
+
+
{{ $t('activity.copyInviteURL') }}
+
+
+
+
+
+
diff --git a/packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue b/packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue
index 59984d352c..c8b509916c 100644
--- a/packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue
+++ b/packages/nc-gui/components/tabs/auth/user-management/UsersModal.vue
@@ -3,7 +3,6 @@ import {
Form,
computed,
extractSdkResponseErrorMsg,
- isEmail,
message,
onMounted,
projectRoleTagColors,
@@ -14,6 +13,7 @@ import {
useI18n,
useNuxtApp,
useProject,
+ validateEmail,
} from '#imports'
import type { User } from '~/lib'
import { ProjectRole } from '~/lib'
@@ -57,7 +57,7 @@ const validators = computed(() => {
callback('Email is required')
return
}
- const invalidEmails = (value || '').split(/\s*,\s*/).filter((e: string) => !isEmail(e))
+ const invalidEmails = (value || '').split(/\s*,\s*/).filter((e: string) => !validateEmail(e))
if (invalidEmails.length > 0) {
callback(`${invalidEmails.length > 1 ? ' Invalid emails:' : 'Invalid email:'} ${invalidEmails.join(', ')} `)
} else {
diff --git a/packages/nc-gui/components/virtual-cell/Lookup.vue b/packages/nc-gui/components/virtual-cell/Lookup.vue
index 942a0879db..1040868cec 100644
--- a/packages/nc-gui/components/virtual-cell/Lookup.vue
+++ b/packages/nc-gui/components/virtual-cell/Lookup.vue
@@ -1,7 +1,6 @@