2
0
mirror of https://github.com/frappe/books.git synced 2025-01-22 14:48:25 +00:00

incr: update routing

- update PrintTemplate UI code
This commit is contained in:
18alantom 2023-02-22 15:51:20 +05:30
parent 2e0eb654e9
commit 28aa0f135e
8 changed files with 263 additions and 22 deletions

View File

@ -1,8 +1,54 @@
import { Doc } from 'fyo/model/doc';
import { SchemaMap } from 'schemas/types';
import { ListsMap, ListViewSettings, ReadOnlyMap } from 'fyo/model/types';
import { ModelNameEnum } from 'models/types';
export class PrintTemplate extends Doc {
name?: string;
type?: string;
template?: string;
isCustom?: boolean;
static getListViewSettings(): ListViewSettings {
return {
formRoute: ({ name }) => `/template-builder/${name}`,
columns: ['name', 'type', 'isCustom'],
};
}
readOnly: ReadOnlyMap = {
name: () => !!this.isCustom,
type: () => !!this.isCustom,
template: () => !!this.isCustom,
};
static lists: ListsMap = {
type(doc?: Doc) {
let enableInventory: boolean = false;
let schemaMap: SchemaMap = {};
if (doc) {
enableInventory = !!doc.fyo.singles.AccountingSettings?.enableInventory;
schemaMap = doc.fyo.schemaMap;
}
const models = [
ModelNameEnum.SalesInvoice,
ModelNameEnum.PurchaseInvoice,
ModelNameEnum.Payment,
];
if (enableInventory) {
models.push(
ModelNameEnum.Shipment,
ModelNameEnum.PurchaseReceipt,
ModelNameEnum.StockMovement
);
}
return models.map((value) => ({
value,
label: schemaMap[value]?.label ?? value,
}));
},
};
}

View File

@ -21,6 +21,7 @@ export enum ModelNameEnum {
Payment = 'Payment',
PaymentFor = 'PaymentFor',
PrintSettings = 'PrintSettings',
PrintTemplate = 'PrintTemplate',
PurchaseInvoice = 'PurchaseInvoice',
PurchaseInvoiceItem = 'PurchaseInvoiceItem',
SalesInvoice = 'SalesInvoice',

View File

@ -13,20 +13,22 @@
{
"fieldname": "type",
"label": "Template Type",
"fieldtype": "Select",
"fieldtype": "AutoComplete",
"default": "SalesInvoice",
"required": true
},
{
"fieldname": "template",
"label": "Template",
"fieldtype": "Data",
"fieldtype": "Text",
"required": true
},
{
"fieldname": "isCustom",
"label": "Is Custom",
"fieldtype": "Check",
"default": false
"default": false,
"readOnly": true
}
]
}

View File

