mirror of
https://github.com/frappe/books.git
synced 2025-01-10 18:24:40 +00:00
fix: add failsafes along db connection paths
This commit is contained in:
parent
415bf0e047
commit
ae5cade05a
@ -2,7 +2,7 @@
|
|||||||
"name": "frappe-books",
|
"name": "frappe-books",
|
||||||
"description": "Simple book-keeping app for everyone",
|
"description": "Simple book-keeping app for everyone",
|
||||||
"homepage": "https://frappebooks.com",
|
"homepage": "https://frappebooks.com",
|
||||||
"version": "0.0.4-beta.0",
|
"version": "0.0.4-beta.1",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Frappe Technologies Pvt. Ltd.",
|
"name": "Frappe Technologies Pvt. Ltd.",
|
||||||
"email": "hello@frappe.io"
|
"email": "hello@frappe.io"
|
||||||
|
17
src/App.vue
17
src/App.vue
@ -30,9 +30,10 @@ import DatabaseSelector from './pages/DatabaseSelector';
|
|||||||
import WindowsTitleBar from '@/components/WindowsTitleBar';
|
import WindowsTitleBar from '@/components/WindowsTitleBar';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { routeTo } from '@/utils';
|
|
||||||
import { IPC_MESSAGES, IPC_ACTIONS } from '@/messages';
|
import { IPC_MESSAGES, IPC_ACTIONS } from '@/messages';
|
||||||
import { connectToLocalDatabase, purgeCache } from '@/initialization';
|
import { connectToLocalDatabase, purgeCache } from '@/initialization';
|
||||||
|
import { routeTo, showErrorDialog } from './utils';
|
||||||
|
import { DB_CONN_FAILURE } from './messages';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'App',
|
name: 'App',
|
||||||
@ -68,15 +69,23 @@ export default {
|
|||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
const lastSelectedFilePath = config.get('lastSelectedFilePath', null);
|
const lastSelectedFilePath = config.get('lastSelectedFilePath', null);
|
||||||
const connectionSuccess = await connectToLocalDatabase(
|
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||||
lastSelectedFilePath
|
lastSelectedFilePath
|
||||||
);
|
);
|
||||||
|
|
||||||
if (connectionSuccess) {
|
if (connectionSuccess) {
|
||||||
this.showSetupWizardOrDesk();
|
this.showSetupWizardOrDesk();
|
||||||
} else {
|
return;
|
||||||
this.activeScreen = 'DatabaseSelector';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lastSelectedFilePath) {
|
||||||
|
await showErrorDialog({
|
||||||
|
title: 'DB Connection Error',
|
||||||
|
content: `reason: ${reason}, filePath: ${lastSelectedFilePath}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.activeScreen = 'DatabaseSelector';
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async showSetupWizardOrDesk(resetRoute = false) {
|
async showSetupWizardOrDesk(resetRoute = false) {
|
||||||
|
@ -185,6 +185,10 @@ ipcMain.handle(IPC_ACTIONS.GET_DIALOG_RESPONSE, async (event, options) => {
|
|||||||
return await dialog.showMessageBox(window, options);
|
return await dialog.showMessageBox(window, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(IPC_ACTIONS.SHOW_ERROR, async (event, { title, content }) => {
|
||||||
|
return await dialog.showErrorBox(title, content);
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle(IPC_ACTIONS.SAVE_HTML_AS_PDF, async (event, html, savePath) => {
|
ipcMain.handle(IPC_ACTIONS.SAVE_HTML_AS_PDF, async (event, html, savePath) => {
|
||||||
return await saveHtmlAsPdf(html, savePath);
|
return await saveHtmlAsPdf(html, savePath);
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@ import fs from 'fs';
|
|||||||
import models from '../models';
|
import models from '../models';
|
||||||
import regionalModelUpdates from '../models/regionalModelUpdates';
|
import regionalModelUpdates from '../models/regionalModelUpdates';
|
||||||
import postStart from '../server/postStart';
|
import postStart from '../server/postStart';
|
||||||
import { IPC_ACTIONS } from './messages';
|
import { DB_CONN_FAILURE, IPC_ACTIONS } from './messages';
|
||||||
import migrate from './migrate';
|
import migrate from './migrate';
|
||||||
|
|
||||||
export async function createNewDatabase() {
|
export async function createNewDatabase() {
|
||||||
@ -52,7 +52,7 @@ async function runRegionalModelUpdates() {
|
|||||||
|
|
||||||
export async function connectToLocalDatabase(filePath) {
|
export async function connectToLocalDatabase(filePath) {
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
return false;
|
return { connectionSuccess: false, reason: DB_CONN_FAILURE.INVALID_FILE };
|
||||||
}
|
}
|
||||||
|
|
||||||
frappe.login('Administrator');
|
frappe.login('Administrator');
|
||||||
@ -63,7 +63,7 @@ export async function connectToLocalDatabase(filePath) {
|
|||||||
await frappe.db.connect();
|
await frappe.db.connect();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return false;
|
return { connectionSuccess: false, reason: DB_CONN_FAILURE.CANT_CONNECT };
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -72,8 +72,17 @@ export async function connectToLocalDatabase(filePath) {
|
|||||||
console.error('regional model updates failed', error);
|
console.error('regional model updates failed', error);
|
||||||
}
|
}
|
||||||
|
|
||||||
await migrate();
|
try {
|
||||||
await postStart();
|
await migrate();
|
||||||
|
await postStart();
|
||||||
|
} catch (error) {
|
||||||
|
if (!error.message.includes('SQLITE_CANTOPEN')) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error(error);
|
||||||
|
return { connectionSuccess: false, reason: DB_CONN_FAILURE.CANT_OPEN };
|
||||||
|
}
|
||||||
|
|
||||||
// set file info in config
|
// set file info in config
|
||||||
const { companyName } = frappe.AccountingSettings;
|
const { companyName } = frappe.AccountingSettings;
|
||||||
@ -95,7 +104,7 @@ export async function connectToLocalDatabase(filePath) {
|
|||||||
|
|
||||||
// set last selected file
|
// set last selected file
|
||||||
config.set('lastSelectedFilePath', filePath);
|
config.set('lastSelectedFilePath', filePath);
|
||||||
return true;
|
return { connectionSuccess: true, reason: '' };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function purgeCache(purgeAll = false) {
|
export function purgeCache(purgeAll = false) {
|
||||||
|
@ -15,5 +15,12 @@ export const IPC_ACTIONS = {
|
|||||||
GET_SAVE_FILEPATH: 'save-dialog',
|
GET_SAVE_FILEPATH: 'save-dialog',
|
||||||
GET_DIALOG_RESPONSE: 'show-message-box',
|
GET_DIALOG_RESPONSE: 'show-message-box',
|
||||||
GET_PRIMARY_DISPLAY_SIZE: 'get-primary-display-size',
|
GET_PRIMARY_DISPLAY_SIZE: 'get-primary-display-size',
|
||||||
SAVE_HTML_AS_PDF: 'save-html-as-pdf'
|
SAVE_HTML_AS_PDF: 'save-html-as-pdf',
|
||||||
|
SHOW_ERROR: 'show-error',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DB_CONN_FAILURE = {
|
||||||
|
INVALID_FILE: 'invalid-file',
|
||||||
|
CANT_OPEN: 'cant-open',
|
||||||
|
CANT_CONNECT: 'cant-connect',
|
||||||
};
|
};
|
||||||
|
@ -156,9 +156,10 @@ import fs from 'fs';
|
|||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { IPC_ACTIONS } from '../messages';
|
import { DB_CONN_FAILURE, IPC_ACTIONS } from '../messages';
|
||||||
|
|
||||||
import { createNewDatabase, connectToLocalDatabase } from '@/initialization';
|
import { createNewDatabase, connectToLocalDatabase } from '@/initialization';
|
||||||
|
import { showErrorDialog } from '../utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DatabaseSelector',
|
name: 'DatabaseSelector',
|
||||||
@ -211,15 +212,25 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.loadingDatabase = true;
|
this.loadingDatabase = true;
|
||||||
const connectionSuccess = await connectToLocalDatabase(filePath);
|
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||||
|
filePath
|
||||||
|
);
|
||||||
this.loadingDatabase = false;
|
this.loadingDatabase = false;
|
||||||
|
|
||||||
|
const title = 'DB Connection Error';
|
||||||
|
|
||||||
if (connectionSuccess) {
|
if (connectionSuccess) {
|
||||||
this.$emit('database-connect');
|
this.$emit('database-connect');
|
||||||
|
} else if (reason === DB_CONN_FAILURE.CANT_OPEN) {
|
||||||
|
await showErrorDialog({
|
||||||
|
title,
|
||||||
|
content: `Can't open database file: ${filePath}, please create a new file.`,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
alert(
|
await showErrorDialog({
|
||||||
frappe._('Please select an existing database or create a new one.')
|
title,
|
||||||
);
|
content: `Please select an existing database or create a new one. reason: ${reason}, filePath: ${filePath}`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getFileLastModified(filePath) {
|
getFileLastModified(filePath) {
|
||||||
|
@ -78,6 +78,7 @@ import {
|
|||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
handleErrorWithDialog,
|
handleErrorWithDialog,
|
||||||
showMessageDialog,
|
showMessageDialog,
|
||||||
|
showErrorDialog,
|
||||||
} from '@/utils';
|
} from '@/utils';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -151,10 +152,18 @@ export default {
|
|||||||
|
|
||||||
purgeCache();
|
purgeCache();
|
||||||
|
|
||||||
const connectionSuccess = await connectToLocalDatabase(filePath);
|
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||||
|
filePath
|
||||||
|
);
|
||||||
|
|
||||||
if (connectionSuccess) {
|
if (connectionSuccess) {
|
||||||
await setupCompany(this.doc);
|
await setupCompany(this.doc);
|
||||||
this.$emit('setup-complete');
|
this.$emit('setup-complete');
|
||||||
|
} else {
|
||||||
|
await showErrorDialog({
|
||||||
|
title: 'DB Connection Error',
|
||||||
|
content: `reason: ${reason}, filePath: ${filePath}`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
10
src/utils.js
10
src/utils.js
@ -27,6 +27,16 @@ export async function showMessageDialog({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function showErrorDialog({ title, content }) {
|
||||||
|
// To be used for show stopper errors
|
||||||
|
title = title ?? 'Error';
|
||||||
|
content =
|
||||||
|
content ??
|
||||||
|
'Something has gone terribly wrong. Please check the console and raise an issue.';
|
||||||
|
|
||||||
|
await ipcRenderer.invoke(IPC_ACTIONS.SHOW_ERROR, { title, content });
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteDocWithPrompt(doc) {
|
export function deleteDocWithPrompt(doc) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
showMessageDialog({
|
showMessageDialog({
|
||||||
|
Loading…
Reference in New Issue
Block a user