Canvas: Add modal resources dialog to Overview tab

- Add Add button to Actions component visible only in Overview tab and edit mode
- Create modal dialog with Resources component for adding new resources
- Modal automatically closes when resource is added
- Resources component accepts optional onResourceAdded callback
- Maintain backward compatibility with existing Resources usage

Change-Id: Ib01fe1417ba2bbb7c91f6e1d0551fe9c52ade8c3
diff --git a/apps/canvas/front/src/components/resources.tsx b/apps/canvas/front/src/components/resources.tsx
index cdd58c5..cd17ac6 100644
--- a/apps/canvas/front/src/components/resources.tsx
+++ b/apps/canvas/front/src/components/resources.tsx
@@ -9,7 +9,7 @@
 import { Icon } from "./icon";
 import { AppNode, NodeType } from "config";
 
-function addResource(i: CategoryItem<NodeType>, store: AppState) {
+function addResource(i: CategoryItem<NodeType>, store: AppState, onResourceAdded?: () => void) {
 	const deselected = store.nodes.map((n) => ({
 		...n,
 		selected: false,
@@ -22,18 +22,25 @@
 		selected: true,
 		connectable: true,
 	} as any); // eslint-disable-line @typescript-eslint/no-explicit-any
+	if (onResourceAdded) {
+		onResourceAdded();
+	}
 }
 
-export function Resources() {
+interface ResourcesProps {
+	onResourceAdded?: () => void;
+}
+
+export function Resources({ onResourceAdded }: ResourcesProps = {}) {
 	const store = useStateStore();
 	const categories = useCategories();
 	const projectId = useProjectId();
 	const mode = useMode();
 	const onResourceAdd = useCallback(
 		(item: CategoryItem<NodeType>) => {
-			return () => addResource(item, store);
+			return () => addResource(item, store, onResourceAdded);
 		},
-		[store],
+		[store, onResourceAdded],
 	);
 
 	const [open, setOpen] = useState<string[]>(categories.map((c) => c.title));