@ -116,6 +116,7 @@ import { docsPathMap } from 'src/utils/misc';
import { docsPathRef, focusedDocsRef } from 'src/utils/refs';
import { ActionGroup, UIGroupedFields } from 'src/utils/types';
import {
getDocFromNameIfExistsElseNew,
getFieldsGroupedByTabAndSection,
getGroupedActionsForDoc,
} from 'src/utils/ui';
@ -277,18 +278,10 @@ export default defineComponent({
return;
}
if (this.name) {
await this.setDocFromName(this.name);
} else {
this.docOrNull = this.fyo.doc.getNewDoc(this.schemaName);
}
},
async setDocFromName(name: string) {
try {
this.docOrNull = await this.fyo.doc.getDoc(this.schemaName, name);
} catch (err) {
this.docOrNull = this.fyo.doc.getNewDoc(this.schemaName);
}
this.docOrNull = await getDocFromNameIfExistsElseNew(
this.schemaName,
this.name
);
},
async toggleQuickEditDoc(doc: Doc | null) {
if (this.quickEditDoc && doc) {

View File

@ -1,11 +1,194 @@
<template>
<div>
<PageHeader :title="t`Template Builder`" />
<PageHeader :title="t`Template Builder`">Hi</PageHeader>
<!-- Template Builder Body -->
<div class="w-full h-full flex" v-if="doc">
<!-- Print View Container -->
<div></div>
<!-- Template Builder Controls -->
<div class="w-quick-edit h-full right-0 ml-auto border-l flex flex-col">
<!-- Print Template Fields -->
<div class="p-4 flex flex-col gap-4">
<FormControl
:df="fields.name"
:border="true"
:value="doc.get('name')"
@change="async (value) => await doc?.set('name', value)"
/>
</div>
<!-- Controls -->
<div class="p-4 border-t">
<div
class="flex justify-between items-center cursor-pointer select-none"
:class="helpersCollapsed ? '' : 'mb-4'"
@click="helpersCollapsed = !helpersCollapsed"
>
<h2 class="text-base text-gray-900 font-semibold">
{{ t`Controls` }}
</h2>
<feather-icon
:name="helpersCollapsed ? 'chevron-up' : 'chevron-down'"
class="w-4 h-4 text-gray-600 resize-none"
/>
</div>
<!--
TODO:
- Select Test Doc
- View Template Data and Keys
-->
<div v-if="!helpersCollapsed" class="w-full flex flex-col gap-4">
<FormControl
:df="fields.type"
:show-label="true"
:border="true"
:value="doc.get('type')"
@change="async (value) => await doc?.set('type', value)"
/>
<FormControl
v-if="doc.type"
:df="displayDocField"
:show-label="true"
:border="true"
:value="displayDoc?.name"
@change="(value: string) => setDisplayDoc(value)"
/>
<FormControl
v-if="doc.isCustom"
:df="fields.isCustom"
:show-label="true"
:border="true"
:value="doc.get('isCustom')"
/>
</div>
</div>
<!-- Template -->
<div class="p-4 border-t">
<div
class="flex justify-between items-center cursor-pointer select-none"
@click="templateCollapsed = !templateCollapsed"
>
<h2 class="text-base text-gray-900 font-semibold">
{{ t`Template` }}
</h2>
<feather-icon
:name="templateCollapsed ? 'chevron-up' : 'chevron-down'"
class="w-4 h-4 text-gray-600"
/>
</div>
<!-- Template Container -->
<textarea
v-if="!templateCollapsed"
:spellcheck="false"
rows="20"
class="
overflow-auto
mt-4
p-2
w-full
border
rounded
text-sm text-gray-900
focus-within:bg-gray-100
outline-none
bg-gray-50
"
style="
font-family: monospace;
white-space: pre;
overflow-wrap: normal;
"
/>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import { PrintTemplate } from 'models/baseModels/PrintTemplate';
import { ModelNameEnum } from 'models/types';
import { Field, TargetField } from 'schemas/types';
import FormControl from 'src/components/Controls/FormControl.vue';
import PageHeader from 'src/components/PageHeader.vue';
import { defineComponent } from 'vue';
import { getDocFromNameIfExistsElseNew } from 'src/utils/ui';
import { getMapFromList } from 'utils/index';
import { computed, defineComponent } from 'vue';
export default defineComponent({ components: { PageHeader } });
export default defineComponent({
props: { name: String },
components: { PageHeader, FormControl },
provide() {
return { doc: computed(() => this.doc) };
},
data() {
return {
doc: null,
templateCollapsed: false,
helpersCollapsed: true,
displayDoc: null,
} as {
doc: PrintTemplate | null;
displayDoc: PrintTemplate | null;
templateCollapsed: boolean;
helpersCollapsed: boolean;
};
},
async mounted() {
// @ts-ignore
window.tb = this;
await this.setDoc();
if (!this.doc?.template) {
this.helpersCollapsed = false;
}
},
methods: {
async setDoc() {
if (this.doc) {
return;
}
this.doc = (await getDocFromNameIfExistsElseNew(
ModelNameEnum.PrintTemplate,
this.name
)) as PrintTemplate;
},
async setDisplayDoc(value: string) {
if (!value) {
this.displayDoc = null;
return;
}
const schemaName = this.doc?.type;
if (!schemaName) {
return;
}
this.displayDoc = await getDocFromNameIfExistsElseNew(schemaName, value);
},
},
computed: {
fields(): Record<string, Field> {
return getMapFromList(
this.fyo.schemaMap.PrintTemplate?.fields ?? [],
'fieldname'
);
},
displayDocField(): TargetField {
const target = this.doc?.type ?? ModelNameEnum.SalesInvoice;
return {
fieldname: 'displayDoc',
label: this.t`Display Doc`,
fieldtype: 'Link',
target,
};
},
},
});
</script>

View File

@ -129,9 +129,10 @@ const routes: RouteRecordRaw[] = [
component: ImportWizard,
},
{
path: '/template-builder',
path: '/template-builder/:name',
name: 'Template Builder',
component: TemplateBuilder,
props: true,
},
{
path: '/settings',

View File

@ -273,9 +273,9 @@ async function getCompleteSidebar(): Promise<SidebarConfig> {
route: '/import-wizard',
},
{
label: t`Template Builder`,
name: 'template-builder',
route: '/template-builder',
label: t`Print Templates`,
name: 'print-template',
route: `/list/PrintTemplate/${t`Print Templates`}`,
},
{
label: t`Settings`,

View File

@ -450,3 +450,18 @@ export function getFormRoute(
return `/list/${schemaName}?edit=1&schemaName=${schemaName}&name=${name}`;
}
export async function getDocFromNameIfExistsElseNew(
schemaName: string,
name?: string
) {
if (!name) {
return fyo.doc.getNewDoc(schemaName);
}
try {
return await fyo.doc.getDoc(schemaName, name);
} catch {
return fyo.doc.getNewDoc(schemaName);
}
}