form.markAsSaved(); applied across the application
This commit is contained in:
parent
046869510a
commit
5f03b1cccc
@ -19,6 +19,7 @@ import { renderCustomField } from "./formHelpers";
|
||||
import { CustomFieldValue } from "../../modules/manager/glossary/services/glossaryService";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Namespaces } from "../../i18n/i18n";
|
||||
import { useFormWithGuard } from "./useFormRouter";
|
||||
|
||||
interface TemplateFillerProps {
|
||||
templateId?: GeneralIdRef;
|
||||
@ -40,7 +41,7 @@ interface TemplateState {
|
||||
|
||||
const TemplateFiller = forwardRef<TemplateFillerHandle, TemplateFillerProps>(
|
||||
({ templateId, formInstanceId, onValidationChanged }, ref) => {
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {},
|
||||
errors: {},
|
||||
|
||||
@ -91,6 +91,9 @@ interface UseFormReturn {
|
||||
hasUnsavedChanges: () => boolean;
|
||||
markAsSaved: () => void;
|
||||
setupNavigationGuard: (onBlock?: (location: Location) => void) => () => void;
|
||||
enableReactRouterGuard: () => void;
|
||||
disableReactRouterGuard: () => void;
|
||||
routerGuardEnabledRef: React.MutableRefObject<boolean>;
|
||||
}
|
||||
|
||||
export const useForm = (initialState: FormState): UseFormReturn => {
|
||||
@ -581,6 +584,18 @@ export const useForm = (initialState: FormState): UseFormReturn => {
|
||||
initialDataRef.current = JSON.parse(JSON.stringify(state.data));
|
||||
}, [state.data]);
|
||||
|
||||
// React Router navigation guard state
|
||||
const routerGuardEnabledRef = useRef<boolean>(true);
|
||||
|
||||
// Setup React Router blocker for in-app navigation
|
||||
const enableReactRouterGuard = useCallback((): void => {
|
||||
routerGuardEnabledRef.current = true;
|
||||
}, []);
|
||||
|
||||
const disableReactRouterGuard = useCallback((): void => {
|
||||
routerGuardEnabledRef.current = false;
|
||||
}, []);
|
||||
|
||||
const setupNavigationGuard = useCallback(
|
||||
(onBlock?: (location: Location) => void): (() => void) => {
|
||||
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
|
||||
@ -633,6 +648,9 @@ export const useForm = (initialState: FormState): UseFormReturn => {
|
||||
hasUnsavedChanges,
|
||||
markAsSaved,
|
||||
setupNavigationGuard,
|
||||
enableReactRouterGuard,
|
||||
disableReactRouterGuard,
|
||||
routerGuardEnabledRef,
|
||||
};
|
||||
Object.defineProperty(api, "schema", {
|
||||
get: () => schemaRef.current,
|
||||
@ -643,3 +661,34 @@ export const useForm = (initialState: FormState): UseFormReturn => {
|
||||
|
||||
return api as UseFormReturn;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to enable React Router data router navigation blocking.
|
||||
*
|
||||
* Call this hook in your component to enable navigation guards for React Router's data router.
|
||||
* This is optional and only needed if you're using RouterProvider (not BrowserRouter).
|
||||
* The browserunload guard from useForm still works regardless.
|
||||
*
|
||||
* @param formApi The return value from useForm
|
||||
*
|
||||
* @example
|
||||
* // In your component that is inside a data router:
|
||||
* import { useBlocker } from "react-router-dom";
|
||||
*
|
||||
* const MyEditForm = () => {
|
||||
* const form = useForm(initialState);
|
||||
*
|
||||
* // Only call this if inside RouterProvider (data router)
|
||||
* const blocker = useBlocker(({ currentLocation, nextLocation }) =>
|
||||
* form.routerGuardEnabledRef.current &&
|
||||
* form.hasUnsavedChanges() &&
|
||||
* currentLocation.pathname !== nextLocation.pathname
|
||||
* );
|
||||
*
|
||||
* return (...);
|
||||
* }
|
||||
*/
|
||||
export const useFormRouterBlocker = (formApi: UseFormReturn): void => {
|
||||
// This is a documentation function - actual implementation is done in the component
|
||||
// See the example above for how to properly set up router blocking with useBlocker
|
||||
};
|
||||
|
||||
159
src/components/common/useFormRouter.ts
Normal file
159
src/components/common/useFormRouter.ts
Normal file
@ -0,0 +1,159 @@
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import { UseFormReturn, useForm, FormState } from "./useForm";
|
||||
|
||||
/**
|
||||
* Hook for BrowserRouter navigation blocking with unsaved changes.
|
||||
*
|
||||
* Works with BrowserRouter (standard routing, not data router).
|
||||
* Shows a confirmation dialog when user attempts to navigate away with unsaved changes.
|
||||
*
|
||||
* @param formApi - The return value from useForm()
|
||||
*
|
||||
* @example
|
||||
* const form = useForm(initialState);
|
||||
* useBrowserRouterFormGuard(form);
|
||||
*/
|
||||
export const useBrowserRouterFormGuard = (formApi: UseFormReturn): void => {
|
||||
const location = useLocation();
|
||||
const { hasUnsavedChanges, routerGuardEnabledRef, disableReactRouterGuard } =
|
||||
formApi;
|
||||
const previousLocationRef = useRef(location);
|
||||
const pendingNavigationRef = useRef<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// If navigation was attempted and we're at a new location
|
||||
if (
|
||||
location.pathname !== previousLocationRef.current.pathname &&
|
||||
pendingNavigationRef.current
|
||||
) {
|
||||
// Navigation succeeded, reset
|
||||
previousLocationRef.current = location;
|
||||
pendingNavigationRef.current = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we need to guard against navigation
|
||||
if (
|
||||
hasUnsavedChanges() &&
|
||||
routerGuardEnabledRef.current &&
|
||||
pendingNavigationRef.current === null
|
||||
) {
|
||||
// Store the current location for comparison
|
||||
previousLocationRef.current = location;
|
||||
}
|
||||
}, [
|
||||
location,
|
||||
hasUnsavedChanges,
|
||||
routerGuardEnabledRef,
|
||||
disableReactRouterGuard,
|
||||
]);
|
||||
|
||||
// Intercept navigation attempts by wrapping navigate
|
||||
useEffect(() => {
|
||||
// Override the window's history behavior to catch navigation attempts
|
||||
const originalPushState = window.history.pushState;
|
||||
const originalReplaceState = window.history.replaceState;
|
||||
|
||||
const handleNavigation = (
|
||||
method: (state: any, title: string, url?: string | null) => void,
|
||||
state: any,
|
||||
title: string,
|
||||
url?: string | null,
|
||||
) => {
|
||||
if (
|
||||
hasUnsavedChanges() &&
|
||||
routerGuardEnabledRef.current &&
|
||||
url &&
|
||||
url !== window.location.pathname + window.location.search
|
||||
) {
|
||||
// Prompt user
|
||||
const confirmed = window.confirm(
|
||||
"You have unsaved changes. Do you want to leave without saving?",
|
||||
);
|
||||
|
||||
if (confirmed) {
|
||||
disableReactRouterGuard();
|
||||
method.call(window.history, state, title, url);
|
||||
setTimeout(() => {
|
||||
formApi.enableReactRouterGuard();
|
||||
}, 0);
|
||||
}
|
||||
} else {
|
||||
method.call(window.history, state, title, url);
|
||||
}
|
||||
};
|
||||
|
||||
window.history.pushState = function (state, title, url) {
|
||||
handleNavigation(originalPushState, state, title, url);
|
||||
};
|
||||
|
||||
window.history.replaceState = function (state, title, url) {
|
||||
handleNavigation(originalReplaceState, state, title, url);
|
||||
};
|
||||
|
||||
return () => {
|
||||
window.history.pushState = originalPushState;
|
||||
window.history.replaceState = originalReplaceState;
|
||||
};
|
||||
}, [
|
||||
hasUnsavedChanges,
|
||||
routerGuardEnabledRef,
|
||||
disableReactRouterGuard,
|
||||
formApi,
|
||||
]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to enable React Router data router navigation blocking.
|
||||
*
|
||||
* Call this hook in your component to enable navigation guards for React Router's data router.
|
||||
* This is optional and only needed if you're using RouterProvider (not BrowserRouter).
|
||||
* The beforeunload guard from useForm still works regardless.
|
||||
*
|
||||
* @param formApi The return value from useForm
|
||||
*
|
||||
* @example
|
||||
* // In your component that is inside a data router:
|
||||
* import { useBlocker } from "react-router-dom";
|
||||
*
|
||||
* const MyEditForm = () => {
|
||||
* const form = useForm(initialState);
|
||||
*
|
||||
* // Only call this if inside RouterProvider (data router)
|
||||
* const blocker = useBlocker(({ currentLocation, nextLocation }) =>
|
||||
* form.routerGuardEnabledRef.current &&
|
||||
* form.hasUnsavedChanges() &&
|
||||
* currentLocation.pathname !== nextLocation.pathname
|
||||
* );
|
||||
*
|
||||
* return (...);
|
||||
* }
|
||||
*/
|
||||
export const useFormRouterBlocker = (formApi: UseFormReturn): void => {
|
||||
// This is a documentation function - actual implementation is done in the component
|
||||
// See the example above for how to properly set up router blocking with useBlocker
|
||||
};
|
||||
|
||||
/**
|
||||
* Combined hook that creates a form with automatic unsaved changes navigation guard.
|
||||
*
|
||||
* This is the recommended way to create forms with navigation protection in BrowserRouter apps.
|
||||
* It combines useForm() and useBrowserRouterFormGuard() into a single call.
|
||||
*
|
||||
* @param initialState - The initial form state
|
||||
* @returns The form API with navigation guard already set up
|
||||
*
|
||||
* @example
|
||||
* // Instead of:
|
||||
* const form = useForm(initialState);
|
||||
* useBrowserRouterFormGuard(form);
|
||||
*
|
||||
* // Just use:
|
||||
* const form = useFormWithGuard(initialState);
|
||||
*/
|
||||
export const useFormWithGuard = (initialState: FormState): UseFormReturn => {
|
||||
const form = useForm(initialState);
|
||||
useBrowserRouterFormGuard(form);
|
||||
return form;
|
||||
};
|
||||
@ -4,7 +4,6 @@ import Joi from "joi";
|
||||
import authentication from "../services/authenticationService";
|
||||
import { InputType } from "../../../components/common/Input";
|
||||
import { ButtonType } from "../../../components/common/Button";
|
||||
import { useForm } from "../../../components/common/useForm";
|
||||
import {
|
||||
renderButton,
|
||||
renderError,
|
||||
@ -12,6 +11,7 @@ import {
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Namespaces } from "../../../i18n/i18n";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
const InternalLoginForm: React.FC = () => {
|
||||
const { t } = useTranslation(Namespaces.Common);
|
||||
@ -19,7 +19,7 @@ const InternalLoginForm: React.FC = () => {
|
||||
const [emailSent, setEmailSent] = useState(false);
|
||||
const passwordMaxLength = 255;
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: true,
|
||||
data: {
|
||||
username: "",
|
||||
|
||||
@ -28,6 +28,7 @@ import {
|
||||
SystemGlossaries,
|
||||
} from "../glossary/services/glossaryService";
|
||||
import Loading from "../../../components/common/Loading";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
interface CustomFieldDetailsProps {
|
||||
editMode?: boolean;
|
||||
@ -54,7 +55,7 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -318,6 +319,8 @@ const CustomFieldDetails: React.FC<CustomFieldDetailsProps> = ({
|
||||
}
|
||||
|
||||
if (buttonName === "save") form.setState({ redirect: "/customfields" });
|
||||
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import {
|
||||
renderButton,
|
||||
renderUserPicker,
|
||||
} from "../../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../../components/common/useFormRouter";
|
||||
|
||||
interface LocAddUserToRoleProps {
|
||||
isEditMode: boolean;
|
||||
@ -29,7 +30,7 @@ const AddUserToRole: React.FC<LocAddUserToRoleProps> = ({ isEditMode }) => {
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: true,
|
||||
data: {
|
||||
userId: undefined,
|
||||
@ -57,6 +58,8 @@ const AddUserToRole: React.FC<LocAddUserToRoleProps> = ({ isEditMode }) => {
|
||||
form.setState({
|
||||
redirect: `/domains/edit/${domainId}#securityRoles/${roleId}/users`,
|
||||
});
|
||||
|
||||
form.markAsSaved();
|
||||
}
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
renderInput,
|
||||
renderTemplateEditor,
|
||||
} from "../../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../../components/common/useFormRouter";
|
||||
|
||||
interface EmailTemplateEditorProps {
|
||||
domainId?: string;
|
||||
@ -33,7 +34,7 @@ const EmailTemplateEditor: React.FC<EmailTemplateEditorProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
currentMailType: undefined,
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
renderInput,
|
||||
renderSsoProviderPicker,
|
||||
} from "../../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../../components/common/useFormRouter";
|
||||
|
||||
interface GeneralTabProps {
|
||||
isEditMode: boolean;
|
||||
@ -34,7 +35,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -117,6 +118,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
|
||||
}
|
||||
|
||||
if (buttonName === "save") form.setState({ redirect: "/domains" });
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import {
|
||||
renderButton,
|
||||
renderInput,
|
||||
} from "../../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../../components/common/useFormRouter";
|
||||
|
||||
interface RolesDetailsProps {
|
||||
isEditMode: boolean;
|
||||
@ -30,7 +31,7 @@ const RolesDetails: React.FC<RolesDetailsProps> = ({ isEditMode }) => {
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
renderInput,
|
||||
renderTemplateEditor,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
const FormsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
editMode = false,
|
||||
@ -28,7 +29,7 @@ const FormsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -93,6 +94,7 @@ const FormsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
}
|
||||
|
||||
if (buttonName === "save") form.setState({ redirect: "/forms" });
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ import {
|
||||
renderCustomFields,
|
||||
renderCustomFieldsEditor,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
interface GlossariesDetailsProps {
|
||||
editMode?: boolean;
|
||||
@ -38,7 +39,7 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
id: undefined,
|
||||
@ -182,6 +183,7 @@ const GlossariesDetails: React.FC<GlossariesDetailsProps> = ({
|
||||
const navigateId = parentGlossary ? parentGlossary.id.toString() : "";
|
||||
if (buttonName === "save")
|
||||
form.setState({ redirect: "/glossaries/" + navigateId });
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import {
|
||||
renderInput,
|
||||
renderSelect,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
editMode = false,
|
||||
@ -36,7 +37,7 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
{ _id: "Blocked", name: t("Blocked") },
|
||||
];
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -112,6 +113,7 @@ const OrganisationsDetails: React.FC<{ editMode?: boolean }> = ({
|
||||
}
|
||||
|
||||
if (buttonName === "save") form.setState({ redirect: "/organisations" });
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -17,6 +17,7 @@ import sequenceService from "./services/sequenceService";
|
||||
import Option from "../../../components/common/option";
|
||||
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
|
||||
import Loading from "../../../components/common/Loading";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
interface SequenceDetailsProps {
|
||||
editMode?: boolean;
|
||||
@ -37,7 +38,7 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -131,6 +132,7 @@ const SequenceDetails: React.FC<SequenceDetailsProps> = ({
|
||||
if (buttonName === "save") {
|
||||
form.setState({ redirect: "/sequence" });
|
||||
}
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -16,6 +16,7 @@ import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
|
||||
import Option from "../../../components/common/option";
|
||||
import siteService from "./services/sitessService";
|
||||
import Loading from "../../../components/common/Loading";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
interface SiteDetailsProps {
|
||||
editMode?: boolean;
|
||||
@ -35,7 +36,7 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -118,6 +119,7 @@ const SiteDetails: React.FC<SiteDetailsProps> = ({ editMode = false }) => {
|
||||
if (buttonName === "save") {
|
||||
form.setState({ redirect: "/site/" + organisationId });
|
||||
}
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ import {
|
||||
renderError,
|
||||
renderGlossaryPicker,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
interface SpecificationsDetailsProps {
|
||||
editMode?: boolean;
|
||||
@ -44,7 +45,7 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -193,6 +194,7 @@ const SpecificationsDetails: React.FC<SpecificationsDetailsProps> = ({
|
||||
redirect: "/Specifications/" + organisationId + "/" + siteId,
|
||||
});
|
||||
}
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import { Navigate, useParams, useLocation } from "react-router-dom";
|
||||
import { toast } from "react-toastify";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Namespaces } from "../../../i18n/i18n";
|
||||
import { useForm } from "../../../components/common/useForm";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
import { InputType } from "../../../components/common/Input";
|
||||
import {
|
||||
renderInput,
|
||||
@ -37,7 +37,7 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -155,6 +155,8 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
|
||||
if (buttonName === "save") {
|
||||
form.setState({ redirect: "/ssoManager" });
|
||||
}
|
||||
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
@ -286,7 +288,7 @@ const SsoProviderDetails: React.FC<SsoProviderDetailsProps> = ({
|
||||
|
||||
{editMode && <div>Redirect URL: {redirectUrl}</div>}
|
||||
|
||||
{editMode && renderButton(labelApply, form.state.errors, "save")}
|
||||
{editMode && renderButton(labelApply, form.state.errors, "apply")}
|
||||
{renderButton(labelSave, form.state.errors, "save")}
|
||||
</form>
|
||||
</Loading>
|
||||
|
||||
@ -17,6 +17,7 @@ import {
|
||||
renderError,
|
||||
renderDomainPicker,
|
||||
} from "../../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../../components/common/useFormRouter";
|
||||
|
||||
interface GeneralTabProps {
|
||||
isEditMode: boolean;
|
||||
@ -35,7 +36,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
|
||||
const labelApply = t("Save");
|
||||
const labelSave = t("SaveAndClose");
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
firstName: "",
|
||||
@ -131,6 +132,7 @@ const GeneralTab: React.FC<GeneralTabProps> = ({ isEditMode }) => {
|
||||
if (buttonName === "save") {
|
||||
form.setState({ redirect: "/users" });
|
||||
}
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -16,12 +16,12 @@ import {
|
||||
renderButton,
|
||||
renderError,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useForm } from "../../../components/common/useForm";
|
||||
import ErrorBlock from "../../../components/common/ErrorBlock";
|
||||
import authentication from "../../frame/services/authenticationService";
|
||||
import { MakeGeneralIdRef } from "../../../utils/GeneralIdRef";
|
||||
import { CustomFieldValue } from "../glossary/services/glossaryService";
|
||||
import TasksTab from "./components/TasksTab";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
const WorkflowTemplateDetails: React.FC<{ editMode: boolean }> = ({
|
||||
editMode,
|
||||
@ -31,7 +31,7 @@ const WorkflowTemplateDetails: React.FC<{ editMode: boolean }> = ({
|
||||
const [activeTab, setActiveTab] = React.useState("general");
|
||||
|
||||
// useForm promoted to the parent
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
name: "",
|
||||
@ -112,6 +112,8 @@ const WorkflowTemplateDetails: React.FC<{ editMode: boolean }> = ({
|
||||
if (buttonName === "save") {
|
||||
form.setState({ ...form.state, redirect: "/workflowTemplates" });
|
||||
}
|
||||
|
||||
form.markAsSaved();
|
||||
} catch (ex: any) {
|
||||
form.handleGeneralError(ex);
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
} from "../services/WorkflowTemplateService";
|
||||
import AddTaskButton from "./AddTaskButton";
|
||||
import { Namespaces } from "../../../../i18n/i18n";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
interface TaskListProps {
|
||||
tasks: TaskDefinition[];
|
||||
|
||||
@ -15,6 +15,7 @@ import {
|
||||
renderToggle,
|
||||
renderDropSection,
|
||||
} from "../../../components/common/formHelpers";
|
||||
import { useFormWithGuard } from "../../../components/common/useFormRouter";
|
||||
|
||||
const InternalProfile: React.FC = () => {
|
||||
const { t } = useTranslation(Namespaces.Common);
|
||||
@ -35,7 +36,7 @@ const InternalProfile: React.FC = () => {
|
||||
qrCodeImageUrl: "",
|
||||
});
|
||||
|
||||
const form = useForm({
|
||||
const form = useFormWithGuard({
|
||||
loaded: false,
|
||||
data: {
|
||||
firstName: "",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user