diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3c200417ff37..578046292d49 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#10887](https://github.com/inventree/InvenTree/pull/10887) adds the ability to auto-allocate tracked items against specific build outputs. Currently, this will only allocate items where the serial number of the tracked item matches the serial number of the build output, but in future this may be extended to allow for more flexible allocation rules.
- [#11372](https://github.com/inventree/InvenTree/pull/11372) adds backup metadata setter and restore metadata validator functions to ensure common footguns are harder to trigger when using the backup and restore functionality.
- [#11374](https://github.com/inventree/InvenTree/pull/11374) adds `updated_at` field on purchase, sales and return orders.
+- [#11074](https://github.com/inventree/InvenTree/pull/11074) adds "Keep form open" option on create form which leaves dialog with form opened after form submitting.
### Changed
diff --git a/docs/docs/assets/images/concepts/ui_form_add_part.png b/docs/docs/assets/images/concepts/ui_form_add_part.png
index af8daf98368c..3f2cc70e2231 100644
Binary files a/docs/docs/assets/images/concepts/ui_form_add_part.png and b/docs/docs/assets/images/concepts/ui_form_add_part.png differ
diff --git a/docs/docs/concepts/user_interface.md b/docs/docs/concepts/user_interface.md
index 665b9fcf02f7..26e7ddf5d02c 100644
--- a/docs/docs/concepts/user_interface.md
+++ b/docs/docs/concepts/user_interface.md
@@ -224,6 +224,8 @@ Example: Creating a new part via the "Add Part" form:
{{ image("concepts/ui_form_add_part.png", "Add Part Button") }}
+On several forms is displayed option "Keep form open" in bottom part of the form on left side of Submit button (option is visible on the screenshot above). When this switch is turned on, form window is not closed after submit and filled form data is not reset. This is useful for creating more entries at one time with similar properties (e.g. only different number in name).
+
### Data Editing
Example: Editing an existing purchase order via the "Edit Purchase Order" form:
diff --git a/src/frontend/lib/types/Forms.tsx b/src/frontend/lib/types/Forms.tsx
index 1bc3dc62f35f..42ba36acfdd3 100644
--- a/src/frontend/lib/types/Forms.tsx
+++ b/src/frontend/lib/types/Forms.tsx
@@ -180,6 +180,8 @@ export interface ApiFormProps {
follow?: boolean;
actions?: ApiFormAction[];
timeout?: number;
+ keepOpenOption?: boolean;
+ onKeepOpenChange?: (keepOpen: boolean) => void;
}
/**
diff --git a/src/frontend/src/components/forms/ApiForm.tsx b/src/frontend/src/components/forms/ApiForm.tsx
index 089ce4f36bf0..43b2b2294846 100644
--- a/src/frontend/src/components/forms/ApiForm.tsx
+++ b/src/frontend/src/components/forms/ApiForm.tsx
@@ -12,7 +12,7 @@ import {
import { useId } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { useQuery, useQueryClient } from '@tanstack/react-query';
-import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
type FieldValues,
FormProvider,
@@ -42,6 +42,7 @@ import {
showTimeoutNotification
} from '../../functions/notifications';
import { Boundary } from '../Boundary';
+import { KeepFormOpenSwitch } from './KeepFormOpenSwitch';
import { ApiFormField } from './fields/ApiFormField';
export function OptionsApiForm({
@@ -169,6 +170,12 @@ export function ApiForm({
}>) {
const api = useApi();
const queryClient = useQueryClient();
+ const keepOpenRef = useRef(false);
+
+ const onKeepOpenChange = (v: boolean) => {
+ keepOpenRef.current = v;
+ props.onKeepOpenChange?.(v);
+ };
// Accessor for the navigation function (which is used to redirect the user)
let navigate: NavigateFunction | null = null;
@@ -459,9 +466,14 @@ export function ApiForm({
props.onFormSuccess(response.data, form);
}
- if (props.follow && props.modelType && response.data?.pk) {
+ if (
+ props.follow &&
+ props.modelType &&
+ response.data?.pk &&
+ !keepOpenRef.current
+ ) {
// If we want to automatically follow the returned data
- if (!!navigate) {
+ if (!!navigate && !keepOpenRef.current) {
navigate(getDetailUrl(props.modelType, response.data?.pk));
}
} else if (props.table) {
@@ -588,7 +600,6 @@ export function ApiForm({
);
}
-
return (
@@ -673,7 +684,12 @@ export function ApiForm({
{/* Footer with Action Buttons */}
-