Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
623d783
Added keep open boolean field to Stock Location modal form
spamik Dec 27, 2025
23daa95
Rewrite keep form open field feature to avoid calling methods in form…
Jan 8, 2026
fdec4b5
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Feb 12, 2026
a4b4566
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Feb 12, 2026
c5cc28f
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Feb 12, 2026
c8af24c
Merge branch 'master' into form-keep-open-feature
matmair Feb 12, 2026
d8adbd8
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 3, 2026
787b8e0
Rewrite keep form open feature as common form property
spamik Mar 8, 2026
045e8c7
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 9, 2026
30cc13b
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 10, 2026
0d7ed88
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 14, 2026
3dc51a3
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 14, 2026
dde261b
Removed unused artefact from previous implementation
spamik Mar 14, 2026
ce614e6
keepOpenOption removed as default option for all create forms. Instea…
spamik Mar 14, 2026
c423bbb
keepOpenOption field speed improvement
spamik Mar 14, 2026
86ec430
Added keep form open feature to changelog
spamik Mar 15, 2026
9eede1c
Updated documentation: keep form open feature added to concepts/user_…
spamik Mar 15, 2026
182ed35
Merge branch 'master' into form-keep-open-feature
SchrodingersGat Mar 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/frontend/lib/types/Forms.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ export interface ApiFormProps {
follow?: boolean;
actions?: ApiFormAction[];
timeout?: number;
keepOpenOption?: boolean;
onKeepOpenChange?: (keepOpen: boolean) => void;
}

/**
Expand Down
38 changes: 31 additions & 7 deletions src/frontend/src/components/forms/ApiForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
LoadingOverlay,
Paper,
Stack,
Switch,
Text
} from '@mantine/core';
import { useId } from '@mantine/hooks';
Expand Down Expand Up @@ -131,7 +132,8 @@ export function OptionsApiForm({
for (const [k, v] of Object.entries(_props.fields)) {
_props.fields[k] = constructField({
field: v,
definition: optionsQuery?.data?.[k]
definition: optionsQuery?.data?.[k],
field_name: k
});

// If the user has specified initial data, use that value here
Expand Down Expand Up @@ -169,6 +171,11 @@ export function ApiForm({
}>) {
const api = useApi();
const queryClient = useQueryClient();
const [keepOpen, setKeepOpen] = useState(false);

useEffect(() => {
props.onKeepOpenChange?.(keepOpen);
}, [keepOpen]);

// Accessor for the navigation function (which is used to redirect the user)
let navigate: NavigateFunction | null = null;
Expand Down Expand Up @@ -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 &&
!keepOpen
) {
// If we want to automatically follow the returned data
if (!!navigate) {
if (!!navigate && !keepOpen) {
navigate(getDetailUrl(props.modelType, response.data?.pk));
}
} else if (props.table) {
Expand Down Expand Up @@ -588,7 +600,6 @@ export function ApiForm({
</Paper>
);
}

return (
<Stack>
<Boundary label={`ApiForm-${id}`}>
Expand Down Expand Up @@ -673,7 +684,19 @@ export function ApiForm({

{/* Footer with Action Buttons */}
<Divider />
<div>
<Group justify='space-between'>
<Group justify='left'>
{props.keepOpenOption && (
<Switch
checked={keepOpen}
radius='lg'
size='sm'
label='Keep form open'
description='Keep form open after submitting'
onChange={(e) => setKeepOpen(e.currentTarget.checked)}
/>
)}
</Group>
<Group justify='right'>
{props.actions?.map((action, i) => (
<Button
Expand All @@ -696,7 +719,7 @@ export function ApiForm({
{props.submitText ?? t`Submit`}
</Button>
</Group>
</div>
</Group>
</Boundary>
</Stack>
);
Expand All @@ -712,7 +735,8 @@ export function CreateApiForm({
const createProps = useMemo<ApiFormProps>(
() => ({
...props,
method: 'POST'
method: 'POST',
keepOpenOption: true
}),
[props]
);
Expand Down
10 changes: 7 additions & 3 deletions src/frontend/src/hooks/UseForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ export function useApiFormModal(props: ApiFormModalProps) {
return props.modalId ?? id;
}, [props.modalId, id]);

const [keepOpen, setKeepOpen] = useState<boolean>(false);

const formProps = useMemo<ApiFormModalProps>(
() => ({
...props,
onKeepOpenChange: setKeepOpen,
actions: [
...(props.actions || []),
{
Expand All @@ -38,7 +41,7 @@ export function useApiFormModal(props: ApiFormModalProps) {
}
],
onFormSuccess: (data, form) => {
if (props.checkClose?.(data, form) ?? true) {
if (!keepOpen && (props.checkClose?.(data, form) ?? true)) {
modalClose.current();
}
props.onFormSuccess?.(data, form);
Expand All @@ -47,7 +50,7 @@ export function useApiFormModal(props: ApiFormModalProps) {
props.onFormError?.(error, form);
}
}),
[props]
[props, keepOpen]
);

const [isOpen, setIsOpen] = useState<boolean>(false);
Expand Down Expand Up @@ -94,7 +97,8 @@ export function useCreateApiFormModal(props: ApiFormModalProps) {
props.successMessage === null
? null
: (props.successMessage ?? t`Item Created`),
method: props.method ?? 'POST'
method: props.method ?? 'POST',
keepOpenOption: true
}),
[props]
);
Expand Down
Loading