多维表格
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
4.6 KiB

<script setup lang="ts">
import { message } from 'ant-design-vue'
import { extractSdkResponseErrorMsg } from './utils'
import { applyNonSelectable, computed, isEeUI, isMac, useCommandPalette, useRouter, useTheme } from '#imports'
import type { CommandPaletteType } from '~/lib'
const router = useRouter()
const route = router.currentRoute
const cmdK = ref(false)
const cmdL = ref(false)
const disableBaseLayout = computed(() => route.value.path.startsWith('/nc/view') || route.value.path.startsWith('/nc/form'))
useTheme()
const { commandPalette, cmdData, cmdPlaceholder, activeScope, loadTemporaryScope, refreshCommandPalette } = useCommandPalette()
applyNonSelectable()
useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
const cmdOrCtrl = isMac() ? e.metaKey : e.ctrlKey
if (cmdOrCtrl) {
switch (e.key.toLowerCase()) {
case 'a':
// prevent Ctrl + A selection for non-editable nodes
if (!['input', 'textarea'].includes((e.target as any).nodeName.toLowerCase())) {
e.preventDefault()
}
break
case 'k':
e.preventDefault()
break
case 'l':
e.preventDefault()
break
case 'j':
e.preventDefault()
break
}
}
})
// TODO: Remove when https://github.com/vuejs/core/issues/5513 fixed
const key = ref(0)
const messages = [
`Uncaught NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.`, // chromium based
`NotFoundError: The object can not be found here.`, // safari
"Cannot read properties of null (reading 'parentNode')",
]
if (typeof window !== 'undefined') {
// @ts-expect-error using arbitrary window key
if (!window.__ncvue) {
window.addEventListener('error', (event) => {
if (messages.includes(event.message)) {
event.preventDefault()
console.warn('Re-rendering layout because of https://github.com/vuejs/core/issues/5513')
key.value++
}
})
}
// @ts-expect-error using arbitrary window key
window.__ncvue = true
}
function onScope(scope: string) {
if (scope === 'root' && isEeUI) {
loadTemporaryScope({ scope: 'root', data: {} })
}
}
function setActiveCmdView(cmd: CommandPaletteType) {
if (cmd === 'cmd-k') {
cmdK.value = true
cmdL.value = false
} else if (cmd === 'cmd-l') {
cmdL.value = true
cmdK.value = false
} else {
cmdL.value = false
cmdK.value = false
document.dispatchEvent(
new KeyboardEvent('keydown', {
key: 'J',
ctrlKey: !isMac() || undefined,
metaKey: isMac() || undefined,
}),
)
}
}
onMounted(() => {
nextTick(() => {
refreshCommandPalette()
})
})
let errorCount = 0
const handleError = async (error, clearError) => {
console.error('UI ERROR', error.value)
// if error is api error, show toast message with error message
if (error.value?.response) {
message.warn(await extractSdkResponseErrorMsg(error.value))
} else {
// else show generic error message
message.warn('Something went wrong. Please reload the page if page is not functioning properly.')
}
clearError()
// if error count is more than 3 within 3 second, navigate to home
// since it's likely endless loop of errors due to some UI issue in certain page
errorCount++
if (errorCount > 3) {
router.push('/')
}
// reset error count after 1 second
setTimeout(() => {
errorCount = 0
}, 3000)
}
</script>
<template>
<a-config-provider>
<NuxtLayout :name="disableBaseLayout ? false : 'base'">
<NuxtErrorBoundary>
<NuxtPage :key="key" :transition="false" />
<!-- on error, clear error and show toast message -->
<template #error="{ error, clearError }">
{{ handleError(error, clearError) }}
</template>
</NuxtErrorBoundary>
</NuxtLayout>
</a-config-provider>
<NuxtErrorBoundary>
<div>
<!-- Command Menu -->
<CmdK
ref="commandPalette"
v-model:open="cmdK"
:scope="activeScope.scope"
:data="cmdData"
:placeholder="cmdPlaceholder"
:load-temporary-scope="loadTemporaryScope"
:set-active-cmd-view="setActiveCmdView"
@scope="onScope"
/>
<!-- Recent Views. Cycles through recently visited Views -->
<CmdL v-model:open="cmdL" :set-active-cmd-view="setActiveCmdView" />
<!-- Documentation. Integrated NocoDB Docs directly inside the Product -->
<CmdJ />
</div>
<!-- on error, clear error and show toast message -->
<template #error="{ error, clearError }">
{{ handleError(error, clearError) }}
</template>
</NuxtErrorBoundary>
</template>