2
0
mirror of https://github.com/frappe/books.git synced 2024-11-09 23:30:56 +00:00

incr: add scaled container

- allow changing the scale of the print view
- prevent deletion of non custom templates
This commit is contained in:
18alantom 2023-02-24 12:14:58 +05:30
parent 6cf4a5ec0c
commit c04098a3eb
6 changed files with 121 additions and 41 deletions

View File

@ -9,6 +9,14 @@ export class PrintTemplate extends Doc {
template?: string;
isCustom?: boolean;
override get canDelete(): boolean {
if (this.isCustom === false) {
return false;
}
return super.canDelete;
}
static getListViewSettings(): ListViewSettings {
return {
formRoute: ({ name }) => `/template-builder/${name}`,

View File

@ -27,7 +27,7 @@
"fieldname": "isCustom",
"label": "Is Custom",
"fieldtype": "Check",
"default": false,
"default": true,
"readOnly": true
}
]

View File

@ -166,6 +166,10 @@ export default {
const { onboardingComplete } = await fyo.doc.getDoc('GetStarted');
const { hideGetStarted } = await fyo.doc.getDoc('SystemSettings');
if (fyo.store.isDevelopment) {
return routeTo('/list/PrintTemplate');
}
if (hideGetStarted || onboardingComplete) {
routeTo('/');
} else {

View File

@ -13,6 +13,7 @@
:value="value"
:placeholder="inputPlaceholder"
:readonly="isReadOnly"
:step="step"
:max="df.maxvalue"
:min="df.minvalue"
@blur="(e) => !isReadOnly && triggerChange(e.target.value)"
@ -32,6 +33,7 @@ export default {
name: 'Base',
props: {
df: Object,
step: { type: Number, default: 1 },
value: [String, Number, Boolean, Object],
inputClass: [Function, String, Object],
border: { type: Boolean, default: false },

View File

@ -0,0 +1,49 @@
<template>
<div class="overflow-hidden" :style="outerContainerStyle">
<div :style="innerContainerStyle">
<slot></slot>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
/**
* This Component is required because * CSS transforms (eg
* scale) don't change the area taken by * an element.
*
* So to circumvent this, the outer element needs to have
* the scaled dimensions without applying a CSS transform.
*/
export default defineComponent({
props: {
height: { type: String, default: '29.7cm' },
width: { type: String, default: '21cm' },
scale: { type: Number, default: 0.65 },
},
computed: {
innerContainerStyle(): Record<string, string> {
const style: Record<string, string> = {};
style['width'] = this.width;
style['height'] = this.height;
style['transform'] = `scale(${this.scale})`;
style['margin-top'] = `calc(-1 * (${this.height} * ${
1 - this.scale
}) / 2)`;
style['margin-left'] = `calc(-1 * (${this.width} * ${
1 - this.scale
}) / 2)`;
return style;
},
outerContainerStyle(): Record<string, string> {
const style: Record<string, string> = {};
style['height'] = `calc(${this.scale} * ${this.height})`;
style['width'] = `calc(${this.scale} * ${this.width})`;
return style;
},
},
});
</script>

View File

@ -14,40 +14,50 @@
</PageHeader>
<!-- Template Builder Body -->
<div
class="w-full h-full bg-gray-25 grid"
style="grid-template-columns: auto var(--w-quick-edit)"
class="w-full overflowauto bg-gray-25 grid"
style="
grid-template-columns: auto var(--w-quick-edit);
height: calc(100vh - var(--h-row-largest) - 1px);
"
v-if="doc"
>
<!-- Print View Container -->
<div class="overflow-auto custom-scroll">
<!-- Template Display Area -->
<div class="overflow-auto custom-scroll p-4">
<!-- Display Hints -->
<div v-if="helperText" class="p-4 text-sm text-gray-700">
<div v-if="helperText" class="text-sm text-gray-700">
{{ helperText }}
</div>
<div
v-if="doc.template && values && !helperText"
ref="printContainer"
class="h-full shadow-lg border bg-white"
style="
width: 21cm;
height: 29.7cm;
transform: scale(0.65);
margin-top: -150px;
margin-left: -100px;
"
<!-- Template Container -->
<ScaledContainer
v-if="doc.template && values"
:scale="Math.max(scale, 0.1)"
ref="scaledContainer"
class="mx-auto shadow-lg border"
>
<!-- Template -->
<component
class="flex-1"
class="flex-1 bg-white"
:doc="values.doc"
:print="values.print"
:is="{ template: doc.template, props: ['doc', 'print'] }"
/>
</div>
</ScaledContainer>
</div>
<!-- Template Builder Controls -->
<div class="h-full w-full ml-auto border-l flex flex-col bg-white">
<div
class="
h-full
w-full
ml-auto
border-l
flex flex-col
bg-white
overflow-auto
custom-scroll
"
>
<!-- Print Template Fields -->
<div class="p-4 flex flex-col gap-4">
<FormControl
@ -62,7 +72,7 @@
/>
</div>
<!-- Controls -->
<!-- Controls Section -->
<div class="p-4 border-t">
<div
class="flex justify-between items-center cursor-pointer select-none"
@ -99,18 +109,25 @@
/>
<FormControl
v-if="doc.isCustom"
v-if="displayDoc && doc.template"
size="small"
:df="fields.isCustom"
:step="0.01"
:df="{
fieldtype: 'Float',
label: t`Display Scale`,
fieldname: 'displayScale',
maxvalue: 10,
minvalue: 0.1,
}"
:show-label="true"
:border="true"
:read-only="true"
:value="doc.get('isCustom')"
:value="scale"
@change="(value: number) => scale = value"
/>
</div>
</div>
<!-- Template -->
<!-- Template Section -->
<div class="p-4 border-t" v-if="doc.type">
<div
class="flex justify-between items-center cursor-pointer select-none"
@ -125,7 +142,7 @@
/>
</div>
<!-- Template Container -->
<!-- Template Editor -->
<textarea
v-if="!templateCollapsed"
style="
@ -197,6 +214,7 @@ import {
import { getActionsForDoc, getDocFromNameIfExistsElseNew } from 'src/utils/ui';
import { getMapFromList } from 'utils/index';
import { computed, defineComponent } from 'vue';
import ScaledContainer from './ScaledContainer.vue';
import TemplateBuilderHint from './TemplateBuilderHint.vue';
export default defineComponent({
@ -209,6 +227,7 @@ export default defineComponent({
FormHeader,
TemplateBuilderHint,
DropdownWithActions,
ScaledContainer,
},
provide() {
return { doc: computed(() => this.doc) };
@ -222,6 +241,7 @@ export default defineComponent({
templateCollapsed: false,
helpersCollapsed: true,
displayDoc: null,
scale: 0.65,
} as {
hint: null | Record<string, unknown>;
values: null | Record<string, unknown>;
@ -230,6 +250,7 @@ export default defineComponent({
displayDoc: PrintTemplate | null;
templateCollapsed: boolean;
helpersCollapsed: boolean;
scale: number;
};
},
async mounted() {
@ -239,20 +260,11 @@ export default defineComponent({
this.helpersCollapsed = false;
}
if (!this.fyo.store.isDevelopment) {
return;
if (this.fyo.store.isDevelopment) {
// @ts-ignore
window.tb = this;
this.setDisplayDoc('SINV-1001');
}
// @ts-ignore
window.tb = this;
// @ts-ignore
window.hints = getPrintTemplatePropHints;
// @ts-ignore
window.values = getPrintTemplatePropValues;
this.setDisplayDoc('SINV-1001');
},
methods: {
async makePDF() {
@ -261,7 +273,12 @@ export default defineComponent({
return;
}
const innerHTML = (this.$refs.printContainer as HTMLDivElement).innerHTML;
// @ts-ignore
const innerHTML = this.$refs.scaledContainer.$el.children[0].innerHTML;
if (!innerHTML) {
return;
}
await getPathAndMakePDF(displayDoc.name!, innerHTML);
},
async sync() {