mirror of
https://github.com/frappe/books.git
synced 2024-12-23 19:39:07 +00:00
feat: add selectors for language
- remove instance config - use app level config instead
This commit is contained in:
parent
ce3d997ed2
commit
c83ac376dd
@ -4,9 +4,7 @@ const {
|
|||||||
DEFAULT_DISPLAY_PRECISION,
|
DEFAULT_DISPLAY_PRECISION,
|
||||||
DEFAULT_INTERNAL_PRECISION,
|
DEFAULT_INTERNAL_PRECISION,
|
||||||
DEFAULT_LOCALE,
|
DEFAULT_LOCALE,
|
||||||
DEFAULT_LANGUAGE,
|
|
||||||
} = require('../../../utils/consts');
|
} = require('../../../utils/consts');
|
||||||
const { languageCodeMap } = require('@/languageCodeMap');
|
|
||||||
|
|
||||||
let dateFormatOptions = (() => {
|
let dateFormatOptions = (() => {
|
||||||
let formats = [
|
let formats = [
|
||||||
@ -53,14 +51,6 @@ module.exports = {
|
|||||||
default: DEFAULT_LOCALE,
|
default: DEFAULT_LOCALE,
|
||||||
description: t`Set the local code, this is used for number formatting.`,
|
description: t`Set the local code, this is used for number formatting.`,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
fieldname: 'language',
|
|
||||||
label: t`Language`,
|
|
||||||
fieldtype: 'Select',
|
|
||||||
options: Object.keys(languageCodeMap),
|
|
||||||
default: DEFAULT_LANGUAGE,
|
|
||||||
description: t`Set the display language.`,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
fieldname: 'displayPrecision',
|
fieldname: 'displayPrecision',
|
||||||
label: t`Display Precision`,
|
label: t`Display Precision`,
|
||||||
@ -104,7 +94,6 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
quickEditFields: [
|
quickEditFields: [
|
||||||
'locale',
|
'locale',
|
||||||
'language',
|
|
||||||
'dateFormat',
|
'dateFormat',
|
||||||
'displayPrecision',
|
'displayPrecision',
|
||||||
'hideGetStarted',
|
'hideGetStarted',
|
||||||
|
45
src/components/Controls/LanguageSelector.vue
Normal file
45
src/components/Controls/LanguageSelector.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<FormControl
|
||||||
|
:df="languageDf"
|
||||||
|
:value="value"
|
||||||
|
@change="setLanguageMap"
|
||||||
|
:input-class="'focus:outline-none rounded '+inputClass"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import config from '@/config';
|
||||||
|
import { languageCodeMap } from '@/languageCodeMap';
|
||||||
|
import { setLanguageMap } from '@/utils';
|
||||||
|
import { DEFAULT_LANGUAGE } from 'frappe/utils/consts';
|
||||||
|
import FormControl from './FormControl';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
methods: {
|
||||||
|
setLanguageMap,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
inputClass: {
|
||||||
|
type: String,
|
||||||
|
default:
|
||||||
|
'bg-gray-100 active:bg-gray-200 focus:bg-gray-200 px-3 py-2 text-base',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: { FormControl },
|
||||||
|
computed: {
|
||||||
|
value() {
|
||||||
|
return config.get('language') ?? DEFAULT_LANGUAGE;
|
||||||
|
},
|
||||||
|
languageDf() {
|
||||||
|
languageCodeMap;
|
||||||
|
return {
|
||||||
|
fieldname: 'language',
|
||||||
|
label: this.t`Language`,
|
||||||
|
fieldtype: 'Select',
|
||||||
|
options: Object.keys(languageCodeMap),
|
||||||
|
default: config.get('language') ?? DEFAULT_LANGUAGE,
|
||||||
|
description: this.t`Set the display language.`,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -14,7 +14,7 @@
|
|||||||
:class="inputClasses"
|
:class="inputClasses"
|
||||||
>
|
>
|
||||||
<select
|
<select
|
||||||
class="appearance-none bg-transparent focus:outline-none w-11/12"
|
class="appearance-none bg-transparent focus:outline-none w-11/12 cursor-pointer"
|
||||||
:class="{
|
:class="{
|
||||||
'pointer-events-none': isReadOnly,
|
'pointer-events-none': isReadOnly,
|
||||||
'text-gray-400': !value,
|
'text-gray-400': !value,
|
||||||
|
@ -72,7 +72,6 @@ export async function connectToLocalDatabase(filePath) {
|
|||||||
|
|
||||||
// set file info in config
|
// set file info in config
|
||||||
const { companyName } = frappe.AccountingSettings;
|
const { companyName } = frappe.AccountingSettings;
|
||||||
await setLanguageMap();
|
|
||||||
let files = config.get('files') || [];
|
let files = config.get('files') || [];
|
||||||
if (
|
if (
|
||||||
!files.find(
|
!files.find(
|
||||||
|
14
src/main.js
14
src/main.js
@ -4,25 +4,27 @@ import { createApp } from 'vue';
|
|||||||
import models from '../models';
|
import models from '../models';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
import FeatherIcon from './components/FeatherIcon';
|
import FeatherIcon from './components/FeatherIcon';
|
||||||
|
import config from './config';
|
||||||
import { getErrorHandled, handleError } from './errorHandling';
|
import { getErrorHandled, handleError } from './errorHandling';
|
||||||
import { IPC_CHANNELS, IPC_MESSAGES } from './messages';
|
import { IPC_CHANNELS, IPC_MESSAGES } from './messages';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
import { outsideClickDirective } from './ui';
|
import { outsideClickDirective } from './ui';
|
||||||
import { showToast, stringifyCircular } from './utils';
|
import { setLanguageMap, showToast, stringifyCircular } from './utils';
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
const language = config.get('language');
|
||||||
|
if (language) {
|
||||||
|
setLanguageMap(language);
|
||||||
|
}
|
||||||
|
|
||||||
frappe.isServer = true;
|
frappe.isServer = true;
|
||||||
frappe.isElectron = true;
|
frappe.isElectron = true;
|
||||||
frappe.initializeAndRegister(models);
|
frappe.initializeAndRegister(models, language);
|
||||||
frappe.fetch = window.fetch.bind();
|
frappe.fetch = window.fetch.bind();
|
||||||
|
|
||||||
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
ipcRenderer.send = getErrorHandled(ipcRenderer.send);
|
||||||
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
ipcRenderer.invoke = getErrorHandled(ipcRenderer.invoke);
|
||||||
|
|
||||||
frappe.events.on('reload-main-window', () => {
|
|
||||||
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
|
|
||||||
});
|
|
||||||
|
|
||||||
window.frappe = frappe;
|
window.frappe = frappe;
|
||||||
window.frappe.store = {};
|
window.frappe.store = {};
|
||||||
|
|
||||||
|
@ -149,6 +149,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="w-full flex justify-end absolute px-8"
|
||||||
|
style="top: 100%; transform: translateY(-175%)"
|
||||||
|
>
|
||||||
|
<LanguageSelector class="w-28" input-class="text-base" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -160,6 +166,7 @@ import { DB_CONN_FAILURE, IPC_ACTIONS } from '../messages';
|
|||||||
|
|
||||||
import { createNewDatabase, connectToLocalDatabase } from '@/initialization';
|
import { createNewDatabase, connectToLocalDatabase } from '@/initialization';
|
||||||
import { showErrorDialog } from '../errorHandling';
|
import { showErrorDialog } from '../errorHandling';
|
||||||
|
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DatabaseSelector',
|
name: 'DatabaseSelector',
|
||||||
@ -211,18 +218,15 @@ export default {
|
|||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadingDatabase = true;
|
this.loadingDatabase = true;
|
||||||
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
const { connectionSuccess, reason } = await connectToLocalDatabase(
|
||||||
filePath
|
filePath
|
||||||
);
|
);
|
||||||
this.loadingDatabase = false;
|
this.loadingDatabase = false;
|
||||||
|
|
||||||
if (connectionSuccess) {
|
if (connectionSuccess) {
|
||||||
this.$emit('database-connect');
|
this.$emit('database-connect');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = this.t`DB Connection Error`;
|
const title = this.t`DB Connection Error`;
|
||||||
let content =
|
let content =
|
||||||
this.t`Please select an existing database or create a new one.` +
|
this.t`Please select an existing database or create a new one.` +
|
||||||
@ -231,7 +235,6 @@ export default {
|
|||||||
content = this
|
content = this
|
||||||
.t`Can't open database file: ${filePath}, please create a new file.`;
|
.t`Can't open database file: ${filePath}, please create a new file.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
await showErrorDialog(title, content);
|
await showErrorDialog(title, content);
|
||||||
},
|
},
|
||||||
getFileLastModified(filePath) {
|
getFileLastModified(filePath) {
|
||||||
@ -239,5 +242,6 @@ export default {
|
|||||||
return DateTime.fromJSDate(stats.mtime).toRelative();
|
return DateTime.fromJSDate(stats.mtime).toRelative();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
components: { LanguageSelector },
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -61,8 +61,10 @@ import Icon from '@/components/Icon';
|
|||||||
import PageHeader from '@/components/PageHeader';
|
import PageHeader from '@/components/PageHeader';
|
||||||
import StatusBadge from '@/components/StatusBadge';
|
import StatusBadge from '@/components/StatusBadge';
|
||||||
import { callInitializeMoneyMaker } from '../../utils';
|
import { callInitializeMoneyMaker } from '../../utils';
|
||||||
import { showToast, setLanguageMap } from '../../utils';
|
import { showToast } from '../../utils';
|
||||||
import { h, markRaw } from 'vue';
|
import { h, markRaw } from 'vue';
|
||||||
|
import { ipcRenderer } from 'electron';
|
||||||
|
import { IPC_MESSAGES } from '@/messages';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Settings',
|
name: 'Settings',
|
||||||
@ -111,8 +113,7 @@ export default {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
fieldnames.includes('displayPrecision') ||
|
fieldnames.includes('displayPrecision') ||
|
||||||
fieldnames.includes('hideGetStarted') ||
|
fieldnames.includes('hideGetStarted')
|
||||||
fieldnames.includes('language')
|
|
||||||
) {
|
) {
|
||||||
this.showReloadToast();
|
this.showReloadToast();
|
||||||
}
|
}
|
||||||
@ -120,10 +121,6 @@ export default {
|
|||||||
if (fieldnames.includes('displayPrecision')) {
|
if (fieldnames.includes('displayPrecision')) {
|
||||||
callInitializeMoneyMaker(undefined, true);
|
callInitializeMoneyMaker(undefined, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldnames.includes('language')) {
|
|
||||||
setLanguageMap();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showReloadToast() {
|
showReloadToast() {
|
||||||
@ -132,7 +129,7 @@ export default {
|
|||||||
actionText: frappe.t`Reload App`,
|
actionText: frappe.t`Reload App`,
|
||||||
type: 'info',
|
type: 'info',
|
||||||
action: async () => {
|
action: async () => {
|
||||||
frappe.events.trigger('reload-main-window');
|
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW)
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -8,9 +8,10 @@
|
|||||||
:emit-change="true"
|
:emit-change="true"
|
||||||
@change="forwardChangeEvent"
|
@change="forwardChangeEvent"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-row justify-end my-4">
|
<div class="flex flex-row justify-between my-4">
|
||||||
|
<LanguageSelector class="text-sm" input-class="px-4 py-1.5"/>
|
||||||
<button
|
<button
|
||||||
class="text-gray-900 text-sm hover:bg-gray-100 rounded-md px-4 py-1.5"
|
class="text-gray-900 text-sm hover:bg-gray-200 rounded-md px-4 py-1.5"
|
||||||
@click="checkForUpdates(true)"
|
@click="checkForUpdates(true)"
|
||||||
>
|
>
|
||||||
Check for Updates
|
Check for Updates
|
||||||
@ -23,11 +24,13 @@
|
|||||||
import frappe from 'frappe';
|
import frappe from 'frappe';
|
||||||
import TwoColumnForm from '@/components/TwoColumnForm';
|
import TwoColumnForm from '@/components/TwoColumnForm';
|
||||||
import { checkForUpdates } from '@/utils';
|
import { checkForUpdates } from '@/utils';
|
||||||
|
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TabSystem',
|
name: 'TabSystem',
|
||||||
components: {
|
components: {
|
||||||
TwoColumnForm,
|
TwoColumnForm,
|
||||||
|
LanguageSelector,
|
||||||
},
|
},
|
||||||
emits: ['change'],
|
emits: ['change'],
|
||||||
data() {
|
data() {
|
||||||
|
@ -1,94 +1,112 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div>
|
||||||
class="flex-1 py-10 bg-white"
|
<Slide
|
||||||
:class="{
|
@primary-clicked="handlePrimary"
|
||||||
'window-drag': platform !== 'Windows',
|
@secondary-clicked="handleSecondary"
|
||||||
}"
|
v-show="index === 0"
|
||||||
>
|
>
|
||||||
<div class="px-12">
|
<template #title>
|
||||||
<h1 class="text-2xl font-semibold">{{ t`Setup your organization` }}</h1>
|
{{ t`Select your language` }}
|
||||||
</div>
|
</template>
|
||||||
<div class="px-8 mt-5 window-no-drag" v-if="doc">
|
<template #content>
|
||||||
<div class="flex items-center px-6 py-5 mb-4 border bg-brand rounded-xl">
|
<div class="flex flex-col justify-center items-center h-96">
|
||||||
<FormControl
|
<LanguageSelector class="w-40" />
|
||||||
:df="meta.getField('companyLogo')"
|
</div>
|
||||||
:value="doc.companyLogo"
|
</template>
|
||||||
@change="(value) => setValue('companyLogo', value)"
|
<template #secondaryButton>
|
||||||
/>
|
{{ t`Cancel` }}
|
||||||
<div class="ml-2">
|
</template>
|
||||||
<FormControl
|
<template #primaryButton>
|
||||||
ref="companyField"
|
{{ t`Next` }}
|
||||||
:df="meta.getField('companyName')"
|
</template>
|
||||||
:value="doc.companyName"
|
</Slide>
|
||||||
@change="(value) => setValue('companyName', value)"
|
<Slide
|
||||||
:input-class="
|
:primary-disabled="!valuesFilled || loading"
|
||||||
(classes) => [
|
@primary-clicked="handlePrimary"
|
||||||
'bg-transparent font-semibold text-xl text-white placeholder-blue-200 focus:outline-none focus:bg-blue-600 px-3 rounded py-1',
|
@secondary-clicked="handleSecondary"
|
||||||
]
|
v-show="index === 1"
|
||||||
"
|
>
|
||||||
:autofocus="true"
|
<template #title>
|
||||||
/>
|
{{ t`Setup your organization` }}
|
||||||
<Popover placement="auto" :show-popup="Boolean(emailError)">
|
</template>
|
||||||
<template #target>
|
<template #content>
|
||||||
|
<div v-if="doc">
|
||||||
|
<div
|
||||||
|
class="flex items-center px-6 py-5 mb-4 border bg-brand rounded-xl"
|
||||||
|
>
|
||||||
|
<FormControl
|
||||||
|
:df="meta.getField('companyLogo')"
|
||||||
|
:value="doc.companyLogo"
|
||||||
|
@change="(value) => setValue('companyLogo', value)"
|
||||||
|
/>
|
||||||
|
<div class="ml-2">
|
||||||
<FormControl
|
<FormControl
|
||||||
:df="meta.getField('email')"
|
ref="companyField"
|
||||||
:value="doc.email"
|
:df="meta.getField('companyName')"
|
||||||
@change="(value) => setValue('email', value)"
|
:value="doc.companyName"
|
||||||
|
@change="(value) => setValue('companyName', value)"
|
||||||
:input-class="
|
:input-class="
|
||||||
(classes) => [
|
(classes) => [
|
||||||
'text-base bg-transparent text-white placeholder-blue-200 focus:bg-blue-600 focus:outline-none rounded px-3 py-1',
|
'bg-transparent font-semibold text-xl text-white placeholder-blue-200 focus:outline-none focus:bg-blue-600 px-3 rounded py-1',
|
||||||
]
|
]
|
||||||
"
|
"
|
||||||
|
:autofocus="true"
|
||||||
/>
|
/>
|
||||||
</template>
|
<Popover placement="auto" :show-popup="Boolean(emailError)">
|
||||||
<template #content>
|
<template #target>
|
||||||
<div class="p-2 text-sm">
|
<FormControl
|
||||||
{{ emailError }}
|
:df="meta.getField('email')"
|
||||||
</div>
|
:value="doc.email"
|
||||||
</template>
|
@change="(value) => setValue('email', value)"
|
||||||
</Popover>
|
:input-class="
|
||||||
|
(classes) => [
|
||||||
|
'text-base bg-transparent text-white placeholder-blue-200 focus:bg-blue-600 focus:outline-none rounded px-3 py-1',
|
||||||
|
]
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
|
<div class="p-2 text-sm">
|
||||||
|
{{ emailError }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<TwoColumnForm :fields="fields" :doc="doc" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<TwoColumnForm :fields="fields" :doc="doc" />
|
<template #secondaryButton>{{ t`Back` }}</template>
|
||||||
</div>
|
<template #primaryButton>{{ t`Submit` }}</template>
|
||||||
<div class="flex justify-between px-8 mt-5 window-no-drag">
|
</Slide>
|
||||||
<Button class="text-sm text-grey-900" @click="$emit('setup-canceled')"
|
|
||||||
>Cancel</Button
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
@click="submit"
|
|
||||||
type="primary"
|
|
||||||
class="text-sm text-white"
|
|
||||||
:disabled="!valuesFilled || loading"
|
|
||||||
>
|
|
||||||
{{ buttonText }}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import frappe from 'frappe';
|
import frappe from 'frappe';
|
||||||
import TwoColumnForm from '@/components/TwoColumnForm';
|
import TwoColumnForm from '@/components/TwoColumnForm';
|
||||||
import FormControl from '@/components/Controls/FormControl';
|
import FormControl from '@/components/Controls/FormControl';
|
||||||
import Button from '@/components/Button';
|
|
||||||
import setupCompany from './setupCompany';
|
import setupCompany from './setupCompany';
|
||||||
import Popover from '@/components/Popover';
|
import Popover from '@/components/Popover';
|
||||||
import config from '@/config';
|
import config from '@/config';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { purgeCache, connectToLocalDatabase } from '@/initialization';
|
import { purgeCache, connectToLocalDatabase } from '@/initialization';
|
||||||
import { showMessageDialog } from '@/utils';
|
import { setLanguageMap, showMessageDialog } from '@/utils';
|
||||||
import {
|
import {
|
||||||
handleErrorWithDialog,
|
handleErrorWithDialog,
|
||||||
getErrorMessage,
|
getErrorMessage,
|
||||||
showErrorDialog,
|
showErrorDialog,
|
||||||
} from '../../errorHandling';
|
} from '../../errorHandling';
|
||||||
|
import Slide from './Slide.vue';
|
||||||
|
import LanguageSelector from '@/components/Controls/LanguageSelector.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SetupWizard',
|
name: 'SetupWizard',
|
||||||
emits: ['setup-complete', 'setup-canceled'],
|
emits: ['setup-complete', 'setup-canceled'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
index: 0,
|
||||||
doc: null,
|
doc: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
valuesFilled: false,
|
valuesFilled: false,
|
||||||
@ -104,16 +122,39 @@ export default {
|
|||||||
components: {
|
components: {
|
||||||
TwoColumnForm,
|
TwoColumnForm,
|
||||||
FormControl,
|
FormControl,
|
||||||
Button,
|
|
||||||
Popover,
|
Popover,
|
||||||
|
Slide,
|
||||||
|
LanguageSelector,
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
if (config.get('language') !== undefined) {
|
||||||
|
this.index = 1;
|
||||||
|
}
|
||||||
|
|
||||||
this.doc = await frappe.newDoc({ doctype: 'SetupWizard' });
|
this.doc = await frappe.newDoc({ doctype: 'SetupWizard' });
|
||||||
this.doc.on('change', () => {
|
this.doc.on('change', () => {
|
||||||
this.valuesFilled = this.allValuesFilled();
|
this.valuesFilled = this.allValuesFilled();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
handlePrimary() {
|
||||||
|
if (this.index === 0) {
|
||||||
|
this.index = 1;
|
||||||
|
} else if (this.index === 1) {
|
||||||
|
this.submit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSecondary() {
|
||||||
|
if (this.index === 1) {
|
||||||
|
this.index = 0;
|
||||||
|
} else if (this.index === 0) {
|
||||||
|
this.$emit('setup-canceled');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async selectLanguage(value) {
|
||||||
|
const success = await setLanguageMap(value);
|
||||||
|
this.setValue('language', value);
|
||||||
|
},
|
||||||
setValue(fieldname, value) {
|
setValue(fieldname, value) {
|
||||||
this.emailError = null;
|
this.emailError = null;
|
||||||
this.doc.set(fieldname, value).catch((e) => {
|
this.doc.set(fieldname, value).catch((e) => {
|
||||||
|
45
src/pages/SetupWizard/Slide.vue
Normal file
45
src/pages/SetupWizard/Slide.vue
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex-1 py-10 bg-white h-screen"
|
||||||
|
:class="{
|
||||||
|
'window-drag': platform !== 'Windows',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div class="px-12">
|
||||||
|
<h1 class="text-2xl font-semibold"><slot name="title"></slot></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-8 mt-5 window-no-drag">
|
||||||
|
<slot name="content"></slot>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="flex justify-between px-8 mt-5 window-no-drag absolute w-full"
|
||||||
|
style="top: 100%; transform: translateY(-260%)"
|
||||||
|
>
|
||||||
|
<Button class="text-sm text-grey-900" @click="$emit('secondary-clicked')">
|
||||||
|
<slot name="secondaryButton"></slot>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
@click="$emit('primary-clicked')"
|
||||||
|
type="primary"
|
||||||
|
class="text-sm text-white"
|
||||||
|
:disabled="primaryDisabled"
|
||||||
|
>
|
||||||
|
<slot name="primaryButton"></slot>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Button from '@/components/Button.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
emits: ['primary-clicked', 'secondary-clicked'],
|
||||||
|
components: { Button },
|
||||||
|
props: {
|
||||||
|
usePrimary: { type: Boolean, default: true },
|
||||||
|
primaryDisabled: { type: Boolean, default: false },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
@ -4,9 +4,9 @@ import { DEFAULT_LOCALE } from 'frappe/utils/consts';
|
|||||||
import countryList from '~/fixtures/countryInfo.json';
|
import countryList from '~/fixtures/countryInfo.json';
|
||||||
import generateTaxes from '../../../models/doctype/Tax/RegionalEntries';
|
import generateTaxes from '../../../models/doctype/Tax/RegionalEntries';
|
||||||
import regionalModelUpdates from '../../../models/regionalModelUpdates';
|
import regionalModelUpdates from '../../../models/regionalModelUpdates';
|
||||||
import { callInitializeMoneyMaker, setLanguageMap } from '../../utils';
|
import { callInitializeMoneyMaker } from '../../utils';
|
||||||
|
|
||||||
export default async function setupCompany(setupWizardValues, language) {
|
export default async function setupCompany(setupWizardValues) {
|
||||||
const {
|
const {
|
||||||
companyLogo,
|
companyLogo,
|
||||||
companyName,
|
companyName,
|
||||||
@ -18,7 +18,6 @@ export default async function setupCompany(setupWizardValues, language) {
|
|||||||
fiscalYearEnd,
|
fiscalYearEnd,
|
||||||
} = setupWizardValues;
|
} = setupWizardValues;
|
||||||
|
|
||||||
await setLanguageMap(language);
|
|
||||||
const accountingSettings = frappe.AccountingSettings;
|
const accountingSettings = frappe.AccountingSettings;
|
||||||
const currency = countryList[country]['currency'];
|
const currency = countryList[country]['currency'];
|
||||||
const locale = countryList[country]['locale'] ?? DEFAULT_LOCALE;
|
const locale = countryList[country]['locale'] ?? DEFAULT_LOCALE;
|
||||||
@ -51,7 +50,7 @@ export default async function setupCompany(setupWizardValues, language) {
|
|||||||
await accountingSettings.update({ setupComplete: 1 });
|
await accountingSettings.update({ setupComplete: 1 });
|
||||||
frappe.AccountingSettings = accountingSettings;
|
frappe.AccountingSettings = accountingSettings;
|
||||||
|
|
||||||
(await frappe.getSingle('SystemSettings')).update({ locale, language });
|
(await frappe.getSingle('SystemSettings')).update({ locale });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setupGlobalCurrencies(countries) {
|
async function setupGlobalCurrencies(countries) {
|
||||||
|
52
src/utils.js
52
src/utils.js
@ -4,9 +4,11 @@ import router from '@/router';
|
|||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import frappe, { t } from 'frappe';
|
import frappe, { t } from 'frappe';
|
||||||
import { isPesa } from 'frappe/utils';
|
import { isPesa } from 'frappe/utils';
|
||||||
|
import { DEFAULT_LANGUAGE } from 'frappe/utils/consts';
|
||||||
import { setLanguageMapOnTranslationString } from 'frappe/utils/translation';
|
import { setLanguageMapOnTranslationString } from 'frappe/utils/translation';
|
||||||
import lodash from 'lodash';
|
import lodash from 'lodash';
|
||||||
import { createApp, h } from 'vue';
|
import { createApp, h } from 'vue';
|
||||||
|
import config from './config';
|
||||||
import { handleErrorWithDialog } from './errorHandling';
|
import { handleErrorWithDialog } from './errorHandling';
|
||||||
import { languageCodeMap } from './languageCodeMap';
|
import { languageCodeMap } from './languageCodeMap';
|
||||||
import { IPC_ACTIONS, IPC_MESSAGES } from './messages';
|
import { IPC_ACTIONS, IPC_MESSAGES } from './messages';
|
||||||
@ -462,14 +464,7 @@ export async function checkForUpdates(force = false) {
|
|||||||
await setLanguageMap();
|
await setLanguageMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setLanguageMap(language) {
|
async function fetchAndSetLanguageMap(code) {
|
||||||
const code = getLanguageCode(language);
|
|
||||||
|
|
||||||
if (code === 'en') {
|
|
||||||
setLanguageMapOnTranslationString(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { success, message, languageMap } = await ipcRenderer.invoke(
|
const { success, message, languageMap } = await ipcRenderer.invoke(
|
||||||
IPC_ACTIONS.GET_LANGUAGE_MAP,
|
IPC_ACTIONS.GET_LANGUAGE_MAP,
|
||||||
code
|
code
|
||||||
@ -477,13 +472,44 @@ export async function setLanguageMap(language) {
|
|||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
showToast({ type: 'error', message });
|
showToast({ type: 'error', message });
|
||||||
return;
|
} else {
|
||||||
|
setLanguageMapOnTranslationString(languageMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLanguageMapOnTranslationString(languageMap);
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLanguageCode(initLanguage) {
|
export async function setLanguageMap(initLanguage) {
|
||||||
const { language } = initLanguage ?? frappe.SystemSettings;
|
const oldLanguage = config.get('language');
|
||||||
return languageCodeMap[language || 'English'];
|
initLanguage ??= oldLanguage;
|
||||||
|
const [code, language, usingDefault] = getLanguageCode(
|
||||||
|
initLanguage,
|
||||||
|
oldLanguage
|
||||||
|
);
|
||||||
|
|
||||||
|
let success = true;
|
||||||
|
if (code === 'en') {
|
||||||
|
setLanguageMapOnTranslationString(undefined);
|
||||||
|
} else {
|
||||||
|
success = await fetchAndSetLanguageMap(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && !usingDefault) {
|
||||||
|
config.set('language', language);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success && initLanguage !== oldLanguage) {
|
||||||
|
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLanguageCode(initLanguage, oldLanguage) {
|
||||||
|
let language = initLanguage ?? oldLanguage;
|
||||||
|
let usingDefault = false;
|
||||||
|
if (!language) {
|
||||||
|
language = DEFAULT_LANGUAGE;
|
||||||
|
usingDefault = true;
|
||||||
|
}
|
||||||
|
return [languageCodeMap[language], language, usingDefault];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user