All files / src/pages/flowsheet-page/flowsheet/revisions FlowsheetRevisionSaveProvider.tsx

64.7% Statements 22/34
50% Branches 7/14
33.33% Functions 1/3
70% Lines 21/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                                            1263x 1263x 1263x   1263x   1263x   1263x     3x 3x               3x           2x 2x 2x   2x 2x 2x           2x 2x 2x                           2x 2x       1263x                                                
import { type PropsWithChildren, useRef, useState } from "react";
import { toast } from "sonner";
import {
  api,
  useCoreFlowsheetsRevisionsCreateMutation,
  useLazyCoreFlowsheetsRevisionsRetrieveQuery,
} from "@/api/apiStore.gen.ts";
import {
  type CloneValidationProblem,
  parseCloneValidationProblem,
} from "@/flowsheet-cloning/cloneValidation";
import { FlowsheetCloneProblemDialog } from "@/flowsheet-cloning/FlowsheetCloneProblemDialog";
import { useFlowsheet } from "@/hooks/project";
import { store } from "@/store/store.ts";
import {
  ACTIVE_TASKS_REVISION_MESSAGE,
  FlowsheetRevisionSaveContext,
  isActiveTasksRevisionConflict,
} from "./FlowsheetRevisionSaveContext";
 
/** Own the single revision-save command shared by every page entry point. */
export function FlowsheetRevisionSaveProvider({ children }: PropsWithChildren) {
  const flowsheet = useFlowsheet();
  const pendingRef = useRef(false);
  const [savePending, setSavePending] = useState(false);
  const [cloneProblem, setCloneProblem] =
    useState<CloneValidationProblem | null>(null);
  const [createRevision, createResult] =
    useCoreFlowsheetsRevisionsCreateMutation();
  const [retrieveRevisionStatus] =
    useLazyCoreFlowsheetsRevisionsRetrieveQuery();
 
  const ensureNoActiveTasks = async (): Promise<boolean> => {
    Iif (flowsheet?.id == null) return false;
    const revisionStatus = await retrieveRevisionStatus(
      { id: String(flowsheet.id), page: 1 },
      false,
    ).unwrap();
    if (revisionStatus.has_active_tasks) {
      toast.error(ACTIVE_TASKS_REVISION_MESSAGE);
      return false;
    }
    return true;
  };
 
  const performSaveRevision = async (
    repairLegacyFormulaUnits = false,
  ): Promise<boolean> => {
    Iif (pendingRef.current || flowsheet?.id == null) return false;
    pendingRef.current = true;
    setSavePending(true);
    try {
      await Promise.all(store.dispatch(api.util.getRunningMutationsThunk()));
      Iif (!(await ensureNoActiveTasks())) return false;
      await createRevision({
        id: String(flowsheet.id),
        createFlowsheetRevision: repairLegacyFormulaUnits
          ? { repair_legacy_formula_units: true }
          : {},
      }).unwrap();
      setCloneProblem(null);
      toast.success("Version saved");
      return true;
    } catch (error) {
      const problem = parseCloneValidationProblem(error);
      if (problem) {
        setCloneProblem(problem);
      } else {
        toast.error(
          isActiveTasksRevisionConflict(error)
            ? ACTIVE_TASKS_REVISION_MESSAGE
            : "Version could not be saved",
        );
      }
      return false;
    } finally {
      pendingRef.current = false;
      setSavePending(false);
    }
  };
 
  const saveRevision = (): Promise<boolean> => performSaveRevision(false);
 
  return (
    <FlowsheetRevisionSaveContext.Provider
      value={{
        ensureNoActiveTasks,
        saveRevision,
        isSaving: savePending || createResult.isLoading,
      }}
    >
      {children}
      <FlowsheetCloneProblemDialog
        problem={cloneProblem}
        scope="flowsheet"
        isRepairingAutomatically={savePending || createResult.isLoading}
        onDismiss={() => setCloneProblem(null)}
        onRepairManually={() => setCloneProblem(null)}
        onRepairAutomatically={async () => {
          await performSaveRevision(true);
        }}
      />
    </FlowsheetRevisionSaveContext.Provider>
  );
}