@@ -46,7 +46,7 @@
@@ -95,7 +95,6 @@ import Paginator from 'src/components/Paginator.vue';
import Row from 'src/components/Row';
import { fyo } from 'src/initFyo';
import { isNumeric } from 'src/utils';
-import { openQuickEdit, routeTo } from 'src/utils/ui';
import { objectForEach } from 'utils/index';
import { defineComponent, toRaw } from 'vue';
import ListCell from './ListCell';
diff --git a/src/pages/ListView/ListCell.vue b/src/pages/ListView/ListCell.vue
index ac56095be..63c8f7552 100644
--- a/src/pages/ListView/ListCell.vue
+++ b/src/pages/ListView/ListCell.vue
@@ -4,26 +4,52 @@
-
diff --git a/src/utils/ui.ts b/src/utils/ui.ts
index 614bf1464..2dabd5234 100644
--- a/src/utils/ui.ts
+++ b/src/utils/ui.ts
@@ -344,36 +344,6 @@ async function openEdit({ name, schemaName }: Doc) {
const route = getFormRoute(schemaName, name);
return await routeTo(route);
-
- /*
- const listConfig = fyo.models[doc.schemaName]?.getListViewSettings?.(fyo);
- const formRoute = listConfig?.formRoute;
- if (!doc.name) {
- return;
- }
-
- if (formRoute) {
- const route = formRoute(doc.name);
- return await routeTo(route);
- }
-
- const isFormEdit = [
- ModelNameEnum.SalesInvoice,
- ModelNameEnum.PurchaseInvoice,
- ModelNameEnum.JournalEntry,
- ModelNameEnum.Shipment,
- ModelNameEnum.PurchaseReceipt,
- ModelNameEnum.StockMovement,
- ModelNameEnum.Payment,
- ModelNameEnum.Item,
- ].includes(doc.schemaName as ModelNameEnum);
-
- if (isFormEdit) {
- return await routeTo(`/edit/${doc.schemaName}/${doc.name}`);
- }
-
- await openQuickEdit({ schemaName: doc.schemaName, name: doc.name });
- */
}
function getDuplicateAction(doc: Doc): Action {
From eda3bb757619926a5b69d072e8ffc8f4193af321 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 7 Mar 2023 14:16:19 +0530
Subject: [PATCH 16/33] incr: insert or update .template.html files - move
.template.html files out of fixtures
---
electron-builder.yml | 1 +
main.ts | 2 +-
main/getPrintTemplates.ts | 41 ++++++++
main/registerIpcMainActionListeners.ts | 7 +-
src/renderer.ts | 2 +
src/utils/initialization.ts | 3 +-
src/utils/ipcCalls.ts | 6 +-
src/utils/printTemplates.ts | 95 ++++++++++++++++++-
.../Basic.template.html | 0
.../Business.template.html | 0
.../Minimal.template.html | 0
utils/messages.ts | 1 +
utils/types.ts | 10 +-
13 files changed, 161 insertions(+), 7 deletions(-)
create mode 100644 main/getPrintTemplates.ts
rename {fixtures/printTemplates => templates}/Basic.template.html (100%)
rename {fixtures/printTemplates => templates}/Business.template.html (100%)
rename {fixtures/printTemplates => templates}/Minimal.template.html (100%)
diff --git a/electron-builder.yml b/electron-builder.yml
index 95647edb5..5cbe2e427 100644
--- a/electron-builder.yml
+++ b/electron-builder.yml
@@ -5,6 +5,7 @@ extraResources:
[
{ from: 'log_creds.txt', to: '../creds/log_creds.txt' },
{ from: 'translations', to: '../translations' },
+ { from: 'translations', to: '../translations' },
]
mac:
type: distribution
diff --git a/main.ts b/main.ts
index 956b82075..792e6dd7e 100644
--- a/main.ts
+++ b/main.ts
@@ -4,7 +4,7 @@ import {
app,
BrowserWindow,
BrowserWindowConstructorOptions,
- protocol
+ protocol,
} from 'electron';
import Store from 'electron-store';
import { autoUpdater } from 'electron-updater';
diff --git a/main/getPrintTemplates.ts b/main/getPrintTemplates.ts
new file mode 100644
index 000000000..d0aa48df2
--- /dev/null
+++ b/main/getPrintTemplates.ts
@@ -0,0 +1,41 @@
+import fs from 'fs/promises';
+import path from 'path';
+import { TemplateFile } from 'utils/types';
+
+export async function getTemplates() {
+ const paths = await getPrintTemplatePaths();
+ if (!paths) {
+ return [];
+ }
+
+ const templates: TemplateFile[] = [];
+ for (const file of paths.files) {
+ const filePath = path.join(paths.root, file);
+ const template = await fs.readFile(filePath, 'utf-8');
+ const { mtime } = await fs.stat(filePath);
+ templates.push({ template, file, modified: mtime.toISOString() });
+ }
+
+ return templates;
+}
+
+async function getPrintTemplatePaths(): Promise<{
+ files: string[];
+ root: string;
+} | null> {
+ let root = path.join(process.resourcesPath, `../templates`);
+
+ try {
+ const files = await fs.readdir(root);
+ return { files, root };
+ } catch {
+ root = path.join(__dirname, `../templates`);
+ }
+
+ try {
+ const files = await fs.readdir(root);
+ return { files, root };
+ } catch {
+ return null;
+ }
+}
diff --git a/main/registerIpcMainActionListeners.ts b/main/registerIpcMainActionListeners.ts
index 17561f93b..0a41cb742 100644
--- a/main/registerIpcMainActionListeners.ts
+++ b/main/registerIpcMainActionListeners.ts
@@ -10,6 +10,7 @@ import { DatabaseMethod } from '../utils/db/types';
import { IPC_ACTIONS } from '../utils/messages';
import { getUrlAndTokenString, sendError } from './contactMothership';
import { getLanguageMap } from './getLanguageMap';
+import { getTemplates } from './getPrintTemplates';
import {
getConfigFilesWithModified,
getErrorHandledReponse,
@@ -117,7 +118,7 @@ export default function registerIpcMainActionListeners(main: Main) {
);
ipcMain.handle(IPC_ACTIONS.GET_CREDS, async (event) => {
- return await getUrlAndTokenString();
+ return getUrlAndTokenString();
});
ipcMain.handle(IPC_ACTIONS.DELETE_FILE, async (_, filePath) => {
@@ -137,6 +138,10 @@ export default function registerIpcMainActionListeners(main: Main) {
};
});
+ ipcMain.handle(IPC_ACTIONS.GET_TEMPLATES, async () => {
+ return getTemplates();
+ });
+
/**
* Database Related Actions
*/
diff --git a/src/renderer.ts b/src/renderer.ts
index 60e090ad6..cd5ed510b 100644
--- a/src/renderer.ts
+++ b/src/renderer.ts
@@ -111,6 +111,8 @@ function setOnWindow(isDevelopment: boolean) {
window.fyo = fyo;
// @ts-ignore
window.DateTime = DateTime;
+ // @ts-ignore
+ window.ipcRenderer = ipcRenderer;
}
function getPlatformName(platform: string) {
diff --git a/src/utils/initialization.ts b/src/utils/initialization.ts
index c5184de75..d83523634 100644
--- a/src/utils/initialization.ts
+++ b/src/utils/initialization.ts
@@ -1,6 +1,5 @@
import { Fyo } from 'fyo';
import { ConfigFile, ConfigKeys } from 'fyo/core/types';
-import { Doc } from 'fyo/model/doc';
import { getRegionalModels, models } from 'models/index';
import { ModelNameEnum } from 'models/types';
import { TargetField } from 'schemas/types';
@@ -9,6 +8,7 @@ import {
getRandomString,
getValueMapFromList,
} from 'utils/index';
+import { updatePrintTemplates } from './printTemplates';
export async function initializeInstance(
dbPath: string,
@@ -34,6 +34,7 @@ export async function initializeInstance(
await setInstanceId(fyo);
await setOpenCount(fyo);
await setCurrencySymbols(fyo);
+ await updatePrintTemplates(fyo);
}
async function closeDbIfConnected(fyo: Fyo) {
diff --git a/src/utils/ipcCalls.ts b/src/utils/ipcCalls.ts
index 3049c82d8..1f1d50ae7 100644
--- a/src/utils/ipcCalls.ts
+++ b/src/utils/ipcCalls.ts
@@ -6,7 +6,7 @@ import { t } from 'fyo';
import { BaseError } from 'fyo/utils/errors';
import { BackendResponse } from 'utils/ipc/types';
import { IPC_ACTIONS, IPC_MESSAGES } from 'utils/messages';
-import { SelectFileOptions, SelectFileReturn } from 'utils/types';
+import { SelectFileOptions, SelectFileReturn, TemplateFile } from 'utils/types';
import { setLanguageMap } from './language';
import { showMessageDialog, showToast } from './ui';
@@ -14,6 +14,10 @@ export function reloadWindow() {
return ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
}
+export async function getTemplates(): Promise
{
+ return await ipcRenderer.invoke(IPC_ACTIONS.GET_TEMPLATES);
+}
+
export async function selectFile(
options: SelectFileOptions
): Promise {
diff --git a/src/utils/printTemplates.ts b/src/utils/printTemplates.ts
index 9f3c45448..2ab4f9b6e 100644
--- a/src/utils/printTemplates.ts
+++ b/src/utils/printTemplates.ts
@@ -3,10 +3,14 @@ import { Doc } from 'fyo/model/doc';
import { Invoice } from 'models/baseModels/Invoice/Invoice';
import { ModelNameEnum } from 'models/types';
import { FieldTypeEnum, Schema, TargetField } from 'schemas/types';
-import { getSavePath, makePDF } from './ipcCalls';
+import { getValueMapFromList } from 'utils/index';
+import { TemplateFile } from 'utils/types';
+import { getSavePath, getTemplates, makePDF } from './ipcCalls';
import { PrintValues } from './types';
+import { getDocFromNameIfExistsElseNew } from './ui';
type PrintTemplateData = Record;
+type TemplateUpdateItem = { name: string; template: string; type: string };
const printSettingsFields = [
'logo',
@@ -256,3 +260,92 @@ function getAllCSSAsStyleElem() {
styleElem.innerHTML = cssTexts.join('\n');
return styleElem;
}
+
+export async function updatePrintTemplates(fyo: Fyo) {
+ const templateFiles = await getTemplates();
+ const existingTemplates = (await fyo.db.getAll(ModelNameEnum.PrintTemplate, {
+ fields: ['name', 'modified'],
+ filters: { isCustom: false },
+ })) as { name: string; modified: Date }[];
+
+ const nameModifiedMap = getValueMapFromList(
+ existingTemplates,
+ 'name',
+ 'modified'
+ );
+
+ const updateList: TemplateUpdateItem[] = [];
+ for (const templateFile of templateFiles) {
+ const updates = getPrintTemplateUpdateList(
+ templateFile,
+ nameModifiedMap,
+ fyo
+ );
+
+ updateList.push(...updates);
+ }
+
+ for (const { name, type, template } of updateList) {
+ const doc = await getDocFromNameIfExistsElseNew(
+ ModelNameEnum.PrintTemplate,
+ name
+ );
+
+ await doc.set({ name, type, template, isCustom: false });
+ await doc.sync();
+ }
+}
+
+function getPrintTemplateUpdateList(
+ { file, template, modified: modifiedString }: TemplateFile,
+ nameModifiedMap: Record,
+ fyo: Fyo
+): TemplateUpdateItem[] {
+ const templateList: TemplateUpdateItem[] = [];
+ const dbModified = new Date(modifiedString);
+
+ for (const { name, type } of getNameAndTypeFromTemplateFile(file, fyo)) {
+ const fileModified = nameModifiedMap[name];
+ if (fileModified && dbModified.valueOf() >= fileModified.valueOf()) {
+ continue;
+ }
+
+ templateList.push({
+ name,
+ type,
+ template,
+ });
+ }
+ return templateList;
+}
+
+function getNameAndTypeFromTemplateFile(
+ file: string,
+ fyo: Fyo
+): { name: string; type: string }[] {
+ /**
+ * Template File Name Format:
+ * TemplateName[.SchemaName].template.html
+ *
+ * If the SchemaName is absent then it is assumed
+ * that the SchemaName is:
+ * - SalesInvoice
+ * - PurchaseInvoice
+ */
+
+ const fileName = file.split('.template.html')[0];
+ const name = fileName.split('.')[0];
+ const schemaName = fileName.split('.')[1];
+
+ if (schemaName) {
+ const label = fyo.schemaMap[schemaName]?.label ?? schemaName;
+ return [{ name: `${name} - ${label}`, type: schemaName }];
+ }
+
+ return [ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice].map(
+ (schemaName) => {
+ const label = fyo.schemaMap[schemaName]?.label ?? schemaName;
+ return { name: `${name} - ${label}`, type: schemaName };
+ }
+ );
+}
diff --git a/fixtures/printTemplates/Basic.template.html b/templates/Basic.template.html
similarity index 100%
rename from fixtures/printTemplates/Basic.template.html
rename to templates/Basic.template.html
diff --git a/fixtures/printTemplates/Business.template.html b/templates/Business.template.html
similarity index 100%
rename from fixtures/printTemplates/Business.template.html
rename to templates/Business.template.html
diff --git a/fixtures/printTemplates/Minimal.template.html b/templates/Minimal.template.html
similarity index 100%
rename from fixtures/printTemplates/Minimal.template.html
rename to templates/Minimal.template.html
diff --git a/utils/messages.ts b/utils/messages.ts
index a69d9b48c..7340d4fb3 100644
--- a/utils/messages.ts
+++ b/utils/messages.ts
@@ -22,6 +22,7 @@ export enum IPC_ACTIONS {
SELECT_FILE = 'select-file',
GET_CREDS = 'get-creds',
GET_DB_LIST = 'get-db-list',
+ GET_TEMPLATES = 'get-templates',
DELETE_FILE = 'delete-file',
// Database messages
DB_CREATE = 'db-create',
diff --git a/utils/types.ts b/utils/types.ts
index 8bdfe203b..af9a5e208 100644
--- a/utils/types.ts
+++ b/utils/types.ts
@@ -23,14 +23,18 @@ export interface VersionParts {
beta?: number;
}
-export type Creds = { errorLogUrl: string; telemetryUrl: string; tokenString: string };
+export type Creds = {
+ errorLogUrl: string;
+ telemetryUrl: string;
+ tokenString: string;
+};
export type UnexpectedLogObject = {
name: string;
message: string;
stack: string;
more: Record;
-}
+};
export interface SelectFileOptions {
title: string;
@@ -48,3 +52,5 @@ export interface SelectFileReturn {
export type PropertyEnum> = {
[key in keyof Required]: key;
};
+
+export type TemplateFile = { file: string; template: string; modified: string };
From 45d39f4fcf2a5490ae73a890638f4502b6c70cf7 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Tue, 7 Mar 2023 15:07:02 +0530
Subject: [PATCH 17/33] refactor: convert sidebar toggler to use ref
---
src/components/PageHeader.vue | 10 +++++++---
src/components/Sidebar.vue | 9 +++++----
src/pages/Desk.vue | 26 +++++++++++---------------
src/utils/refs.ts | 1 +
src/utils/ui.ts | 9 +++++++++
5 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/src/components/PageHeader.vue b/src/components/PageHeader.vue
index 1f6355a01..31076740e 100644
--- a/src/components/PageHeader.vue
+++ b/src/components/PageHeader.vue
@@ -8,9 +8,9 @@
>
@@ -31,12 +31,13 @@
-
From 11c714a9571f83e19678ee9d0d4d4d2471976ea6 Mon Sep 17 00:00:00 2001
From: 18alantom <2.alan.tom@gmail.com>
Date: Thu, 9 Mar 2023 11:47:25 +0530
Subject: [PATCH 20/33] feat: add autocomplete for linklabels - update editor
styling
---
package.json | 1 +
src/pages/TemplateBuilder/TemplateBuilder.vue | 17 ++-
.../TemplateBuilder/TemplateBuilderHint.vue | 6 +-
src/pages/TemplateBuilder/TemplateEditor.vue | 143 +++++++++++++++++-
yarn.lock | 2 +-
5 files changed, 150 insertions(+), 19 deletions(-)
diff --git a/package.json b/package.json
index 420698589..0c05a90ef 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"test": "scripts/test.sh"
},
"dependencies": {
+ "@codemirror/autocomplete": "^6.4.2",
"@codemirror/lang-vue": "^0.1.1",
"@popperjs/core": "^2.10.2",
"better-sqlite3": "^7.5.3",
diff --git a/src/pages/TemplateBuilder/TemplateBuilder.vue b/src/pages/TemplateBuilder/TemplateBuilder.vue
index 62e4e9e2c..407f3663d 100644
--- a/src/pages/TemplateBuilder/TemplateBuilder.vue
+++ b/src/pages/TemplateBuilder/TemplateBuilder.vue
@@ -178,7 +178,7 @@
>