Browse Source

Merge branch 'develop' into nc-refactor/1767-links

pull/6920/head
Pranav C 10 months ago committed by GitHub
parent
commit
4e98130a3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/nc-gui/components/account/License.vue
  2. 2
      packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue
  3. 3
      packages/nc-gui/components/dashboard/TreeView/TableList.vue
  4. 3
      packages/nc-gui/components/dashboard/TreeView/TableNode.vue
  5. 3
      packages/nc-gui/components/dashboard/TreeView/index.vue
  6. 41
      packages/nc-gui/components/dashboard/View.vue
  7. 9
      packages/nc-gui/components/dashboard/settings/DataSources.vue
  8. 51
      packages/nc-gui/components/dashboard/settings/UIAcl.vue
  9. 2
      packages/nc-gui/components/dlg/QuickImport.vue
  10. 35
      packages/nc-gui/components/general/CopyUrl.vue
  11. 15
      packages/nc-gui/components/general/DeleteModal.vue
  12. 15
      packages/nc-gui/components/smartsheet/expanded-form/Comments.vue
  13. 13
      packages/nc-gui/components/smartsheet/expanded-form/index.vue
  14. 27
      packages/nc-gui/components/smartsheet/grid/Table.vue
  15. 6
      packages/nc-gui/components/smartsheet/toolbar/ViewInfo.vue
  16. 16
      packages/nc-gui/components/virtual-cell/QrCode.vue
  17. 8
      packages/nc-gui/components/virtual-cell/barcode/Barcode.vue
  18. 42
      packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.vue
  19. 2
      packages/nc-gui/components/workspace/ProjectList.vue
  20. 3
      packages/nc-gui/composables/useGlobal/actions.ts
  21. 2
      packages/nc-gui/composables/useGlobal/index.ts
  22. 2
      packages/nc-gui/helpers/parsers/JSONUrlTemplateAdapter.ts
  23. 8
      packages/nc-gui/lang/en.json
  24. 2
      packages/nc-gui/package.json
  25. 2
      packages/nc-gui/plugins/state.ts
  26. 4
      packages/nc-gui/store/config.ts
  27. 2457
      pnpm-lock.yaml

2
packages/nc-gui/components/account/License.vue

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useNuxtApp } from '#app'
import { useNuxtApp } from '#imports'
import { message } from 'ant-design-vue'
import { extractSdkResponseErrorMsg, useApi, useGlobal } from '#imports'

2
packages/nc-gui/components/dashboard/TreeView/ProjectNode.vue

