mirror of
https://github.com/frappe/books.git
synced 2024-11-09 15:20:56 +00:00
chore: ignore linting in component/**/*.vue
- fix linting errors in the rest of the files
This commit is contained in:
parent
7c202ecee8
commit
247d4a4718
12
.eslintrc.js
12
.eslintrc.js
@ -37,6 +37,17 @@ module.exports = {
|
||||
'plugin:@typescript-eslint/recommended-requiring-type-checking',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.vue'],
|
||||
rules: {
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
'@typescript-eslint/no-unsafe-assignment': 'off',
|
||||
'@typescript-eslint/no-unsafe-member-access': 'off',
|
||||
'@typescript-eslint/no-unsafe-call': 'off',
|
||||
},
|
||||
},
|
||||
],
|
||||
ignorePatterns: [
|
||||
'*.mjs',
|
||||
'.eslintrc.js',
|
||||
@ -46,5 +57,6 @@ module.exports = {
|
||||
'*.spec.ts',
|
||||
'vite.config.ts',
|
||||
'postcss.config.js',
|
||||
'src/components/**/*.vue', // Incrementally fix these
|
||||
],
|
||||
};
|
||||
|
@ -305,7 +305,7 @@ export class DatabaseHandler extends DatabaseBase {
|
||||
)) as IncomeExpense;
|
||||
}
|
||||
|
||||
async getTotalCreditAndDebit(): Promise<unknown> {
|
||||
async getTotalCreditAndDebit(): Promise<TotalCreditAndDebit[]> {
|
||||
return (await this.#demux.callBespoke(
|
||||
'getTotalCreditAndDebit'
|
||||
)) as TotalCreditAndDebit[];
|
||||
|
11
src/App.vue
11
src/App.vue
@ -116,12 +116,12 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
language(value) {
|
||||
language(value: string) {
|
||||
this.languageDirection = getLanguageDirection(value);
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
this.setInitialScreen();
|
||||
await this.setInitialScreen();
|
||||
},
|
||||
methods: {
|
||||
async setInitialScreen(): Promise<void> {
|
||||
@ -209,7 +209,8 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
if (actionSymbol === dbErrorActionSymbols.SelectFile) {
|
||||
return await this.databaseSelector?.existingDatabase();
|
||||
await this.databaseSelector?.existingDatabase();
|
||||
return;
|
||||
}
|
||||
|
||||
throw error;
|
||||
@ -219,9 +220,9 @@ export default defineComponent({
|
||||
const { hideGetStarted } = await fyo.doc.getDoc('SystemSettings');
|
||||
|
||||
if (hideGetStarted || onboardingComplete) {
|
||||
routeTo('/');
|
||||
await routeTo('/');
|
||||
} else {
|
||||
routeTo('/get-started');
|
||||
await routeTo('/get-started');
|
||||
}
|
||||
},
|
||||
async showDbSelector(): Promise<void> {
|
||||
|
@ -93,7 +93,7 @@
|
||||
fieldname: 'value',
|
||||
fieldtype: 'Data',
|
||||
}"
|
||||
:value="filter.value"
|
||||
:value="String(filter.value)"
|
||||
@change="(value) => (filter.value = value)"
|
||||
/>
|
||||
</div>
|
||||
@ -127,7 +127,7 @@
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { t } from 'fyo';
|
||||
import { Field, FieldTypeEnum, SelectOption } from 'schemas/types';
|
||||
import { Field, FieldTypeEnum } from 'schemas/types';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { getRandomString } from 'utils';
|
||||
import { defineComponent } from 'vue';
|
||||
@ -136,7 +136,7 @@ import Data from './Controls/Data.vue';
|
||||
import Select from './Controls/Select.vue';
|
||||
import Icon from './Icon.vue';
|
||||
import Popover from './Popover.vue';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { QueryFilter } from 'utils/db/types';
|
||||
|
||||
const conditions = [
|
||||
{ label: t`Is`, value: '=' },
|
||||
@ -154,7 +154,7 @@ type Condition = typeof conditions[number]['value'];
|
||||
type Filter = {
|
||||
fieldname: string;
|
||||
condition: Condition;
|
||||
value: string;
|
||||
value: QueryFilter[string];
|
||||
implicit: boolean;
|
||||
};
|
||||
|
||||
@ -237,7 +237,7 @@ export default defineComponent({
|
||||
addFilter(
|
||||
fieldname: string,
|
||||
condition: Condition,
|
||||
value: string,
|
||||
value: Filter['value'],
|
||||
implicit?: boolean
|
||||
): void {
|
||||
this.filters.push({ fieldname, condition, value, implicit: !!implicit });
|
||||
@ -245,16 +245,17 @@ export default defineComponent({
|
||||
removeFilter(filter: Filter): void {
|
||||
this.filters = this.filters.filter((f) => f !== filter);
|
||||
},
|
||||
setFilter(filters: Record<string, Filter>, implicit?: boolean): void {
|
||||
setFilter(filters: QueryFilter, implicit?: boolean): void {
|
||||
this.filters = [];
|
||||
|
||||
Object.keys(filters).map((fieldname) => {
|
||||
let parts = filters[fieldname];
|
||||
let condition, value;
|
||||
let condition: Condition;
|
||||
let value: Filter['value'];
|
||||
|
||||
if (Array.isArray(parts)) {
|
||||
condition = parts[0];
|
||||
value = parts[1];
|
||||
condition = parts[0] as Condition;
|
||||
value = parts[1] as Filter['value'];
|
||||
} else {
|
||||
condition = '=';
|
||||
value = parts;
|
||||
@ -266,7 +267,7 @@ export default defineComponent({
|
||||
this.emitFilterChange();
|
||||
},
|
||||
emitFilterChange(): void {
|
||||
const filters: Record<string, [Condition, string]> = {};
|
||||
const filters: Record<string, [Condition, Filter['value']]> = {};
|
||||
for (const { condition, value, fieldname } of this.filters) {
|
||||
if (value === '' && condition) {
|
||||
continue;
|
||||
|
@ -34,7 +34,7 @@
|
||||
:style="getItemStyle(account.level)"
|
||||
@click="onClick(account)"
|
||||
>
|
||||
<component :is="getIconComponent(account)" />
|
||||
<component :is="getIconComponent(!!account.isGroup, account.name)" />
|
||||
<div class="flex items-baseline">
|
||||
<div
|
||||
class="ms-4"
|
||||
@ -91,9 +91,7 @@
|
||||
"
|
||||
:style="getGroupStyle(account.level + 1)"
|
||||
>
|
||||
<component
|
||||
:is="getIconComponent({ isGroup: account.addingGroupAccount })"
|
||||
/>
|
||||
<component :is="getIconComponent(account.addingGroupAccount)" />
|
||||
<div class="flex ms-4 h-row-mid items-center">
|
||||
<input
|
||||
:ref="account.name"
|
||||
@ -140,7 +138,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { t } from 'fyo';
|
||||
import { isCredit } from 'models/helpers';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
@ -151,12 +149,32 @@ import { docsPathMap } from 'src/utils/misc';
|
||||
import { docsPathRef } from 'src/utils/refs';
|
||||
import { openQuickEdit } from 'src/utils/ui';
|
||||
import { getMapFromList, removeAtIndex } from 'utils/index';
|
||||
import { nextTick } from 'vue';
|
||||
import { defineComponent, nextTick } from 'vue';
|
||||
import Button from '../components/Button.vue';
|
||||
import { inject } from 'vue';
|
||||
import { handleErrorWithDialog } from '../errorHandling';
|
||||
import { AccountRootType, AccountType } from 'models/baseModels/Account/types';
|
||||
import { TreeViewSettings } from 'fyo/model/types';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Component } from 'vue';
|
||||
|
||||
export default {
|
||||
type AccountItem = {
|
||||
name: string;
|
||||
parentAccount: string;
|
||||
rootType: AccountRootType;
|
||||
accountType: AccountType;
|
||||
level: number;
|
||||
location: number[];
|
||||
isGroup?: boolean;
|
||||
children: AccountItem[];
|
||||
expanded: boolean;
|
||||
addingAccount: boolean;
|
||||
addingGroupAccount: boolean;
|
||||
};
|
||||
|
||||
type AccKey = 'addingAccount' | 'addingGroupAccount';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
Button,
|
||||
PageHeader,
|
||||
@ -170,21 +188,26 @@ export default {
|
||||
return {
|
||||
isAllCollapsed: true,
|
||||
isAllExpanded: false,
|
||||
root: null,
|
||||
accounts: [],
|
||||
root: null as null | { label: string; balance: number; currency: string },
|
||||
accounts: [] as AccountItem[],
|
||||
schemaName: 'Account',
|
||||
newAccountName: '',
|
||||
insertingAccount: false,
|
||||
totals: {},
|
||||
totals: {} as Record<string, { totalDebit: number; totalCredit: number }>,
|
||||
refetchTotals: false,
|
||||
settings: null as null | TreeViewSettings,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
allAccounts() {
|
||||
const allAccounts = [];
|
||||
const allAccounts: AccountItem[] = [];
|
||||
|
||||
(function getAccounts(accounts, level, location) {
|
||||
for (let i in accounts) {
|
||||
(function getAccounts(
|
||||
accounts: AccountItem[],
|
||||
level: number,
|
||||
location: number[]
|
||||
) {
|
||||
for (let i = 0; i < accounts.length; i++) {
|
||||
const account = accounts[i];
|
||||
|
||||
account.level = level;
|
||||
@ -207,12 +230,13 @@ export default {
|
||||
});
|
||||
},
|
||||
async activated() {
|
||||
this.fetchAccounts();
|
||||
await this.fetchAccounts();
|
||||
if (fyo.store.isDevelopment) {
|
||||
// @ts-ignore
|
||||
window.coa = this;
|
||||
}
|
||||
|
||||
docsPathRef.value = docsPathMap.ChartOfAccounts;
|
||||
docsPathRef.value = docsPathMap.ChartOfAccounts!;
|
||||
|
||||
if (this.refetchTotals) {
|
||||
await this.setTotalDebitAndCredit();
|
||||
@ -233,7 +257,7 @@ export default {
|
||||
this.isAllExpanded = false;
|
||||
this.isAllCollapsed = true;
|
||||
},
|
||||
async toggleAll(accounts, expand) {
|
||||
async toggleAll(accounts: AccountItem | AccountItem[], expand: boolean) {
|
||||
if (!Array.isArray(accounts)) {
|
||||
await this.toggle(accounts, expand);
|
||||
accounts = accounts.children ?? [];
|
||||
@ -243,14 +267,14 @@ export default {
|
||||
await this.toggleAll(account, expand);
|
||||
}
|
||||
},
|
||||
async toggle(account, expand) {
|
||||
async toggle(account: AccountItem, expand: boolean) {
|
||||
if (account.expanded === expand || !account.isGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.toggleChildren(account);
|
||||
},
|
||||
getBalance(account) {
|
||||
getBalance(account: AccountItem) {
|
||||
const total = this.totals[account.name];
|
||||
if (!total) {
|
||||
return 0;
|
||||
@ -264,7 +288,7 @@ export default {
|
||||
|
||||
return totalDebit - totalCredit;
|
||||
},
|
||||
getBalanceString(account) {
|
||||
getBalanceString(account: AccountItem) {
|
||||
const suffix = isCredit(account.rootType) ? t`Cr.` : t`Dr.`;
|
||||
const balance = this.getBalance(account);
|
||||
return `${fyo.format(balance, 'Currency')} ${suffix}`;
|
||||
@ -274,16 +298,19 @@ export default {
|
||||
this.totals = getMapFromList(totals, 'account');
|
||||
},
|
||||
async fetchAccounts() {
|
||||
this.settings = fyo.models[ModelNameEnum.Account].getTreeSettings(fyo);
|
||||
const { currency } = await fyo.doc.getDoc('AccountingSettings');
|
||||
this.settings =
|
||||
fyo.models[ModelNameEnum.Account]?.getTreeSettings(fyo) ?? null;
|
||||
const currency = this.fyo.singles.SystemSettings?.currency ?? '';
|
||||
const label = (await this.settings?.getRootLabel()) ?? '';
|
||||
|
||||
this.root = {
|
||||
label: await this.settings.getRootLabel(),
|
||||
label,
|
||||
balance: 0,
|
||||
currency,
|
||||
};
|
||||
this.accounts = await this.getChildren();
|
||||
},
|
||||
async onClick(account) {
|
||||
async onClick(account: AccountItem) {
|
||||
let shouldOpen = !account.isGroup;
|
||||
if (account.isGroup) {
|
||||
shouldOpen = !(await this.toggleChildren(account));
|
||||
@ -305,21 +332,29 @@ export default {
|
||||
this.setOpenAccountDocListener(doc, account);
|
||||
await openQuickEdit({ doc });
|
||||
},
|
||||
setOpenAccountDocListener(doc, account, parentAccount) {
|
||||
setOpenAccountDocListener(
|
||||
doc: Doc,
|
||||
account?: AccountItem,
|
||||
parentAccount?: AccountItem
|
||||
) {
|
||||
if (doc.hasListener('afterDelete')) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.once('afterDelete', () => {
|
||||
this.removeAccount(doc.name, account, parentAccount);
|
||||
this.removeAccount(doc.name!, account, parentAccount);
|
||||
});
|
||||
},
|
||||
removeAccount(name, account, parentAccount) {
|
||||
removeAccount(
|
||||
name: string,
|
||||
account?: AccountItem,
|
||||
parentAccount?: AccountItem
|
||||
) {
|
||||
if (account == null && parentAccount == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (account == null) {
|
||||
if (account == null && parentAccount) {
|
||||
account = parentAccount.children.find((ch) => ch?.name === name);
|
||||
}
|
||||
|
||||
@ -334,7 +369,7 @@ export default {
|
||||
let children = this.accounts[i].children;
|
||||
|
||||
while (indices.length > 1) {
|
||||
i = indices.shift();
|
||||
i = indices.shift()!;
|
||||
|
||||
parent = children[i];
|
||||
children = children[i].children;
|
||||
@ -348,7 +383,7 @@ export default {
|
||||
|
||||
parent.children = removeAtIndex(children, i);
|
||||
},
|
||||
async toggleChildren(account) {
|
||||
async toggleChildren(account: AccountItem) {
|
||||
const hasChildren = await this.fetchChildren(account);
|
||||
if (!hasChildren) {
|
||||
return false;
|
||||
@ -356,20 +391,20 @@ export default {
|
||||
|
||||
account.expanded = !account.expanded;
|
||||
if (!account.expanded) {
|
||||
account.addingAccount = 0;
|
||||
account.addingGroupAccount = 0;
|
||||
account.addingAccount = false;
|
||||
account.addingGroupAccount = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
async fetchChildren(account, force = false) {
|
||||
async fetchChildren(account: AccountItem, force = false) {
|
||||
if (account.children == null || force) {
|
||||
account.children = await this.getChildren(account.name);
|
||||
}
|
||||
|
||||
return !!account?.children?.length;
|
||||
},
|
||||
async getChildren(parent = null) {
|
||||
async getChildren(parent: null | string = null): Promise<AccountItem[]> {
|
||||
const children = await fyo.db.getAll(ModelNameEnum.Account, {
|
||||
filters: {
|
||||
parentAccount: parent,
|
||||
@ -380,39 +415,39 @@ export default {
|
||||
});
|
||||
|
||||
return children.map((d) => {
|
||||
d.expanded = 0;
|
||||
d.addingAccount = 0;
|
||||
d.addingGroupAccount = 0;
|
||||
return d;
|
||||
d.expanded = false;
|
||||
d.addingAccount = false;
|
||||
d.addingGroupAccount = false;
|
||||
|
||||
return d as unknown as AccountItem;
|
||||
});
|
||||
},
|
||||
async addAccount(parentAccount, key) {
|
||||
async addAccount(parentAccount: AccountItem, key: AccKey) {
|
||||
if (!parentAccount.expanded) {
|
||||
await this.fetchChildren(parentAccount);
|
||||
parentAccount.expanded = true;
|
||||
}
|
||||
// activate editing of type 'key' and deactivate other type
|
||||
let otherKey =
|
||||
let otherKey: AccKey =
|
||||
key === 'addingAccount' ? 'addingGroupAccount' : 'addingAccount';
|
||||
parentAccount[key] = 1;
|
||||
parentAccount[otherKey] = 0;
|
||||
parentAccount[key] = true;
|
||||
parentAccount[otherKey] = false;
|
||||
|
||||
nextTick(() => {
|
||||
let input = this.$refs[parentAccount.name][0];
|
||||
input.focus();
|
||||
});
|
||||
await nextTick();
|
||||
let input = (this.$refs[parentAccount.name] as HTMLInputElement[])[0];
|
||||
input.focus();
|
||||
},
|
||||
cancelAddingAccount(parentAccount) {
|
||||
parentAccount.addingAccount = 0;
|
||||
parentAccount.addingGroupAccount = 0;
|
||||
cancelAddingAccount(parentAccount: AccountItem) {
|
||||
parentAccount.addingAccount = false;
|
||||
parentAccount.addingGroupAccount = false;
|
||||
this.newAccountName = '';
|
||||
},
|
||||
async createNewAccount(parentAccount, isGroup) {
|
||||
async createNewAccount(parentAccount: AccountItem, isGroup: boolean) {
|
||||
// freeze input
|
||||
this.insertingAccount = true;
|
||||
|
||||
const accountName = this.newAccountName.trim();
|
||||
const doc = await fyo.doc.getNewDoc('Account');
|
||||
const doc = fyo.doc.getNewDoc('Account');
|
||||
try {
|
||||
let { name, rootType, accountType } = parentAccount;
|
||||
await doc.set({
|
||||
@ -425,15 +460,15 @@ export default {
|
||||
await doc.sync();
|
||||
|
||||
// turn off editing
|
||||
parentAccount.addingAccount = 0;
|
||||
parentAccount.addingGroupAccount = 0;
|
||||
parentAccount.addingAccount = false;
|
||||
parentAccount.addingGroupAccount = false;
|
||||
|
||||
// update accounts
|
||||
await this.fetchChildren(parentAccount, true);
|
||||
|
||||
// open quick edit
|
||||
await openQuickEdit({ doc });
|
||||
this.setOpenAccountDocListener(doc, null, parentAccount);
|
||||
this.setOpenAccountDocListener(doc, undefined, parentAccount);
|
||||
|
||||
// unfreeze input
|
||||
this.insertingAccount = false;
|
||||
@ -444,11 +479,11 @@ export default {
|
||||
await handleErrorWithDialog(e, doc);
|
||||
}
|
||||
},
|
||||
isQuickEditOpen(account) {
|
||||
isQuickEditOpen(account: AccountItem) {
|
||||
let { edit, schemaName, name } = this.$route.query;
|
||||
return !!(edit && schemaName === 'Account' && name === account.name);
|
||||
},
|
||||
getIconComponent(account) {
|
||||
getIconComponent(isGroup: boolean, name?: string): Component {
|
||||
let icons = {
|
||||
'Application of Funds (Assets)': `<svg class="w-4 h-4" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
@ -481,14 +516,14 @@ export default {
|
||||
<path d="M8.333 3.367L6.333.7H.667A.667.667 0 000 1.367v12a2 2 0 002 2h12a2 2 0 002-2V4.033a.667.667 0 00-.667-.666h-7z" fill="#415668" fill-rule="evenodd"/>
|
||||
</svg>`;
|
||||
|
||||
let icon = account.isGroup ? folder : leaf;
|
||||
let icon = isGroup ? folder : leaf;
|
||||
|
||||
return {
|
||||
template: icons[account.name] || icon,
|
||||
template: icons[name as keyof typeof icons] || icon,
|
||||
};
|
||||
},
|
||||
getItemStyle(level) {
|
||||
const styles = {
|
||||
getItemStyle(level: number) {
|
||||
const styles: Record<string, string> = {
|
||||
height: 'calc(var(--h-row-mid) + 1px)',
|
||||
};
|
||||
if (this.languageDirection === 'rtl') {
|
||||
@ -498,8 +533,8 @@ export default {
|
||||
}
|
||||
return styles;
|
||||
},
|
||||
getGroupStyle(level) {
|
||||
const styles = {
|
||||
getGroupStyle(level: number) {
|
||||
const styles: Record<string, string> = {
|
||||
height: 'height: calc(var(--h-row-mid) + 1px)',
|
||||
};
|
||||
if (this.languageDirection === 'rtl') {
|
||||
@ -510,5 +545,5 @@ export default {
|
||||
return styles;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -81,13 +81,13 @@
|
||||
<!-- Section Container -->
|
||||
<div v-if="hasDoc" class="overflow-auto custom-scroll">
|
||||
<CommonFormSection
|
||||
v-for="([name, fields], idx) in activeGroup.entries()"
|
||||
:key="name + idx"
|
||||
v-for="([n, fields], idx) in activeGroup.entries()"
|
||||
:key="n + idx"
|
||||
ref="section"
|
||||
class="p-4"
|
||||
:class="idx !== 0 && activeGroup.size > 1 ? 'border-t' : ''"
|
||||
:show-title="activeGroup.size > 1 && name !== t`Default`"
|
||||
:title="name"
|
||||
:show-title="activeGroup.size > 1 && n !== t`Default`"
|
||||
:title="n"
|
||||
:fields="fields"
|
||||
:doc="doc"
|
||||
:errors="errors"
|
||||
@ -348,7 +348,7 @@ export default defineComponent({
|
||||
const group = this.groupedFields.get(this.activeTab);
|
||||
if (!group) {
|
||||
const tab = [...this.groupedFields.keys()][0];
|
||||
return this.groupedFields.get(tab) ?? new Map();
|
||||
return this.groupedFields.get(tab) ?? new Map<string, Field[]>();
|
||||
}
|
||||
|
||||
return group;
|
||||
@ -361,7 +361,7 @@ export default defineComponent({
|
||||
return getGroupedActionsForDoc(this.doc);
|
||||
},
|
||||
},
|
||||
async beforeMount() {
|
||||
beforeMount() {
|
||||
this.useFullWidth = !!this.fyo.singles.Misc?.useFullWidth;
|
||||
},
|
||||
async mounted() {
|
||||
@ -438,14 +438,14 @@ export default defineComponent({
|
||||
this.name
|
||||
);
|
||||
},
|
||||
async replacePathAfterSync() {
|
||||
replacePathAfterSync() {
|
||||
if (!this.hasDoc || this.doc.inserted) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.doc.once('afterSync', () => {
|
||||
this.doc.once('afterSync', async () => {
|
||||
const route = getFormRoute(this.schemaName, this.doc.name!);
|
||||
this.$router.replace(route);
|
||||
await this.$router.replace(route);
|
||||
});
|
||||
},
|
||||
async showRowEditForm(doc: Doc) {
|
||||
|
@ -56,6 +56,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { DocValue } from 'fyo/core/types';
|
||||
import { Doc } from 'fyo/model/doc';
|
||||
import { Field } from 'schemas/types';
|
||||
@ -67,12 +68,15 @@ import { defineComponent, PropType } from 'vue';
|
||||
export default defineComponent({
|
||||
components: { FormControl, Table },
|
||||
props: {
|
||||
title: String,
|
||||
errors: Object as PropType<Record<string, string>>,
|
||||
title: { type: String, default: '' },
|
||||
errors: {
|
||||
type: Object as PropType<Record<string, string>>,
|
||||
required: true,
|
||||
},
|
||||
showTitle: Boolean,
|
||||
doc: { type: Object as PropType<Doc>, required: true },
|
||||
collapsible: { type: Boolean, default: true },
|
||||
fields: Array as PropType<Field[]>,
|
||||
fields: { type: Array as PropType<Field[]>, required: true },
|
||||
},
|
||||
emits: ['editrow', 'value-change', 'row-change'],
|
||||
data() {
|
||||
|
@ -80,7 +80,9 @@ export default defineComponent({
|
||||
return rows[this.index];
|
||||
}
|
||||
|
||||
const label = `${this.doc.name}.${this.fieldname}[${this.index}]`;
|
||||
const label = `${this.doc.name ?? '_name'}.${this.fieldname}[${
|
||||
this.index
|
||||
}]`;
|
||||
throw new ValueError(this.t`Invalid value found for ${label}`);
|
||||
},
|
||||
fields() {
|
||||
|
@ -1,19 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { PeriodKey } from 'src/utils/types';
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
commonPeriod: String,
|
||||
commonPeriod: { type: String as PropType<PeriodKey>, default: 'This Year' },
|
||||
},
|
||||
emits: ['period-change'],
|
||||
data() {
|
||||
return {
|
||||
period: 'This Year',
|
||||
periodOptions: ['This Year', 'This Quarter', 'This Month'],
|
||||
period: 'This Year' as PeriodKey,
|
||||
periodOptions: ['This Year', 'This Quarter', 'This Month'] as PeriodKey[],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
period: 'periodChange',
|
||||
commonPeriod(val) {
|
||||
commonPeriod(val: PeriodKey) {
|
||||
if (!this.periodOptions.includes(val)) {
|
||||
return;
|
||||
}
|
||||
@ -26,7 +29,9 @@ export default defineComponent({
|
||||
this.$emit('period-change', this.period);
|
||||
await this.setData();
|
||||
},
|
||||
async setData() {},
|
||||
async setData() {
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
@ -42,7 +42,7 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { AccountTypeEnum } from 'models/baseModels/Account/types';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import LineChart from 'src/components/Charts/LineChart.vue';
|
||||
@ -50,11 +50,19 @@ import { fyo } from 'src/initFyo';
|
||||
import { formatXLabels, getYMax } from 'src/utils/chart';
|
||||
import { uicolors } from 'src/utils/colors';
|
||||
import { getDatesAndPeriodList } from 'src/utils/misc';
|
||||
import { getMapFromList } from 'utils/';
|
||||
import DashboardChartBase from './BaseDashboardChart.vue';
|
||||
import PeriodSelector from './PeriodSelector.vue';
|
||||
import { defineComponent } from 'vue';
|
||||
import { getMapFromList } from 'utils/index';
|
||||
import { PeriodKey } from 'src/utils/types';
|
||||
|
||||
export default {
|
||||
// Linting broken in this file cause of `extends: ...`
|
||||
/*
|
||||
eslint-disable @typescript-eslint/no-unsafe-argument,
|
||||
@typescript-eslint/no-unsafe-return
|
||||
*/
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Cashflow',
|
||||
components: {
|
||||
PeriodSelector,
|
||||
@ -62,7 +70,7 @@ export default {
|
||||
},
|
||||
extends: DashboardChartBase,
|
||||
data: () => ({
|
||||
data: [],
|
||||
data: [] as { inflow: number; outflow: number; yearmonth: string }[],
|
||||
periodList: [],
|
||||
periodOptions: ['This Year', 'This Quarter'],
|
||||
hasData: false,
|
||||
@ -76,10 +84,12 @@ export default {
|
||||
colors = [uicolors.gray['200'], uicolors.gray['100']];
|
||||
}
|
||||
|
||||
const xLabels = data.map((cf) => cf['yearmonth']);
|
||||
const points = ['inflow', 'outflow'].map((k) => data.map((d) => d[k]));
|
||||
const xLabels = data.map((cf) => cf.yearmonth);
|
||||
const points = (['inflow', 'outflow'] as const).map((k) =>
|
||||
data.map((d) => d[k])
|
||||
);
|
||||
|
||||
const format = (value) => fyo.format(value ?? 0, 'Currency');
|
||||
const format = (value: number) => fyo.format(value ?? 0, 'Currency');
|
||||
const yMax = getYMax(points);
|
||||
return { points, xLabels, colors, format, yMax, formatX: formatXLabels };
|
||||
},
|
||||
@ -92,8 +102,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async setData() {
|
||||
const { periodList, fromDate, toDate } = await getDatesAndPeriodList(
|
||||
this.period
|
||||
const { periodList, fromDate, toDate } = getDatesAndPeriodList(
|
||||
this.period as PeriodKey
|
||||
);
|
||||
|
||||
const data = await fyo.db.getCashflow(fromDate.toISO(), toDate.toISO());
|
||||
@ -118,14 +128,14 @@ export default {
|
||||
accountType: ['in', [AccountTypeEnum.Cash, AccountTypeEnum.Bank]],
|
||||
},
|
||||
});
|
||||
const accountNames = accounts.map((a) => a.name);
|
||||
const accountNames = accounts.map((a) => a.name as string);
|
||||
const count = await fyo.db.count(ModelNameEnum.AccountingLedgerEntry, {
|
||||
filters: { account: ['in', accountNames] },
|
||||
});
|
||||
this.hasData = count > 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
const dummyData = [
|
||||
{
|
||||
|
@ -13,7 +13,7 @@
|
||||
<!-- Ledgend Item -->
|
||||
<div
|
||||
v-for="(d, i) in expenses"
|
||||
:key="d.name"
|
||||
:key="d.account"
|
||||
class="flex items-center text-sm"
|
||||
@mouseover="active = i"
|
||||
@mouseleave="active = null"
|
||||
@ -34,9 +34,9 @@
|
||||
:offset-x="3"
|
||||
:thickness="10"
|
||||
:text-offset-x="6.5"
|
||||
:value-formatter="(value) => fyo.format(value, 'Currency')"
|
||||
:value-formatter="(value: number) => fyo.format(value, 'Currency')"
|
||||
:total-label="t`Total Spending`"
|
||||
@change="(value) => (active = value)"
|
||||
@change="(value: number) => (active = value)"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -52,17 +52,24 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { truncate } from 'lodash';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { uicolors } from 'src/utils/colors';
|
||||
import { getDatesAndPeriodList } from 'src/utils/misc';
|
||||
import { defineComponent } from 'vue';
|
||||
import DonutChart from '../../components/Charts/DonutChart.vue';
|
||||
import DashboardChartBase from './BaseDashboardChart.vue';
|
||||
import PeriodSelector from './PeriodSelector.vue';
|
||||
import SectionHeader from './SectionHeader.vue';
|
||||
|
||||
export default {
|
||||
// Linting broken in this file cause of `extends: ...`
|
||||
/*
|
||||
eslint-disable @typescript-eslint/no-unsafe-argument,
|
||||
@typescript-eslint/no-unsafe-return,
|
||||
@typescript-eslint/restrict-plus-operands
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'Expenses',
|
||||
components: {
|
||||
DonutChart,
|
||||
@ -71,17 +78,22 @@ export default {
|
||||
},
|
||||
extends: DashboardChartBase,
|
||||
data: () => ({
|
||||
active: null,
|
||||
expenses: [],
|
||||
active: null as null | number,
|
||||
expenses: [] as {
|
||||
account: string;
|
||||
total: number;
|
||||
color: string;
|
||||
class: string;
|
||||
}[],
|
||||
}),
|
||||
computed: {
|
||||
totalExpense() {
|
||||
totalExpense(): number {
|
||||
return this.expenses.reduce((sum, expense) => sum + expense.total, 0);
|
||||
},
|
||||
hasData() {
|
||||
hasData(): boolean {
|
||||
return this.expenses.length > 0;
|
||||
},
|
||||
sectors() {
|
||||
sectors(): { color: string; label: string; value: number }[] {
|
||||
return this.expenses.map(({ account, color, total }) => ({
|
||||
color,
|
||||
label: truncate(account, { length: 21 }),
|
||||
@ -94,7 +106,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async setData() {
|
||||
const { fromDate, toDate } = await getDatesAndPeriodList(this.period);
|
||||
const { fromDate, toDate } = getDatesAndPeriodList(this.period);
|
||||
let topExpenses = await fyo.db.getTopExpenses(
|
||||
fromDate.toISO(),
|
||||
toDate.toISO()
|
||||
@ -108,16 +120,16 @@ export default {
|
||||
{ class: 'bg-pink-100', hex: uicolors.pink['100'] },
|
||||
];
|
||||
|
||||
topExpenses = topExpenses
|
||||
this.expenses = topExpenses
|
||||
.filter((e) => e.total > 0)
|
||||
.map((d, i) => {
|
||||
d.color = shades[i].hex;
|
||||
d.class = shades[i].class;
|
||||
return d;
|
||||
return {
|
||||
...d,
|
||||
color: shades[i].hex,
|
||||
class: shades[i].class,
|
||||
};
|
||||
});
|
||||
|
||||
this.expenses = topExpenses;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -35,27 +35,30 @@
|
||||
</Dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { t } from 'fyo';
|
||||
import Dropdown from 'src/components/Dropdown.vue';
|
||||
import { PeriodKey } from 'src/utils/types';
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
name: 'PeriodSelector',
|
||||
components: {
|
||||
Dropdown,
|
||||
},
|
||||
props: {
|
||||
value: String,
|
||||
value: { type: String as PropType<PeriodKey>, default: 'This Year' },
|
||||
options: {
|
||||
type: Array,
|
||||
type: Array as PropType<PeriodKey[]>,
|
||||
default: () => ['This Year', 'This Quarter', 'This Month'],
|
||||
},
|
||||
},
|
||||
emits: ['change'],
|
||||
data() {
|
||||
return {
|
||||
periodSelectorMap: {},
|
||||
periodOptions: [],
|
||||
periodSelectorMap: {} as Record<PeriodKey | '', string>,
|
||||
periodOptions: [] as { label: string; action: () => void }[],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
@ -76,10 +79,12 @@ export default {
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
selectOption(value) {
|
||||
selectOption(value: PeriodKey) {
|
||||
this.$emit('change', value);
|
||||
this.$refs.dropdown.toggleDropdown(false);
|
||||
(this.$refs.dropdown as InstanceType<typeof Dropdown>).toggleDropdown(
|
||||
false
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -29,7 +29,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import BarChart from 'src/components/Charts/BarChart.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { formatXLabels, getYMax, getYMin } from 'src/utils/chart';
|
||||
@ -39,8 +39,14 @@ import { getValueMapFromList } from 'utils';
|
||||
import DashboardChartBase from './BaseDashboardChart.vue';
|
||||
import PeriodSelector from './PeriodSelector.vue';
|
||||
import SectionHeader from './SectionHeader.vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default {
|
||||
// Linting broken in this file cause of `extends: ...`
|
||||
/*
|
||||
eslint-disable @typescript-eslint/no-unsafe-argument,
|
||||
@typescript-eslint/no-unsafe-return
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'ProfitAndLoss',
|
||||
components: {
|
||||
PeriodSelector,
|
||||
@ -49,7 +55,7 @@ export default {
|
||||
},
|
||||
extends: DashboardChartBase,
|
||||
data: () => ({
|
||||
data: [],
|
||||
data: [] as { yearmonth: string; balance: number }[],
|
||||
hasData: false,
|
||||
periodOptions: ['This Year', 'This Quarter'],
|
||||
}),
|
||||
@ -59,7 +65,7 @@ export default {
|
||||
const colors = [
|
||||
{ positive: uicolors.blue['500'], negative: uicolors.pink['500'] },
|
||||
];
|
||||
const format = (value) => fyo.format(value ?? 0, 'Currency');
|
||||
const format = (value: number) => fyo.format(value ?? 0, 'Currency');
|
||||
const yMax = getYMax(points);
|
||||
const yMin = getYMin(points);
|
||||
return {
|
||||
@ -78,7 +84,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async setData() {
|
||||
const { fromDate, toDate, periodList } = await getDatesAndPeriodList(
|
||||
const { fromDate, toDate, periodList } = getDatesAndPeriodList(
|
||||
this.period
|
||||
);
|
||||
|
||||
@ -102,5 +108,5 @@ export default {
|
||||
this.hasData = data.income.length > 0 || data.expense.length > 0;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -89,11 +89,17 @@ import { getDatesAndPeriodList } from 'src/utils/misc';
|
||||
import { PeriodKey } from 'src/utils/types';
|
||||
import { routeTo } from 'src/utils/ui';
|
||||
import { safeParseFloat } from 'utils/index';
|
||||
import { defineComponent } from 'vue';
|
||||
import { PropType, defineComponent } from 'vue';
|
||||
import BaseDashboardChart from './BaseDashboardChart.vue';
|
||||
import PeriodSelector from './PeriodSelector.vue';
|
||||
import SectionHeader from './SectionHeader.vue';
|
||||
|
||||
// Linting broken in this file cause of `extends: ...`
|
||||
/*
|
||||
eslint-disable @typescript-eslint/no-unsafe-argument,
|
||||
@typescript-eslint/restrict-template-expressions,
|
||||
@typescript-eslint/no-unsafe-return
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'UnpaidInvoices',
|
||||
components: {
|
||||
@ -103,7 +109,7 @@ export default defineComponent({
|
||||
},
|
||||
extends: BaseDashboardChart,
|
||||
props: {
|
||||
schemaName: { type: String, required: true },
|
||||
schemaName: { type: String as PropType<string>, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -211,7 +217,7 @@ export default defineComponent({
|
||||
},
|
||||
async newInvoice() {
|
||||
const doc = fyo.doc.getNewDoc(this.schemaName);
|
||||
await routeTo(`/edit/${this.schemaName}/${doc.name}`);
|
||||
await routeTo(`/edit/${this.schemaName}/${doc.name!}`);
|
||||
},
|
||||
|
||||
async getCounts(schemaName: string, fromDate: DateTime, toDate: DateTime) {
|
||||
|
@ -280,7 +280,7 @@ export default defineComponent({
|
||||
},
|
||||
async deleteDb(i: number) {
|
||||
const file = this.files[i];
|
||||
const vm = this;
|
||||
const setFiles = this.setFiles.bind(this);
|
||||
|
||||
await showDialog({
|
||||
title: t`Delete ${file.companyName}?`,
|
||||
@ -291,13 +291,15 @@ export default defineComponent({
|
||||
label: this.t`Yes`,
|
||||
async action() {
|
||||
await deleteDb(file.dbPath);
|
||||
await vm.setFiles();
|
||||
await setFiles();
|
||||
},
|
||||
isPrimary: true,
|
||||
},
|
||||
{
|
||||
label: this.t`No`,
|
||||
action() {},
|
||||
action() {
|
||||
return null;
|
||||
},
|
||||
isEscape: true,
|
||||
},
|
||||
],
|
||||
@ -305,7 +307,7 @@ export default defineComponent({
|
||||
},
|
||||
async createDemo() {
|
||||
if (!fyo.store.isDevelopment) {
|
||||
this.startDummyInstanceSetup();
|
||||
await this.startDummyInstanceSetup();
|
||||
} else {
|
||||
this.openModal = true;
|
||||
}
|
||||
@ -363,14 +365,14 @@ export default defineComponent({
|
||||
const filePath = (await getSelectedFilePath())?.filePaths?.[0];
|
||||
this.emitFileSelected(filePath);
|
||||
},
|
||||
async selectFile(file: ConfigFilesWithModified) {
|
||||
selectFile(file: ConfigFilesWithModified) {
|
||||
if (this.creatingDemo) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.emitFileSelected(file.dbPath);
|
||||
this.emitFileSelected(file.dbPath);
|
||||
},
|
||||
async emitFileSelected(filePath: string, isNew?: boolean) {
|
||||
emitFileSelected(filePath: string, isNew?: boolean) {
|
||||
if (!filePath) {
|
||||
return;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { toggleSidebar } from 'src/utils/ui';
|
||||
<template>
|
||||
<div class="flex overflow-hidden">
|
||||
<Transition name="sidebar">
|
||||
<!-- eslint-disable vue/require-explicit-emits -->
|
||||
<Sidebar
|
||||
v-show="showSidebar"
|
||||
class="flex-shrink-0 border-e whitespace-nowrap w-sidebar"
|
||||
|
@ -47,7 +47,7 @@
|
||||
@click="handleAction(item)"
|
||||
>
|
||||
<span class="text-base text-white">
|
||||
{{ item.actionLabel || t`Set Up` }}
|
||||
{{ t`Set Up` }}
|
||||
</span>
|
||||
</Button>
|
||||
<Button
|
||||
@ -69,15 +69,21 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { DocValue } from 'fyo/core/types';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import Icon from 'src/components/Icon.vue';
|
||||
import PageHeader from 'src/components/PageHeader.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { getGetStartedConfig } from 'src/utils/getStartedConfig';
|
||||
import { openLink } from 'src/utils/ipcCalls';
|
||||
import { h } from 'vue';
|
||||
export default {
|
||||
import { GetStartedConfigItem } from 'src/utils/types';
|
||||
import { Component } from 'vue';
|
||||
import { defineComponent, h } from 'vue';
|
||||
|
||||
type ListItem = GetStartedConfigItem['items'][number];
|
||||
|
||||
export default defineComponent({
|
||||
name: 'GetStarted',
|
||||
components: {
|
||||
PageHeader,
|
||||
@ -86,19 +92,19 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeCard: null,
|
||||
sections: [],
|
||||
activeCard: null as string | null,
|
||||
sections: getGetStartedConfig(),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.sections = getGetStartedConfig();
|
||||
// this.sections = getGetStartedConfig();
|
||||
},
|
||||
async activated() {
|
||||
await fyo.doc.getDoc('GetStarted');
|
||||
this.checkForCompletedTasks();
|
||||
await this.checkForCompletedTasks();
|
||||
},
|
||||
methods: {
|
||||
async handleDocumentation({ key, documentation }) {
|
||||
async handleDocumentation({ key, documentation }: ListItem) {
|
||||
if (documentation) {
|
||||
openLink(documentation);
|
||||
}
|
||||
@ -109,7 +115,7 @@ export default {
|
||||
break;
|
||||
}
|
||||
},
|
||||
async handleAction({ key, action }) {
|
||||
async handleAction({ key, action }: ListItem) {
|
||||
if (action) {
|
||||
action();
|
||||
this.activeCard = null;
|
||||
@ -134,12 +140,12 @@ export default {
|
||||
}
|
||||
},
|
||||
async checkIsOnboardingComplete() {
|
||||
if (fyo.singles.GetStarted.onboardingComplete) {
|
||||
if (fyo.singles.GetStarted?.onboardingComplete) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const doc = await fyo.doc.getDoc('GetStarted');
|
||||
const onboardingComplete = fyo.schemaMap.GetStarted.fields
|
||||
const onboardingComplete = fyo.schemaMap.GetStarted?.fields
|
||||
.filter(({ fieldname }) => fieldname !== 'onboardingComplete')
|
||||
.map(({ fieldname }) => doc.get(fieldname))
|
||||
.every(Boolean);
|
||||
@ -154,41 +160,41 @@ export default {
|
||||
return onboardingComplete;
|
||||
},
|
||||
async checkForCompletedTasks() {
|
||||
let toUpdate = {};
|
||||
let toUpdate: Record<string, DocValue> = {};
|
||||
if (await this.checkIsOnboardingComplete()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.salesItemCreated) {
|
||||
if (!fyo.singles.GetStarted?.salesItemCreated) {
|
||||
const count = await fyo.db.count('Item', { filters: { for: 'Sales' } });
|
||||
toUpdate.salesItemCreated = count > 0;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.purchaseItemCreated) {
|
||||
if (!fyo.singles.GetStarted?.purchaseItemCreated) {
|
||||
const count = await fyo.db.count('Item', {
|
||||
filters: { for: 'Purchases' },
|
||||
});
|
||||
toUpdate.purchaseItemCreated = count > 0;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.invoiceCreated) {
|
||||
if (!fyo.singles.GetStarted?.invoiceCreated) {
|
||||
const count = await fyo.db.count('SalesInvoice');
|
||||
toUpdate.invoiceCreated = count > 0;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.customerCreated) {
|
||||
if (!fyo.singles.GetStarted?.customerCreated) {
|
||||
const count = await fyo.db.count('Party', {
|
||||
filters: { role: 'Customer' },
|
||||
});
|
||||
toUpdate.customerCreated = count > 0;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.billCreated) {
|
||||
if (!fyo.singles.GetStarted?.billCreated) {
|
||||
const count = await fyo.db.count('SalesInvoice');
|
||||
toUpdate.billCreated = count > 0;
|
||||
}
|
||||
|
||||
if (!fyo.singles.GetStarted.supplierCreated) {
|
||||
if (!fyo.singles.GetStarted?.supplierCreated) {
|
||||
const count = await fyo.db.count('Party', {
|
||||
filters: { role: 'Supplier' },
|
||||
});
|
||||
@ -196,20 +202,21 @@ export default {
|
||||
}
|
||||
await this.updateChecks(toUpdate);
|
||||
},
|
||||
async updateChecks(toUpdate) {
|
||||
await fyo.singles.GetStarted.setAndSync(toUpdate);
|
||||
async updateChecks(toUpdate: Record<string, DocValue>) {
|
||||
await fyo.singles.GetStarted?.setAndSync(toUpdate);
|
||||
await fyo.doc.getDoc('GetStarted');
|
||||
},
|
||||
isCompleted(item) {
|
||||
return fyo.singles.GetStarted.get(item.fieldname) || false;
|
||||
isCompleted(item: ListItem) {
|
||||
return fyo.singles.GetStarted?.get(item.fieldname) || false;
|
||||
},
|
||||
getIconComponent(item) {
|
||||
let completed = fyo.singles.GetStarted[item.fieldname] || false;
|
||||
getIconComponent(item: ListItem) {
|
||||
let completed = fyo.singles.GetStarted?.[item.fieldname] || false;
|
||||
let name = completed ? 'green-check' : item.icon;
|
||||
let size = completed ? '24' : '18';
|
||||
return {
|
||||
name,
|
||||
render() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
return h(Icon, {
|
||||
...Object.assign(
|
||||
{
|
||||
@ -220,8 +227,8 @@ export default {
|
||||
),
|
||||
});
|
||||
},
|
||||
};
|
||||
} as Component;
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
@ -384,10 +384,10 @@ import DropdownWithActions from 'src/components/DropdownWithActions.vue';
|
||||
import FormHeader from 'src/components/FormHeader.vue';
|
||||
import Modal from 'src/components/Modal.vue';
|
||||
import PageHeader from 'src/components/PageHeader.vue';
|
||||
import { getColumnLabel, Importer, TemplateField } from 'src/importer';
|
||||
import { Importer, TemplateField, getColumnLabel } from 'src/importer';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { showDialog } from 'src/utils/interactive';
|
||||
import { getSavePath, saveData, selectFile } from 'src/utils/ipcCalls';
|
||||
import { getSavePath, saveData } from 'src/utils/ipcCalls';
|
||||
import { docsPathMap } from 'src/utils/misc';
|
||||
import { docsPathRef } from 'src/utils/refs';
|
||||
import { selectTextFile } from 'src/utils/ui';
|
||||
@ -603,7 +603,7 @@ export default defineComponent({
|
||||
component: {
|
||||
template: `<span>{{ "${selectFileLabel}" }}</span>`,
|
||||
},
|
||||
action: this.selectFile,
|
||||
action: this.selectFile.bind(this),
|
||||
});
|
||||
}
|
||||
|
||||
@ -620,7 +620,7 @@ export default defineComponent({
|
||||
component: {
|
||||
template: '<span class="text-red-700" >{{ t`Cancel` }}</span>',
|
||||
},
|
||||
action: this.clear,
|
||||
action: this.clear.bind(this),
|
||||
};
|
||||
actions.push(pickColumnsAction, cancelAction);
|
||||
|
||||
@ -668,8 +668,8 @@ export default defineComponent({
|
||||
},
|
||||
pickedArray(): string[] {
|
||||
return [...this.importer.templateFieldsPicked.entries()]
|
||||
.filter(([_, picked]) => picked)
|
||||
.map(([key, _]) => key);
|
||||
.filter(([, picked]) => picked)
|
||||
.map(([key]) => key);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
@ -750,7 +750,11 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
for (const idx in this.importer.assignedTemplateFields) {
|
||||
for (
|
||||
let idx = 0;
|
||||
idx < this.importer.assignedTemplateFields.length;
|
||||
idx++
|
||||
) {
|
||||
this.importer.assignedTemplateFields[idx] = null;
|
||||
}
|
||||
|
||||
@ -764,10 +768,10 @@ export default defineComponent({
|
||||
idx += 1;
|
||||
}
|
||||
},
|
||||
showMe(): void {
|
||||
async showMe(): Promise<void> {
|
||||
const schemaName = this.importer.schemaName;
|
||||
this.clear();
|
||||
this.$router.push(`/list/${schemaName}`);
|
||||
await this.$router.push(`/list/${schemaName}`);
|
||||
},
|
||||
clear(): void {
|
||||
this.file = null;
|
||||
@ -821,7 +825,7 @@ export default defineComponent({
|
||||
title,
|
||||
type: 'error',
|
||||
detail: this.t`Following links do not exist: ${absentLinks
|
||||
.map((l) => `(${l.schemaLabel}, ${l.name})`)
|
||||
.map((l) => `(${l.schemaLabel ?? l.schemaName}, ${l.name})`)
|
||||
.join(', ')}.`,
|
||||
});
|
||||
return false;
|
||||
@ -883,7 +887,9 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
label: this.t`No`,
|
||||
action() {},
|
||||
action() {
|
||||
return null;
|
||||
},
|
||||
isEscape: true,
|
||||
},
|
||||
],
|
||||
|
@ -37,7 +37,7 @@
|
||||
|
||||
<!-- Data Rows -->
|
||||
<div v-if="dataSlice.length !== 0" class="overflow-y-auto custom-scroll">
|
||||
<div v-for="(row, i) in dataSlice" :key="row.name">
|
||||
<div v-for="(row, i) in dataSlice" :key="(row.name as string)">
|
||||
<!-- Row Content -->
|
||||
<div class="flex hover:bg-gray-50 items-center">
|
||||
<p class="w-8 text-end me-4 text-gray-900">
|
||||
@ -56,7 +56,7 @@
|
||||
'text-end': isNumeric(column.fieldtype),
|
||||
'pe-4': c === columns.length - 1,
|
||||
}"
|
||||
:row="row"
|
||||
:row="(row as RenderData)"
|
||||
:column="column"
|
||||
/>
|
||||
</Row>
|
||||
@ -93,14 +93,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { ListViewSettings, RenderData } from 'fyo/model/types';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import Button from 'src/components/Button.vue';
|
||||
import Paginator from 'src/components/Paginator.vue';
|
||||
import Row from 'src/components/Row.vue';
|
||||
import { fyo } from 'src/initFyo';
|
||||
import { isNumeric } from 'src/utils';
|
||||
import { defineComponent } from 'vue';
|
||||
import { QueryFilter } from 'utils/db/types';
|
||||
import { PropType, defineComponent } from 'vue';
|
||||
import ListCell from './ListCell.vue';
|
||||
|
||||
export default defineComponent({
|
||||
@ -112,15 +114,21 @@ export default defineComponent({
|
||||
Paginator,
|
||||
},
|
||||
props: {
|
||||
listConfig: Object,
|
||||
filters: Object,
|
||||
schemaName: String,
|
||||
listConfig: {
|
||||
type: Object as PropType<ListViewSettings | undefined>,
|
||||
default: () => ({ columns: [] }),
|
||||
},
|
||||
filters: {
|
||||
type: Object as PropType<QueryFilter>,
|
||||
default: () => ({}),
|
||||
},
|
||||
schemaName: { type: String, required: true },
|
||||
canCreate: Boolean,
|
||||
},
|
||||
emits: ['openDoc', 'makeNewDoc', 'updatedData'],
|
||||
data() {
|
||||
return {
|
||||
data: [],
|
||||
data: [] as RenderData[],
|
||||
pageStart: 0,
|
||||
pageEnd: 0,
|
||||
};
|
||||
@ -136,7 +144,7 @@ export default defineComponent({
|
||||
let columns = this.listConfig?.columns ?? [];
|
||||
|
||||
if (columns.length === 0) {
|
||||
columns = fyo.schemaMap[this.schemaName].quickEditFields ?? [];
|
||||
columns = fyo.schemaMap[this.schemaName]?.quickEditFields ?? [];
|
||||
columns = [...new Set(['name', ...columns])];
|
||||
}
|
||||
|
||||
@ -152,12 +160,12 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
schemaName(oldValue, newValue) {
|
||||
async schemaName(oldValue, newValue) {
|
||||
if (oldValue === newValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateData();
|
||||
await this.updateData();
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
@ -166,7 +174,7 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
isNumeric,
|
||||
setPageIndices({ start, end }) {
|
||||
setPageIndices({ start, end }: { start: number; end: number }) {
|
||||
this.pageStart = start;
|
||||
this.pageEnd = end;
|
||||
},
|
||||
@ -175,11 +183,11 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
const listener = () => {
|
||||
this.updateData();
|
||||
const listener = async () => {
|
||||
await this.updateData();
|
||||
};
|
||||
|
||||
if (fyo.schemaMap[this.schemaName].isSubmittable) {
|
||||
if (fyo.schemaMap[this.schemaName]?.isSubmittable) {
|
||||
fyo.doc.observer.on(`submit:${this.schemaName}`, listener);
|
||||
fyo.doc.observer.on(`revert:${this.schemaName}`, listener);
|
||||
}
|
||||
@ -188,7 +196,7 @@ export default defineComponent({
|
||||
fyo.db.observer.on(`delete:${this.schemaName}`, listener);
|
||||
fyo.doc.observer.on(`rename:${this.schemaName}`, listener);
|
||||
},
|
||||
async updateData(filters) {
|
||||
async updateData(filters?: Record<string, unknown>) {
|
||||
if (!filters) {
|
||||
filters = { ...this.filters };
|
||||
}
|
||||
@ -201,13 +209,16 @@ export default defineComponent({
|
||||
orderBy.unshift('date');
|
||||
}
|
||||
|
||||
this.data = (
|
||||
await fyo.db.getAll(this.schemaName, {
|
||||
fields: ['*'],
|
||||
filters,
|
||||
orderBy,
|
||||
})
|
||||
).map((d) => ({ ...d, schema: fyo.schemaMap[this.schemaName] }));
|
||||
const tableData = await fyo.db.getAll(this.schemaName, {
|
||||
fields: ['*'],
|
||||
filters: filters as QueryFilter,
|
||||
orderBy,
|
||||
});
|
||||
|
||||
this.data = tableData.map((d) => ({
|
||||
...d,
|
||||
schema: fyo.schemaMap[this.schemaName],
|
||||
})) as RenderData[];
|
||||
this.$emit('updatedData', filters);
|
||||
},
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="flex items-center truncate" :class="cellClass">
|
||||
<span v-if="!customRenderer" class="truncate">{{ columnValue }}</span>
|
||||
<component :is="customRenderer" v-else />
|
||||
<component :is="(customRenderer as {})" v-else />
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
|
@ -28,9 +28,9 @@
|
||||
:filters="filters"
|
||||
:can-create="canCreate"
|
||||
class="flex-1 flex h-full"
|
||||
@openDoc="openDoc"
|
||||
@updatedData="updatedData"
|
||||
@makeNewDoc="makeNewDoc"
|
||||
@open-doc="openDoc"
|
||||
@updated-data="updatedData"
|
||||
@make-new-doc="makeNewDoc"
|
||||
/>
|
||||
<Modal :open-modal="openExportModal" @closemodal="openExportModal = false">
|
||||
<ExportWizard
|
||||
@ -73,7 +73,7 @@ export default defineComponent({
|
||||
},
|
||||
props: {
|
||||
schemaName: { type: String, required: true },
|
||||
filters: Object,
|
||||
filters: { type: Object, default: undefined },
|
||||
pageTitle: { type: String, default: '' },
|
||||
},
|
||||
setup() {
|
||||
@ -114,7 +114,7 @@ export default defineComponent({
|
||||
return fyo.schemaMap[this.schemaName]?.create !== false;
|
||||
},
|
||||
},
|
||||
async activated() {
|
||||
activated() {
|
||||
if (typeof this.filters === 'object') {
|
||||
this.filterDropdown?.setFilter(this.filters, true);
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ export default defineComponent({
|
||||
|
||||
this.templateList = list.map(({ name }) => name);
|
||||
},
|
||||
async savePDF() {
|
||||
savePDF() {
|
||||
const printContainer = this.$refs.printContainer as {
|
||||
savePDF: (name?: string) => void;
|
||||
};
|
||||
|
@ -205,11 +205,13 @@ export default defineComponent({
|
||||
const matrix: { value: string; idx: number }[][] = [columns];
|
||||
const start = Math.max(this.start - 1, 1);
|
||||
const end = Math.min(start + this.limit, this.report.reportData.length);
|
||||
for (const i in this.report.reportData.slice(start, end)) {
|
||||
const row = this.report.reportData[Number(i) + start];
|
||||
const slice = this.report.reportData.slice(start, end);
|
||||
|
||||
for (let i = 0; i < slice.length; i++) {
|
||||
const row = slice[i];
|
||||
|
||||
matrix.push([]);
|
||||
for (const j in row.cells) {
|
||||
for (let j = 0; j < row.cells.length; j++) {
|
||||
if (!this.columnSelection[j]) {
|
||||
continue;
|
||||
}
|
||||
|
@ -87,8 +87,6 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { t } from 'fyo';
|
||||
import { DocValue } from 'fyo/core/types';
|
||||
import { Field, Schema } from 'schemas/types';
|
||||
import Button from 'src/components/Button.vue';
|
||||
@ -104,7 +102,7 @@ import {
|
||||
focusOrSelectFormControl,
|
||||
} from 'src/utils/ui';
|
||||
import { useDocShortcuts } from 'src/utils/vueUtils';
|
||||
import { defineComponent, inject, ref } from 'vue';
|
||||
import { computed, defineComponent, inject, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'QuickEditForm',
|
||||
@ -191,6 +189,7 @@ export default defineComponent({
|
||||
activated() {
|
||||
this.setShortcuts();
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
async mounted() {
|
||||
await this.initialize();
|
||||
|
||||
@ -203,8 +202,8 @@ export default defineComponent({
|
||||
},
|
||||
methods: {
|
||||
setShortcuts() {
|
||||
this.shortcuts?.set(this.context, ['Escape'], () => {
|
||||
this.routeToPrevious();
|
||||
this.shortcuts?.set(this.context, ['Escape'], async () => {
|
||||
await this.routeToPrevious();
|
||||
});
|
||||
},
|
||||
async initialize() {
|
||||
|
@ -45,8 +45,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { t } from 'fyo';
|
||||
import { DocValue } from 'fyo/core/types';
|
||||
import { reports } from 'reports';
|
||||
import { Report } from 'reports/Report';
|
||||
import Button from 'src/components/Button.vue';
|
||||
@ -60,7 +60,7 @@ import { docsPathMap, getReport } from 'src/utils/misc';
|
||||
import { docsPathRef } from 'src/utils/refs';
|
||||
import { ActionGroup } from 'src/utils/types';
|
||||
import { routeTo } from 'src/utils/ui';
|
||||
import { PropType, defineComponent, inject } from 'vue';
|
||||
import { PropType, computed, defineComponent, inject } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -119,12 +119,13 @@ export default defineComponent({
|
||||
return Object.values(actionsMap);
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
async activated() {
|
||||
docsPathRef.value =
|
||||
docsPathMap[this.reportClassName] ?? docsPathMap.Reports!;
|
||||
await this.setReportData();
|
||||
|
||||
const filters = JSON.parse(this.defaultFilters);
|
||||
const filters = JSON.parse(this.defaultFilters) as Record<string, DocValue>;
|
||||
const filterKeys = Object.keys(filters);
|
||||
for (const key of filterKeys) {
|
||||
await this.report?.set(key, filters[key]);
|
||||
@ -139,8 +140,8 @@ export default defineComponent({
|
||||
window.rep = this;
|
||||
}
|
||||
|
||||
this.shortcuts?.pmod.set(this.reportClassName, ['KeyP'], () => {
|
||||
routeTo(`/report-print/${this.reportClassName}`);
|
||||
this.shortcuts?.pmod.set(this.reportClassName, ['KeyP'], async () => {
|
||||
await routeTo(`/report-print/${this.reportClassName}`);
|
||||
});
|
||||
},
|
||||
deactivated() {
|
||||
|
@ -176,12 +176,12 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
docsPathRef.value = docsPathMap.Settings ?? '';
|
||||
this.shortcuts?.pmod.set(COMPONENT_NAME, ['KeyS'], () => {
|
||||
this.shortcuts?.pmod.set(COMPONENT_NAME, ['KeyS'], async () => {
|
||||
if (!this.canSave) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.sync();
|
||||
await this.sync();
|
||||
});
|
||||
},
|
||||
async deactivated(): Promise<void> {
|
||||
@ -214,7 +214,7 @@ export default defineComponent({
|
||||
}
|
||||
|
||||
this.update();
|
||||
showDialog({
|
||||
await showDialog({
|
||||
title: this.t`Reload Frappe Books?`,
|
||||
detail: this.t`Changes made to settings will be visible on reload.`,
|
||||
type: 'info',
|
||||
@ -226,7 +226,7 @@ export default defineComponent({
|
||||
},
|
||||
{
|
||||
label: this.t`No`,
|
||||
action() {},
|
||||
action: () => null,
|
||||
isEscape: true,
|
||||
},
|
||||
],
|
||||
|
@ -97,7 +97,8 @@ export default defineComponent({
|
||||
return '';
|
||||
},
|
||||
},
|
||||
} as {} /** to silence :is type check */;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
} as {};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
@ -128,8 +129,8 @@ export default defineComponent({
|
||||
this.error = null;
|
||||
return compile(template, {
|
||||
hoistStatic: true,
|
||||
onWarn: this.onError,
|
||||
onError: this.onError,
|
||||
onWarn: this.onError.bind(this),
|
||||
onError: this.onError.bind(this),
|
||||
});
|
||||
},
|
||||
handleErrorCaptured(error: unknown) {
|
||||
@ -160,6 +161,8 @@ export default defineComponent({
|
||||
return generateCodeFrame(this.template, loc.start.offset, loc.end.offset);
|
||||
},
|
||||
async savePDF(name?: string) {
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* To be called through ref by the parent component.
|
||||
*/
|
||||
|
@ -29,8 +29,8 @@ export default defineComponent({
|
||||
computed: {
|
||||
innerContainerStyle(): Record<string, string> {
|
||||
const style: Record<string, string> = {};
|
||||
style['width'] = this.width + 'cm';
|
||||
style['height'] = this.height + 'cm';
|
||||
style['width'] = `${this.width}cm`;
|
||||
style['height'] = `${this.height}cm`;
|
||||
style['transform'] = `scale(${this.scale})`;
|
||||
style['margin-top'] = `calc(-1 * (${this.height}cm * ${
|
||||
1 - this.scale
|
||||
|
@ -55,6 +55,7 @@ type SizeName = typeof printSizes[number];
|
||||
export default defineComponent({
|
||||
components: { Float, FormHeader, Select, Button },
|
||||
props: { doc: { type: PrintTemplate, required: true } },
|
||||
emits: ['done'],
|
||||
data() {
|
||||
return { size: 'A4', width: 21, height: 29.7 };
|
||||
},
|
||||
@ -100,9 +101,9 @@ export default defineComponent({
|
||||
this.size = 'Custom';
|
||||
this[name] = v;
|
||||
},
|
||||
done() {
|
||||
this.doc.set('width', this.width);
|
||||
this.doc.set('height', this.height);
|
||||
async done() {
|
||||
await this.doc.set('width', this.width);
|
||||
await this.doc.set('height', this.height);
|
||||
this.$emit('done');
|
||||
},
|
||||
},
|
||||
|
@ -235,6 +235,7 @@ import { showDialog, showToast } from 'src/utils/interactive';
|
||||
import { getSavePath } from 'src/utils/ipcCalls';
|
||||
import { docsPathMap } from 'src/utils/misc';
|
||||
import {
|
||||
PrintTemplateHint,
|
||||
baseTemplate,
|
||||
getPrintTemplatePropHints,
|
||||
getPrintTemplatePropValues,
|
||||
@ -275,7 +276,7 @@ export default defineComponent({
|
||||
provide() {
|
||||
return { doc: computed(() => this.doc) };
|
||||
},
|
||||
props: { name: String },
|
||||
props: { name: { type: String, required: true } },
|
||||
setup() {
|
||||
const doc = ref(null) as DocRef<PrintTemplate>;
|
||||
const shortcuts = inject(shortcutsKey);
|
||||
@ -310,7 +311,7 @@ export default defineComponent({
|
||||
} as {
|
||||
editMode: boolean;
|
||||
showHints: boolean;
|
||||
hints?: Record<string, unknown>;
|
||||
hints?: PrintTemplateHint;
|
||||
values: null | PrintValues;
|
||||
displayDoc: PrintTemplate | null;
|
||||
showSizeModal: boolean;
|
||||
@ -377,14 +378,14 @@ export default defineComponent({
|
||||
actions.push({
|
||||
label: this.t`Select Template File`,
|
||||
group: this.t`Action`,
|
||||
action: this.selectFile,
|
||||
action: this.selectFile.bind(this),
|
||||
});
|
||||
}
|
||||
|
||||
actions.push({
|
||||
label: this.t`Save Template File`,
|
||||
group: this.t`Action`,
|
||||
action: this.saveFile,
|
||||
action: this.saveFile.bind(this),
|
||||
});
|
||||
|
||||
return actions;
|
||||
@ -464,9 +465,21 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
|
||||
this.shortcuts.ctrl.set(this.context, ['Enter'], this.setTemplate);
|
||||
this.shortcuts.ctrl.set(this.context, ['KeyE'], this.toggleEditMode);
|
||||
this.shortcuts.ctrl.set(this.context, ['KeyH'], this.toggleShowHints);
|
||||
this.shortcuts.ctrl.set(
|
||||
this.context,
|
||||
['Enter'],
|
||||
this.setTemplate.bind(this)
|
||||
);
|
||||
this.shortcuts.ctrl.set(
|
||||
this.context,
|
||||
['KeyE'],
|
||||
this.toggleEditMode.bind(this)
|
||||
);
|
||||
this.shortcuts.ctrl.set(
|
||||
this.context,
|
||||
['KeyH'],
|
||||
this.toggleShowHints.bind(this)
|
||||
);
|
||||
this.shortcuts.ctrl.set(this.context, ['Equal'], () =>
|
||||
this.setScale(this.scale + 0.1)
|
||||
);
|
||||
@ -523,7 +536,7 @@ export default defineComponent({
|
||||
toggleShowHints() {
|
||||
this.showHints = !this.showHints;
|
||||
},
|
||||
async toggleEditMode() {
|
||||
toggleEditMode() {
|
||||
if (!this.doc?.isCustom) {
|
||||
return;
|
||||
}
|
||||
@ -558,7 +571,7 @@ export default defineComponent({
|
||||
},
|
||||
getEditModeScale(): number {
|
||||
// @ts-ignore
|
||||
const div = this.$refs.printContainer.$el;
|
||||
const div = this.$refs.printContainer.$el as unknown;
|
||||
if (!(div instanceof HTMLDivElement)) {
|
||||
return this.scale;
|
||||
}
|
||||
@ -570,7 +583,7 @@ export default defineComponent({
|
||||
|
||||
return Number(targetScale.toFixed(2));
|
||||
},
|
||||
async savePDF() {
|
||||
savePDF() {
|
||||
const printContainer = this.$refs.printContainer as {
|
||||
savePDF: (name?: string) => void;
|
||||
};
|
||||
@ -695,14 +708,14 @@ export default defineComponent({
|
||||
const template = this.getTemplateEditorState();
|
||||
|
||||
if (!name) {
|
||||
return await showToast({
|
||||
return showToast({
|
||||
type: 'warning',
|
||||
message: this.t`Print Template Name not set`,
|
||||
});
|
||||
}
|
||||
|
||||
if (!template) {
|
||||
return await showToast({
|
||||
return showToast({
|
||||
type: 'warning',
|
||||
message: this.t`Print Template is empty`,
|
||||
});
|
||||
|
@ -63,10 +63,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { PrintTemplateHint } from 'src/utils/printTemplates';
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent } from 'vue';
|
||||
type HintRow = {
|
||||
key: string;
|
||||
value: string | Record<string, unknown>;
|
||||
value: PrintTemplateHint[string];
|
||||
isCollapsible: boolean;
|
||||
collapsed: boolean;
|
||||
};
|
||||
@ -74,7 +76,10 @@ export default defineComponent({
|
||||
name: 'TemplateBuilderHint',
|
||||
props: {
|
||||
prefix: { type: String, default: '' },
|
||||
hints: { type: Object, required: true },
|
||||
hints: {
|
||||
type: Object as PropType<PrintTemplateHint>,
|
||||
required: true,
|
||||
},
|
||||
level: { type: Number, default: 0 },
|
||||
},
|
||||
data() {
|
||||
|
@ -20,7 +20,7 @@ export default defineComponent({
|
||||
props: {
|
||||
initialValue: { type: String, required: true },
|
||||
disabled: { type: Boolean, default: false },
|
||||
hints: { type: Object },
|
||||
hints: { type: Object, default: undefined },
|
||||
},
|
||||
emits: ['input', 'blur'],
|
||||
data() {
|
||||
@ -76,7 +76,7 @@ export default defineComponent({
|
||||
const view = new EditorView({
|
||||
doc: this.initialValue,
|
||||
extensions: [
|
||||
EditorView.updateListener.of(this.updateListener),
|
||||
EditorView.updateListener.of(this.updateListener.bind(this)),
|
||||
readOnly.of(EditorState.readOnly.of(this.disabled)),
|
||||
editable.of(EditorView.editable.of(!this.disabled)),
|
||||
basicSetup,
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { t } from 'fyo';
|
||||
import { ModelNameEnum } from 'models/types';
|
||||
import { openSettings, routeTo } from './ui';
|
||||
import { GetStartedConfigItem } from './types';
|
||||
|
||||
export function getGetStartedConfig() {
|
||||
export function getGetStartedConfig(): GetStartedConfigItem[] {
|
||||
/* eslint-disable @typescript-eslint/no-misused-promises */
|
||||
return [
|
||||
{
|
||||
label: t`Organisation`,
|
||||
|
||||
items: [
|
||||
{
|
||||
key: 'General',
|
||||
@ -36,7 +37,6 @@ export function getGetStartedConfig() {
|
||||
},
|
||||
{
|
||||
label: t`Accounts`,
|
||||
|
||||
items: [
|
||||
{
|
||||
key: 'Review Accounts',
|
||||
@ -71,7 +71,6 @@ export function getGetStartedConfig() {
|
||||
},
|
||||
{
|
||||
label: t`Sales`,
|
||||
|
||||
items: [
|
||||
{
|
||||
key: 'Add Sales Items',
|
||||
@ -119,7 +118,6 @@ export function getGetStartedConfig() {
|
||||
},
|
||||
{
|
||||
label: t`Purchase`,
|
||||
|
||||
items: [
|
||||
{
|
||||
key: 'Add Purchase Items',
|
||||
|
@ -9,6 +9,9 @@ import { getSavePath, getTemplates, makePDF } from './ipcCalls';
|
||||
import { PrintValues } from './types';
|
||||
import { getDocFromNameIfExistsElseNew } from './ui';
|
||||
|
||||
export type PrintTemplateHint = {
|
||||
[key: string]: string | PrintTemplateHint | PrintTemplateHint[];
|
||||
};
|
||||
type PrintTemplateData = Record<string, unknown>;
|
||||
type TemplateUpdateItem = { name: string; template: string; type: string };
|
||||
|
||||
@ -62,11 +65,11 @@ export async function getPrintTemplatePropValues(
|
||||
}
|
||||
|
||||
export function getPrintTemplatePropHints(schemaName: string, fyo: Fyo) {
|
||||
const hints: PrintTemplateData = {};
|
||||
const hints: PrintTemplateHint = {};
|
||||
const schema = fyo.schemaMap[schemaName]!;
|
||||
hints.doc = getPrintTemplateDocHints(schema, fyo);
|
||||
(hints.doc as PrintTemplateData).entryType = fyo.t`Entry Type`;
|
||||
(hints.doc as PrintTemplateData).entryLabel = fyo.t`Entry Label`;
|
||||
hints.doc.entryType = fyo.t`Entry Type`;
|
||||
hints.doc.entryLabel = fyo.t`Entry Label`;
|
||||
|
||||
const printSettingsHints = getPrintTemplateDocHints(
|
||||
fyo.schemaMap[ModelNameEnum.PrintSettings]!,
|
||||
@ -119,10 +122,10 @@ function getPrintTemplateDocHints(
|
||||
fyo: Fyo,
|
||||
fieldnames?: string[],
|
||||
linkLevel?: number
|
||||
): PrintTemplateData {
|
||||
): PrintTemplateHint {
|
||||
linkLevel ??= 0;
|
||||
const hints: PrintTemplateData = {};
|
||||
const links: PrintTemplateData = {};
|
||||
const hints: PrintTemplateHint = {};
|
||||
const links: PrintTemplateHint = {};
|
||||
|
||||
let fields = schema.fields;
|
||||
if (fieldnames) {
|
||||
|
@ -118,3 +118,16 @@ export type DialogButton = {
|
||||
isPrimary?: boolean;
|
||||
isEscape?: boolean;
|
||||
};
|
||||
|
||||
export type GetStartedConfigItem = {
|
||||
label: string;
|
||||
items: {
|
||||
key: string;
|
||||
label: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
fieldname: string;
|
||||
documentation?: string;
|
||||
action?: () => void;
|
||||
}[];
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user