diff --git a/packages/nc-gui-v2/components.d.ts b/packages/nc-gui-v2/components.d.ts
index 9b0fa75f45..79e596ccda 100644
--- a/packages/nc-gui-v2/components.d.ts
+++ b/packages/nc-gui-v2/components.d.ts
@@ -202,6 +202,7 @@ declare module '@vue/runtime-core' {
MdiSearch: typeof import('~icons/mdi/search')['default']
MdiShieldLockOutline: typeof import('~icons/mdi/shield-lock-outline')['default']
MdiSlack: typeof import('~icons/mdi/slack')['default']
+ MdiSort: typeof import('~icons/mdi/sort')['default']
MdiStar: typeof import('~icons/mdi/star')['default']
MdiStarOutline: typeof import('~icons/mdi/star-outline')['default']
MdiStore: typeof import('~icons/mdi/store')['default']
diff --git a/packages/nc-gui-v2/components/api-client/Headers.vue b/packages/nc-gui-v2/components/api-client/Headers.vue
index 7d5685275b..314c455187 100644
--- a/packages/nc-gui-v2/components/api-client/Headers.vue
+++ b/packages/nc-gui-v2/components/api-client/Headers.vue
@@ -87,7 +87,7 @@ const deleteHeaderRow = (idx: number) => vModel.value.splice(idx, 1)
-
+ |
-
+
|
diff --git a/packages/nc-gui-v2/components/cell/Text.vue b/packages/nc-gui-v2/components/cell/Text.vue
index 2c8e54d0d7..23575fc222 100644
--- a/packages/nc-gui-v2/components/cell/Text.vue
+++ b/packages/nc-gui-v2/components/cell/Text.vue
@@ -1,10 +1,9 @@
-
+
@@ -124,6 +138,7 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
+
@@ -144,7 +158,7 @@ const { isSharedForm } = useSmartsheetStoreOrThrow()
([])
-
/** keep user selected File object */
- const storedFiles = ref([])
+ const storedFiles = ref([])
const attachments = ref([])
@@ -54,37 +60,41 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
/** remove a file from our stored attachments (either locally stored or saved ones) */
function removeFile(i: number) {
if (isPublic.value) {
- storedFilesData.value.splice(i, 1)
storedFiles.value.splice(i, 1)
- updateModelValue(storedFilesData.value.map((storedFile) => storedFile.file))
+ updateModelValue(storedFiles.value.map((stored) => stored.file))
} else {
attachments.value.splice(i, 1)
+
updateModelValue(attachments.value)
}
}
/** save a file on select / drop, either locally (in-memory) or in the db */
async function onFileSelect(selectedFiles: FileList | File[]) {
- if (!selectedFiles.length || isPublicGrid) return
+ if (!selectedFiles.length) return
if (isPublic.value) {
- storedFiles.value.push(...selectedFiles)
- storedFilesData.value.push(
+ storedFiles.value.push(
...(await Promise.all(
Array.from(selectedFiles).map(
(file) =>
new Promise((resolve) => {
- const res: AttachmentProps = { file, title: file.name }
- if (isImage(file.name, (file as any).mimetype)) {
+ const res: AttachmentProps = { ...file, file, title: file.name, mimetype: file.type }
+
+ if (isImage(file.name, (file).mimetype ?? file.type)) {
const reader = new FileReader()
- reader.onload = (e: any) => {
+
+ reader.onload = (e) => {
res.data = e.target?.result
+
resolve(res)
}
+
reader.onerror = () => {
resolve(res)
}
+
reader.readAsDataURL(file)
} else {
resolve(res)
@@ -94,7 +104,7 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
)),
)
- return updateModelValue(storedFilesData.value.map((storedFile) => storedFile.file))
+ return updateModelValue(storedFiles.value.map((stored) => stored.file))
}
const newAttachments = []
@@ -149,17 +159,14 @@ export const [useProvideAttachmentCell, useAttachmentCell] = useInjectionState(
}
/** our currently visible items, either the locally stored or the ones from db, depending on isPublicForm status */
- const visibleItems = computed(() => (isPublic.value ? storedFilesData.value : attachments.value) || ([] as any[]))
+ const visibleItems = computed(() => (isPublic.value ? storedFiles.value : attachments.value))
watch(files, (nextFiles) => nextFiles && onFileSelect(nextFiles))
return {
attachments,
- storedFilesData,
visibleItems,
isPublic,
- isForm,
- isPublicGrid,
isReadonly,
meta,
column,
diff --git a/packages/nc-gui-v2/components/dashboard/TreeView.vue b/packages/nc-gui-v2/components/dashboard/TreeView.vue
index 15bf46ee56..483a72dedd 100644
--- a/packages/nc-gui-v2/components/dashboard/TreeView.vue
+++ b/packages/nc-gui-v2/components/dashboard/TreeView.vue
@@ -238,7 +238,7 @@ function openTableCreateDialog() {
>
- {{ $t('tooltip.addTable') }}
+ {{ $t('tooltip.addTable') }}
diff --git a/packages/nc-gui-v2/components/general/HelpAndSupport.vue b/packages/nc-gui-v2/components/general/HelpAndSupport.vue
index 4e638d1fe9..6477d5322d 100644
--- a/packages/nc-gui-v2/components/general/HelpAndSupport.vue
+++ b/packages/nc-gui-v2/components/general/HelpAndSupport.vue
@@ -19,12 +19,13 @@ const openSwaggerLink = () => {
class="flex items-center space-x-1 w-full cursor-pointer pl-3 py-1.5 hover:(text-primary bg-primary bg-opacity-5)"
@click="showDrawer = true"
>
-
+
APIs & Support
-import { RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
-import { useSharedFormStoreOrThrow } from '#imports'
-
-const {
- sharedFormView,
- submitForm,
- v$,
- formState,
- notFound,
- formColumns,
- submitted,
- secondsRemain,
- passwordDlg,
- password,
- loadSharedView,
-} = useSharedFormStoreOrThrow()
-
-function isRequired(_columnObj: Record, required = false) {
- let columnObj = _columnObj
- if (
- columnObj.uidt === UITypes.LinkToAnotherRecord &&
- columnObj.colOptions &&
- columnObj.colOptions.type === RelationTypes.BELONGS_TO
- ) {
- columnObj = formColumns.value?.find((c: Record) => c.id === columnObj.colOptions.fk_child_column_id) as Record<
- string,
- any
- >
- }
-
- return required || (columnObj && columnObj.rqd && !columnObj.cdf)
-}
-
-
-
-
-
- ![](~/assets/img/icons/512x512-trans.png)
-
-
-
-
-
-
-
-
-
-
- New form will be loaded after {{ secondsRemain }} seconds
-
-
-
-
-
-
-
-
-
-
- This shared view is protected
-
-
-
-
- Unlock
-
-
-
-
-
-
-
diff --git a/packages/nc-gui-v2/components/shared-view/Grid.vue b/packages/nc-gui-v2/components/shared-view/Grid.vue
index 59f5310c5e..7c0c8690e9 100644
--- a/packages/nc-gui-v2/components/shared-view/Grid.vue
+++ b/packages/nc-gui-v2/components/shared-view/Grid.vue
@@ -26,7 +26,8 @@ useProvideSmartsheetStore(sharedView as Ref, meta, true, sorts, neste
diff --git a/packages/nc-gui-v2/components/smartsheet-toolbar/Export.vue b/packages/nc-gui-v2/components/smartsheet-toolbar/Export.vue
new file mode 100644
index 0000000000..c9f30b06e3
--- /dev/null
+++ b/packages/nc-gui-v2/components/smartsheet-toolbar/Export.vue
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/nc-gui-v2/components/smartsheet-toolbar/ExportSubActions.vue b/packages/nc-gui-v2/components/smartsheet-toolbar/ExportSubActions.vue
new file mode 100644
index 0000000000..cca5403190
--- /dev/null
+++ b/packages/nc-gui-v2/components/smartsheet-toolbar/ExportSubActions.vue
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue b/packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue
index 36cfbf6417..0adc4306ce 100644
--- a/packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue
+++ b/packages/nc-gui-v2/components/smartsheet-toolbar/FieldsMenu.vue
@@ -64,7 +64,7 @@ watch(
{ immediate: true },
)
-const isAnyFieldHidden = computed(() => fields.value?.some((field) => !(!showSystemFields && field.system) && !field.show))
+const isAnyFieldHidden = computed(() => filteredFieldList.value?.some((field) => !field.show))
const onMove = (event: { moved: { newIndex: number } }) => {
// todo : sync with server
@@ -130,7 +130,7 @@ const getIcon = (c: ColumnType) =>
-
+
{{ $t('activity.showSystemFields') }}
diff --git a/packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue b/packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue
index b91c78f768..704f21c48a 100644
--- a/packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue
+++ b/packages/nc-gui-v2/components/smartsheet-toolbar/SortListMenu.vue
@@ -1,27 +1,34 @@
+
+
+
+
+ {{
+ selectedView?.title
+ }}
+
+
diff --git a/packages/nc-gui-v2/components/smartsheet/Cell.vue b/packages/nc-gui-v2/components/smartsheet/Cell.vue
index 4175fb2b4c..26b9087cdd 100644
--- a/packages/nc-gui-v2/components/smartsheet/Cell.vue
+++ b/packages/nc-gui-v2/components/smartsheet/Cell.vue
@@ -23,6 +23,7 @@ interface Props {
column: ColumnType
modelValue: any
editEnabled: boolean
+ readOnly?: boolean
rowIndex?: number
active?: boolean
virtual?: boolean
@@ -38,12 +39,18 @@ const active = toRef(props, 'active', false)
const virtual = toRef(props, 'virtual', false)
+const readOnly = toRef(props, 'readOnly', undefined)
+
provide(ColumnInj, column)
provide(EditModeInj, useVModel(props, 'editEnabled', emit))
provide(ActiveCellInj, active)
+if (readOnly?.value) {
+ provide(ReadonlyInj, readOnly.value)
+}
+
const isForm = inject(IsFormInj, ref(false))
const isPublic = inject(IsPublicInj, ref(false))
diff --git a/packages/nc-gui-v2/components/smartsheet/Form.vue b/packages/nc-gui-v2/components/smartsheet/Form.vue
index 79d1478466..c023884dbf 100644
--- a/packages/nc-gui-v2/components/smartsheet/Form.vue
+++ b/packages/nc-gui-v2/components/smartsheet/Form.vue
@@ -152,9 +152,8 @@ function onMoveCallback(event: any) {
function onMove(event: any) {
const { newIndex, element, oldIndex } = event.added || event.moved || event.removed
- console.log(event)
+
if (shouldSkipColumn(element)) {
- console.log('SKIPPED')
return
}
@@ -408,7 +407,14 @@ onMounted(async () => {
-
+
()
+const expandedFormRowState = ref>()
const { loadData, paginationData, formattedData: data, loadGalleryData, galleryData, changePage } = useViewData(meta, view as any)
+const { isUIAllowed } = useUIPermission()
+
provide(IsFormInj, ref(false))
provide(IsGridInj, false)
provide(PaginationDataInj, paginationData)
provide(ChangePageInj, changePage)
-provide(ReadonlyInj, true)
+provide(ReadonlyInj, !isUIAllowed('xcDatatableEditable'))
const fields = inject(FieldsInj, ref([]))
@@ -49,12 +57,23 @@ const attachments = (record: any): Array => {
return []
}
}
+
+reloadViewDataHook?.on(async () => {
+ await loadData()
+})
+
+const expandForm = (row: RowType, state?: Record) => {
+ if (!isUIAllowed('xcDatatableEditable')) return
+ expandedFormRow.value = row
+ expandedFormRowState.value = state
+ expandedFormDlg.value = true
+}
-
+
@@ -84,8 +103,8 @@ const attachments = (record: any): Array => {
@@ -94,6 +113,13 @@ const attachments = (record: any): Array => {
+
diff --git a/packages/nc-gui-v2/components/smartsheet/Grid.vue b/packages/nc-gui-v2/components/smartsheet/Grid.vue
index aff46ce8f7..a5db17b0b0 100644
--- a/packages/nc-gui-v2/components/smartsheet/Grid.vue
+++ b/packages/nc-gui-v2/components/smartsheet/Grid.vue
@@ -15,6 +15,7 @@ import {
PaginationDataInj,
ReadonlyInj,
ReloadViewDataHookInj,
+ createEventHook,
enumColor,
inject,
onClickOutside,
@@ -44,8 +45,8 @@ const fields = inject(FieldsInj, ref([]))
const readOnly = inject(ReadonlyInj, false)
const isLocked = inject(IsLockedInj, ref(false))
-const reloadViewDataHook = inject(ReloadViewDataHookInj)
-const openNewRecordFormHook = inject(OpenNewRecordFormHookInj)
+const reloadViewDataHook = inject(ReloadViewDataHookInj, createEventHook())
+const openNewRecordFormHook = inject(OpenNewRecordFormHookInj, createEventHook())
const { isUIAllowed } = useUIPermission()
@@ -382,7 +383,7 @@ const onNavigate = (dir: NavigateDir) => {
diff --git a/packages/nc-gui-v2/components/smartsheet/Toolbar.vue b/packages/nc-gui-v2/components/smartsheet/Toolbar.vue
index 01260b88b3..ec91b6cd7e 100644
--- a/packages/nc-gui-v2/components/smartsheet/Toolbar.vue
+++ b/packages/nc-gui-v2/components/smartsheet/Toolbar.vue
@@ -4,7 +4,7 @@ import ToggleDrawer from '~/components/smartsheet/sidebar/toolbar/ToggleDrawer.v
const { isGrid, isForm, isGallery } = useSmartsheetStoreOrThrow()
const isPublic = inject(IsPublicInj, ref(false))
-const { allowCSVDownload } = useSharedView()
+const { isUIAllowed } = useUIPermission()
const { isOpen } = useSidebar()
@@ -15,11 +15,13 @@ const { isOpen } = useSidebar()
style="z-index: 7"
>
+
+
@@ -28,14 +30,15 @@ const { isOpen } = useSidebar()
+
-
-
+
+
-
+
diff --git a/packages/nc-gui-v2/components/smartsheet/sidebar/toolbar/ToggleDrawer.vue b/packages/nc-gui-v2/components/smartsheet/sidebar/toolbar/ToggleDrawer.vue
index 25ce4945c6..e280cc6533 100644
--- a/packages/nc-gui-v2/components/smartsheet/sidebar/toolbar/ToggleDrawer.vue
+++ b/packages/nc-gui-v2/components/smartsheet/sidebar/toolbar/ToggleDrawer.vue
@@ -5,7 +5,7 @@ const { isOpen, toggle } = useSidebar({ storageKey: 'nc-right-sidebar' })
-
+
Views
diff --git a/packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue b/packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue
index 4c5ffb19ba..618a18f6f2 100644
--- a/packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue
+++ b/packages/nc-gui-v2/components/tabs/auth/user-management/ShareBase.vue
@@ -143,7 +143,7 @@ onMounted(() => {
{{ $t('activity.shareBase.link') }}
- {{ url }}
+ {{ url }}
@@ -191,7 +191,7 @@ onMounted(() => {
-
+
{{ $t('activity.shareBase.enable') }}
{{ $t('activity.shareBase.disable') }}
@@ -208,7 +208,7 @@ onMounted(() => {
-
+
diff --git a/packages/nc-gui-v2/components/webhook/Editor.vue b/packages/nc-gui-v2/components/webhook/Editor.vue
index 9d92a2b0fc..f69863c632 100644
--- a/packages/nc-gui-v2/components/webhook/Editor.vue
+++ b/packages/nc-gui-v2/components/webhook/Editor.vue
@@ -413,14 +413,14 @@ onMounted(async () => {
-
+
-
+
{{ event.text.join(' ') }}
@@ -432,6 +432,7 @@ onMounted(async () => {
@@ -470,7 +471,7 @@ onMounted(async () => {
-
+
@@ -482,7 +483,7 @@ onMounted(async () => {
-
+
@@ -566,7 +567,7 @@ onMounted(async () => {
- On Condition
+ On Condition
diff --git a/packages/nc-gui-v2/components/webhook/List.vue b/packages/nc-gui-v2/components/webhook/List.vue
index 2fbdd8f8b2..3a829798dc 100644
--- a/packages/nc-gui-v2/components/webhook/List.vue
+++ b/packages/nc-gui-v2/components/webhook/List.vue
@@ -52,7 +52,7 @@ onMounted(() => {
{{ meta.title }} : Webhooks
-
+
{{ $t('activity.addWebhook') }}
diff --git a/packages/nc-gui-v2/composables/useSharedFormViewStore.ts b/packages/nc-gui-v2/composables/useSharedFormViewStore.ts
index 902405b41c..46508aab80 100644
--- a/packages/nc-gui-v2/composables/useSharedFormViewStore.ts
+++ b/packages/nc-gui-v2/composables/useSharedFormViewStore.ts
@@ -1,12 +1,21 @@
import useVuelidate from '@vuelidate/core'
import { minLength, required } from '@vuelidate/validators'
+import type { Ref } from 'vue'
import { message } from 'ant-design-vue'
import type { ColumnType, FormType, LinkToAnotherRecordType, TableType, ViewType } from 'nocodb-sdk'
import { ErrorMessages, RelationTypes, UITypes, isVirtualCol } from 'nocodb-sdk'
-import type { Ref } from 'vue'
-import { SharedViewPasswordInj } from '~/context'
-import { extractSdkResponseErrorMsg } from '~/utils'
-import { useInjectionState, useMetas } from '#imports'
+import {
+ SharedViewPasswordInj,
+ computed,
+ extractSdkResponseErrorMsg,
+ provide,
+ ref,
+ useApi,
+ useInjectionState,
+ useMetas,
+ useProvideSmartsheetRowStore,
+ watch,
+} from '#imports'
const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((sharedViewId: string) => {
const progress = ref(false)
@@ -23,8 +32,10 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
const meta = ref ()
const columns = ref<(ColumnType & { required?: boolean; show?: boolean })[]>()
- const { $api } = useNuxtApp()
+ const { api, isLoading } = useApi()
+
const { metas, setMeta } = useMetas()
+
const formState = ref({})
const { state: additionalState } = useProvideSmartsheetRowStore(
@@ -37,11 +48,11 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
)
const formColumns = computed(() =>
- columns?.value?.filter((c) => c.show)?.filter((col) => !isVirtualCol(col) || col.uidt === UITypes.LinkToAnotherRecord),
+ columns.value?.filter((c) => c.show).filter((col) => !isVirtualCol(col) || col.uidt === UITypes.LinkToAnotherRecord),
)
const loadSharedView = async () => {
try {
- const viewMeta = await $api.public.sharedViewMetaGet(sharedViewId, {
+ const viewMeta: Record = await api.public.sharedViewMetaGet(sharedViewId, {
headers: {
'xc-password': password.value,
},
@@ -54,9 +65,10 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
meta.value = viewMeta.model
columns.value = viewMeta.model?.columns
- setMeta(viewMeta.model)
+ await setMeta(viewMeta.model)
const relatedMetas = { ...viewMeta.relatedMetas }
+
Object.keys(relatedMetas).forEach((key) => setMeta(relatedMetas[key]))
} catch (e: any) {
if (e.response && e.response.status === 404) {
@@ -68,11 +80,14 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
}
const validators = computed(() => {
- const obj: any = {
+ const obj: Record> = {
localState: {},
virtual: {},
}
- for (const column of formColumns?.value ?? []) {
+
+ if (!formColumns.value) return obj
+
+ for (const column of formColumns.value) {
if (
!isVirtualCol(column) &&
((column.rqd && !column.cdf) || (column.pk && !(column.ai || column.cdf)) || (column as any).required)
@@ -103,7 +118,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
const v$ = useVuelidate(
validators,
- computed(() => ({ localState: formState?.value, virtual: additionalState?.value })),
+ computed(() => ({ localState: formState.value, virtual: additionalState.value })),
)
const submitForm = async () => {
@@ -113,18 +128,20 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
}
progress.value = true
- const data: Record = { ...(formState?.value ?? {}), ...(additionalState?.value || {}) }
+ const data: Record = { ...formState.value, ...additionalState.value }
const attachment: Record = {}
- for (const col of metas?.value?.[sharedView?.value?.fk_model_id as string]?.columns ?? []) {
+ /** find attachments in form data */
+ for (const col of metas.value?.[sharedView.value?.fk_model_id as string]?.columns) {
if (col.uidt === UITypes.Attachment) {
- attachment[`_${col.title}`] = data[col.title!]
- delete data[col.title!]
+ if (data[col.title]) {
+ attachment[`_${col.title}`] = data[col.title].map((item: { file: File }) => item.file)
+ }
}
}
- await $api.public.dataCreate(
- sharedView?.value?.uuid as string,
+ await api.public.dataCreate(
+ (sharedView.value as any)?.uuid as string,
{
data,
...attachment,
@@ -139,7 +156,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
submitted.value = true
progress.value = false
- await message.success(sharedFormView.value?.success_msg || 'Saved successfully.')
+ await message.success(sharedFormView.value?.sucess_msg || 'Saved successfully.')
} catch (e: any) {
console.log(e)
await message.error(await extractSdkResponseErrorMsg(e))
@@ -148,13 +165,15 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
}
/** reset form if show_blank_form is true */
- watch(submitted, (nextVal: boolean) => {
- if (nextVal && sharedFormView.value?.show_blank_form) {
+ watch(submitted, (nextVal) => {
+ if (nextVal && (sharedFormView.value as any)?.show_blank_form) {
secondsRemain.value = 5
const intvl = setInterval(() => {
secondsRemain.value = secondsRemain.value - 1
+
if (secondsRemain.value < 0) {
submitted.value = false
+
clearInterval(intvl)
}
}, 1000)
@@ -185,6 +204,7 @@ const [useProvideSharedFormStore, useSharedFormStore] = useInjectionState((share
submitted,
secondsRemain,
passwordDlg,
+ isLoading,
}
}, 'expanded-form-store')
@@ -192,6 +212,8 @@ export { useProvideSharedFormStore }
export function useSharedFormStoreOrThrow() {
const sharedFormStore = useSharedFormStore()
+
if (sharedFormStore == null) throw new Error('Please call `useProvideSharedFormStore` on the appropriate parent component')
+
return sharedFormStore
}
diff --git a/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts b/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts
index de2987577e..5267fc4498 100644
--- a/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts
+++ b/packages/nc-gui-v2/composables/useSmartsheetRowStore.ts
@@ -2,27 +2,41 @@ import { message } from 'ant-design-vue'
import { UITypes } from 'nocodb-sdk'
import type { ColumnType, LinkToAnotherRecordType, RelationTypes, TableType } from 'nocodb-sdk'
import type { Ref } from 'vue'
+import type { MaybeRef } from '@vueuse/core'
import type { Row } from './useViewData'
-import { useInjectionState, useMetas, useNuxtApp, useProject, useVirtualCell } from '#imports'
-import { NOCO } from '~/lib'
-import { deepCompare, extractPkFromRow, extractSdkResponseErrorMsg } from '~/utils'
+import {
+ NOCO,
+ computed,
+ deepCompare,
+ extractPkFromRow,
+ extractSdkResponseErrorMsg,
+ ref,
+ unref,
+ useInjectionState,
+ useMetas,
+ useNuxtApp,
+ useProject,
+ useVirtualCell,
+} from '#imports'
-const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState((meta: Ref, row: Ref) => {
+const [useProvideSmartsheetRowStore, useSmartsheetRowStore] = useInjectionState((meta: Ref, row: MaybeRef) => {
const { $api } = useNuxtApp()
+
const { project } = useProject()
+
const { metas } = useMetas()
// state
const state = ref | Record[] | null>>({})
// getters
- const isNew = computed(() => row.value?.rowMeta?.new ?? false)
+ const isNew = computed(() => unref(row).rowMeta?.new ?? false)
// actions
const addLTARRef = async (value: Record, column: ColumnType) => {
const { isHm, isMm, isBt } = $(useVirtualCell(ref(column)))
if (isHm || isMm) {
- state.value[column.title!] = state.value[column.title!] || []
+ if (!state.value[column.title!]) state.value[column.title!] = []
if (state.value[column.title!]!.find((ln: Record) => deepCompare(ln, value))) {
return message.info('This value is already in the list')
@@ -106,6 +120,8 @@ export { useProvideSmartsheetRowStore }
export function useSmartsheetRowStoreOrThrow() {
const smartsheetRowStore = useSmartsheetRowStore()
+
if (smartsheetRowStore == null) throw new Error('Please call `useSmartsheetRowStore` on the appropriate parent component')
+
return smartsheetRowStore
}
diff --git a/packages/nc-gui-v2/composables/useUIPermission/rolePermissions.ts b/packages/nc-gui-v2/composables/useUIPermission/rolePermissions.ts
index b0884700bd..b89ef57c00 100644
--- a/packages/nc-gui-v2/composables/useUIPermission/rolePermissions.ts
+++ b/packages/nc-gui-v2/composables/useUIPermission/rolePermissions.ts
@@ -8,6 +8,7 @@ const rolePermissions = {
column: true,
tableAttachment: true,
tableRowUpdate: true,
+ dataInsert: true,
rowComments: true,
gridViewOptions: true,
sortSync: true,
diff --git a/packages/nc-gui-v2/composables/useViewColumns.ts b/packages/nc-gui-v2/composables/useViewColumns.ts
index 830e9651eb..ac1da0e890 100644
--- a/packages/nc-gui-v2/composables/useViewColumns.ts
+++ b/packages/nc-gui-v2/composables/useViewColumns.ts
@@ -19,6 +19,22 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
const { isSharedBase } = useProject()
+ const isLocalMode = computed(
+ () => isPublic.value || !isUIAllowed('hideAllColumns') || !isUIAllowed('showAllColumns') || isSharedBase.value,
+ )
+
+ const metaColumnById = computed>(() => {
+ if (!meta.value?.columns) return {}
+
+ return meta.value?.columns?.reduce(
+ (acc: ColumnType, curr: ColumnType) => ({
+ ...acc,
+ [curr.id!]: curr,
+ }),
+ {} as any,
+ )
+ })
+
const loadViewColumns = async () => {
if (!meta || !view) return
@@ -35,6 +51,7 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
[curr.fk_column_id]: curr,
}
}, {})
+
fields.value = meta.value?.columns
?.map((column: ColumnType) => {
const currentColumnField = fieldById[column.id!] || {}
@@ -44,7 +61,7 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
fk_column_id: column.id,
...currentColumnField,
order: currentColumnField.order || order++,
- system: isSystemColumn(currentColumnField.type || false),
+ system: isSystemColumn(metaColumnById?.value?.[currentColumnField.fk_column_id!]),
}
})
.sort((a: Field, b: Field) => a.order - b.order)
@@ -52,7 +69,7 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
}
const showAll = async (ignoreIds?: any) => {
- if (isPublic.value || isSharedBase.value) {
+ if (isLocalMode.value) {
fields.value = fields.value?.map((field: Field) => ({
...field,
show: true,
@@ -75,7 +92,7 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
reloadData?.()
}
const hideAll = async (ignoreIds?: any) => {
- if (isPublic.value || isSharedBase.value) {
+ if (isLocalMode.value) {
fields.value = fields.value?.map((field: Field) => ({
...field,
show: false,
@@ -125,18 +142,6 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
reloadData?.()
}
- const metaColumnById = computed>(() => {
- if (!meta.value?.columns) return {}
-
- return meta.value?.columns?.reduce(
- (acc: ColumnType, curr: ColumnType) => ({
- ...acc,
- [curr.id!]: curr,
- }),
- {} as any,
- )
- })
-
const showSystemFields = computed({
get() {
// todo: show_system_fields missing from ViewType
@@ -144,7 +149,7 @@ export function useViewColumns(view: Ref | undefined, meta: ComputedRe
},
set(v: boolean) {
if (view?.value?.id) {
- if (!isPublic.value && !isSharedBase.value) {
+ if (!isLocalMode.value) {
$api.dbView
.update(view.value.id, {
show_system_fields: v,
diff --git a/packages/nc-gui-v2/layouts/base.vue b/packages/nc-gui-v2/layouts/base.vue
index 213e023889..4f07833abb 100644
--- a/packages/nc-gui-v2/layouts/base.vue
+++ b/packages/nc-gui-v2/layouts/base.vue
@@ -59,8 +59,6 @@ hooks.hook('page:finish', () => {
-
-
Switch language
diff --git a/packages/nc-gui-v2/layouts/default.vue b/packages/nc-gui-v2/layouts/default.vue
index 0b68f61af8..289aa78aa9 100644
--- a/packages/nc-gui-v2/layouts/default.vue
+++ b/packages/nc-gui-v2/layouts/default.vue
@@ -1,14 +1,14 @@
-
+
+
+
diff --git a/packages/nc-gui-v2/pages/[projectType]/form/[viewId]/index.vue b/packages/nc-gui-v2/pages/[projectType]/form/[viewId]/index.vue
new file mode 100644
index 0000000000..97b17d9724
--- /dev/null
+++ b/packages/nc-gui-v2/pages/[projectType]/form/[viewId]/index.vue
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
diff --git a/packages/nc-gui-v2/pages/index/index/index.vue b/packages/nc-gui-v2/pages/index/index/index.vue
index 00063525f0..8e472399fd 100644
--- a/packages/nc-gui-v2/pages/index/index/index.vue
+++ b/packages/nc-gui-v2/pages/index/index/index.vue
@@ -72,7 +72,7 @@ await loadProjects()
- {{ $t('title.myProject') }}
+ {{ $t('title.myProject') }}
{
export const isValidURL = (str: string) => {
const pattern =
/^(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00A1-\uFFFF0-9]-*)*[a-z\u00A1-\uFFFF0-9]+)(?:\.(?:[a-z\u00A1-\uFFFF0-9]-*)*[a-z\u00A1-\uFFFF0-9]+)*(?:\.(?:[a-z\u00A1-\uFFFF]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/i
- return !!pattern.test(str)
+
+ return pattern.test(str)
}
-export const openLink = (path: string, baseURL: string, target = '_blank') => {
+export const openLink = (path: string, baseURL?: string, target = '_blank') => {
const url = new URL(path, baseURL)
window.open(url.href, target)
}
diff --git a/packages/nc-gui-v2/windi.config.ts b/packages/nc-gui-v2/windi.config.ts
index 306b909724..5762ea30d4 100644
--- a/packages/nc-gui-v2/windi.config.ts
+++ b/packages/nc-gui-v2/windi.config.ts
@@ -65,10 +65,6 @@ export default defineConfig({
primary: 'rgba(var(--color-primary), var(--tw-bg-opacity))',
accent: 'rgba(var(--color-accent), var(--tw-bg-opacity))',
},
- ringColor: {
- primary: 'rgba(var(--color-primary), var(--tw-ring-opacity))',
- accent: 'rgba(var(--color-accent), var(--tw-ring-opacity))',
- },
colors: {
...windiColors,
...themeColors,
diff --git a/packages/nocodb/src/run/docker.ts b/packages/nocodb/src/run/docker.ts
index b506b91a63..d26d109970 100644
--- a/packages/nocodb/src/run/docker.ts
+++ b/packages/nocodb/src/run/docker.ts
@@ -6,7 +6,8 @@ process.env.NC_VERSION = '0009044';
const server = express();
server.enable('trust proxy');
-
+server.disable('etag');
+server.disable('x-powered-by');
server.use(
cors({
exposedHeaders: 'xc-db-response',
@@ -15,12 +16,6 @@ server.use(
server.set('view engine', 'ejs');
-// process.env[`NC_DB`] = `mysql2://localhost:3306?u=root&p=password&d=mar_21`;
-// process.env[`NC_DB`] = `pg://localhost:3306?u=root&p=password&d=mar_24`;
-// process.env[`NC_DB`] = `pg://localhost:5432?u=postgres&p=password&d=abcde`;
-// process.env[`NC_TRY`] = 'true';
-// process.env[`NC_DASHBOARD_URL`] = '/test';
-
process.env[`DEBUG`] = 'xc*';
(async () => {
diff --git a/packages/nocodb/src/run/dockerRunMysql.ts b/packages/nocodb/src/run/dockerRunMysql.ts
index 5eaecdd51d..56cc4b939c 100644
--- a/packages/nocodb/src/run/dockerRunMysql.ts
+++ b/packages/nocodb/src/run/dockerRunMysql.ts
@@ -6,7 +6,8 @@ process.env.NC_VERSION = '0009044';
const server = express();
server.enable('trust proxy');
-
+server.disable('etag');
+server.disable('x-powered-by');
server.use(
cors({
exposedHeaders: 'xc-db-response',
@@ -25,7 +26,7 @@ process.env[`NC_DB`] = `mysql2://localhost:3306?u=root&p=password&d=${metaDb}`;
// process.env[`NC_TRY`] = 'true';
// process.env[`NC_DASHBOARD_URL`] = '/test';
-process.env[`DEBUG`] = 'xc*';
+// process.env[`DEBUG`] = 'xc*';
(async () => {
const httpServer = server.listen(process.env.PORT || 8080, () => {
diff --git a/packages/nocodb/src/run/dockerRunPG.ts b/packages/nocodb/src/run/dockerRunPG.ts
index 8c2d40b3c7..930c1ee62a 100644
--- a/packages/nocodb/src/run/dockerRunPG.ts
+++ b/packages/nocodb/src/run/dockerRunPG.ts
@@ -6,7 +6,8 @@ process.env.NC_VERSION = '0009044';
const server = express();
server.enable('trust proxy');
-
+server.disable('etag');
+server.disable('x-powered-by');
server.use(
cors({
exposedHeaders: 'xc-db-response',
@@ -25,7 +26,7 @@ process.env[`NC_DB`] = `pg://localhost:5432?u=postgres&p=password&d=${metaDb}`;
// process.env[`NC_TRY`] = 'true';
// process.env[`NC_DASHBOARD_URL`] = '/test';
-process.env[`DEBUG`] = 'xc*';
+// process.env[`DEBUG`] = 'xc*';
(async () => {
const httpServer = server.listen(process.env.PORT || 8080, () => {
diff --git a/packages/nocodb/src/run/dockerRunPG_CyQuick.ts b/packages/nocodb/src/run/dockerRunPG_CyQuick.ts
index 7d3ebf3e42..b26d86b0dd 100644
--- a/packages/nocodb/src/run/dockerRunPG_CyQuick.ts
+++ b/packages/nocodb/src/run/dockerRunPG_CyQuick.ts
@@ -6,7 +6,8 @@ process.env.NC_VERSION = '0009044';
const server = express();
server.enable('trust proxy');
-
+server.disable('etag');
+server.disable('x-powered-by');
server.use(
cors({
exposedHeaders: 'xc-db-response',
@@ -18,7 +19,7 @@ process.env[
`NC_DB`
] = `pg://localhost:5432?u=postgres&p=password&d=meta_v2_2022_06_13`;
-process.env[`DEBUG`] = 'xc*';
+//process.env[`DEBUG`] = 'xc*';
(async () => {
const httpServer = server.listen(process.env.PORT || 8080, () => {
| |