mirror of
https://github.com/frappe/books.git
synced 2025-02-02 12:08:27 +00:00
incr: fix a bunch of vue files
- no modes in the first pane
This commit is contained in:
parent
1bcd0f0afb
commit
a2cd1bac21
@ -348,7 +348,9 @@ export default class DatabaseCore extends DatabaseBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #removeColumns(schemaName: string, targetColumns: string[]) {
|
async #removeColumns(schemaName: string, targetColumns: string[]) {
|
||||||
// TODO: Implement this for sqlite
|
const fields = this.schemaMap[schemaName]?.fields.map((f) => f.fieldname);
|
||||||
|
const tableRows = await this.getAll(schemaName, { fields });
|
||||||
|
this.prestigeTheTable(schemaName, tableRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
#getError(err: Error) {
|
#getError(err: Error) {
|
||||||
|
@ -88,6 +88,8 @@ export class Converter {
|
|||||||
return toRawFloat(value, field);
|
return toRawFloat(value, field);
|
||||||
case FieldTypeEnum.Check:
|
case FieldTypeEnum.Check:
|
||||||
return toRawCheck(value, field);
|
return toRawCheck(value, field);
|
||||||
|
case FieldTypeEnum.Link:
|
||||||
|
return toRawLink(value, field);
|
||||||
default:
|
default:
|
||||||
return toRawString(value, field);
|
return toRawString(value, field);
|
||||||
}
|
}
|
||||||
@ -335,6 +337,18 @@ function toRawString(value: DocValue, field: Field): string | null {
|
|||||||
throwError(value, field, 'raw');
|
throwError(value, field, 'raw');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toRawLink(value: DocValue, field: Field): string | null {
|
||||||
|
if (value === null || !(value as string)?.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
throwError(value, field, 'raw');
|
||||||
|
}
|
||||||
|
|
||||||
function throwError<T>(value: T, field: Field, type: 'raw' | 'doc'): never {
|
function throwError<T>(value: T, field: Field, type: 'raw' | 'doc'): never {
|
||||||
throw new ValueError(
|
throw new ValueError(
|
||||||
`invalid ${type} conversion '${value}' of type ${typeof value} found, field: ${JSON.stringify(
|
`invalid ${type} conversion '${value}' of type ${typeof value} found, field: ${JSON.stringify(
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
ConflictError,
|
ConflictError,
|
||||||
MandatoryError,
|
MandatoryError,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
ValidationError,
|
ValidationError
|
||||||
} from 'fyo/utils/errors';
|
} from 'fyo/utils/errors';
|
||||||
import Observable from 'fyo/utils/observable';
|
import Observable from 'fyo/utils/observable';
|
||||||
import Money from 'pesa/dist/types/src/money';
|
import Money from 'pesa/dist/types/src/money';
|
||||||
@ -15,7 +15,7 @@ import {
|
|||||||
FieldTypeEnum,
|
FieldTypeEnum,
|
||||||
OptionField,
|
OptionField,
|
||||||
Schema,
|
Schema,
|
||||||
TargetField,
|
TargetField
|
||||||
} from 'schemas/types';
|
} from 'schemas/types';
|
||||||
import { getIsNullOrUndef, getMapFromList, getRandomString } from 'utils';
|
import { getIsNullOrUndef, getMapFromList, getRandomString } from 'utils';
|
||||||
import { markRaw } from 'vue';
|
import { markRaw } from 'vue';
|
||||||
@ -24,7 +24,7 @@ import {
|
|||||||
areDocValuesEqual,
|
areDocValuesEqual,
|
||||||
getMissingMandatoryMessage,
|
getMissingMandatoryMessage,
|
||||||
getPreDefaultValues,
|
getPreDefaultValues,
|
||||||
shouldApplyFormula,
|
shouldApplyFormula
|
||||||
} from './helpers';
|
} from './helpers';
|
||||||
import { setName } from './naming';
|
import { setName } from './naming';
|
||||||
import {
|
import {
|
||||||
@ -42,7 +42,7 @@ import {
|
|||||||
ReadOnlyMap,
|
ReadOnlyMap,
|
||||||
RequiredMap,
|
RequiredMap,
|
||||||
TreeViewSettings,
|
TreeViewSettings,
|
||||||
ValidationMap,
|
ValidationMap
|
||||||
} from './types';
|
} from './types';
|
||||||
import { validateOptions, validateRequired } from './validationFunction';
|
import { validateOptions, validateRequired } from './validationFunction';
|
||||||
|
|
||||||
@ -139,14 +139,16 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set value and trigger change
|
// set value and trigger change
|
||||||
async set(fieldname: string | DocValueMap, value?: DocValue | Doc[]) {
|
async set(
|
||||||
|
fieldname: string | DocValueMap,
|
||||||
|
value?: DocValue | Doc[]
|
||||||
|
): Promise<boolean> {
|
||||||
if (typeof fieldname === 'object') {
|
if (typeof fieldname === 'object') {
|
||||||
await this.setMultiple(fieldname as DocValueMap);
|
return await this.setMultiple(fieldname as DocValueMap);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._canSet(fieldname, value)) {
|
if (!this._canSet(fieldname, value)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setDirty(true);
|
this._setDirty(true);
|
||||||
@ -168,12 +170,19 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
} else {
|
} else {
|
||||||
await this._applyChange(fieldname);
|
await this._applyChange(fieldname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async setMultiple(docValueMap: DocValueMap) {
|
async setMultiple(docValueMap: DocValueMap): Promise<boolean> {
|
||||||
|
let hasSet = false;
|
||||||
for (const fieldname in docValueMap) {
|
for (const fieldname in docValueMap) {
|
||||||
await this.set(fieldname, docValueMap[fieldname] as DocValue | Doc[]);
|
hasSet ||= await this.set(
|
||||||
|
fieldname,
|
||||||
|
docValueMap[fieldname] as DocValue | Doc[]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
return hasSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
_canSet(fieldname: string, value?: DocValue | Doc[]): boolean {
|
_canSet(fieldname: string, value?: DocValue | Doc[]): boolean {
|
||||||
@ -197,12 +206,14 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
return !areDocValuesEqual(currentValue as DocValue, value as DocValue);
|
return !areDocValuesEqual(currentValue as DocValue, value as DocValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _applyChange(fieldname: string) {
|
async _applyChange(fieldname: string): Promise<boolean> {
|
||||||
await this._applyFormula(fieldname);
|
await this._applyFormula(fieldname);
|
||||||
await this.trigger('change', {
|
await this.trigger('change', {
|
||||||
doc: this,
|
doc: this,
|
||||||
changed: fieldname,
|
changed: fieldname,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setDefaults() {
|
_setDefaults() {
|
||||||
@ -232,13 +243,29 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
// push child row and trigger change
|
// push child row and trigger change
|
||||||
this.push(fieldname, docValueMap);
|
this.push(fieldname, docValueMap);
|
||||||
this._dirty = true;
|
this._dirty = true;
|
||||||
await this._applyChange(fieldname);
|
return await this._applyChange(fieldname);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove(fieldname: string, idx: number) {
|
||||||
|
let rows = this[fieldname] as Doc[] | undefined;
|
||||||
|
if (!Array.isArray(rows)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setDirty(true);
|
||||||
|
rows = rows.filter((row, i) => row.idx !== idx || i !== idx)!;
|
||||||
|
rows.forEach((row, i) => {
|
||||||
|
row.idx = i;
|
||||||
|
});
|
||||||
|
this[fieldname] = rows;
|
||||||
|
return await this._applyChange(fieldname);
|
||||||
}
|
}
|
||||||
|
|
||||||
push(fieldname: string, docValueMap: Doc | DocValueMap = {}) {
|
push(fieldname: string, docValueMap: Doc | DocValueMap = {}) {
|
||||||
// push child row without triggering change
|
// push child row without triggering change
|
||||||
this[fieldname] ??= [];
|
this[fieldname] ??= [];
|
||||||
const childDoc = this._getChildDoc(docValueMap, fieldname);
|
const childDoc = this._getChildDoc(docValueMap, fieldname);
|
||||||
|
childDoc.parentdoc = this;
|
||||||
(this[fieldname] as Doc[]).push(childDoc);
|
(this[fieldname] as Doc[]).push(childDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -389,6 +416,7 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
throw new NotFoundError(`Not Found: ${this.schemaName} ${this.name}`);
|
throw new NotFoundError(`Not Found: ${this.schemaName} ${this.name}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._setDirty(false);
|
||||||
this._notInserted = false;
|
this._notInserted = false;
|
||||||
this.fyo.doc.observer.trigger(`load:${this.schemaName}`, this.name);
|
this.fyo.doc.observer.trigger(`load:${this.schemaName}`, this.name);
|
||||||
}
|
}
|
||||||
@ -744,9 +772,7 @@ export class Doc extends Observable<DocValue | Doc[]> {
|
|||||||
updateMap.name = updateMap.name + ' CPY';
|
updateMap.name = updateMap.name + ' CPY';
|
||||||
}
|
}
|
||||||
|
|
||||||
const doc = this.fyo.doc.getNewDoc(this.schemaName, {}, false);
|
const doc = this.fyo.doc.getNewDoc(this.schemaName, updateMap, false);
|
||||||
await doc.setMultiple(updateMap);
|
|
||||||
|
|
||||||
if (shouldSync) {
|
if (shouldSync) {
|
||||||
await doc.sync();
|
await doc.sync();
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ export function getDeviceId(fyo: Fyo): UniqueId {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getInstanceId(fyo: Fyo): UniqueId {
|
export function getInstanceId(fyo: Fyo): UniqueId {
|
||||||
const files = fyo.config.get(ConfigKeys.Files) as ConfigFile[];
|
const files = (fyo.config.get(ConfigKeys.Files) ?? []) as ConfigFile[];
|
||||||
|
|
||||||
const companyName = fyo.singles.AccountingSettings?.companyName as string;
|
const companyName = fyo.singles.AccountingSettings?.companyName as string;
|
||||||
if (companyName === undefined) {
|
if (companyName === undefined) {
|
||||||
|
@ -129,7 +129,7 @@ function getNumberFormatter(fyo: Fyo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCurrency(field: Field, doc: Doc | null, fyo: Fyo): string {
|
function getCurrency(field: Field, doc: Doc | null, fyo: Fyo): string {
|
||||||
let getCurrency = doc?.getCurrencies[field.fieldname];
|
let getCurrency = doc?.getCurrencies?.[field.fieldname];
|
||||||
if (getCurrency !== undefined) {
|
if (getCurrency !== undefined) {
|
||||||
return getCurrency();
|
return getCurrency();
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ export class Party extends Doc {
|
|||||||
},
|
},
|
||||||
currency: async () =>
|
currency: async () =>
|
||||||
this.fyo.singles.AccountingSettings!.currency as string,
|
this.fyo.singles.AccountingSettings!.currency as string,
|
||||||
addressDisplay: async () => {
|
address: async () => {
|
||||||
const address = this.address as string | undefined;
|
const address = this.address as string | undefined;
|
||||||
if (address) {
|
if (address) {
|
||||||
return this.getFrom('Address', address, 'addressDisplay') as string;
|
return this.getFrom('Address', address, 'addressDisplay') as string;
|
||||||
|
@ -1 +1,6 @@
|
|||||||
export type PartyRole = 'Both' | 'Supplier' | 'Customer';
|
export type PartyRole = 'Both' | 'Supplier' | 'Customer';
|
||||||
|
export enum PartyRoleEnum {
|
||||||
|
'Both' = 'Both',
|
||||||
|
'Supplier' = 'Supplier',
|
||||||
|
'Customer' = 'Customer',
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
|
|
||||||
import { Fyo } from 'fyo';
|
import { Fyo } from 'fyo';
|
||||||
import { Action, ListViewSettings } from 'fyo/model/types';
|
import { Action, ListViewSettings } from 'fyo/model/types';
|
||||||
|
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
|
||||||
import {
|
import {
|
||||||
getTransactionActions,
|
getTransactionActions,
|
||||||
getTransactionStatusColumn,
|
getTransactionStatusColumn,
|
||||||
@ -40,13 +40,13 @@ export class PurchaseInvoice extends Invoice {
|
|||||||
return getTransactionActions('PurchaseInvoice', fyo);
|
return getTransactionActions('PurchaseInvoice', fyo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getListViewSettings(fyo: Fyo): ListViewSettings {
|
static getListViewSettings(): ListViewSettings {
|
||||||
return {
|
return {
|
||||||
formRoute: (name) => `/edit/PurchaseInvoice/${name}`,
|
formRoute: (name) => `/edit/PurchaseInvoice/${name}`,
|
||||||
columns: [
|
columns: [
|
||||||
'party',
|
'party',
|
||||||
'name',
|
'name',
|
||||||
getTransactionStatusColumn(fyo),
|
getTransactionStatusColumn(),
|
||||||
'date',
|
'date',
|
||||||
'grandTotal',
|
'grandTotal',
|
||||||
'outstandingAmount',
|
'outstandingAmount',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
|
|
||||||
import { Fyo } from 'fyo';
|
import { Fyo } from 'fyo';
|
||||||
import { Action, ListViewSettings } from 'fyo/model/types';
|
import { Action, ListViewSettings } from 'fyo/model/types';
|
||||||
|
import { LedgerPosting } from 'models/ledgerPosting/ledgerPosting';
|
||||||
import {
|
import {
|
||||||
getTransactionActions,
|
getTransactionActions,
|
||||||
getTransactionStatusColumn,
|
getTransactionStatusColumn,
|
||||||
@ -38,13 +38,13 @@ export class SalesInvoice extends Invoice {
|
|||||||
return getTransactionActions('SalesInvoice', fyo);
|
return getTransactionActions('SalesInvoice', fyo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getListViewSettings(fyo: Fyo): ListViewSettings {
|
static getListViewSettings(): ListViewSettings {
|
||||||
return {
|
return {
|
||||||
formRoute: (name) => `/edit/SalesInvoice/${name}`,
|
formRoute: (name) => `/edit/SalesInvoice/${name}`,
|
||||||
columns: [
|
columns: [
|
||||||
'party',
|
'party',
|
||||||
'name',
|
'name',
|
||||||
getTransactionStatusColumn(fyo),
|
getTransactionStatusColumn(),
|
||||||
'date',
|
'date',
|
||||||
'grandTotal',
|
'grandTotal',
|
||||||
'outstandingAmount',
|
'outstandingAmount',
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Fyo } from 'fyo';
|
import { Fyo, t } from 'fyo';
|
||||||
import { Doc } from 'fyo/model/doc';
|
import { Doc } from 'fyo/model/doc';
|
||||||
import { Action, ColumnConfig } from 'fyo/model/types';
|
import { Action, ColumnConfig } from 'fyo/model/types';
|
||||||
import { NotFoundError } from 'fyo/utils/errors';
|
import { NotFoundError } from 'fyo/utils/errors';
|
||||||
@ -75,16 +75,16 @@ export function getTransactionActions(schemaName: string, fyo: Fyo): Action[] {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTransactionStatusColumn(fyo: Fyo): ColumnConfig {
|
export function getTransactionStatusColumn(): ColumnConfig {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
Unpaid: fyo.t`Unpaid`,
|
Unpaid: t`Unpaid`,
|
||||||
Paid: fyo.t`Paid`,
|
Paid: t`Paid`,
|
||||||
Draft: fyo.t`Draft`,
|
Draft: t`Draft`,
|
||||||
Cancelled: fyo.t`Cancelled`,
|
Cancelled: t`Cancelled`,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
label: fyo.t`Status`,
|
label: t`Status`,
|
||||||
fieldname: 'status',
|
fieldname: 'status',
|
||||||
fieldtype: 'Select',
|
fieldtype: 'Select',
|
||||||
render(doc: Doc) {
|
render(doc: Doc) {
|
||||||
|
@ -79,6 +79,13 @@
|
|||||||
"fieldtype": "Data"
|
"fieldtype": "Data"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quickEditFields": ["email", "role", "phone", "address", "defaultAccount", "currency", "taxId"],
|
"quickEditFields": [
|
||||||
|
"email",
|
||||||
|
"phone",
|
||||||
|
"address",
|
||||||
|
"defaultAccount",
|
||||||
|
"currency",
|
||||||
|
"taxId"
|
||||||
|
],
|
||||||
"keywordFields": ["name"]
|
"keywordFields": ["name"]
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ export default {
|
|||||||
inputClass: {
|
inputClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default:
|
default:
|
||||||
'bg-gray-100 active:bg-gray-200 focus:bg-gray-200 px-3 py-2 text-base',
|
'px-3 py-2 text-base',
|
||||||
},
|
},
|
||||||
dontReload: {
|
dontReload: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -21,7 +21,7 @@ export default {
|
|||||||
const filters = await this.getFilters(keyword);
|
const filters = await this.getFilters(keyword);
|
||||||
|
|
||||||
if (keyword && !filters.keywords) {
|
if (keyword && !filters.keywords) {
|
||||||
filters.keywords = ['like', keyword];
|
filters[schema.titleField] = ['like', keyword];
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
|
@ -3,8 +3,10 @@
|
|||||||
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
<div class="text-gray-600 text-sm mb-1" v-if="showLabel">
|
||||||
{{ df.label }}
|
{{ df.label }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Title Row -->
|
||||||
<Row :ratio="ratio" class="border-b px-2 text-gray-600 w-full">
|
<Row :ratio="ratio" class="border-b px-2 text-gray-600 w-full">
|
||||||
<div class="flex items-center pl-2">No</div>
|
<div class="flex items-center pl-2">#</div>
|
||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'px-2 py-3': size === 'small',
|
'px-2 py-3': size === 'small',
|
||||||
@ -17,6 +19,8 @@
|
|||||||
{{ df.label }}
|
{{ df.label }}
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
<!-- Data Rows -->
|
||||||
<div class="overflow-auto" :style="{ 'max-height': rowContainerHeight }">
|
<div class="overflow-auto" :style="{ 'max-height': rowContainerHeight }">
|
||||||
<TableRow
|
<TableRow
|
||||||
:class="{ 'pointer-events-none': isReadOnly }"
|
:class="{ 'pointer-events-none': isReadOnly }"
|
||||||
@ -27,6 +31,8 @@
|
|||||||
@remove="removeRow(row)"
|
@remove="removeRow(row)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Add Row and Row Count -->
|
||||||
<Row
|
<Row
|
||||||
:ratio="ratio"
|
:ratio="ratio"
|
||||||
class="text-gray-500 cursor-pointer border-transparent px-2 w-full"
|
class="text-gray-500 cursor-pointer border-transparent px-2 w-full"
|
||||||
@ -54,7 +60,7 @@
|
|||||||
}"
|
}"
|
||||||
v-if="maxRowsBeforeOverflow && value.length > maxRowsBeforeOverflow"
|
v-if="maxRowsBeforeOverflow && value.length > maxRowsBeforeOverflow"
|
||||||
>
|
>
|
||||||
{{ value.length }} rows
|
{{ t`${value.length} rows` }}
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
@ -71,9 +77,11 @@ export default {
|
|||||||
extends: Base,
|
extends: Base,
|
||||||
props: {
|
props: {
|
||||||
showHeader: {
|
showHeader: {
|
||||||
|
type: Boolean,
|
||||||
default: true,
|
default: true,
|
||||||
},
|
},
|
||||||
maxRowsBeforeOverflow: {
|
maxRowsBeforeOverflow: {
|
||||||
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -81,6 +89,7 @@ export default {
|
|||||||
Row,
|
Row,
|
||||||
TableRow,
|
TableRow,
|
||||||
},
|
},
|
||||||
|
inject: ['doc'],
|
||||||
data: () => ({ rowContainerHeight: null }),
|
data: () => ({ rowContainerHeight: null }),
|
||||||
watch: {
|
watch: {
|
||||||
value: {
|
value: {
|
||||||
@ -101,19 +110,28 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
focus() {},
|
focus() {},
|
||||||
addRow() {
|
addRow() {
|
||||||
let rows = this.value || [];
|
this.doc.append(this.df.fieldname, {}).then((s) => {
|
||||||
this.triggerChange([...rows, {}]);
|
if (!s) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.scrollToRow(this.value.length - 1);
|
this.scrollToRow(this.value.length - 1);
|
||||||
});
|
});
|
||||||
|
this.triggerChange(this.value);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
removeRow(row) {
|
removeRow(row) {
|
||||||
let rows = this.value || [];
|
this.doc.remove(this.df.fieldname, row.idx).then((s) => {
|
||||||
rows = rows.filter((_row) => _row !== row);
|
if (!s) {
|
||||||
this.triggerChange(rows);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.triggerChange(this.value);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
scrollToRow(index) {
|
scrollToRow(index) {
|
||||||
let row = this.$refs['table-row'][index];
|
const row = this.$refs['table-row'][index];
|
||||||
row && row.$el.scrollIntoView({ block: 'nearest' });
|
row && row.$el.scrollIntoView({ block: 'nearest' });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<Row :ratio="ratio" class="w-full px-2 border-b hover:bg-brand-100 group">
|
<Row :ratio="ratio" class="w-full px-2 border-b hover:bg-brand-100 group">
|
||||||
|
<!-- Index or Remove button -->
|
||||||
<div class="flex items-center pl-2 text-gray-600">
|
<div class="flex items-center pl-2 text-gray-600">
|
||||||
<span class="hidden group-hover:inline-block">
|
<span class="hidden group-hover:inline-block">
|
||||||
<feather-icon
|
<feather-icon
|
||||||
@ -12,6 +13,8 @@
|
|||||||
{{ row.idx + 1 }}
|
{{ row.idx + 1 }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Data Input Form Control -->
|
||||||
<FormControl
|
<FormControl
|
||||||
:size="size"
|
:size="size"
|
||||||
class="py-2"
|
class="py-2"
|
||||||
@ -23,6 +26,8 @@
|
|||||||
@change="(value) => onChange(df, value)"
|
@change="(value) => onChange(df, value)"
|
||||||
@new-doc="(doc) => row.set(df.fieldname, doc.name)"
|
@new-doc="(doc) => row.set(df.fieldname, doc.name)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Error Display -->
|
||||||
<div
|
<div
|
||||||
class="text-sm text-red-600 mb-2 pl-2 col-span-full"
|
class="text-sm text-red-600 mb-2 pl-2 col-span-full"
|
||||||
v-if="Object.values(errors).length"
|
v-if="Object.values(errors).length"
|
||||||
@ -32,13 +37,20 @@
|
|||||||
</Row>
|
</Row>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { Doc } from 'fyo/model/doc';
|
||||||
import Row from 'src/components/Row.vue';
|
import Row from 'src/components/Row.vue';
|
||||||
import { getErrorMessage } from 'src/utils';
|
import { getErrorMessage } from 'src/utils';
|
||||||
import FormControl from './FormControl.vue';
|
import FormControl from './FormControl.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TableRow',
|
name: 'TableRow',
|
||||||
props: ['row', 'tableFields', 'size', 'ratio', 'isNumeric'],
|
props: {
|
||||||
|
row: Doc,
|
||||||
|
tableFields: Array,
|
||||||
|
size: String,
|
||||||
|
ratio: Array,
|
||||||
|
isNumeric: Function,
|
||||||
|
},
|
||||||
emits: ['remove'],
|
emits: ['remove'],
|
||||||
components: {
|
components: {
|
||||||
Row,
|
Row,
|
||||||
@ -50,7 +62,7 @@ export default {
|
|||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
doctype: this.row.doctype,
|
schemaName: this.row.schemaName,
|
||||||
name: this.row.name,
|
name: this.row.name,
|
||||||
doc: this.row,
|
doc: this.row,
|
||||||
};
|
};
|
||||||
@ -62,11 +74,6 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.errors[df.fieldname] = null;
|
this.errors[df.fieldname] = null;
|
||||||
const oldValue = this.row.get(df.fieldname);
|
|
||||||
if (oldValue === value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.row.set(df.fieldname, value).catch((e) => {
|
this.row.set(df.fieldname, value).catch((e) => {
|
||||||
this.errors[df.fieldname] = getErrorMessage(e, this.row);
|
this.errors[df.fieldname] = getErrorMessage(e, this.row);
|
||||||
});
|
});
|
||||||
|
@ -117,6 +117,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
inlineEditDoc: null,
|
inlineEditDoc: null,
|
||||||
inlineEditField: null,
|
inlineEditField: null,
|
||||||
|
formFields: [],
|
||||||
errors: {},
|
errors: {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -133,8 +134,9 @@ export default {
|
|||||||
TwoColumnForm: () => TwoColumnForm,
|
TwoColumnForm: () => TwoColumnForm,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.setFormFields();
|
||||||
if (this.focusFirstInput) {
|
if (this.focusFirstInput) {
|
||||||
this.$refs['controls'][0].focus();
|
this.$refs['controls']?.[0].focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fyo.store.isDevelopment) {
|
if (fyo.store.isDevelopment) {
|
||||||
@ -176,28 +178,34 @@ export default {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldValue = this.doc.get(df.fieldname);
|
|
||||||
this.errors[df.fieldname] = null;
|
|
||||||
if (oldValue === value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.emitChange) {
|
|
||||||
this.$emit('change', df, value, oldValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle rename
|
// handle rename
|
||||||
if (this.autosave && df.fieldname === 'name' && !this.doc.notInserted) {
|
if (this.autosave && df.fieldname === 'name' && !this.doc.notInserted) {
|
||||||
return this.doc.rename(value);
|
return this.doc.rename(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onChangeCommon(df, value);
|
const oldValue = this.doc.get(df.fieldname);
|
||||||
|
this.errors[df.fieldname] = null;
|
||||||
|
this.onChangeCommon(df, value, oldValue);
|
||||||
},
|
},
|
||||||
onChangeCommon(df, value) {
|
onChangeCommon(df, value, oldValue) {
|
||||||
this.doc.set(df.fieldname, value).catch((e) => {
|
this.doc
|
||||||
// set error message for this field
|
.set(df.fieldname, value)
|
||||||
|
.catch((e) => {
|
||||||
this.errors[df.fieldname] = getErrorMessage(e, this.doc);
|
this.errors[df.fieldname] = getErrorMessage(e, this.doc);
|
||||||
|
})
|
||||||
|
.then((success) => {
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handlePostSet(df, value, oldValue);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
handlePostSet(df, value, oldValue) {
|
||||||
|
this.setFormFields();
|
||||||
|
if (this.emitChange) {
|
||||||
|
this.$emit('change', df, value, oldValue);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.autosave && this.doc.dirty) {
|
if (this.autosave && this.doc.dirty) {
|
||||||
if (df.fieldtype === 'Table') {
|
if (df.fieldtype === 'Table') {
|
||||||
@ -250,15 +258,14 @@ export default {
|
|||||||
await this.stopInlineEditing();
|
await this.stopInlineEditing();
|
||||||
},
|
},
|
||||||
async stopInlineEditing() {
|
async stopInlineEditing() {
|
||||||
if (this.inlineEditDoc?.dirty) {
|
if (this.inlineEditDoc?.dirty && !this.inlineEditDoc?.notInserted) {
|
||||||
await this.inlineEditDoc.load();
|
await this.inlineEditDoc.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inlineEditDoc = null;
|
this.inlineEditDoc = null;
|
||||||
this.inlineEditField = null;
|
this.inlineEditField = null;
|
||||||
},
|
},
|
||||||
},
|
setFormFields() {
|
||||||
computed: {
|
|
||||||
formFields() {
|
|
||||||
let fieldList = this.fields;
|
let fieldList = this.fields;
|
||||||
|
|
||||||
if (fieldList.length === 0) {
|
if (fieldList.length === 0) {
|
||||||
@ -269,10 +276,12 @@ export default {
|
|||||||
fieldList = this.doc.schema.fields.filter((f) => f.required);
|
fieldList = this.doc.schema.fields.filter((f) => f.required);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fieldList.filter(
|
this.formFields = fieldList.filter(
|
||||||
(field) => field && !evaluateHidden(field, this.doc)
|
(field) => field && !evaluateHidden(field, this.doc)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
style() {
|
style() {
|
||||||
let templateColumns = (this.columnRatio || [1, 1])
|
let templateColumns = (this.columnRatio || [1, 1])
|
||||||
.map((r) => `${r}fr`)
|
.map((r) => `${r}fr`)
|
||||||
|
@ -20,16 +20,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span>
|
<span>
|
||||||
{{ fyo.format(invoice.date, invoiceMeta.getField('date')) }}
|
{{ fyo.format(invoice.date, getInvoiceField(invoice, 'date')) }}
|
||||||
</span>
|
</span>
|
||||||
<div>
|
<div>
|
||||||
<span
|
<span class="font-medium text-gray-900">
|
||||||
class="font-medium text-gray-900"
|
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
fyo.format(
|
fyo.format(
|
||||||
amountPaid(invoice),
|
amountPaid(invoice),
|
||||||
invoiceMeta.getField('baseGrandTotal')
|
getInvoiceField(invoice, 'baseGrandTotal')
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
@ -37,7 +35,7 @@
|
|||||||
({{
|
({{
|
||||||
fyo.format(
|
fyo.format(
|
||||||
invoice.outstandingAmount,
|
invoice.outstandingAmount,
|
||||||
invoiceMeta.getField('outstandingAmount')
|
getInvoiceField(invoice, 'outstandingAmount')
|
||||||
)
|
)
|
||||||
}})
|
}})
|
||||||
</span>
|
</span>
|
||||||
@ -49,37 +47,45 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { Doc } from 'fyo/model/doc';
|
||||||
|
import { PartyRoleEnum } from 'models/baseModels/Party/types';
|
||||||
|
import { getTransactionStatusColumn } from 'models/helpers';
|
||||||
|
import { ModelNameEnum } from 'models/types';
|
||||||
import { fyo } from 'src/initFyo';
|
import { fyo } from 'src/initFyo';
|
||||||
import { routeTo } from 'src/utils';
|
import { routeTo } from 'src/utils';
|
||||||
// import { getStatusColumn } from '../Transaction/Transaction';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PartyWidget',
|
name: 'PartyWidget',
|
||||||
props: ['doc'],
|
props: { doc: Doc },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pendingInvoices: [],
|
pendingInvoices: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
invoiceDoctype() {
|
invoiceSchemaNames() {
|
||||||
let isCustomer = this.doc.doctype === 'Customer';
|
switch (this.doc.get('role')) {
|
||||||
return isCustomer ? 'SalesInvoice' : 'PurchaseInvoice';
|
case PartyRoleEnum.Customer:
|
||||||
},
|
return [ModelNameEnum.SalesInvoice];
|
||||||
invoiceMeta() {
|
case PartyRoleEnum.Supplier:
|
||||||
return fyo.getMeta(this.invoiceDoctype);
|
return [ModelNameEnum.PurchaseInvoice];
|
||||||
|
case PartyRoleEnum.Both:
|
||||||
|
default:
|
||||||
|
return [ModelNameEnum.SalesInvoice, ModelNameEnum.PurchaseInvoice];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.fetchPendingInvoices();
|
this.fetchPendingInvoices();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getInvoiceField(invoice, fieldname) {
|
||||||
|
return fyo.getField(invoice.schemaName, fieldname);
|
||||||
|
},
|
||||||
async fetchPendingInvoices() {
|
async fetchPendingInvoices() {
|
||||||
let isCustomer = this.doc.doctype === 'Customer';
|
const pendingInvoices = [];
|
||||||
let doctype = this.invoiceDoctype;
|
for (const schemaName of this.invoiceSchemaNames) {
|
||||||
let partyField = isCustomer ? 'customer' : 'supplier';
|
const invoices = await fyo.db.getAll(schemaName, {
|
||||||
this.pendingInvoices = await fyo.db.getAll({
|
|
||||||
doctype,
|
|
||||||
fields: [
|
fields: [
|
||||||
'name',
|
'name',
|
||||||
'date',
|
'date',
|
||||||
@ -88,20 +94,27 @@ export default {
|
|||||||
'submitted',
|
'submitted',
|
||||||
],
|
],
|
||||||
filters: {
|
filters: {
|
||||||
[partyField]: this.doc.name,
|
party: this.doc.name,
|
||||||
},
|
},
|
||||||
limit: 3,
|
limit: 3,
|
||||||
orderBy: 'created',
|
orderBy: 'created',
|
||||||
});
|
});
|
||||||
window.pendingInvoices = this.pendingInvoices;
|
|
||||||
|
invoices.forEach((i) => {
|
||||||
|
i.schemaName = schemaName;
|
||||||
|
});
|
||||||
|
|
||||||
|
pendingInvoices.push(...invoices);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.pendingInvoices = pendingInvoices;
|
||||||
},
|
},
|
||||||
getStatusBadge(doc) {
|
getStatusBadge(doc) {
|
||||||
// let statusColumn = getStatusColumn();
|
const statusColumn = getTransactionStatusColumn();
|
||||||
// return statusColumn.render(doc);
|
return statusColumn.render(doc);
|
||||||
return {}
|
|
||||||
},
|
},
|
||||||
routeToForm(doc) {
|
routeToForm(invoice) {
|
||||||
routeTo(`/edit/${this.invoiceDoctype}/${doc.name}`);
|
routeTo(`/edit/${invoice.schemaName}/${invoice.name}`);
|
||||||
},
|
},
|
||||||
fullyPaid(invoice) {
|
fullyPaid(invoice) {
|
||||||
return invoice.outstandingAmount.isZero();
|
return invoice.outstandingAmount.isZero();
|
||||||
|
@ -10,147 +10,121 @@
|
|||||||
class="w-full w-600 shadow rounded-lg border relative"
|
class="w-full w-600 shadow rounded-lg border relative"
|
||||||
style="height: 700px"
|
style="height: 700px"
|
||||||
>
|
>
|
||||||
<div class="px-6 py-8">
|
<!-- Welcome to Frappe Books -->
|
||||||
<h1 class="text-2xl font-semibold">
|
<div class="px-6 py-10">
|
||||||
|
<h1 class="text-2xl font-semibold select-none">
|
||||||
{{ t`Welcome to Frappe Books` }}
|
{{ t`Welcome to Frappe Books` }}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="text-gray-600 text-base" v-if="!showFiles">
|
<p class="text-gray-600 text-base select-none">
|
||||||
{{
|
{{
|
||||||
t`Create a new file or select an existing one from your computer`
|
t`Create a new file or select an existing one from your computer`
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-gray-600 text-base" v-if="showFiles">
|
|
||||||
{{ t`Select a file to load the company transactions` }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="px-12 mt-6 window-no-drag" v-if="!showFiles">
|
|
||||||
<div class="flex">
|
<hr />
|
||||||
|
|
||||||
|
<!-- New File (Blue Icon) -->
|
||||||
<div
|
<div
|
||||||
@click="newDatabase"
|
@click="newDatabase"
|
||||||
class="
|
class="
|
||||||
w-1/2
|
px-6
|
||||||
border
|
h-18
|
||||||
rounded-xl
|
flex flex-row
|
||||||
flex flex-col
|
|
||||||
items-center
|
items-center
|
||||||
py-8
|
|
||||||
px-5
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
hover:shadow
|
gap-4
|
||||||
|
p-2
|
||||||
|
hover:bg-gray-100
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div class="w-8 h-8 rounded-full bg-blue-500 relative flex-center">
|
||||||
class="w-14 h-14 rounded-full bg-blue-200 relative flex-center"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="w-12 h-12 absolute rounded-full bg-blue-500 flex-center"
|
|
||||||
>
|
|
||||||
<feather-icon name="plus" class="text-white w-5 h-5" />
|
<feather-icon name="plus" class="text-white w-5 h-5" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="mt-5 font-medium">
|
<div>
|
||||||
<template
|
<p class="font-medium">
|
||||||
v-if="loadingDatabase && fileSelectedFrom === 'New File'"
|
|
||||||
>
|
|
||||||
{{ t`Loading...` }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ t`New File` }}
|
{{ t`New File` }}
|
||||||
</template>
|
</p>
|
||||||
</div>
|
<p class="text-sm text-gray-600">
|
||||||
<div class="mt-2 text-sm text-gray-600 text-center">
|
|
||||||
{{ t`Create a new file and store it in your computer.` }}
|
{{ t`Create a new file and store it in your computer.` }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Existing File (Green Icon) -->
|
||||||
<div
|
<div
|
||||||
@click="existingDatabase"
|
@click="existingDatabase"
|
||||||
class="
|
class="
|
||||||
ml-6
|
px-6
|
||||||
w-1/2
|
h-18
|
||||||
border
|
flex flex-row
|
||||||
rounded-xl
|
|
||||||
flex flex-col
|
|
||||||
items-center
|
items-center
|
||||||
py-8
|
|
||||||
px-5
|
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
hover:shadow
|
gap-4
|
||||||
|
p-2
|
||||||
|
hover:bg-gray-100
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<div class="w-8 h-8 rounded-full bg-green-500 relative flex-center">
|
||||||
class="w-14 h-14 rounded-full bg-green-200 relative flex-center"
|
|
||||||
>
|
|
||||||
<div class="w-12 h-12 rounded-full bg-green-500 flex-center">
|
|
||||||
<feather-icon name="upload" class="w-4 h-4 text-white" />
|
<feather-icon name="upload" class="w-4 h-4 text-white" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div class="mt-5 font-medium">
|
<p class="font-medium">
|
||||||
<template
|
|
||||||
v-if="loadingDatabase && fileSelectedFrom === 'Existing File'"
|
|
||||||
>
|
|
||||||
{{ t`Loading...` }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ t`Existing File` }}
|
{{ t`Existing File` }}
|
||||||
</template>
|
</p>
|
||||||
</div>
|
<p class="text-sm text-gray-600">
|
||||||
<div class="mt-2 text-sm text-gray-600 text-center">
|
|
||||||
{{ t`Load an existing .db file from your computer.` }}
|
{{ t`Load an existing .db file from your computer.` }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<hr />
|
||||||
<a
|
|
||||||
v-if="files.length > 0"
|
|
||||||
class="text-brand text-sm mt-4 inline-block cursor-pointer"
|
|
||||||
@click="showFiles = true"
|
|
||||||
>
|
|
||||||
{{ t`Select from existing files` }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="showFiles">
|
<!-- File List -->
|
||||||
<div class="px-12 mt-6">
|
<div class="overflow-scroll" style="max-height: 340px">
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
py-2
|
h-18
|
||||||
px-4
|
px-6
|
||||||
text-sm
|
|
||||||
flex
|
flex
|
||||||
justify-between
|
gap-4
|
||||||
items-center
|
items-center
|
||||||
hover:bg-gray-100
|
hover:bg-gray-100
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
border-b
|
|
||||||
"
|
"
|
||||||
:class="{ 'border-t': i === 0 }"
|
|
||||||
v-for="(file, i) in files"
|
v-for="(file, i) in files"
|
||||||
:key="file.filePath"
|
:key="file.dbPath"
|
||||||
@click="selectFile(file)"
|
@click="selectFile(file)"
|
||||||
>
|
>
|
||||||
<div class="flex items-baseline">
|
<div
|
||||||
<span>
|
class="
|
||||||
<template v-if="loadingDatabase && fileSelectedFrom === file">
|
w-8
|
||||||
{{ t`Loading...` }}
|
h-8
|
||||||
</template>
|
rounded-full
|
||||||
<template v-else>
|
flex
|
||||||
{{ file.companyName }}
|
justify-center
|
||||||
</template>
|
items-center
|
||||||
</span>
|
bg-gray-200
|
||||||
</div>
|
text-gray-500
|
||||||
<div class="text-gray-700">
|
font-semibold
|
||||||
{{ file.modified }}
|
text-base
|
||||||
</div>
|
"
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="px-12 mt-4">
|
|
||||||
<a
|
|
||||||
class="text-brand text-sm cursor-pointer"
|
|
||||||
@click="showFiles = false"
|
|
||||||
>
|
>
|
||||||
{{ t`Select file manually` }}
|
{{ i + 1 }}
|
||||||
</a>
|
</div>
|
||||||
|
<div>
|
||||||
|
<p class="font-medium">
|
||||||
|
{{ file.companyName }}
|
||||||
|
</p>
|
||||||
|
<p class="text-sm text-gray-600">
|
||||||
|
{{ file.modified }}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr v-if="files?.length" />
|
||||||
|
|
||||||
|
<!-- Language Selector -->
|
||||||
<div
|
<div
|
||||||
class="w-full flex justify-end absolute px-6 py-6"
|
class="w-full flex justify-end absolute px-6 py-6"
|
||||||
style="top: 100%; transform: translateY(-100%)"
|
style="top: 100%; transform: translateY(-100%)"
|
||||||
@ -177,27 +151,20 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loadingDatabase: false,
|
loadingDatabase: false,
|
||||||
fileSelectedFrom: null,
|
fileSelectedFrom: null,
|
||||||
showFiles: false,
|
|
||||||
files: [],
|
files: [],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setFiles();
|
this.setFiles();
|
||||||
this.showFiles = this.files.length > 0;
|
window.ds = this;
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
showFiles() {
|
|
||||||
this.setFiles();
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setFiles() {
|
setFiles() {
|
||||||
this.files = cloneDeep(fyo.config.get('files', [])).filter(
|
const files = cloneDeep(fyo.config.get('files', []));
|
||||||
({ filePath }) => fs.existsSync(filePath)
|
this.files = files.filter(({ dbPath }) => fs.existsSync(dbPath));
|
||||||
);
|
|
||||||
|
|
||||||
for (const file of this.files) {
|
for (const file of this.files) {
|
||||||
const stats = fs.statSync(file.filePath);
|
const stats = fs.statSync(file.dbPath);
|
||||||
file.modified = DateTime.fromJSDate(stats.mtime).toRelative();
|
file.modified = DateTime.fromJSDate(stats.mtime).toRelative();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -223,7 +190,7 @@ export default {
|
|||||||
},
|
},
|
||||||
async selectFile(file) {
|
async selectFile(file) {
|
||||||
this.fileSelectedFrom = file;
|
this.fileSelectedFrom = file;
|
||||||
await this.connectToDatabase(file.filePath);
|
await this.connectToDatabase(file.dbPath);
|
||||||
},
|
},
|
||||||
async connectToDatabase(filePath, isNew) {
|
async connectToDatabase(filePath, isNew) {
|
||||||
if (!filePath) {
|
if (!filePath) {
|
||||||
|
@ -112,7 +112,7 @@ export default {
|
|||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'Opening Balances':
|
case 'Opening Balances':
|
||||||
await this.updateChecks({ openingBalanceChecked: 1 });
|
await this.updateChecks({ openingBalanceChecked: true });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -124,19 +124,19 @@ export default {
|
|||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'Invoice':
|
case 'Invoice':
|
||||||
await this.updateChecks({ invoiceSetup: 1 });
|
await this.updateChecks({ invoiceSetup: true });
|
||||||
break;
|
break;
|
||||||
case 'General':
|
case 'General':
|
||||||
await this.updateChecks({ companySetup: 1 });
|
await this.updateChecks({ companySetup: true });
|
||||||
break;
|
break;
|
||||||
case 'System':
|
case 'System':
|
||||||
await this.updateChecks({ systemSetup: 1 });
|
await this.updateChecks({ systemSetup: true });
|
||||||
break;
|
break;
|
||||||
case 'Review Accounts':
|
case 'Review Accounts':
|
||||||
await this.updateChecks({ chartOfAccountsReviewed: 1 });
|
await this.updateChecks({ chartOfAccountsReviewed: true });
|
||||||
break;
|
break;
|
||||||
case 'Add Taxes':
|
case 'Add Taxes':
|
||||||
await this.updateChecks({ taxesAdded: 1 });
|
await this.updateChecks({ taxesAdded: true });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -154,7 +154,7 @@ export default {
|
|||||||
if (onboardingComplete) {
|
if (onboardingComplete) {
|
||||||
await this.updateChecks({ onboardingComplete });
|
await this.updateChecks({ onboardingComplete });
|
||||||
const systemSettings = await fyo.doc.getSingle('SystemSettings');
|
const systemSettings = await fyo.doc.getSingle('SystemSettings');
|
||||||
await systemSettings.set({ hideGetStarted: 1 });
|
await systemSettings.set('hideGetStarted', true);
|
||||||
await systemSettings.sync();
|
await systemSettings.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,9 +207,8 @@ export default {
|
|||||||
await this.updateChecks(toUpdate);
|
await this.updateChecks(toUpdate);
|
||||||
},
|
},
|
||||||
async updateChecks(toUpdate) {
|
async updateChecks(toUpdate) {
|
||||||
await fyo.singles.GetStarted.setMultiple(toUpdate);
|
await fyo.singles.GetStarted.setAndSync(toUpdate);
|
||||||
await fyo.singles.GetStarted.sync();
|
await fyo.doc.getSingle('GetStarted');
|
||||||
fyo.singles.GetStarted = await fyo.doc.getSingle('GetStarted');
|
|
||||||
},
|
},
|
||||||
isCompleted(item) {
|
isCompleted(item) {
|
||||||
return fyo.singles.GetStarted.get(item.fieldname) || 0;
|
return fyo.singles.GetStarted.get(item.fieldname) || 0;
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
<div class="mx-4 pb-16 text-base flex flex-col overflow-y-hidden">
|
<div class="mx-4 pb-16 text-base flex flex-col overflow-y-hidden">
|
||||||
<!-- Title Row -->
|
<!-- Title Row -->
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="py-4 mr-3 w-7 border-b" v-if="hasImage">
|
<div class="py-4 mr-3 w-7" v-if="hasImage" />
|
||||||
<p class="text-gray-700">Img</p>
|
|
||||||
</div>
|
|
||||||
<Row
|
<Row
|
||||||
class="flex-1 text-gray-700"
|
class="flex-1 text-gray-700"
|
||||||
:columnCount="columns.length"
|
:columnCount="columns.length"
|
||||||
@ -25,11 +23,7 @@
|
|||||||
|
|
||||||
<!-- Data Rows -->
|
<!-- Data Rows -->
|
||||||
<div class="overflow-y-auto" v-if="data.length !== 0">
|
<div class="overflow-y-auto" v-if="data.length !== 0">
|
||||||
<div
|
<div class="flex hover:bg-gray-100" v-for="doc in data" :key="doc.name">
|
||||||
class="px-3 flex hover:bg-gray-100 rounded-md"
|
|
||||||
v-for="doc in data"
|
|
||||||
:key="doc.name"
|
|
||||||
>
|
|
||||||
<div class="w-7 py-4 mr-3" v-if="hasImage">
|
<div class="w-7 py-4 mr-3" v-if="hasImage">
|
||||||
<Avatar :imageURL="doc.image" :label="doc.name" />
|
<Avatar :imageURL="doc.image" :label="doc.name" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="border-l h-full">
|
<div class="border-l h-full">
|
||||||
|
<!-- Quick edit Tool bar -->
|
||||||
<div class="flex items-center justify-between px-4 pt-4">
|
<div class="flex items-center justify-between px-4 pt-4">
|
||||||
|
<!-- Close Button and Status Text -->
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<Button :icon="true" @click="routeToPrevious">
|
<Button :icon="true" @click="routeToPrevious">
|
||||||
<feather-icon name="x" class="w-4 h-4" />
|
<feather-icon name="x" class="w-4 h-4" />
|
||||||
@ -9,6 +11,8 @@
|
|||||||
statusText
|
statusText
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Actions, Badge and Status Change Buttons -->
|
||||||
<div class="flex items-stretch">
|
<div class="flex items-stretch">
|
||||||
<DropdownWithActions :actions="actions" />
|
<DropdownWithActions :actions="actions" />
|
||||||
<StatusBadge :status="status" />
|
<StatusBadge :status="status" />
|
||||||
@ -16,7 +20,7 @@
|
|||||||
:icon="true"
|
:icon="true"
|
||||||
@click="sync"
|
@click="sync"
|
||||||
type="primary"
|
type="primary"
|
||||||
v-if="doc && doc.notInserted"
|
v-if="doc?.dirty || doc?.notInserted"
|
||||||
class="ml-2 text-white text-xs"
|
class="ml-2 text-white text-xs"
|
||||||
>
|
>
|
||||||
{{ t`Save` }}
|
{{ t`Save` }}
|
||||||
@ -27,10 +31,9 @@
|
|||||||
type="primary"
|
type="primary"
|
||||||
v-if="
|
v-if="
|
||||||
schema?.isSubmittable &&
|
schema?.isSubmittable &&
|
||||||
doc &&
|
!doc?.submitted &&
|
||||||
!doc.submitted &&
|
!doc?.notInserted &&
|
||||||
!doc.notInserted &&
|
!(doc?.cancelled || false)
|
||||||
!(doc.cancelled || false)
|
|
||||||
"
|
"
|
||||||
class="ml-2 text-white text-xs"
|
class="ml-2 text-white text-xs"
|
||||||
>
|
>
|
||||||
@ -38,6 +41,8 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Name and image -->
|
||||||
<div class="px-4 pt-2 pb-4 flex-center" v-if="doc">
|
<div class="px-4 pt-2 pb-4 flex-center" v-if="doc">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<FormControl
|
<FormControl
|
||||||
@ -63,15 +68,19 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Rest of the form -->
|
||||||
<TwoColumnForm
|
<TwoColumnForm
|
||||||
ref="form"
|
ref="form"
|
||||||
v-if="doc"
|
v-if="doc"
|
||||||
:doc="doc"
|
:doc="doc"
|
||||||
:fields="fields"
|
:fields="fields"
|
||||||
:autosave="true"
|
:autosave="false"
|
||||||
:column-ratio="[1.1, 2]"
|
:column-ratio="[1.1, 2]"
|
||||||
/>
|
/>
|
||||||
<component v-if="doc && quickEditWidget" :is="quickEditWidget" />
|
|
||||||
|
<!-- QuickEdit Widgets -->
|
||||||
|
<component v-if="quickEditWidget" :is="quickEditWidget" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -167,6 +176,10 @@ export default {
|
|||||||
return getActionsForDocument(this.doc);
|
return getActionsForDocument(this.doc);
|
||||||
},
|
},
|
||||||
quickEditWidget() {
|
quickEditWidget() {
|
||||||
|
if (this.doc?.notInserted ?? true) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const widget = getQuickEditWidget(this.schemaName);
|
const widget = getQuickEditWidget(this.schemaName);
|
||||||
if (widget === null) {
|
if (widget === null) {
|
||||||
return null;
|
return null;
|
||||||
@ -212,7 +225,7 @@ export default {
|
|||||||
this.doc.set(fieldname, '');
|
this.doc.set(fieldname, '');
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$refs.titleControl.focus();
|
this.$refs.titleControl?.focus();
|
||||||
}, 300);
|
}, 300);
|
||||||
},
|
},
|
||||||
async fetchDoc() {
|
async fetchDoc() {
|
||||||
@ -225,9 +238,11 @@ export default {
|
|||||||
name: this.doc.name,
|
name: this.doc.name,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.doc.on('beforeSync', () => {
|
this.doc.on('beforeSync', () => {
|
||||||
this.statusText = t`Saving...`;
|
this.statusText = t`Saving...`;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.doc.on('afterSync', () => {
|
this.doc.on('afterSync', () => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.statusText = null;
|
this.statusText = null;
|
||||||
@ -252,6 +267,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
routeToPrevious() {
|
routeToPrevious() {
|
||||||
|
if (this.doc.dirty && !this.doc.notInserted) {
|
||||||
|
this.doc.load();
|
||||||
|
}
|
||||||
this.$router.back();
|
this.$router.back();
|
||||||
},
|
},
|
||||||
setTitleSize() {
|
setTitleSize() {
|
||||||
@ -261,13 +279,8 @@ export default {
|
|||||||
|
|
||||||
const input = this.$refs.titleControl.getInput();
|
const input = this.$refs.titleControl.getInput();
|
||||||
const value = input.value;
|
const value = input.value;
|
||||||
let valueLength = (value || '').length + 1;
|
const valueLength = (value || '').length + 1;
|
||||||
|
input.size = Math.max(valueLength, 15);
|
||||||
if (valueLength < 7) {
|
|
||||||
valueLength = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.size = valueLength;
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user