2
0
mirror of https://github.com/frappe/books.git synced 2025-01-24 15:48:25 +00:00
books/src/App.vue
2023-07-11 13:43:32 +05:30

257 lines
7.4 KiB
Vue

<template>
<div
id="app"
class="h-screen flex flex-col font-sans overflow-hidden antialiased"
:dir="languageDirection"
:language="language"
>
<WindowsTitleBar
v-if="platform === 'Windows'"
:db-path="dbPath"
:company-name="companyName"
/>
<!-- Main Contents -->
<Desk
v-if="activeScreen === 'Desk'"
class="flex-1"
@change-db-file="showDbSelector"
/>
<DatabaseSelector
v-if="activeScreen === 'DatabaseSelector'"
ref="databaseSelector"
@new-database="newDatabase"
@file-selected="fileSelected"
/>
<SetupWizard
v-if="activeScreen === 'SetupWizard'"
@setup-complete="setupComplete"
@setup-canceled="showDbSelector"
/>
<!-- Render target for toasts -->
<div
id="toast-container"
class="absolute bottom-0 flex flex-col items-end mb-3 pe-6"
style="width: 100%; pointer-events: none"
></div>
</div>
</template>
<script lang="ts">
import { RTL_LANGUAGES } from 'fyo/utils/consts';
import { ModelNameEnum } from 'models/types';
import { systemLanguageRef } from 'src/utils/refs';
import { defineComponent, provide, ref, Ref } from 'vue';
import WindowsTitleBar from './components/WindowsTitleBar.vue';
import { handleErrorWithDialog } from './errorHandling';
import { fyo } from './initFyo';
import DatabaseSelector from './pages/DatabaseSelector.vue';
import Desk from './pages/Desk.vue';
import SetupWizard from './pages/SetupWizard/SetupWizard.vue';
import setupInstance from './setup/setupInstance';
import { SetupWizardOptions } from './setup/types';
import './styles/index.css';
import { connectToDatabase, dbErrorActionSymbols } from './utils/db';
import { initializeInstance } from './utils/initialization';
import * as injectionKeys from './utils/injectionKeys';
import { showDialog } from './utils/interactive';
import { setLanguageMap } from './utils/language';
import { updateConfigFiles } from './utils/misc';
import { updatePrintTemplates } from './utils/printTemplates';
import { Search } from './utils/search';
import { Shortcuts } from './utils/shortcuts';
import { routeTo } from './utils/ui';
import { useKeys } from './utils/vueUtils';
enum Screen {
Desk = 'Desk',
DatabaseSelector = 'DatabaseSelector',
SetupWizard = 'SetupWizard',
}
export default defineComponent({
name: 'App',
components: {
Desk,
SetupWizard,
DatabaseSelector,
WindowsTitleBar,
},
setup() {
const keys = useKeys();
const searcher: Ref<null | Search> = ref(null);
const shortcuts = new Shortcuts(keys);
const languageDirection = ref(
getLanguageDirection(systemLanguageRef.value)
);
provide(injectionKeys.keysKey, keys);
provide(injectionKeys.searcherKey, searcher);
provide(injectionKeys.shortcutsKey, shortcuts);
provide(injectionKeys.languageDirectionKey, languageDirection);
const databaseSelector = ref<InstanceType<typeof DatabaseSelector> | null>(
null
);
return {
keys,
searcher,
shortcuts,
languageDirection,
databaseSelector,
};
},
data() {
return {
activeScreen: null,
dbPath: '',
companyName: '',
} as {
activeScreen: null | Screen;
dbPath: string;
companyName: string;
};
},
computed: {
language(): string {
return systemLanguageRef.value;
},
},
watch: {
language(value: string) {
this.languageDirection = getLanguageDirection(value);
},
},
async mounted() {
await this.setInitialScreen();
},
methods: {
async setInitialScreen(): Promise<void> {
const lastSelectedFilePath = fyo.config.get('lastSelectedFilePath', null);
if (
typeof lastSelectedFilePath !== 'string' ||
!lastSelectedFilePath.length
) {
this.activeScreen = Screen.DatabaseSelector;
return;
}
await this.fileSelected(lastSelectedFilePath);
},
async setSearcher(): Promise<void> {
this.searcher = new Search(fyo);
await this.searcher.initializeKeywords();
},
async setDesk(filePath: string): Promise<void> {
this.activeScreen = Screen.Desk;
await this.setDeskRoute();
await fyo.telemetry.start(true);
await ipc.checkForUpdates();
await setLanguageMap();
this.dbPath = filePath;
this.companyName = (await fyo.getValue(
ModelNameEnum.AccountingSettings,
'companyName'
)) as string;
await this.setSearcher();
updateConfigFiles(fyo);
},
newDatabase() {
this.activeScreen = Screen.SetupWizard;
},
async fileSelected(filePath: string): Promise<void> {
fyo.config.set('lastSelectedFilePath', filePath);
if (filePath !== ':memory:' && !(await ipc.checkDbAccess(filePath))) {
await showDialog({
title: this.t`Cannot open file`,
type: 'error',
detail: this
.t`Frappe Books does not have access to the selected file: ${filePath}`,
});
fyo.config.set('lastSelectedFilePath', null);
return;
}
try {
await this.showSetupWizardOrDesk(filePath);
} catch (error) {
await handleErrorWithDialog(error, undefined, true, true);
await this.showDbSelector();
}
},
async setupComplete(setupWizardOptions: SetupWizardOptions): Promise<void> {
const companyName = setupWizardOptions.companyName;
const filePath = await ipc.getDbDefaultPath(companyName);
await setupInstance(filePath, setupWizardOptions, fyo);
fyo.config.set('lastSelectedFilePath', filePath);
await this.setDesk(filePath);
},
async showSetupWizardOrDesk(filePath: string): Promise<void> {
const { countryCode, error, actionSymbol } = await connectToDatabase(
this.fyo,
filePath
);
if (!countryCode && error && actionSymbol) {
return await this.handleConnectionFailed(error, actionSymbol);
}
const setupComplete = await fyo.getValue(
ModelNameEnum.AccountingSettings,
'setupComplete'
);
if (!setupComplete) {
this.activeScreen = Screen.SetupWizard;
return;
}
await initializeInstance(filePath, false, countryCode, fyo);
await updatePrintTemplates(fyo);
await this.setDesk(filePath);
},
async handleConnectionFailed(error: Error, actionSymbol: symbol) {
await this.showDbSelector();
if (actionSymbol === dbErrorActionSymbols.CancelSelection) {
return;
}
if (actionSymbol === dbErrorActionSymbols.SelectFile) {
await this.databaseSelector?.existingDatabase();
return;
}
throw error;
},
async setDeskRoute(): Promise<void> {
const { onboardingComplete } = await fyo.doc.getDoc('GetStarted');
const { hideGetStarted } = await fyo.doc.getDoc('SystemSettings');
let route = '/get-started';
if (hideGetStarted || onboardingComplete) {
route = '/';
}
await routeTo(localStorage.getItem('lastRoute') || route);
},
async showDbSelector(): Promise<void> {
localStorage.clear();
fyo.config.set('lastSelectedFilePath', null);
fyo.telemetry.stop();
await fyo.purgeCache();
this.activeScreen = Screen.DatabaseSelector;
this.dbPath = '';
this.searcher = null;
this.companyName = '';
},
},
});
function getLanguageDirection(language: string): 'rtl' | 'ltr' {
return RTL_LANGUAGES.includes(language) ? 'rtl' : 'ltr';
}
</script>