mirror of
https://github.com/inventree/InvenTree.git
synced 2026-07-04 06:00:38 +00:00
Remember last used label template and printer plugin per model type (#12146)
* Remember last used label template and printer plugin per model type * Added playwright test for printing preference persistence and format code * Used waitFor for react-select assertions for test case fixing and persist plugin key correctly * Updated the problem resolution code and the tests * Fixed printing test assertion to avoid word boundary failure with concatenated text
This commit is contained in:
@@ -11,6 +11,7 @@ import { api } from '../../App';
|
||||
import { extractAvailableFields } from '../../functions/forms';
|
||||
import useDataOutput from '../../hooks/UseDataOutput';
|
||||
import { useCreateApiFormModal } from '../../hooks/UseForm';
|
||||
import { useLocalState } from '../../states/LocalState';
|
||||
import {
|
||||
useGlobalSettingsState,
|
||||
useUserSettingsState
|
||||
@@ -32,6 +33,11 @@ export function PrintingActions({
|
||||
}) {
|
||||
const userSettings = useUserSettingsState();
|
||||
const globalSettings = useGlobalSettingsState();
|
||||
const localState = useLocalState();
|
||||
|
||||
const lastUsedPrinting = useMemo(() => {
|
||||
return modelType ? localState.lastUsedPrinting[modelType] : undefined;
|
||||
}, [localState.lastUsedPrinting, modelType]);
|
||||
|
||||
const enabled = useMemo(() => items.length > 0, [items]);
|
||||
|
||||
@@ -118,6 +124,7 @@ export function PrintingActions({
|
||||
fields.template = {
|
||||
...fields.template,
|
||||
autoFill: true,
|
||||
value: lastUsedPrinting?.template,
|
||||
filters: {
|
||||
enabled: true,
|
||||
model_type: modelType,
|
||||
@@ -147,7 +154,14 @@ export function PrintingActions({
|
||||
};
|
||||
|
||||
return fields;
|
||||
}, [defaultLabelPlugin, pluginKey, printingFields.data, itemIdList]);
|
||||
}, [
|
||||
defaultLabelPlugin,
|
||||
pluginKey,
|
||||
printingFields.data,
|
||||
itemIdList,
|
||||
lastUsedPrinting,
|
||||
modelType
|
||||
]);
|
||||
|
||||
const labelModal = useCreateApiFormModal({
|
||||
url: apiUrl(ApiEndpoints.label_print),
|
||||
@@ -158,15 +172,21 @@ export function PrintingActions({
|
||||
onOpen: () => {
|
||||
setLabelDialogOpen(true);
|
||||
setItemIdList(items);
|
||||
setPluginKey(lastUsedPrinting?.plugin ?? null);
|
||||
},
|
||||
onClose: () => {
|
||||
setLabelDialogOpen(false);
|
||||
setPluginKey('');
|
||||
},
|
||||
submitText: t`Print`,
|
||||
successMessage: null,
|
||||
onFormSuccess: (response: any) => {
|
||||
setPluginKey('');
|
||||
onFormSuccess: (response: any, form: any) => {
|
||||
if (modelType) {
|
||||
const values = form?.getValues?.();
|
||||
localState.setLastUsedPrinting(modelType, {
|
||||
plugin: pluginKey || undefined,
|
||||
template: values?.template ? Number(values.template) : undefined
|
||||
});
|
||||
}
|
||||
setLabelId(response.pk);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -33,6 +33,12 @@ interface LocalStateProps {
|
||||
setLayouts: (layouts: any, noPatch?: boolean) => void;
|
||||
showSampleDashboard: boolean;
|
||||
setShowSampleDashboard: (value: boolean) => void;
|
||||
// printing
|
||||
lastUsedPrinting: Record<string, { plugin?: string; template?: number }>;
|
||||
setLastUsedPrinting: (
|
||||
modelType: string,
|
||||
values: { plugin?: string; template?: number }
|
||||
) => void;
|
||||
// panels
|
||||
lastUsedPanels: Record<string, string>;
|
||||
setLastUsedPanel: (panelKey: string) => (value: string) => void;
|
||||
@@ -122,6 +128,25 @@ export const useLocalState = create<LocalStateProps>()(
|
||||
setShowSampleDashboard: (value) => {
|
||||
set({ showSampleDashboard: value });
|
||||
},
|
||||
// printing
|
||||
lastUsedPrinting: {},
|
||||
setLastUsedPrinting: (modelType, values) => {
|
||||
const current = get().lastUsedPrinting[modelType] || {};
|
||||
if (
|
||||
current.plugin !== values.plugin ||
|
||||
current.template !== values.template
|
||||
) {
|
||||
set({
|
||||
lastUsedPrinting: {
|
||||
...get().lastUsedPrinting,
|
||||
[modelType]: {
|
||||
...current,
|
||||
...values
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
// panels
|
||||
lastUsedPanels: {},
|
||||
setLastUsedPanel: (panelKey) => (value) => {
|
||||
|
||||
@@ -65,7 +65,42 @@ test('Printing - Label Printing', async ({ browser }) => {
|
||||
await page.getByRole('button', { name: 'Print', exact: true }).isEnabled();
|
||||
await page.getByRole('button', { name: 'Print', exact: true }).click();
|
||||
|
||||
await page.getByText('Process completed successfully').first().waitFor();
|
||||
const successMessage = page
|
||||
.getByText('Process completed successfully')
|
||||
.first();
|
||||
await successMessage.waitFor();
|
||||
await successMessage.waitFor({ state: 'hidden' });
|
||||
|
||||
// Re-open print dialog to verify persistence (issue #12129)
|
||||
await page
|
||||
.getByLabel('Stock Items')
|
||||
.getByLabel('action-menu-printing-actions')
|
||||
.click();
|
||||
await page.getByLabel('action-menu-printing-actions-print-labels').click();
|
||||
|
||||
const labelDialog = page.getByRole('dialog', { name: 'Print Label' });
|
||||
|
||||
// Wait for the dialog to fully load
|
||||
await labelDialog.getByLabel('related-field-template').waitFor();
|
||||
await labelDialog.getByLabel('related-field-plugin').waitFor();
|
||||
|
||||
// Verify the last-used template is preselected
|
||||
await expect(labelDialog).toContainText('InvenTree Stock Item Label');
|
||||
|
||||
// Verify the last-used plugin is preselected
|
||||
await expect(labelDialog).toContainText('InvenTreeLabel');
|
||||
|
||||
// Submit again without re-selecting template or plugin
|
||||
const printResponse = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/api/label/print/') &&
|
||||
response.request().method() === 'POST' &&
|
||||
response.ok()
|
||||
);
|
||||
await labelDialog.getByRole('button', { name: 'Print', exact: true }).click();
|
||||
|
||||
await printResponse;
|
||||
|
||||
await page.context().close();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user