2
0
mirror of https://github.com/frappe/books.git synced 2024-12-28 04:55:40 +00:00
books/src/utils.js

278 lines
6.5 KiB
JavaScript
Raw Normal View History

2019-12-03 08:15:12 +00:00
import frappe from 'frappejs';
import fs from 'fs';
import { _ } from 'frappejs/utils';
2020-01-28 11:10:01 +00:00
import migrate from './migrate';
import { ipcRenderer } from 'electron';
import { IPC_MESSAGES, IPC_ACTIONS } from './messages';
import SQLite from 'frappejs/backends/sqlite';
import postStart from '../server/postStart';
import router from '@/router';
import Avatar from '@/components/Avatar';
import config from '@/config';
2021-08-24 20:10:16 +00:00
export async function createNewDatabase() {
const options = {
title: _('Select folder'),
defaultPath: 'frappe-books.db',
2021-08-24 20:10:16 +00:00
};
let { filePath } = await ipcRenderer.invoke(
IPC_ACTIONS.GET_SAVE_FILEPATH,
options
);
2021-08-24 20:10:16 +00:00
if (filePath) {
if (!filePath.endsWith('.db')) {
filePath = filePath + '.db';
}
if (fs.existsSync(filePath)) {
showMessageDialog({
// prettier-ignore
message: _('A file exists with the same name and it will be overwritten. Are you sure you want to continue?'),
buttons: [
{
label: _('Overwrite'),
action() {
fs.unlinkSync(filePath);
return filePath;
},
2021-08-24 20:10:16 +00:00
},
2021-11-05 19:41:39 +00:00
{
label: _('Cancel'),
action() {
return '';
},
},
],
2021-08-24 20:10:16 +00:00
});
} else {
return filePath;
}
}
}
2021-09-04 15:57:58 +00:00
export async function loadExistingDatabase() {
const options = {
title: _('Select file'),
properties: ['openFile'],
filters: [{ name: 'SQLite DB File', extensions: ['db'] }],
2021-09-04 15:57:58 +00:00
};
const { filePaths } = await ipcRenderer.invoke(
IPC_ACTIONS.GET_OPEN_FILEPATH,
options
);
2021-09-04 15:57:58 +00:00
if (filePaths && filePaths[0]) {
return filePaths[0];
2021-09-04 15:57:58 +00:00
}
}
export async function connectToLocalDatabase(filepath) {
2021-11-05 19:41:39 +00:00
if (!filepath) {
return false;
}
frappe.login('Administrator');
2021-11-05 19:41:39 +00:00
try {
frappe.db = new SQLite({
dbPath: filepath,
});
await frappe.db.connect();
} catch (error) {
return false;
}
2020-01-28 11:10:01 +00:00
await migrate();
await postStart();
// set file info in config
let files = config.get('files') || [];
if (!files.find((file) => file.filePath === filepath)) {
files = [
{
companyName: frappe.AccountingSettings.companyName,
filePath: filepath,
},
...files,
];
config.set('files', files);
}
// set last selected file
config.set('lastSelectedFilePath', filepath);
2021-11-05 19:41:39 +00:00
return true;
}
2021-08-18 07:01:05 +00:00
export async function showMessageDialog({
message,
description,
buttons = [],
2021-08-18 07:01:05 +00:00
}) {
const options = {
message,
detail: description,
buttons: buttons.map((a) => a.label),
};
const { response } = await ipcRenderer.invoke(
IPC_ACTIONS.GET_DIALOG_RESPONSE,
options
);
2021-08-18 06:32:45 +00:00
let button = buttons[response];
if (button && button.action) {
button.action();
}
}
2019-12-03 08:15:12 +00:00
export function deleteDocWithPrompt(doc) {
return new Promise((resolve) => {
2019-12-03 08:15:12 +00:00
showMessageDialog({
message: _('Are you sure you want to delete {0} "{1}"?', [
doc.doctype,
doc.name,
2019-12-03 08:15:12 +00:00
]),
description: _('This action is permanent'),
buttons: [
{
label: _('Delete'),
action: () => {
doc
.delete()
.then(() => resolve(true))
.catch((e) => {
handleErrorWithDialog(e, doc);
2019-12-03 08:15:12 +00:00
});
},
2019-12-03 08:15:12 +00:00
},
{
label: _('Cancel'),
action() {
resolve(false);
},
},
],
2019-12-03 08:15:12 +00:00
});
});
}
export function partyWithAvatar(party) {
return {
data() {
return {
imageURL: null,
label: null,
};
},
components: {
Avatar,
},
async mounted() {
this.imageURL = await frappe.db.getValue('Party', party, 'image');
this.label = party;
},
template: `
<div class="flex items-center" v-if="label">
<Avatar class="flex-shrink-0" :imageURL="imageURL" :label="label" size="sm" />
<span class="ml-2 truncate">{{ label }}</span>
</div>
`,
};
}
export function openQuickEdit({ doctype, name, hideFields, defaults = {} }) {
let currentRoute = router.currentRoute;
2019-12-04 17:26:17 +00:00
let query = currentRoute.query;
let method = 'push';
if (query.edit && query.doctype === doctype) {
// replace the current route if we are
// editing another document of the same doctype
method = 'replace';
}
router[method]({
query: {
edit: 1,
doctype,
name,
hideFields,
values: defaults,
lastRoute: currentRoute,
},
});
}
2020-01-29 11:01:45 +00:00
export function getErrorMessage(e, doc) {
let errorMessage = e.message || _('An error occurred');
2021-11-05 19:41:39 +00:00
const { doctype, name } = doc;
const canElaborate = doctype && name;
if (e.type === frappe.errors.LinkValidationError && canElaborate) {
errorMessage = _('{0} {1} is linked with existing records.', [
2021-11-05 19:41:39 +00:00
doctype,
name,
]);
2021-11-05 19:41:39 +00:00
} else if (e.type === frappe.errors.DuplicateEntryError && canElaborate) {
errorMessage = _('{0} {1} already exists.', [doctype, name]);
}
2020-01-29 11:01:45 +00:00
return errorMessage;
}
2020-01-29 11:01:45 +00:00
export function handleErrorWithDialog(e, doc) {
let errorMessage = getErrorMessage(e, doc);
showMessageDialog({ message: errorMessage });
throw e;
}
export async function makePDF(html, savePath) {
ipcRenderer.invoke(IPC_ACTIONS.SAVE_HTML_AS_PDF, html, savePath);
}
export function getActionsForDocument(doc) {
if (!doc) return [];
let deleteAction = {
component: {
template: `<span class="text-red-700">{{ _('Delete') }}</span>`,
},
condition: (doc) => !doc.isNew() && !doc.submitted && !doc.meta.isSingle,
action: () =>
deleteDocWithPrompt(doc).then((res) => {
if (res) {
router.push(`/list/${doc.doctype}`);
}
}),
};
let actions = [...(doc.meta.actions || []), deleteAction]
.filter((d) => (d.condition ? d.condition(doc) : true))
.map((d) => {
return {
label: d.label,
component: d.component,
action: d.action.bind(this, doc, router),
};
});
return actions;
}
2020-01-02 17:06:57 +00:00
export function openSettings(tab = 'General') {
ipcRenderer.send(IPC_MESSAGES.OPEN_SETTINGS, tab);
}
export async function runWindowAction(name) {
switch (name) {
case 'close':
ipcRenderer.send(IPC_MESSAGES.CLOSE_CURRENT_WINDOW);
break;
case 'minimize':
ipcRenderer.send(IPC_MESSAGES.MINIMIZE_CURRENT_WINDOW);
break;
case 'maximize':
const maximizing = await ipcRenderer.invoke(
IPC_ACTIONS.TOGGLE_MAXIMIZE_CURRENT_WINDOW
);
name = maximizing ? name : 'unmaximize';
break;
}
return name;
2020-01-02 17:06:57 +00:00
}