diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
index 34f47dde4..4b47856ae 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
@@ -11,6 +11,7 @@ import { track } from "@/customization/utils/analytics";
import { useDarkStore } from "@/stores/darkStore";
import useFlowStore from "@/stores/flowStore";
import { useShortcutsStore } from "@/stores/shortcuts";
+import { useUtilityStore } from "@/stores/utilityStore";
import { VertexBuildTypeAPI } from "@/types/api";
import { NodeDataType } from "@/types/flow";
import { findLastNode } from "@/utils/reactflowUtils";
@@ -34,6 +35,7 @@ export default function NodeStatus({
isOutdated,
isUserEdited,
getValidationStatus,
+ handleUpdateComponent,
}: {
nodeId: string;
display_name: string;
@@ -46,6 +48,7 @@ export default function NodeStatus({
isOutdated: boolean;
isUserEdited: boolean;
getValidationStatus: (data) => VertexBuildTypeAPI | null;
+ handleUpdateComponent: () => void;
}) {
const nodeId_ = data.node?.flow?.data
? (findLastNode(data.node?.flow.data!)?.id ?? nodeId)
@@ -84,6 +87,8 @@ export default function NodeStatus({
getValidationStatus,
);
+ const dismissAll = useUtilityStore((state) => state.dismissAll);
+
const getBaseBorderClass = (selected) => {
let className =
selected && !isBuilding
@@ -91,7 +96,9 @@ export default function NodeStatus({
: "border ring-[0.5px] hover:shadow-node ring-border";
let frozenClass = selected ? "border-ring-frozen" : "border-frozen";
let updateClass =
- isOutdated && !isUserEdited ? "border-warning ring-2 ring-warning" : "";
+ isOutdated && !isUserEdited && !dismissAll
+ ? "border-warning ring-2 ring-warning"
+ : "";
return cn(frozen ? frozenClass : className, updateClass);
};
const getNodeBorderClassName = (
@@ -122,6 +129,7 @@ export default function NodeStatus({
isOutdated,
isUserEdited,
frozen,
+ dismissAll,
]);
useEffect(() => {
@@ -248,6 +256,36 @@ export default function NodeStatus({
)}
+ {dismissAll && isOutdated && !isUserEdited && (
+
+ {
+ e.stopPropagation();
+ handleUpdateComponent();
+ e.stopPropagation();
+ }}
+ >
+ {showNode && (
+
+ )}
+
+
+ )}
>
) : (
diff --git a/src/frontend/src/CustomNodes/GenericNode/index.tsx b/src/frontend/src/CustomNodes/GenericNode/index.tsx
index 0e149f633..1d4be5b2e 100644
--- a/src/frontend/src/CustomNodes/GenericNode/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/index.tsx
@@ -20,6 +20,7 @@ import { NodeDataType } from "../../types/flow";
import { checkHasToolMode } from "../../utils/reactflowUtils";
import { classNames, cn } from "../../utils/utils";
+import { useUtilityStore } from "@/stores/utilityStore";
import { processNodeAdvancedFields } from "../helpers/process-node-advanced-fields";
import useCheckCodeValidity from "../hooks/use-check-code-validity";
import useUpdateNodeCode from "../hooks/use-update-node-code";
@@ -87,6 +88,7 @@ function GenericNode({
const edges = useFlowStore((state) => state.edges);
const shortcuts = useShortcutsStore((state) => state.shortcuts);
const buildStatus = useBuildStatus(data, data.id);
+ const dismissAll = useUtilityStore((state) => state.dismissAll);
const showNode = data.showNode ?? true;
@@ -322,6 +324,7 @@ function GenericNode({
isOutdated={isOutdated}
isUserEdited={isUserEdited}
getValidationStatus={getValidationStatus}
+ handleUpdateComponent={handleUpdateCode}
/>
);
}, [
@@ -332,6 +335,8 @@ function GenericNode({
isOutdated,
isUserEdited,
getValidationStatus,
+ dismissAll,
+ handleUpdateCode,
]);
const renderDescription = useCallback(() => {
@@ -359,7 +364,11 @@ function GenericNode({
}, [data, types, isToolMode, showNode, shownOutputs, showHiddenOutputs]);
return (
-
+
{memoizedNodeToolbarComponent}
- {isOutdated && !isUserEdited && (
+ {isOutdated && !isUserEdited && !dismissAll && (
{/* Left Section */}
diff --git a/src/frontend/src/hooks/use-reset-dismiss-update-all.ts b/src/frontend/src/hooks/use-reset-dismiss-update-all.ts
new file mode 100644
index 000000000..a49f3e773
--- /dev/null
+++ b/src/frontend/src/hooks/use-reset-dismiss-update-all.ts
@@ -0,0 +1,14 @@
+import { useEffect } from "react";
+import { useLocation } from "react-router-dom";
+import { useUtilityStore } from "../stores/utilityStore";
+export const useResetDismissUpdateAll = () => {
+ const location = useLocation();
+ const flowLocationPath = location.pathname.includes("flow");
+ const setDismissAll = useUtilityStore((state) => state.setDismissAll);
+
+ useEffect(() => {
+ if (flowLocationPath) {
+ setDismissAll(false);
+ }
+ }, [location]);
+};
diff --git a/src/frontend/src/pages/FlowPage/components/UpdateAllComponents/index.tsx b/src/frontend/src/pages/FlowPage/components/UpdateAllComponents/index.tsx
index 3928367aa..9e06919c4 100644
--- a/src/frontend/src/pages/FlowPage/components/UpdateAllComponents/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/UpdateAllComponents/index.tsx
@@ -9,6 +9,7 @@ import useAlertStore from "@/stores/alertStore";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import useFlowStore from "@/stores/flowStore";
import { useTypesStore } from "@/stores/typesStore";
+import { useUtilityStore } from "@/stores/utilityStore";
import { cn } from "@/utils/utils";
import { useUpdateNodeInternals } from "@xyflow/react";
import { useState } from "react";
@@ -27,6 +28,8 @@ export default function UpdateAllComponents() {
const [dismissed, setDismissed] = useState(false);
+ const setDismissAll = useUtilityStore((state) => state.setDismissAll);
+
const handleUpdateAllComponents = () => {
setLoadingUpdate(true);
takeSnapshot();
@@ -124,8 +127,10 @@ export default function UpdateAllComponents() {
variant="link"
size="icon"
className="shrink-0 text-sm text-warning-foreground"
- onClick={() => {
+ onClick={(e) => {
setDismissed(true);
+ setDismissAll(true);
+ e.stopPropagation();
}}
>
Dismiss
diff --git a/src/frontend/src/stores/utilityStore.ts b/src/frontend/src/stores/utilityStore.ts
index fc302836a..4b4308597 100644
--- a/src/frontend/src/stores/utilityStore.ts
+++ b/src/frontend/src/stores/utilityStore.ts
@@ -3,6 +3,8 @@ import { UtilityStoreType } from "@/types/zustand/utility";
import { create } from "zustand";
export const useUtilityStore = create((set, get) => ({
+ dismissAll: false,
+ setDismissAll: (dismissAll: boolean) => set({ dismissAll }),
chatValueStore: "",
setChatValueStore: (value: string) => set({ chatValueStore: value }),
selectedItems: [],
diff --git a/src/frontend/src/style/index.css b/src/frontend/src/style/index.css
index 217337401..914d1f287 100644
--- a/src/frontend/src/style/index.css
+++ b/src/frontend/src/style/index.css
@@ -307,7 +307,7 @@
--datatype-fuchsia: 291.1 93.1% 82.9%;
--datatype-fuchsia-foreground: 293.4 69.5% 48.8%;
-
+
--datatype-purple: 268.6 100% 91.8%;
--datatype-purple-foreground: 272.1 71.7% 47.1%;
diff --git a/src/frontend/src/types/zustand/utility/index.ts b/src/frontend/src/types/zustand/utility/index.ts
index 333f30f17..fda8add9d 100644
--- a/src/frontend/src/types/zustand/utility/index.ts
+++ b/src/frontend/src/types/zustand/utility/index.ts
@@ -17,4 +17,6 @@ export type UtilityStoreType = {
setFeatureFlags: (featureFlags: Record) => void;
chatValueStore: string;
setChatValueStore: (value: string) => void;
+ dismissAll: boolean;
+ setDismissAll: (dismissAll: boolean) => void;
};