All files / src/pages/flowsheet-page/flowsheet/Canvas useAutoSortCanvas.ts

42.5% Statements 17/40
84.61% Branches 11/13
33.33% Functions 1/3
45.45% Lines 15/33

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                                        8015x 8015x 8015x 8015x 8015x 8015x 8015x 8015x 8015x                                 1x                 1x                   1x   1x                     1x           13679x                      
import { useCallback } from "react";
import { toast } from "sonner";
import {
  api,
  useGraphicsObjectsAutoSortCreateMutation,
} from "@/api/apiStore.gen";
import { useFlowsheetAccess } from "@/hooks/flowsheetAccess";
import {
  useCurrentGroupId,
  useGraphicsObjects,
} from "@/hooks/flowsheetObjects";
import { useProjectId } from "@/hooks/project";
import { useUndoRedoStore } from "@/hooks/useUndoRedoStore";
import { useAppDispatch } from "@/store/hooks";
import { createMoveCommand } from "@/utils/commandCreators";
 
/**
 * Auto-sorts the current canvas group and keeps the local graphics cache and
 * undo history in step with the backend response.
 */
export function useAutoSortCanvas() {
  const dispatch = useAppDispatch();
  const access = useFlowsheetAccess();
  const canMutate = access?.can_edit ?? true;
  const projectId = useProjectId();
  const currentGroupId = useCurrentGroupId();
  const graphicsObjects = useGraphicsObjects();
  const [autoSortCanvas] = useGraphicsObjectsAutoSortCreateMutation();
  const { addHistory, isReady } = useUndoRedoStore();
 
  return useCallback(async () => {
    if (!canMutate) {
      return;
    }
    if (!currentGroupId) {
      return;
    }
    if (!projectId) {
      return;
    }
    if (!graphicsObjects) {
      toast.info("Canvas objects are still loading.");
      return;
    }
 
    const visibleGraphics = graphicsObjects.filter(
      (graphic) => graphic.visible !== false,
    );
    if (!visibleGraphics.length) {
      toast.warning("No visible canvas objects to sort.");
      return;
    }
 
    try {
      const { movedObjects } = await autoSortCanvas({
        flowsheet: projectId,
        autoSortCanvas: { group: currentGroupId },
      }).unwrap();
 
      if (!movedObjects.length) {
        return;
      }
 
      if (isReady) {
        const [primaryMove, ...groupMoves] = movedObjects;
        // TODO: create a single command for bulk move or multiple actions at once.
        addHistory(
          createMoveCommand({
            objectId: primaryMove.objectId,
            graphicObjectId: primaryMove.graphicObjectId,
            oldPosition: primaryMove.oldPosition,
            newPosition: primaryMove.newPosition,
            groupObjects: groupMoves,
          }),
        );
      }
 
      toast.success(`Auto-sorted ${movedObjects.length} canvas objects.`);
    } catch (error) {
      dispatch(api.util.invalidateTags(["GraphicsObjects"]));
      toast.error("Failed to auto-sort the canvas.");
      console.error("[useAutoSortCanvas] Auto-sort failed:", error);
    }
  }, [
    addHistory,
    autoSortCanvas,
    canMutate,
    currentGroupId,
    dispatch,
    graphicsObjects,
    isReady,
    projectId,
  ]);
}