mirror of
https://github.com/nocodb/nocodb.git
synced 2026-04-29 02:56:49 +00:00
147 lines
4.1 KiB
Vue
147 lines
4.1 KiB
Vue
<script lang="ts">
|
|
// modified version of default NuxtErrorBoundary component - https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/nuxt-error-boundary.ts
|
|
import { message } from 'ant-design-vue'
|
|
import { computed, onErrorCaptured, ref, useCopy, useNuxtApp } from '#imports'
|
|
|
|
export default {
|
|
emits: {
|
|
error(_error: unknown) {
|
|
return true
|
|
},
|
|
},
|
|
setup(_props, { emit }) {
|
|
const nuxtApp = useNuxtApp()
|
|
const error = ref()
|
|
const prevError = ref()
|
|
const errModal = computed(() => !!error.value)
|
|
const key = ref(0)
|
|
const isErrorExpanded = ref(false)
|
|
const { copy } = useCopy()
|
|
|
|
onErrorCaptured((err) => {
|
|
if (import.meta.client && (!nuxtApp.isHydrating || !nuxtApp.payload.serverRendered)) {
|
|
console.log('UI Error :', err)
|
|
emit('error', err)
|
|
error.value = err
|
|
return false
|
|
}
|
|
})
|
|
|
|
const copyError = async () => {
|
|
try {
|
|
if (error.value) await copy(`message: ${error.value.message}\n\n${error.value.stack}`)
|
|
message.info('Error message copied to clipboard.')
|
|
} catch (e) {
|
|
message.error('Something went wrong while copying to clipboard, please copy from browser console.')
|
|
}
|
|
}
|
|
|
|
const reload = () => {
|
|
prevError.value = error.value
|
|
error.value = null
|
|
key.value++
|
|
}
|
|
|
|
const navigateToHome = () => {
|
|
prevError.value = error.value
|
|
error.value = null
|
|
location.hash = '/'
|
|
location.reload()
|
|
}
|
|
|
|
return {
|
|
errModal,
|
|
error,
|
|
key,
|
|
isErrorExpanded,
|
|
prevError,
|
|
copyError,
|
|
reload,
|
|
navigateToHome,
|
|
}
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<slot :key="key"></slot>
|
|
<slot name="error">
|
|
<NcModal v-model:visible="errModal" :class="{ active: errModal }" :centered="true" :closable="false" :footer="null">
|
|
<div class="w-full flex flex-col gap-1">
|
|
<h2 class="text-xl font-semibold">Oops! Something unexpected happened :/</h2>
|
|
|
|
<p class="mb-0">
|
|
<span
|
|
>Please report this error in our
|
|
<a href="https://discord.gg/8jX2GQn" target="_blank" rel="noopener noreferrer">Discord channel</a>. You can copy the
|
|
error message by clicking the "Copy" button below.</span
|
|
>
|
|
</p>
|
|
|
|
<span class="cursor-pointer" @click="isErrorExpanded = !isErrorExpanded"
|
|
>{{ isErrorExpanded ? 'Hide' : 'Show' }} details
|
|
<GeneralIcon
|
|
icon="arrowDown"
|
|
class="transition-transform transform duration-300"
|
|
:class="{
|
|
'rotate-180': isErrorExpanded,
|
|
}"
|
|
/></span>
|
|
<div
|
|
class="nc-error"
|
|
:class="{
|
|
active: isErrorExpanded,
|
|
}"
|
|
>
|
|
<div class="nc-left-vertical-bar"></div>
|
|
<div class="nc-error-content">
|
|
<span class="font-weight-bold">Message: {{ error.message }}</span>
|
|
<br />
|
|
<div class="text-gray-500 mt-2">{{ error.stack }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end gap-2">
|
|
<NcButton size="small" type="secondary" @click="copyError">
|
|
<div class="flex items-center gap-1">
|
|
<GeneralIcon icon="copy" />
|
|
Copy Error
|
|
</div>
|
|
</NcButton>
|
|
<NcButton v-if="!prevError || error.message !== prevError.message" size="small" @click="reload">
|
|
<div class="flex items-center gap-1">
|
|
<GeneralIcon icon="reload" />
|
|
Reload
|
|
</div>
|
|
</NcButton>
|
|
<NcButton v-else size="small" @click="navigateToHome">
|
|
<div class="flex items-center gap-1">
|
|
<GeneralIcon icon="link" />
|
|
Home
|
|
</div>
|
|
</NcButton>
|
|
</div>
|
|
</div>
|
|
</NcModal>
|
|
</slot>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
.nc-error {
|
|
@apply flex gap-2 mb-2 max-h-0;
|
|
white-space: pre;
|
|
transition: max-height 300ms linear;
|
|
|
|
&.active {
|
|
max-height: 250px;
|
|
}
|
|
|
|
.nc-left-vertical-bar {
|
|
@apply w-6px min-w-6px rounded min-h-full bg-gray-300;
|
|
}
|
|
|
|
.nc-error-content {
|
|
@apply min-w-0 overflow-auto pl-2 flex-shrink;
|
|
}
|
|
}
|
|
</style>
|