Browse Source

fix(nc-gui): show page does not exist if shared url is invalid

Ramesh Mane 4 days ago
parent
commit
ec46068554
  1. 8
      packages/nc-gui/assets/style.scss
  2. 2
      packages/nc-gui/components/general/PageDoesNotExist.vue
  3. 13
      packages/nc-gui/composables/useSharedView.ts
  4. 109
      packages/nc-gui/layouts/shared-view.vue
  5. 4
      packages/nc-gui/pages/index/[typeOrId]/calendar/[viewId]/index.vue
  6. 7
      packages/nc-gui/pages/index/[typeOrId]/form/[viewId].vue
  7. 4
      packages/nc-gui/pages/index/[typeOrId]/gallery/[viewId]/index.vue
  8. 4
      packages/nc-gui/pages/index/[typeOrId]/kanban/[viewId]/index.vue
  9. 4
      packages/nc-gui/pages/index/[typeOrId]/map/[viewId]/index.vue
  10. 4
      packages/nc-gui/pages/index/[typeOrId]/view/[viewId].vue

8
packages/nc-gui/assets/style.scss

@ -14,6 +14,14 @@
scrollbar-width: none; /* Firefox */
}
}
.nc-h-screen {
height: 100vh;
@supports (height: 100dvh) {
height: 100dvh;
}
}
}
* {

2
packages/nc-gui/components/general/PageDoesNotExist.vue

@ -1,5 +1,5 @@
<template>
<div class="h-full grid place-items-center text-center">
<div class="nc-h-screen grid place-items-center text-center">
<div class="flex flex-col items-center gap-6">
<slot name="icon">
<img width="48" alt="NocoDB" src="~/assets/img/icons/256x256.png" />

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

@ -13,6 +13,8 @@ import type {
import { UITypes, ViewTypes } from 'nocodb-sdk'
export function useSharedView() {
const router = useRouter()
const nestedFilters = ref<(FilterType & { status?: 'update' | 'delete' | 'create'; parentId?: string })[]>([])
const { appInfo } = useGlobal()
@ -70,6 +72,7 @@ export function useSharedView() {
'xc-password': localPassword ?? password.value,
},
})
try {
allowCSVDownload.value = parseProp(viewMeta.meta)?.allowCSVDownload
} catch {
@ -421,6 +424,15 @@ export function useSharedView() {
} as RequestParams)
}
const triggerNotFound = () => {
const currentQuery = { ...router.currentRoute.value.query, ncNotFound: 'true' }
router.push({
path: router.currentRoute.value.path,
query: currentQuery,
})
}
return {
sharedView,
loadSharedView,
@ -441,5 +453,6 @@ export function useSharedView() {
formColumns,
allowCSVDownload,
fetchCount,
triggerNotFound,
}
}

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

