2
0
mirror of https://github.com/frappe/books.git synced 2025-02-02 12:08:27 +00:00

fix(ux): display template compilation errors

- fix failing tests due vue imports on ts-node compile
- prevent fyo access in templates
- update default template
- change outline colour
This commit is contained in:
18alantom 2023-03-13 15:42:19 +05:30
parent 8f84f2677c
commit dced1ed559
5 changed files with 97 additions and 7 deletions

View File

@ -11,7 +11,6 @@ import {
import { DEFAULT_CURRENCY } from 'fyo/utils/consts'; import { DEFAULT_CURRENCY } from 'fyo/utils/consts';
import { ValidationError } from 'fyo/utils/errors'; import { ValidationError } from 'fyo/utils/errors';
import { addItem, getExchangeRate, getNumberSeries } from 'models/helpers'; import { addItem, getExchangeRate, getNumberSeries } from 'models/helpers';
import { validateBatch } from 'models/inventory/helpers';
import { InventorySettings } from 'models/inventory/InventorySettings'; import { InventorySettings } from 'models/inventory/InventorySettings';
import { StockTransfer } from 'models/inventory/StockTransfer'; import { StockTransfer } from 'models/inventory/StockTransfer';
import { Transactional } from 'models/Transactional/Transactional'; import { Transactional } from 'models/Transactional/Transactional';

View File

@ -6,20 +6,60 @@
> >
<!-- Template --> <!-- Template -->
<component <component
v-if="!error"
class="flex-1 bg-white" class="flex-1 bg-white"
:doc="values.doc" :doc="values.doc"
:print="values.print" :print="values.print"
:is="{ template, props: ['doc', 'print'] }" :is="templateComponent"
/> />
<!-- Compilation Error -->
<div
v-else
class="
h-full
bg-red-100
w-full
text-2xl text-gray-900
flex flex-col
gap-4
"
>
<h1 class="text-4xl font-bold text-red-500 p-4 border-b border-red-200">
{{ t`Template Compilation Error` }}
</h1>
<p class="px-4 font-semibold">{{ error.message }}</p>
<pre v-if="error.codeframe" class="px-4 text-xl text-gray-700">{{
error.codeframe
}}</pre>
</div>
</ScaledContainer> </ScaledContainer>
</template> </template>
<script lang="ts"> <script lang="ts">
import {
compile,
CompilerError,
generateCodeFrame,
SourceLocation,
} from '@vue/compiler-dom';
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';
import ScaledContainer from './ScaledContainer.vue'; import ScaledContainer from './ScaledContainer.vue';
export const baseSafeTemplate = `<main class="h-full w-full bg-white">
<p class="p-4 text-red-500">
<span class="font-bold">ERROR</span>: Template failed to load due to errors.
</p>
</main>
`;
export default defineComponent({ export default defineComponent({
data() {
return { error: null } as {
error: null | { codeframe: string; message: string };
};
},
props: { props: {
template: { type: String, required: true }, template: { type: String, required: true },
scale: { type: Number, default: 0.65 }, scale: { type: Number, default: 0.65 },
@ -28,7 +68,30 @@ export default defineComponent({
required: true, required: true,
}, },
}, },
watch: {
template(value: string) {
this.compile(value);
},
},
mounted() {
this.compile(this.template);
},
methods: { methods: {
compile(template: string) {
this.error = null;
return compile(template, {
hoistStatic: true,
onWarn: this.onError,
onError: this.onError,
});
},
onError({ message, loc }: CompilerError) {
const codeframe = loc ? this.getCodeFrame(loc) : '';
this.error = { codeframe, message };
},
getCodeFrame(loc: SourceLocation) {
return generateCodeFrame(this.template, loc.start.offset, loc.end.offset);
},
async savePDF(name?: string) { async savePDF(name?: string) {
/** /**
* To be called through ref by the parent component. * To be called through ref by the parent component.
@ -43,6 +106,27 @@ export default defineComponent({
await getPathAndMakePDF(name ?? this.t`Entry`, innerHTML); await getPathAndMakePDF(name ?? this.t`Entry`, innerHTML);
}, },
}, },
computed: {
templateComponent() {
let template = this.template;
if (this.error) {
template = baseSafeTemplate;
}
return {
template,
props: ['doc', 'print'],
computed: {
fyo() {
return {};
},
platform() {
return '';
},
},
};
},
},
components: { ScaledContainer }, components: { ScaledContainer },
}); });
</script> </script>

View File

@ -7,7 +7,7 @@
} }
* { * {
outline-color: theme('colors.pink.500'); outline-color: theme('colors.pink.400');
font-variation-settings: 'slnt' 0deg; font-variation-settings: 'slnt' 0deg;
} }
.italic { .italic {

View File

@ -8,7 +8,6 @@ import {
getRandomString, getRandomString,
getValueMapFromList, getValueMapFromList,
} from 'utils/index'; } from 'utils/index';
import { updatePrintTemplates } from './printTemplates';
export async function initializeInstance( export async function initializeInstance(
dbPath: string, dbPath: string,
@ -34,7 +33,6 @@ export async function initializeInstance(
await setInstanceId(fyo); await setInstanceId(fyo);
await setOpenCount(fyo); await setOpenCount(fyo);
await setCurrencySymbols(fyo); await setCurrencySymbols(fyo);
await updatePrintTemplates(fyo);
} }
async function closeDbIfConnected(fyo: Fyo) { async function closeDbIfConnected(fyo: Fyo) {

View File

@ -351,7 +351,9 @@ function getNameAndTypeFromTemplateFile(
} }
export const baseTemplate = `<main class="h-full w-full bg-white"> export const baseTemplate = `<main class="h-full w-full bg-white">
<header class="p-4 flex justify-between bg-gray-50">
<!-- Edit This Code -->
<header class="p-4 flex justify-between border-b">
<h2 <h2
class="font-semibold text-2xl" class="font-semibold text-2xl"
:style="{ color: print.color }" :style="{ color: print.color }"
@ -362,4 +364,11 @@ export const baseTemplate = `<main class="h-full w-full bg-white">
{{ doc.name }} {{ doc.name }}
</h2> </h2>
</header> </header>
</main>`;
<div class="p-4 text-gray-600">
Edit the code in the Template Editor on the right
to create your own personalized custom template.
</div>
</main>
`;