2
0
mirror of https://github.com/frappe/books.git synced 2025-01-03 15:17:30 +00:00

incr: grouped action dropdowns

This commit is contained in:
18alantom 2022-11-30 12:29:52 +05:30
parent 332bf93a1e
commit 1f259524b9
6 changed files with 91 additions and 19 deletions

View File

@ -64,6 +64,8 @@ export interface Action {
label: string;
action: (doc: Doc, router: Router) => Promise<void> | void;
condition?: (doc: Doc) => boolean;
group?: string;
type?: 'primary' | 'secondary';
component?: {
template?: string;
};

View File

@ -26,7 +26,8 @@ export function getInvoiceActions(fyo: Fyo): Action[] {
export function getMakeStockTransferAction(fyo: Fyo): Action {
return {
label: fyo.t`Make Stock Transfer`,
label: fyo.t`Stock Transfer`,
group: fyo.t`Create`,
condition: (doc: Doc) => doc.isSubmitted && !!doc.stockNotTransferred,
action: async (doc: Doc) => {
const transfer = await (doc as Invoice).getStockTransfer();
@ -43,7 +44,8 @@ export function getMakeStockTransferAction(fyo: Fyo): Action {
export function getMakePaymentAction(fyo: Fyo): Action {
return {
label: fyo.t`Make Payment`,
label: fyo.t`Payment`,
group: fyo.t`Create`,
condition: (doc: Doc) =>
doc.isSubmitted && !(doc.outstandingAmount as Money).isZero(),
action: async (doc: Doc) => {
@ -79,6 +81,7 @@ export function getLedgerLinkAction(
return {
label,
group: fyo.t`View`,
condition: (doc: Doc) => doc.isSubmitted,
action: async (doc: Doc, router: Router) => {
router.push({

View File

@ -3,7 +3,17 @@
<!-- Page Header (Title, Buttons, etc) -->
<template #header v-if="doc">
<StatusBadge :status="status" />
<DropdownWithActions :actions="actions()" />
<DropdownWithActions
v-for="group of groupedActions()"
:key="group.label"
:type="group.type"
:actions="group.actions"
>
<p v-if="group.group">
{{ group.group }}
</p>
<feather-icon v-else name="more-horizontal" class="w-4 h-4" />
</DropdownWithActions>
<Button
v-if="doc?.notInserted || doc?.dirty"
type="primary"
@ -154,6 +164,7 @@ import { docsPathMap } from 'src/utils/misc';
import {
docsPath,
getActionsForDocument,
getGroupedActionsForDocument,
routeTo,
showMessageDialog,
} from 'src/utils/ui';
@ -237,8 +248,8 @@ export default {
this.quickEditDoc = doc;
this.quickEditFields = fields;
},
actions() {
return getActionsForDocument(this.doc);
groupedActions() {
return getGroupedActionsForDocument(this.doc);
},
getField(fieldname) {
return fyo.getField(this.schemaName, fieldname);

View File

@ -27,7 +27,17 @@
>
<feather-icon name="settings" class="w-4 h-4" />
</Button>
<DropdownWithActions :actions="actions()" />
<DropdownWithActions
v-for="group of groupedActions()"
:key="group.label"
:type="group.type"
:actions="group.actions"
>
<p v-if="group.group">
{{ group.group }}
</p>
<feather-icon v-else name="more-horizontal" class="w-4 h-4" />
</DropdownWithActions>
<Button
v-if="doc?.notInserted || doc?.dirty"
type="primary"
@ -290,7 +300,7 @@ import { fyo } from 'src/initFyo';
import { docsPathMap } from 'src/utils/misc';
import {
docsPath,
getActionsForDocument,
getGroupedActionsForDocument,
routeTo,
showMessageDialog,
} from 'src/utils/ui';
@ -436,8 +446,8 @@ export default {
this.quickEditFields = fields;
},
actions() {
return getActionsForDocument(this.doc);
groupedActions() {
return getGroupedActionsForDocument(this.doc);
},
getField(fieldname) {
return fyo.getField(this.schemaName, fieldname);

View File

@ -3,7 +3,17 @@
<!-- Page Header (Title, Buttons, etc) -->
<template #header v-if="doc">
<StatusBadge :status="status" />
<DropdownWithActions :actions="actions" />
<DropdownWithActions
v-for="group of groupedActions()"
:key="group.label"
:type="group.type"
:actions="group.actions"
>
<p v-if="group.group">
{{ group.group }}
</p>
<feather-icon v-else name="more-horizontal" class="w-4 h-4" />
</DropdownWithActions>
<Button
v-if="doc?.notInserted || doc?.dirty"
type="primary"
@ -139,10 +149,11 @@ import StatusBadge from 'src/components/StatusBadge.vue';
import { fyo } from 'src/initFyo';
import { docsPathMap } from 'src/utils/misc';
import {
docsPath,
getActionsForDocument,
routeTo,
showMessageDialog
docsPath,
getActionsForDocument,
getGroupedActionsForDocument,
routeTo,
showMessageDialog,
} from 'src/utils/ui';
import { handleErrorWithDialog } from '../errorHandling';
@ -156,8 +167,8 @@ export default {
FormControl,
Table,
FormContainer,
FormHeader
},
FormHeader,
},
provide() {
return {
schemaName: this.schemaName,
@ -211,14 +222,14 @@ export default {
}
return fyo.format(value, 'Currency');
},
actions() {
return getActionsForDocument(this.doc);
},
},
methods: {
getField(fieldname) {
return fyo.getField(ModelNameEnum.JournalEntry, fieldname);
},
groupedActions() {
return getGroupedActionsForDocument(this.doc);
},
async sync() {
try {
await this.doc.sync();

View File

@ -271,6 +271,7 @@ export function getActionsForDocument(doc?: Doc): Action[] {
.filter((d) => d.condition?.(doc) ?? true)
.map((d) => {
return {
group: d.group,
label: d.label,
component: d.component,
action: d.action,
@ -278,6 +279,39 @@ export function getActionsForDocument(doc?: Doc): Action[] {
});
}
export function getGroupedActionsForDocument(doc?: Doc) {
type Group = {
group: string;
label: string;
type: string;
actions: Action[];
};
const actions = getActionsForDocument(doc);
const actionsMap = actions.reduce((acc, ac) => {
if (!ac.group) {
ac.group = '';
}
acc[ac.group] ??= {
group: ac.group,
label: ac.label ?? '',
type: ac.type ?? 'secondary',
actions: [],
};
acc[ac.group].actions.push(ac);
return acc;
}, {} as Record<string, Group>);
const grouped = Object.keys(actionsMap)
.filter(Boolean)
.sort()
.map((k) => actionsMap[k]);
return [grouped, actionsMap['']].flat();
}
function getCancelAction(doc: Doc): Action {
return {
label: t`Cancel`,
@ -329,6 +363,7 @@ function getDuplicateAction(doc: Doc): Action {
const isSubmittable = !!doc.schema.isSubmittable;
return {
label: t`Duplicate`,
group: t`Create`,
condition: (doc: Doc) =>
!!(
((isSubmittable && doc.submitted) || !isSubmittable) &&