@ -26,6 +26,7 @@ import {
useDialog,
useGlobal,
useI18n,
useNuxtApp,
useRoles,
useRouter,
useTablesStore,
@ -33,7 +34,6 @@ import {
useToggle,
} from '#imports'
import type { NcProject } from '#imports'
import { useNuxtApp } from '#app'
const indicator = h(LoadingOutlined, {
class: '!text-gray-400',

3
packages/nc-gui/components/dashboard/TreeView/TableList.vue

@ -3,8 +3,7 @@ import type { BaseType, TableType } from 'nocodb-sdk'
import { storeToRefs } from 'pinia'
import Sortable from 'sortablejs'
import TableNode from './TableNode.vue'
import { useNuxtApp } from '#app'
import { toRef } from '#imports'
import { toRef, useNuxtApp } from '#imports'
const props = withDefaults(
defineProps<{

3
packages/nc-gui/components/dashboard/TreeView/TableNode.vue

@ -4,8 +4,7 @@ import { toRef } from '@vue/reactivity'
import { message } from 'ant-design-vue'
import { storeToRefs } from 'pinia'
import { useNuxtApp } from '#app'
import { ProjectRoleInj, TreeViewInj, useRoles, useTabs } from '#imports'
import { ProjectRoleInj, TreeViewInj, useNuxtApp, useRoles, useTabs } from '#imports'
const props = withDefaults(
defineProps<{

3
packages/nc-gui/components/dashboard/TreeView/index.vue

@ -18,11 +18,10 @@ import {
useDialog,
useNuxtApp,
useRoles,
useRouter,
useTablesStore,
} from '#imports'
import { useRouter } from '#app'
const { isUIAllowed } = useRoles()
const { $e } = useNuxtApp()

41
packages/nc-gui/components/dashboard/View.vue

@ -125,6 +125,11 @@ onMounted(() => {
handleSidebarOpenOnMobileForNonViews()
})
const remToPx = (rem: number) => {
const fontSize = parseFloat(getComputedStyle(document.documentElement).fontSize)
return rem * fontSize
}
function onResize(widthPercent: any) {
if (isMobileMode.value) return
@ -135,23 +140,31 @@ function onResize(widthPercent: any) {
const widthRem = width / fontSize
if (widthRem < 16) {
currentSidebarSize.value = ((16 * fontSize) / viewportWidth.value) * 100
sideBarSize.value.old = ((16 * fontSize) / viewportWidth.value) * 100
if (isLeftSidebarOpen.value) sideBarSize.value.current = sideBarSize.value.old
return
} else if (widthRem > 23.5) {
currentSidebarSize.value = ((23.5 * fontSize) / viewportWidth.value) * 100
sideBarSize.value.old = ((23.5 * fontSize) / viewportWidth.value) * 100
if (isLeftSidebarOpen.value) sideBarSize.value.current = sideBarSize.value.old
return
}
console.log('onResize', widthRem, fontSize)
currentSidebarSize.value = widthPercent
sideBarSize.value.old = widthPercent
sideBarSize.value.current = sideBarSize.value.old
}
watch(
() => sideBarSize.value.current,
() => {
console.log('sidebarState', sideBarSize.value.current)
},
)
const normalizedWidth = computed(() => {
const maxSize = remToPx(23.5)
const minSize = remToPx(16)
if (sidebarWidth.value > maxSize) {
return maxSize
} else if (sidebarWidth.value < minSize) {
return minSize
} else {
return sidebarWidth.value
}
})
</script>
<template>
@ -166,14 +179,14 @@ watch(
min-size="15%"
:size="mobileNormalizedSidebarSize"
max-size="40%"
class="nc-sidebar-splitpane !sm:(min-w-64 max-w-94) relative !overflow-visible"
class="nc-sidebar-splitpane !sm:max-w-94 relative !overflow-visible flex"
:style="{
width: `${mobileNormalizedSidebarSize}%`,
}"
>
<div
ref="wrapperRef"
class="nc-sidebar-wrapper relative flex flex-col h-full justify-center !sm:(min-w-64 max-w-94) absolute overflow-visible"
class="nc-sidebar-wrapper relative flex flex-col h-full justify-center !sm:(max-w-94) absolute overflow-visible"
:class="{
'mobile': isMobileMode,
'minimized-height': !isLeftSidebarOpen,
@ -181,6 +194,7 @@ watch(
}"
:style="{
width: sidebarState === 'hiddenEnd' ? '0px' : `${sidebarWidth}px`,
minWidth: sidebarState === 'hiddenEnd' ? '0px' : `${normalizedWidth}px`,
}"
>
<slot name="sidebar" />
@ -188,8 +202,9 @@ watch(
</Pane>
<Pane
:size="mobileNormalizedContentSize"
class="flex-grow"
:style="{
width: `${100 - mobileNormalizedSidebarSize}%`,
'min-width': `${100 - mobileNormalizedSidebarSize}%`,
}"
>
<slot name="content" />

9
packages/nc-gui/components/dashboard/settings/DataSources.vue

@ -529,7 +529,7 @@ const isEditBaseModalOpen = computed({
</NcTooltip>
<NcTooltip>
<template #title>
{{ $t('general.delete') }}
{{ $t('general.remove') }}
</template>
<NcButton
v-if="!source.is_meta && !source.is_local"
@ -581,7 +581,12 @@ const isEditBaseModalOpen = computed({
<LazyDashboardSettingsBaseAudit :source-id="activeBaseId" @close="isBaseAuditModalOpen = false" />
</div>
</GeneralModal>
<GeneralDeleteModal v-model:visible="isDeleteBaseModalOpen" :entity-name="$t('general.datasource')" :on-delete="deleteBase">
<GeneralDeleteModal
v-model:visible="isDeleteBaseModalOpen"
:entity-name="$t('general.datasource')"
:on-delete="deleteBase"
:delete-label="$t('general.remove')"
>
<template #entity-preview>
<div v-if="toBeDeletedBase" class="flex flex-row items-center py-2 px-3.25 bg-gray-50 rounded-lg text-gray-700 mb-4">
<GeneralBaseLogo :source-type="toBeDeletedBase.type" />

51
packages/nc-gui/components/dashboard/settings/UIAcl.vue

@ -16,6 +16,8 @@ import {
useNuxtApp,
} from '#imports'
type Role = 'editor' | 'commenter' | 'viewer'
const props = defineProps<{
sourceId: string
}>()
@ -39,6 +41,12 @@ const tables = ref<any[]>([])
const searchInput = ref('')
const selectAll = ref({
editor: false,
commenter: false,
viewer: false,
})
const filteredTables = computed(() =>
tables.value.filter(
(el) =>
@ -80,15 +88,21 @@ async function saveUIAcl() {
$e('a:proj-meta:ui-acl')
}
const onRoleCheck = (record: any, role: string) => {
const onRoleCheck = (record: any, role: Role) => {
record.disabled[role] = !record.disabled[role]
record.edited = true
selectAll.value[role as Role] = filteredTables.value.every((t) => !t.disabled[role])
}
onMounted(async () => {
if (tables.value.length === 0) {
await loadTableList()
}
for (const role of roles.value) {
selectAll.value[role as Role] = filteredTables.value.every((t) => !t.disabled[role])
}
})
const tableHeaderRenderer = (label: string) => () => h('div', { class: 'text-gray-500' }, label)
@ -96,11 +110,11 @@ const tableHeaderRenderer = (label: string) => () => h('div', { class: 'text-gra
const columns = [
{
title: tableHeaderRenderer(t('labels.tableName')),
name: 'table_name',
name: 'Table Name',
},
{
title: tableHeaderRenderer(t('labels.viewName')),
name: 'view_name',
name: 'View Name',
},
{
title: tableHeaderRenderer(t('objects.roleType.editor')),
@ -118,6 +132,16 @@ const columns = [
width: 120,
},
]
const toggleSelectAll = (role: Role) => {
selectAll.value[role] = !selectAll.value[role]
const enabled = selectAll.value[role]
filteredTables.value.forEach((t) => {
t.disabled[role] = !enabled
t.edited = true
})
}
</script>
<template>
@ -163,12 +187,23 @@ const columns = [
})
"
>
<template #headerCell="{ column }">
<template v-if="['editor', 'commenter', 'viewer'].includes(column.name)">
<div class="flex flex-row gap-x-1">
<NcCheckbox :checked="selectAll[column.name as Role]" @change="() => toggleSelectAll(column.name)" />
<div class="flex capitalize">
{{ column.name }}
</div>
</div>
</template>
<template v-else>{{ column.name }}</template>
</template>
<template #emptyText>
<a-empty :image="Empty.PRESENTED_IMAGE_SIMPLE" :description="$t('labels.noData')" />
</template>
<template #bodyCell="{ record, column }">
<div v-if="column.name === 'table_name'">
<div v-if="column.name === 'Table Name'">
<div class="flex items-center gap-1">
<div class="min-w-5 flex items-center justify-center">
<GeneralTableIcon :meta="{ meta: record.table_meta, type: record.ptype }" class="text-gray-500" />
@ -179,7 +214,7 @@ const columns = [
</div>
</div>
<div v-if="column.name === 'view_name'">
<div v-if="column.name === 'View Name'">
<div class="flex items-center gap-1">
<div class="min-w-5 flex items-center justify-center">
<GeneralViewIcon :meta="record" class="text-gray-500"></GeneralViewIcon>
@ -202,10 +237,10 @@ const columns = [
>
</template>
<a-checkbox
<NcCheckbox
:checked="!record.disabled[role]"
:class="`nc-acl-${record.title}-${role}-chkbox`"
@change="onRoleCheck(record, role)"
:class="`nc-acl-${record.title}-${role}-chkbox !ml-0.25`"
@change="onRoleCheck(record, role as Role)"
/>
</a-tooltip>
</div>

2
packages/nc-gui/components/dlg/QuickImport.vue

@ -31,12 +31,12 @@ import {
useBase,
useGlobal,
useI18n,
useNuxtApp,
useVModel,
} from '#imports'
// import worker script according to the doc of Vite
import importWorkerUrl from '~/workers/importWorker?worker&url'
import { useNuxtApp } from '#app'
interface Props {
modelValue: boolean

35
packages/nc-gui/components/general/CopyUrl.vue

@ -40,18 +40,29 @@ const copyUrl = async () => {
<div class="overflow-hidden whitespace-nowrap text-gray-500">{{ url }}</div>
</div>
<div class="flex flex-row gap-x-1">
<div class="button" @click="openUrl">
<RiExternalLinkLine class="h-3.75" />
</div>
<div
class="button"
:class="{
'!text-gray-300 !border-gray-200 !cursor-not-allowed': isCopied.embed,
}"
@click="embedHtml"
>
<MdiCodeTags class="h-4" />
</div>
<NcTooltip>
<template #title>
{{ $t('activity.openInANewTab') }}
</template>
<div class="button" @click="openUrl">
<RiExternalLinkLine class="h-3.75" />
</div>
</NcTooltip>
<NcTooltip>
<template #title>
{{ $t('activity.copyIFrameCode') }}
</template>
<div
class="button"
:class="{
'!text-gray-300 !border-gray-200 !cursor-not-allowed': isCopied.embed,
}"
@click="embedHtml"
>
<MdiCodeTags class="h-4" />
</div>
</NcTooltip>
<div class="button" data-testid="docs-share-page-copy-link" @click="copyUrl">
<MdiCheck v-if="isCopied.link" class="h-3.5" />
<MdiContentCopy v-else class="h-3.5" />

15
packages/nc-gui/components/general/DeleteModal.vue

@ -5,6 +5,7 @@ const props = defineProps<{
visible: boolean
entityName: string
onDelete: () => Promise<void>
deleteLabel?: string | undefined
}>()
const emits = defineEmits(['update:visible'])
@ -12,6 +13,10 @@ const visible = useVModel(props, 'visible', emits)
const isLoading = ref(false)
const { t } = useI18n()
const deleteLabel = computed(() => props.deleteLabel ?? t('general.delete'))
const onDelete = async () => {
isLoading.value = true
try {
@ -43,11 +48,15 @@ onKeyStroke('Enter', () => {
<GeneralModal v-model:visible="visible" size="small" centered>
<div class="flex flex-col p-6">
<div class="flex flex-row pb-2 mb-4 font-medium text-lg border-b-1 border-gray-50 text-gray-800">
{{ $t('general.delete') }} {{ props.entityName }}
{{ deleteLabel }} {{ props.entityName }}
</div>
<div class="mb-3 text-gray-800">
{{ $t('msg.areYouSureUWantTo') }}<span class="ml-1">{{ props.entityName.toLowerCase() }}?</span>
{{
$t('msg.areYouSureUWantToDeleteLabel', {
deleteLabel: deleteLabel.toLowerCase(),
})
}}<span class="ml-1">{{ props.entityName.toLowerCase() }}?</span>
</div>
<slot name="entity-preview"></slot>
@ -65,7 +74,7 @@ onKeyStroke('Enter', () => {
data-testid="nc-delete-modal-delete-btn"
@click="onDelete"
>
{{ `${$t('general.delete')} ${props.entityName}` }}
{{ `${deleteLabel} ${props.entityName}` }}
<template #loading>
{{ $t('general.deleting') }}
</template>

15
packages/nc-gui/components/smartsheet/expanded-form/Comments.vue

@ -10,6 +10,8 @@ const props = defineProps<{
const { loadCommentsAndLogs, commentsAndLogs, saveComment: _saveComment, comment, updateComment } = useExpandedFormStoreOrThrow()
const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())
const commentsWrapperEl = ref<HTMLDivElement>()
const { user, appInfo } = useGlobal()
@ -26,6 +28,8 @@ const editLog = ref<AuditType>()
const isEditing = ref<boolean>(false)
const commentInputDomRef = ref<HTMLInputElement>()
const focusInput: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
function onKeyDown(event: KeyboardEvent) {
@ -123,6 +127,15 @@ const onClickAudit = () => {
tab.value = 'audits'
}
watch(commentInputDomRef, () => {
if (commentInputDomRef.value && isExpandedFormCommentMode.value) {
setTimeout(() => {
commentInputDomRef.value?.focus()
isExpandedFormCommentMode.value = false
}, 400)
}
})
</script>
<template>
@ -240,9 +253,11 @@ const onClickAudit = () => {
<div class="h-14 flex flex-row w-full bg-white py-2.75 px-1.5 items-center rounded-xl border-1 border-gray-200">
<GeneralUserIcon size="base" class="!w-10" :email="user?.email" :name="user?.display_name" />
<a-input
ref="commentInputDomRef"
v-model:value="comment"
class="!rounded-lg border-1 bg-white !px-2.5 !py-2 !border-gray-200 nc-comment-box !outline-none"
placeholder="Start typing..."
data-testid="expanded-form-comment-input"
:bordered="false"
@keyup.enter.prevent="saveComment"
>

13
packages/nc-gui/components/smartsheet/expanded-form/index.vue

@ -90,6 +90,8 @@ const reloadTrigger = inject(ReloadRowDataHookInj, createEventHook())
const { addOrEditStackRow } = useKanbanViewStoreOrThrow()
const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())
// override cell click hook to avoid unexpected behavior at form fields
provide(CellClickHookInj, undefined)
@ -283,6 +285,9 @@ const cellWrapperEl = ref()
onMounted(async () => {
isRecordLinkCopied.value = false
isLoading.value = true
const focusFirstCell = !isExpandedFormCommentMode.value
if (props.loadRow) {
await _loadRow()
await loadCommentsAndLogs()
@ -302,9 +307,11 @@ onMounted(async () => {
isLoading.value = false
setTimeout(() => {
cellWrapperEl.value?.$el?.querySelector('input,select,textarea')?.focus()
}, 300)
if (focusFirstCell) {
setTimeout(() => {
cellWrapperEl.value?.$el?.querySelector('input,select,textarea')?.focus()
}, 300)
}
})
const addNewRow = () => {

27
packages/nc-gui/components/smartsheet/grid/Table.vue

@ -144,6 +144,8 @@ const { addUndo, clone, defineViewScope } = useUndoRedo()
const { isViewColumnsLoading, updateGridViewColumn, gridViewCols, resizingColOldWith } = useViewColumnsOrThrow()
const { isExpandedFormCommentMode } = storeToRefs(useConfigStore())
const {
predictingNextColumn,
predictedNextColumn,
@ -710,6 +712,23 @@ const confirmDeleteRow = (row: number) => {
}
}
const commentRow = (rowId: number) => {
try {
isExpandedFormCommentMode.value = true
const row = dataRef.value[rowId]
if (expandForm) {
expandForm(row)
}
activeCell.row = null
activeCell.col = null
selectedRange.clear()
} catch (e: any) {
message.error(e.message)
}
}
const deleteSelectedRangeOfRows = () => {
deleteRangeOfRows?.(selectedRange).then(() => {
clearSelectedRange()
@ -1712,6 +1731,14 @@ onKeyStroke('ArrowDown', onDown)
{{ $t('general.clear') }}
</NcMenuItem>
<template v-if="contextMenuTarget && selectedRange.isSingleCell() && isUIAllowed('commentEdit') && !isMobileMode">
<NcDivider />
<NcMenuItem v-e="['a:row:comment']" class="nc-base-menu-item" @click="commentRow(contextMenuTarget.row)">
<MdiMessageOutline class="h-4 w-4" />
{{ $t('general.comment') }}
</NcMenuItem>
</template>
<NcDivider v-if="!(!contextMenuClosing && !contextMenuTarget && data.some((r) => r.rowMeta.selected))" />
<NcMenuItem
v-if="contextMenuTarget && (selectedRange.isSingleCell() || selectedRange.isSingleRow())"

6
packages/nc-gui/components/smartsheet/toolbar/ViewInfo.vue

@ -43,7 +43,9 @@ const openedBaseUrl = computed(() => {
>
<NcTooltip class="!text-inherit">
<template #title>
{{ base?.title }}
<span class="capitalize">
{{ base?.title }}
</span>
</template>
<div class="flex flex-row items-center gap-x-1.5">
<GeneralProjectIcon
@ -59,7 +61,7 @@ const openedBaseUrl = computed(() => {
'!flex': isSharedBase && !isMobileMode,
}"
>
<span class="truncate !text-inherit">
<span class="truncate !text-inherit capitalize">
{{ base?.title }}
</span>
</div>

16
packages/nc-gui/components/virtual-cell/QrCode.vue

@ -59,8 +59,20 @@ const { showEditNonEditableFieldWarning, showClearNonEditableFieldWarning } = us
@ok="handleModalOkClick"
>
<template #footer>
<div class="mr-4 overflow-scroll p-2" data-testid="nc-qr-code-large-value-label">
{{ qrValue }}
<div class="flex flex-row">
<div class="flex flex-row flex-grow mr-2 !overflow-y-auto py-2" data-testid="nc-qr-code-large-value-label">
{{ qrValue }}
</div>
<a v-if="showQrCode" :href="qrCodeLarge" :download="`${qrValue}.png`">
<NcTooltip>
<template #title>
{{ $t('labels.clickToDownload') }}
</template>
<NcButton size="small" type="secondary">
<GeneralIcon icon="download" class="w-4 h-4" />
</NcButton>
</NcTooltip>
</a>
</div>
</template>
<img v-if="showQrCode" :src="qrCodeLarge" :alt="$t('title.qrCode')" />

8
packages/nc-gui/components/virtual-cell/barcode/Barcode.vue

@ -46,9 +46,15 @@ const rowHeight = inject(RowHeightInj, ref(undefined))
:footer="null"
@ok="handleModalOkClick"
>
<JsBarcodeWrapper v-if="showBarcode" :barcode-value="barcodeValue" :barcode-format="barcodeMeta.barcodeFormat" />
<JsBarcodeWrapper
v-if="showBarcode"
:barcode-value="barcodeValue"
:barcode-format="barcodeMeta.barcodeFormat"
show-download
/>
</a-modal>
<div
v-if="!tooManyCharsForBarcode"
class="flex ml-2 w-full items-center"
:class="{
'justify-start': isExpandedFormOpen,

42
packages/nc-gui/components/virtual-cell/barcode/JsBarcodeWrapper.vue

@ -1,18 +1,20 @@
<script lang="ts" setup>
import JsBarcode from 'jsbarcode'
import { IsGalleryInj, onMounted } from '#imports'
import { downloadSvg as _downloadSvg } from '~/utils/svgToPng'
const props = defineProps({
barcodeValue: { type: String, required: true },
barcodeFormat: { type: String, required: true },
customStyle: { type: Object, required: false },
showDownload: { type: Boolean, required: false, default: false },
})
const emit = defineEmits(['onClickBarcode'])
const isGallery = inject(IsGalleryInj, ref(false))
const barcodeSvgRef = ref<HTMLElement>()
const barcodeSvgRef = ref<SVGGraphicsElement>()
const errorForCurrentInput = ref(false)
const generate = () => {
@ -34,6 +36,12 @@ const generate = () => {
}
}
const downloadSvg = () => {
if (!barcodeSvgRef.value) return
_downloadSvg(barcodeSvgRef.value, `${props.barcodeValue}.png`)
}
const onBarcodeClick = (ev: MouseEvent) => {
if (isGallery.value) return
ev.stopPropagation()
@ -45,15 +53,25 @@ onMounted(generate)
</script>
<template>
<svg
v-show="!errorForCurrentInput"
ref="barcodeSvgRef"
:class="{
'w-full': !isGallery,
'w-auto': isGallery,
}"
data-testid="barcode"
@click="onBarcodeClick"
></svg>
<slot v-if="errorForCurrentInput" name="barcodeRenderError" />
<div class="relative">
<svg
v-show="!errorForCurrentInput"
ref="barcodeSvgRef"
:class="{
'w-full': !isGallery,
'w-auto': isGallery,
}"
data-testid="barcode"
@click="onBarcodeClick"
></svg>
<slot v-if="errorForCurrentInput" name="barcodeRenderError" />
<NcTooltip class="!absolute bottom-0 right-0">
<template #title>
{{ $t('labels.clickToDownload') }}
</template>
<NcButton v-if="props.showDownload" size="small" type="secondary" @click="downloadSvg">
<GeneralIcon icon="download" class="w-4 h-4" />
</NcButton>
</NcTooltip>
</div>
</template>

2
packages/nc-gui/components/workspace/ProjectList.vue

@ -15,10 +15,10 @@ import {
timeAgo,
useBases,
useGlobal,
useNuxtApp,
useRoles,
useWorkspace,
} from '#imports'
import { useNuxtApp } from '#app'
const workspaceStore = useWorkspace()

3
packages/nc-gui/composables/useGlobal/actions.ts

@ -1,8 +1,7 @@
import { getActivePinia } from 'pinia'
import type { Actions, AppInfo, State } from './types'
import type { NcProjectType } from '#imports'
import { message, useNuxtApp } from '#imports'
import { navigateTo } from '#app'
import { message, navigateTo, useNuxtApp } from '#imports'
export function useGlobalActions(state: State): Actions {
const setIsMobileMode = (isMobileMode: boolean) => {

2
packages/nc-gui/composables/useGlobal/index.ts

@ -16,7 +16,7 @@ export * from './types'
*
* @example
* ```js
* import { useNuxtApp } from '#app'
* import { useNuxtApp } from '#imports'
*
* const { $state } = useNuxtApp()
*

2
packages/nc-gui/helpers/parsers/JSONUrlTemplateAdapter.ts

@ -1,6 +1,6 @@
import type { Api } from 'nocodb-sdk'
import JSONTemplateAdapter from './JSONTemplateAdapter'
// import { useNuxtApp } from '#app'
// import { useNuxtApp } from '#imports'
export default class JSONUrlTemplateAdapter extends JSONTemplateAdapter {
url: string

8
packages/nc-gui/lang/en.json

@ -69,6 +69,7 @@
"hex": "Hex",
"clear": "Clear",
"slack": "Slack",
"comment": "Comment",
"microsoftTeams": "Microsoft Teams",
"discord": "Discord",
"matterMost": "Mattermost",
@ -444,6 +445,7 @@
"inUI": "in UI Dashboard",
"projectSettings": "Base Settings",
"clickToHide": "Click to hide",
"clickToDownload": "Click to download",
"forRole": "for role",
"searchUsers": "Search Users",
"superAdmin": "Super Admin",
@ -620,6 +622,8 @@
"newFormLoaded": "New form will be loaded after"
},
"activity": {
"openInANewTab": "Open in a new tab",
"copyIFrameCode": "Copy IFrame code",
"onCondition": "On Condition",
"bulkDownload": "Bulk Download",
"attachFile": "Attach File",
@ -994,6 +998,7 @@
"createWebhookMsg2": "Create web-hooks to power you automations,",
"createWebhookMsg3": "Get notified as soon as there are changes in your data",
"areYouSureUWantTo": "Are you sure you want to delete the following",
"areYouSureUWantToDeleteLabel": "Are you sure you want to {deleteLabel} the following",
"idColumnRequired": "ID field is required, you can rename this later if required.",
"length59Required": "The length exceeds the max 59 characters",
"noNewNotifications": "You have no new notifications",
@ -1009,7 +1014,8 @@
},
"nonEditableFields": {
"computedFieldUnableToClear": "Warning: Computed field - unable to clear text",
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed."
"qrFieldsCannotBeDirectlyChanged": "Warning: QR fields cannot be directly changed.",
"barcodeFieldsCannotBeDirectlyChanged": "Warning: Barcode fields cannot be directly changed."
},
"duplicateProject": "Are you sure you want to duplicate the base?",
"duplicateTable": "Are you sure you want to duplicate the table?"

2
packages/nc-gui/package.json

@ -143,7 +143,7 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"happy-dom": "^6.0.3",
"nuxt": "^3.6.5",
"nuxt": "^3.8.1",
"nuxt-windicss": "^2.6.1",
"prettier": "^2.7.1",
"sass": "^1.63.4",

2
packages/nc-gui/plugins/state.ts

@ -6,7 +6,7 @@ import { loadLocaleMessages, setI18nLanguage } from '~/plugins/a.i18n'
*
* @example
* ```js
* import { useNuxtApp } from '#app'
* import { useNuxtApp } from '#imports'
*
* const { $state } = useNuxtApp()
*

4
packages/nc-gui/store/config.ts

@ -13,6 +13,9 @@ export const useConfigStore = defineStore('configStore', () => {
const isViewPortMobile = () => width.value < MAX_WIDTH_FOR_MOBILE_MODE
// When set to true expanded form will auto focus on comment input and state will be set to false after focussing
const isExpandedFormCommentMode = ref(false)
const isMobileMode = ref(isViewPortMobile())
const projectPageTab = ref<'allTable' | 'collaborator' | 'data-source'>('allTable')
@ -67,6 +70,7 @@ export const useConfigStore = defineStore('configStore', () => {
isViewPortMobile,
handleSidebarOpenOnMobileForNonViews,
projectPageTab,
isExpandedFormCommentMode,
}
})

2457
pnpm-lock.yaml

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save