2
0
mirror of https://github.com/frappe/books.git synced 2025-01-03 07:12:21 +00:00

fix: capture key errors in print container

- add error boundary component
This commit is contained in:
18alantom 2023-03-17 11:03:37 +05:30
parent fe6ef65d3d
commit fe9f1f7e3a
3 changed files with 55 additions and 15 deletions

View File

@ -0,0 +1,14 @@
<template>
<slot></slot>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
emits: ['error-captured'],
props: { propagate: { type: Boolean, default: true } },
errorCaptured(error) {
this.$emit('error-captured', error);
return this.propagate;
},
});
</script>

View File

@ -4,14 +4,19 @@
ref="scaledContainer" ref="scaledContainer"
class="mx-auto shadow-lg border" class="mx-auto shadow-lg border"
> >
<!-- Template --> <ErrorBoundary
<component
v-if="!error" v-if="!error"
class="flex-1 bg-white" @error-captured="handleErrorCaptured"
:doc="values.doc" :propagate="false"
:print="values.print" >
:is="templateComponent" <!-- Template -->
/> <component
class="flex-1 bg-white"
:doc="values.doc"
:print="values.print"
:is="templateComponent"
/>
</ErrorBoundary>
<!-- Compilation Error --> <!-- Compilation Error -->
<div <div
@ -26,11 +31,11 @@
" "
> >
<h1 class="text-4xl font-bold text-red-500 p-4 border-b border-red-200"> <h1 class="text-4xl font-bold text-red-500 p-4 border-b border-red-200">
{{ t`Template Compilation Error` }} {{ error.name }}
</h1> </h1>
<p class="px-4 font-semibold">{{ error.message }}</p> <p class="px-4 font-semibold">{{ error.message }}</p>
<pre v-if="error.codeframe" class="px-4 text-xl text-gray-700">{{ <pre v-if="error.detail" class="px-4 text-xl text-gray-700">{{
error.codeframe error.detail
}}</pre> }}</pre>
</div> </div>
</ScaledContainer> </ScaledContainer>
@ -42,6 +47,7 @@ import {
generateCodeFrame, generateCodeFrame,
SourceLocation, SourceLocation,
} from '@vue/compiler-dom'; } from '@vue/compiler-dom';
import ErrorBoundary from 'src/components/ErrorBoundary.vue';
import { getPathAndMakePDF } from 'src/utils/printTemplates'; import { getPathAndMakePDF } from 'src/utils/printTemplates';
import { PrintValues } from 'src/utils/types'; import { PrintValues } from 'src/utils/types';
import { defineComponent, PropType } from 'vue'; import { defineComponent, PropType } from 'vue';
@ -57,7 +63,7 @@ export const baseSafeTemplate = `<main class="h-full w-full bg-white">
export default defineComponent({ export default defineComponent({
data() { data() {
return { error: null } as { return { error: null } as {
error: null | { codeframe: string; message: string }; error: null | { name: string; message: string; detail?: string };
}; };
}, },
props: { props: {
@ -82,7 +88,7 @@ export default defineComponent({
* Note: This is a hacky method to prevent * Note: This is a hacky method to prevent
* broken templates from reaching the `<component />` * broken templates from reaching the `<component />`
* element. * element.
* *
* It's required because the CompilerOptions doesn't * It's required because the CompilerOptions doesn't
* have an option to capture the errors. * have an option to capture the errors.
* *
@ -100,9 +106,29 @@ export default defineComponent({
onError: this.onError, onError: this.onError,
}); });
}, },
handleErrorCaptured(error: unknown) {
if (!(error instanceof Error)) {
throw error;
}
const message = error.message;
let name = error.name;
let detail = '';
if (name === 'TypeError' && message.includes('Cannot read')) {
name = this.t`Invalid Key Error`;
detail = this.t`Please check Key Hints for valid key names`;
}
this.error = { name, message, detail };
},
onError({ message, loc }: CompilerError) { onError({ message, loc }: CompilerError) {
const codeframe = loc ? this.getCodeFrame(loc) : ''; const codeframe = loc ? this.getCodeFrame(loc) : '';
this.error = { codeframe, message };
this.error = {
name: this.t`Template Compilation Error`,
detail: codeframe,
message,
};
}, },
getCodeFrame(loc: SourceLocation) { getCodeFrame(loc: SourceLocation) {
return generateCodeFrame(this.template, loc.start.offset, loc.end.offset); return generateCodeFrame(this.template, loc.start.offset, loc.end.offset);
@ -142,6 +168,6 @@ export default defineComponent({
}; };
}, },
}, },
components: { ScaledContainer }, components: { ScaledContainer, ErrorBoundary },
}); });
</script> </script>

View File

@ -149,7 +149,7 @@
</div> </div>
<div <div
v-if="templateChanged" v-if="templateChanged"
class="flex gap-2 p-2 text-sm text-gray-600 items-center mt-auto" class="flex gap-2 p-2 text-sm text-gray-600 items-center mt-auto border-t"
> >
<ShortcutKeys :keys="applyChangesShortcut" :simple="true" /> <ShortcutKeys :keys="applyChangesShortcut" :simple="true" />
{{ t` to apply changes` }} {{ t` to apply changes` }}