@ -11,6 +11,8 @@ const route = router.currentRoute
const disableTopbar = computed(() => route.value.query?.disableTopbar === 'true')
const ncNotFound = computed(() => route.value.query?.ncNotFound === 'true')
onMounted(() => {
// check if we are inside an iframe
// if we are, communicate to the parent page whenever we navigate to a new url,
@ -53,63 +55,66 @@ export default {
<template>
<a-layout id="nc-app">
<a-layout class="!flex-col bg-white">
<a-layout-header
v-if="!disableTopbar"
class="nc-table-topbar flex items-center justify-between !bg-transparent !px-3 !py-2 border-b-1 border-gray-200 !h-[46px]"
>
<div class="flex items-center gap-6 h-7 max-w-[calc(100%_-_280px)] xs:max-w-[calc(100%_-_90px)]">
<a
class="transition-all duration-200 cursor-pointer transform hover:scale-105"
href="https://github.com/nocodb/nocodb"
target="_blank"
rel="noopener noreferrer"
>
<img width="96" alt="NocoDB" src="~/assets/img/brand/nocodb.png" class="flex-none min-w-[96px]" />
</a>
<div class="flex items-center gap-2 text-gray-900 text-sm truncate">
<template v-if="isLoading">
<span data-testid="nc-loading">{{ $t('general.loading') }}</span>
<component :is="iconMap.reload" :class="{ 'animate-infinite animate-spin ': isLoading }" />
</template>
<div v-else class="text-sm font-semibold truncate nc-shared-view-title flex gap-2 items-center">
<GeneralViewIcon v-if="sharedView" class="h-4 w-4 ml-0.5" :meta="sharedView" />
<span class="truncate">
{{ sharedView?.title }}
</span>
<NcTooltip v-if="sharedView?.description?.length" placement="bottom">
<template #title>
{{ sharedView?.description }}
</template>
<NcButton type="text" class="!hover:bg-transparent" size="xsmall">
<GeneralIcon icon="info" class="!w-3.5 !h-3.5 nc-info-icon text-gray-600" />
</NcButton>
</NcTooltip>
<GeneralPageDoesNotExist v-if="ncNotFound" />
<template v-else>
<a-layout-header
v-if="!disableTopbar"
class="nc-table-topbar flex items-center justify-between !bg-transparent !px-3 !py-2 border-b-1 border-gray-200 !h-[46px]"
>
<div class="flex items-center gap-6 h-7 max-w-[calc(100%_-_280px)] xs:max-w-[calc(100%_-_90px)]">
<a
class="transition-all duration-200 cursor-pointer transform hover:scale-105"
href="https://github.com/nocodb/nocodb"
target="_blank"
rel="noopener noreferrer"
>
<img width="96" alt="NocoDB" src="~/assets/img/brand/nocodb.png" class="flex-none min-w-[96px]" />
</a>
<div class="flex items-center gap-2 text-gray-900 text-sm truncate">
<template v-if="isLoading">
<span data-testid="nc-loading">{{ $t('general.loading') }}</span>
<component :is="iconMap.reload" :class="{ 'animate-infinite animate-spin ': isLoading }" />
</template>
<div v-else class="text-sm font-semibold truncate nc-shared-view-title flex gap-2 items-center">
<GeneralViewIcon v-if="sharedView" class="h-4 w-4 ml-0.5" :meta="sharedView" />
<span class="truncate">
{{ sharedView?.title }}
</span>
<NcTooltip v-if="sharedView?.description?.length" placement="bottom">
<template #title>
{{ sharedView?.description }}
</template>
<NcButton type="text" class="!hover:bg-transparent" size="xsmall">
<GeneralIcon icon="info" class="!w-3.5 !h-3.5 nc-info-icon text-gray-600" />
</NcButton>
</NcTooltip>
</div>
</div>
</div>
</div>
<div class="flex items-center gap-3">
<LazySmartsheetToolbarExport v-if="allowCSVDownload" />
<div class="flex items-center gap-3">
<LazySmartsheetToolbarExport v-if="allowCSVDownload" />
<a href="https://app.nocodb.com/#/signin" target="_blank" class="!no-underline xs:hidden" rel="noopener">
<NcButton size="xs"> {{ $t('labels.signUpForFree') }} </NcButton>
</a>
<a href="https://app.nocodb.com/#/signin" target="_blank" class="!no-underline xs:hidden" rel="noopener">
<NcButton size="xs"> {{ $t('labels.signUpForFree') }} </NcButton>
</a>
</div>
</a-layout-header>
<div
class="nc-shared-view-container w-full overflow-hidden"
:class="{
'nc-shared-mobile-view': isMobileMode,
}"
>
<slot />
</div>
</a-layout-header>
<div
class="nc-shared-view-container w-full overflow-hidden"
:class="{
'nc-shared-mobile-view': isMobileMode,
}"
>
<slot />
</div>
</template>
</a-layout>
</a-layout>
</template>

4
packages/nc-gui/pages/index/[typeOrId]/calendar/[viewId]/index.vue

@ -11,7 +11,7 @@ definePageMeta({
const route = useRoute()
const { loadSharedView } = useSharedView()
const { loadSharedView, triggerNotFound } = useSharedView()
const showPassword = ref(false)
@ -20,6 +20,8 @@ try {
} catch (e: any) {
if (e?.response?.status === 403) {
showPassword.value = true
} else if (e?.response?.status === 404) {
triggerNotFound()
} else {
message.error(await extractSdkResponseErrorMsg(e))
}

7
packages/nc-gui/pages/index/[typeOrId]/form/[viewId].vue

@ -27,9 +27,6 @@ if (!notFound.value) {
useProvideSmartsheetStore(sharedView, meta, true)
applyLanguageDirection(sharedViewMeta.value.rtl ? 'rtl' : 'ltr')
} else {
navigateTo('/error/404')
throw createError({ statusCode: 404, statusMessage: t('msg.pageNotFound') })
}
const form = reactive({
@ -51,7 +48,9 @@ const focus: VNodeRef = (el: typeof InputPassword) => {
<template>
<div>
<NuxtLayout>
<NuxtPage v-if="!passwordDlg" />
<NuxtPage v-if="!passwordDlg && !notFound" />
<GeneralPageDoesNotExist v-if="notFound" />
<a-modal
v-model:visible="passwordDlg"

4
packages/nc-gui/pages/index/[typeOrId]/gallery/[viewId]/index.vue

@ -10,7 +10,7 @@ definePageMeta({
const route = useRoute()
const { loadSharedView } = useSharedView()
const { loadSharedView, triggerNotFound } = useSharedView()
const showPassword = ref(false)
@ -19,6 +19,8 @@ try {
} catch (e: any) {
if (e?.response?.status === 403) {
showPassword.value = true
} else if (e?.response?.status === 404) {
triggerNotFound()
} else {
message.error(await extractSdkResponseErrorMsg(e))
}

4
packages/nc-gui/pages/index/[typeOrId]/kanban/[viewId]/index.vue

@ -11,7 +11,7 @@ definePageMeta({
const route = useRoute()
const { loadSharedView } = useSharedView()
const { loadSharedView, triggerNotFound } = useSharedView()
const showPassword = ref(false)
@ -20,6 +20,8 @@ try {
} catch (e: any) {
if (e?.response?.status === 403) {
showPassword.value = true
} else if (e?.response?.status === 404) {
triggerNotFound()
} else {
message.error(await extractSdkResponseErrorMsg(e))
}

4
packages/nc-gui/pages/index/[typeOrId]/map/[viewId]/index.vue

@ -10,7 +10,7 @@ definePageMeta({
const route = useRoute()
const { loadSharedView } = useSharedView()
const { loadSharedView , triggerNotFound} = useSharedView()
const showPassword = ref(false)
@ -19,6 +19,8 @@ try {
} catch (e: any) {
if (e?.response?.status === 403) {
showPassword.value = true
} else if (e?.response?.status === 404) {
triggerNotFound()
} else {
message.error(await extractSdkResponseErrorMsg(e))
}

4
packages/nc-gui/pages/index/[typeOrId]/view/[viewId].vue

@ -10,7 +10,7 @@ definePageMeta({
const route = useRoute()
const { loadSharedView, meta } = useSharedView()
const { loadSharedView, meta, triggerNotFound } = useSharedView()
const { isViewDataLoading } = storeToRefs(useViewsStore())
provide(MetaInj, meta)
@ -24,6 +24,8 @@ onMounted(async () => {
} catch (e: any) {
if (e?.response?.status === 403) {
showPassword.value = true
} else if (e?.response?.status === 404) {
triggerNotFound()
} else {
console.error(e)
message.error(await extractSdkResponseErrorMsg(e))

Loading…
Cancel
Save