Browse Source

fix(gui):shared view creation bug and show icon in shared view

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4630/head
Pranav C 2 years ago
parent
commit
a757da6838
  1. 1
      packages/nc-gui/components/smartsheet/sidebar/MenuTop.vue
  2. 16
      packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue
  3. 7
      packages/nc-gui/composables/useSharedView.ts
  4. 3
      packages/nc-gui/layouts/shared-view.vue
  5. 12
      packages/nocodb/src/lib/models/View.ts
  6. 18
      packages/nocodb/src/lib/utils/modelUtils.ts

1
packages/nc-gui/components/smartsheet/sidebar/MenuTop.vue

@ -216,6 +216,7 @@ function openDeleteDialog(view: ViewType) {
const setIcon = async (icon: string, view: ViewType) => { const setIcon = async (icon: string, view: ViewType) => {
try { try {
// modify the icon property in meta
view.meta = { view.meta = {
...(view.meta || {}), ...(view.meta || {}),
icon, icon,

16
packages/nc-gui/components/smartsheet/sidebar/RenameableMenuItem.vue

@ -12,6 +12,8 @@ import {
useVModel, useVModel,
} from '#imports' } from '#imports'
import { Tooltip } from 'ant-design-vue'
interface Props { interface Props {
view: ViewType view: ViewType
onValidate: (view: ViewType) => boolean | string onValidate: (view: ViewType) => boolean | string
@ -173,10 +175,14 @@ function onStopEdit() {
@dblclick.stop="onDblClick" @dblclick.stop="onDblClick"
@click.stop="onClick" @click.stop="onClick"
> >
<div v-e="['a:view:open', { view: vModel.type }]" class="text-xs flex items-center w-full gap-2" data-testid="view-item"> <div v-e="['a:view:open', { view: vModel.type }]" class="text-xs flex items-center w-full gap-2"
data-testid="view-item">
<div class="flex w-auto min-w-5" :data-testid="`view-sidebar-drag-handle-${vModel.alias || vModel.title}`"> <div class="flex w-auto min-w-5" :data-testid="`view-sidebar-drag-handle-${vModel.alias || vModel.title}`">
<a-dropdown :trigger="['click']" @click.stop> <a-dropdown :trigger="['click']" @click.stop>
<GeneralViewIcon :meta="props.view"></GeneralViewIcon> <component :is="isUIAllowed('tableIconCustomisation') ? Tooltip : 'div'">
<GeneralViewIcon :meta="props.view"></GeneralViewIcon>
<template v-if="isUIAllowed('tableIconCustomisation')" #title>Change icon</template>
</component>
<template v-if="isUIAllowed('viewIconCustomisation')" #overlay> <template v-if="isUIAllowed('viewIconCustomisation')" #overlay>
<GeneralEmojiIcons class="shadow bg-white p-2" @select-icon="emits('selectIcon', $event)" /> <GeneralEmojiIcons class="shadow bg-white p-2" @select-icon="emits('selectIcon', $event)" />
@ -184,7 +190,8 @@ function onStopEdit() {
</a-dropdown> </a-dropdown>
</div> </div>
<a-input v-if="isEditing" :ref="focusInput" v-model:value="vModel.title" @blur="onCancel" @keydown="onKeyDown($event)" /> <a-input v-if="isEditing" :ref="focusInput" v-model:value="vModel.title" @blur="onCancel"
@keydown="onKeyDown($event)" />
<div v-else> <div v-else>
<LazyGeneralTruncateText>{{ vModel.alias || vModel.title }}</LazyGeneralTruncateText> <LazyGeneralTruncateText>{{ vModel.alias || vModel.title }}</LazyGeneralTruncateText>
@ -199,7 +206,8 @@ function onStopEdit() {
{{ $t('activity.copyView') }} {{ $t('activity.copyView') }}
</template> </template>
<MdiContentCopy class="hidden group-hover:block text-gray-500 nc-view-copy-icon" @click.stop="onDuplicate" /> <MdiContentCopy class="hidden group-hover:block text-gray-500 nc-view-copy-icon"
@click.stop="onDuplicate" />
</a-tooltip> </a-tooltip>
<template v-if="!vModel.is_default"> <template v-if="!vModel.is_default">

7
packages/nc-gui/composables/useSharedView.ts

@ -58,8 +58,11 @@ export function useSharedView() {
'xc-password': localPassword ?? password.value, 'xc-password': localPassword ?? password.value,
}, },
}) })
try {
allowCSVDownload.value = JSON.parse(viewMeta.meta)?.allowCSVDownload allowCSVDownload.value = (typeof viewMeta.meta === 'string' ? JSON.parse(viewMeta.meta) : viewMeta.meta)?.allowCSVDownload
} catch {
allowCSVDownload.value = false
}
if (localPassword) password.value = localPassword if (localPassword) password.value = localPassword
sharedView.value = { title: '', ...viewMeta } sharedView.value = { title: '', ...viewMeta }

3
packages/nc-gui/layouts/shared-view.vue

@ -58,7 +58,8 @@ export default {
<MdiReload :class="{ 'animate-infinite animate-spin ': isLoading }" /> <MdiReload :class="{ 'animate-infinite animate-spin ': isLoading }" />
</template> </template>
<div v-else class="text-xl font-semibold truncate text-white nc-shared-view-title"> <div v-else class="text-xl font-semibold truncate text-white nc-shared-view-title flex gap-2 items-center">
<GeneralViewIcon class="!text-2xl" :meta="sharedView" />
{{ sharedView?.title }} {{ sharedView?.title }}
</div> </div>
</div> </div>

12
packages/nocodb/src/lib/models/View.ts

@ -5,7 +5,7 @@ import {
CacheScope, CacheScope,
MetaTable, MetaTable,
} from '../utils/globals'; } from '../utils/globals';
import { parseMetaProp, stringifyMetaProp } from '../utils/modelUtils' import { parseMetaProp, stringifyMetaProp } from '../utils/modelUtils';
import Model from './Model'; import Model from './Model';
import FormView from './FormView'; import FormView from './FormView';
import GridView from './GridView'; import GridView from './GridView';
@ -715,11 +715,16 @@ export default class View implements ViewType {
} }
} }
// todo: cache
static async getByUUID(uuid: string, ncMeta = Noco.ncMeta) { static async getByUUID(uuid: string, ncMeta = Noco.ncMeta) {
const view = await ncMeta.metaGet2(null, null, MetaTable.VIEWS, { const view = await ncMeta.metaGet2(null, null, MetaTable.VIEWS, {
uuid, uuid,
}); });
if (view) {
parseMetaProp(view);
}
return view && new View(view); return view && new View(view);
} }
@ -748,8 +753,9 @@ export default class View implements ViewType {
viewId viewId
); );
} }
if (!view.meta) { if (!view.meta || !('allowCSVDownload' in view.meta)) {
const defaultMeta = { const defaultMeta = {
...(view.meta ?? {}),
allowCSVDownload: true, allowCSVDownload: true,
}; };
// get existing cache // get existing cache
@ -757,7 +763,7 @@ export default class View implements ViewType {
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT);
if (o) { if (o) {
// update data // update data
o.meta = JSON.stringify(defaultMeta); o.meta = defaultMeta;
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o);
} }

18
packages/nocodb/src/lib/utils/modelUtils.ts

@ -1,5 +1,7 @@
export function parseMetaProp(modelOrModelList: { meta: any } | { meta: any }[]) { export function parseMetaProp(
if (!modelOrModelList) return modelOrModelList: { meta: any } | { meta: any }[]
) {
if (!modelOrModelList) return;
// parse meta property // parse meta property
for (const model of Array.isArray(modelOrModelList) for (const model of Array.isArray(modelOrModelList)
@ -7,17 +9,17 @@ export function parseMetaProp(modelOrModelList: { meta: any } | { meta: any }[])
: [modelOrModelList]) { : [modelOrModelList]) {
try { try {
model.meta = model.meta =
typeof model.meta === 'string' ? JSON.parse(model.meta) : model.meta typeof model.meta === 'string' ? JSON.parse(model.meta) : model.meta;
} catch { } catch {
model.meta = {} model.meta = {};
} }
} }
} }
export function stringifyMetaProp( export function stringifyMetaProp(
modelOrModelList: { meta?: any } | { meta?: any }[], modelOrModelList: { meta?: any } | { meta?: any }[]
) { ) {
if (!modelOrModelList) return if (!modelOrModelList) return;
// parse meta property // parse meta property
for (const model of Array.isArray(modelOrModelList) for (const model of Array.isArray(modelOrModelList)
@ -25,9 +27,9 @@ export function stringifyMetaProp(
: [modelOrModelList]) { : [modelOrModelList]) {
try { try {
model.meta = model.meta =
typeof model.meta !== 'string' ? model.meta : JSON.parse(model.meta) typeof model.meta === 'string' ? model.meta : JSON.stringify(model.meta);
} catch (e) { } catch (e) {
model.meta = '{}' model.meta = '{}';
} }
} }
} }

Loading…
Cancel
Save