From 93d5e9b9521c125ee312efbc8f2273e7128f91e6 Mon Sep 17 00:00:00 2001
From: PintoGideon
Date: Tue, 20 Feb 2024 11:33:36 -0500
Subject: [PATCH 1/4] Cleanup
---
src/components/CreateFeed/Pipelines.tsx | 3 +
src/components/CreateFeed/utils.ts | 12 ++-
src/components/Dashboard/index.tsx | 17 ++---
src/components/Feeds/FeedListView.tsx | 11 ++-
src/components/IconContainer/index.tsx | 12 +--
src/components/NodeDetails/PluginTitle.tsx | 5 +-
src/components/NodeDetails/Status.tsx | 7 +-
.../Pipelines/ClipboardCopyCommand.tsx | 12 ++-
src/components/Pipelines/Tree.tsx | 73 ++++++++++---------
src/store/user/types.ts | 2 +-
src/types/index.d.ts | 4 -
vite.config.ts | 22 +++---
12 files changed, 96 insertions(+), 84 deletions(-)
diff --git a/src/components/CreateFeed/Pipelines.tsx b/src/components/CreateFeed/Pipelines.tsx
index d86407130..9bcb4f287 100644
--- a/src/components/CreateFeed/Pipelines.tsx
+++ b/src/components/CreateFeed/Pipelines.tsx
@@ -482,10 +482,13 @@ const Pipelines = ({
}
handleSetCurrentNodeTitle={handleSetCurrentNodeTitle}
/>
+ {/*
+
+ */}
,
): Promise => {
- const arr: any[] = [];
+ const arr: {
+ breadcrumb: string;
+ title: string;
+ key: string;
+ isLeaf: boolean;
+ checkable: boolean;
+ }[] = [];
//@ts-ignore
const { files, folders } = await fetchFilesFromAPath(treeNode.breadcrumb);
const items = [...files, ...folders];
@@ -74,20 +80,20 @@ export const generateTreeNodes = async (
const filePath = items[i].data.fname.split("/");
const fileName = filePath[filePath.length - 1];
arr.push({
- //@ts-ignore
breadcrumb: `${treeNode.breadcrumb}/${fileName}`,
title: fileName,
key: `${treeNode.key}-${i}`,
isLeaf: true,
+ checkable: false,
});
} else {
const checkList = ["uploads", "SERVICES", "PACS"];
const isCheckable = !checkList.includes(items[i]);
arr.push({
- //@ts-ignore
breadcrumb: `${treeNode.breadcrumb}/${items[i]}`,
title: items[i],
key: `${treeNode.key}-${i}`,
+ isLeaf: false,
checkable: isCheckable,
});
}
diff --git a/src/components/Dashboard/index.tsx b/src/components/Dashboard/index.tsx
index c05fd2734..88fa36f5d 100644
--- a/src/components/Dashboard/index.tsx
+++ b/src/components/Dashboard/index.tsx
@@ -1,12 +1,13 @@
import React from "react";
import { useDispatch } from "react-redux";
+import preval from "preval.macro";
import WrapperConnect from "../Wrapper";
import { PageSection, Grid, GridItem } from "@patternfly/react-core";
import { Typography } from "antd";
import { setSidebarActive } from "../../store/ui/actions";
-import "./dashboard.css";
import { InfoIcon } from "../Common";
import { CatalogTile } from "@patternfly/react-catalog-view-extension";
+import "./dashboard.css";
const { Paragraph } = Typography;
@@ -28,15 +29,11 @@ const DashboardPage = (props: DashboardProps) => {
);
}, [dispatch]);
- /*
-
const buildVersion = preval`
const { execSync } = require('child_process')
module.exports = execSync('npm run -s print-version', {encoding: 'utf-8'})
`;
- */
-
return (
@@ -50,7 +47,7 @@ const DashboardPage = (props: DashboardProps) => {
Let's get started.
- Build:
+ Build: {buildVersion}
}
@@ -69,7 +66,7 @@ const DashboardPage = (props: DashboardProps) => {
description={
'Visit the "Library" in the main navigation to review your data collection'
}
- >
+ />{" "}
@@ -80,7 +77,7 @@ const DashboardPage = (props: DashboardProps) => {
description={
'Visit "New and Existing Analyses" in the main navigation to review your data analyses'
}
- >
+ />
@@ -91,7 +88,7 @@ const DashboardPage = (props: DashboardProps) => {
description={
'Visit "PACS Query/Retrieve" in the main navigation to pull medical data and save it your library'
}
- >
+ />
@@ -102,7 +99,7 @@ const DashboardPage = (props: DashboardProps) => {
description={
'Visit "Run a Quick Workflow" to choose from existing analysis templates that allow for detailed analysis'
}
- >
+ />
diff --git a/src/components/Feeds/FeedListView.tsx b/src/components/Feeds/FeedListView.tsx
index 0c7f90b62..e13258eae 100644
--- a/src/components/Feeds/FeedListView.tsx
+++ b/src/components/Feeds/FeedListView.tsx
@@ -96,13 +96,20 @@ const TableSelectable: React.FunctionComponent = () => {
(state) => state.feed,
);
- const onSetPage = (_e: any, newPage: number) => {
+ const onSetPage = (
+ _e: React.MouseEvent | React.KeyboardEvent | MouseEvent,
+ newPage: number,
+ ) => {
navigate(
`/feeds?search=${search}&searchType=${searchType}&page=${newPage}&perPage=${perPage}&type=${type}`,
);
};
- const onPerPageSelect = (_e: any, newPerPage: number, newPage: number) => {
+ const onPerPageSelect = (
+ _e: React.MouseEvent | React.KeyboardEvent | MouseEvent,
+ newPerPage: number,
+ newPage: number,
+ ) => {
navigate(
`/feeds?search=${search}&searchType=${searchType}&page=${newPage}&perPage=${newPerPage}&type=${type}`,
);
diff --git a/src/components/IconContainer/index.tsx b/src/components/IconContainer/index.tsx
index 158f1d8b0..7c22f480c 100644
--- a/src/components/IconContainer/index.tsx
+++ b/src/components/IconContainer/index.tsx
@@ -131,9 +131,9 @@ const IconContainer = ({ allFeeds }: { allFeeds: Feed[] }) => {
});
};
- const handleDelete = (bulkSelect: Feed[]) => {
+ const handleDelete = async (bulkSelect: Feed[]) => {
if (bulkSelect && allFeeds) {
- bulkSelect.forEach(async (feed: Feed) => {
+ for (const feed of bulkSelect) {
try {
await feed.delete();
} catch (error: any) {
@@ -142,13 +142,13 @@ const IconContainer = ({ allFeeds }: { allFeeds: Feed[] }) => {
: error.message;
handleError(errorMessage);
}
- });
+ }
dispatch(setBulkSelect([], false));
- handleModalToggle(false);
queryClient.invalidateQueries({
queryKey: ["feeds"],
});
+ handleModalToggle(false);
}
};
@@ -240,8 +240,8 @@ const IconContainer = ({ allFeeds }: { allFeeds: Feed[] }) => {
const feedIdList = [];
const data = feedList[i].data;
const newFeedName = feedName
- ? feedName + "-" + data.name
- : "duplicate-" + data.name;
+ ? `${feedName}-${data.name}`
+ : `duplicate-${data.name}`;
feedIdList.push(data.id);
try {
const createdFeed: Feed = await cujs.mergeMultipleFeeds(
diff --git a/src/components/NodeDetails/PluginTitle.tsx b/src/components/NodeDetails/PluginTitle.tsx
index 5c7b37ab4..14713b0b2 100644
--- a/src/components/NodeDetails/PluginTitle.tsx
+++ b/src/components/NodeDetails/PluginTitle.tsx
@@ -25,7 +25,7 @@ const PluginTitle = () => {
setValue(title);
}, [selectedPlugin]);
- if (selectedPlugin && selectedPlugin.data) {
+ if (selectedPlugin?.data) {
const { title, plugin_version, plugin_name } = selectedPlugin.data;
const pluginName = `${
title ? title : `${plugin_name} v.${plugin_version}`
@@ -97,9 +97,8 @@ const PluginTitle = () => {
)}
>
);
- } else {
- return No Plugin was selected;
}
+ return No Plugin was selected;
};
export default PluginTitle;
diff --git a/src/components/NodeDetails/Status.tsx b/src/components/NodeDetails/Status.tsx
index 6a7440223..a39b0c3f9 100644
--- a/src/components/NodeDetails/Status.tsx
+++ b/src/components/NodeDetails/Status.tsx
@@ -4,8 +4,7 @@ import usePluginInstanceResource from "./usePluginInstanceResource";
const Status = () => {
const pluginInstanceResource = usePluginInstanceResource();
- const pluginStatus =
- pluginInstanceResource && pluginInstanceResource.pluginStatus;
+ const pluginStatus = pluginInstanceResource?.pluginStatus;
if (pluginStatus && pluginStatus.length > 0) {
const items = pluginStatus.map((label: any, index: number) => {
@@ -31,7 +30,9 @@ const Status = () => {
items={items}
/>
);
- } else return null;
+ }
+
+ return null;
};
export default Status;
diff --git a/src/components/Pipelines/ClipboardCopyCommand.tsx b/src/components/Pipelines/ClipboardCopyCommand.tsx
index ab202a8f0..24e7b90f0 100644
--- a/src/components/Pipelines/ClipboardCopyCommand.tsx
+++ b/src/components/Pipelines/ClipboardCopyCommand.tsx
@@ -14,13 +14,11 @@ const ClipboardCopyCommand = ({ state }: { state: SinglePipeline }) => {
const { currentNode, parameterList } = state;
const params = parameterList && currentNode && parameterList[currentNode];
- const pluginPiping =
- state.pluginPipings &&
- state.pluginPipings.filter((piping) => {
- if (currentNode && piping.data.id === currentNode) {
- return piping;
- }
- });
+ const pluginPiping = state?.pluginPipings?.filter((piping) => {
+ if (currentNode && piping.data.id === currentNode) {
+ return piping;
+ }
+ });
let generatedCommand = "";
diff --git a/src/components/Pipelines/Tree.tsx b/src/components/Pipelines/Tree.tsx
index da21a1596..c64dd8691 100644
--- a/src/components/Pipelines/Tree.tsx
+++ b/src/components/Pipelines/Tree.tsx
@@ -132,11 +132,12 @@ const Tree = (props: TreeProps) => {
pluginParameters,
currentPipelineId,
handleSetCurrentNodeCallback,
+ pipelinePlugins?.[0],
]);
React.useEffect(() => {
//@ts-ignore
- if (size && size.width) {
+ if (size?.width) {
setTranslate({
//@ts-ignore
x: size.width / 2.5,
@@ -158,7 +159,7 @@ const Tree = (props: TreeProps) => {
const newLinksToAdd: any[] = [];
if (tsIds) {
- links.forEach((link) => {
+ for (const link of links) {
const targetId = link.target.data.id;
const sourceId = link.target.data.id;
@@ -174,24 +175,22 @@ const Tree = (props: TreeProps) => {
const parents = tsIds[topologicalLink.data.id];
const dict: any = {};
- links &&
- links.forEach((link) => {
- for (let i = 0; i < parents.length; i++) {
- if (
- link.source.data.id === parents[i] &&
- !dict[link.source.data.id]
- ) {
- dict[link.source.data.id] = link.source;
- } else if (
- link.target.data.id === parents[i] &&
- !dict[link.target.data.id]
- ) {
- dict[link.target.data.id] = link.target;
- }
- }
- return dict;
- });
+ for (const link of links) {
+ for (let i = 0; i < parents.length; i++) {
+ if (
+ link.source.data.id === parents[i] &&
+ !dict[link.source.data.id]
+ ) {
+ dict[link.source.data.id] = link.source;
+ } else if (
+ link.target.data.id === parents[i] &&
+ !dict[link.target.data.id]
+ ) {
+ dict[link.target.data.id] = link.target;
+ }
+ }
+ }
for (const i in dict) {
newLinksToAdd.push({
@@ -200,7 +199,7 @@ const Tree = (props: TreeProps) => {
});
}
}
- });
+ }
}
newLinks = [...links, ...newLinksToAdd];
}
@@ -211,11 +210,16 @@ const Tree = (props: TreeProps) => {
return (
<>
-
+
{loading ? (
Fetching Pipeline.....
) : translate.x > 0 && translate.y > 0 ? (
+
+ {isError && (
+
{error.message} } />
+ )}
+
+ {isLoading ? (
+
+ ) : pipelines.length > 0 ? (
+ pipelines.map((pipeline: Pipeline) => {
+ return (
+ {
+ handleOnExpand(pipeline);
+ }}
+ key={pipeline.data.id}
+ items={[
+ {
+ key: pipeline.data.id,
+ label: (
+
+
+ {pipeline.data.name}
+
+
+
+
+ {showDelete && (
+
+ )}
+
+
+ ),
+ children:
+ (expanded?.[pipeline.data.id] ||
+ state.pipelineData[pipeline.data.id]) &&
+ !isResourcesLoading &&
+ !isResourceError ? (
+ <>
+
+
+
+
+
+
+
+ >
+ ) : (
+
+ ),
+ },
+ ]}
+ />
+ );
+ })
+ ) : (
+
+ )}
+
+ {/*
+
+ */}
{Object.keys(errors).length > 0 && (
diff --git a/src/components/CreateFeed/createFeedHelper.ts b/src/components/CreateFeed/createFeedHelper.ts
index fc5b72774..1eeb2d1fa 100644
--- a/src/components/CreateFeed/createFeedHelper.ts
+++ b/src/components/CreateFeed/createFeedHelper.ts
@@ -1,9 +1,9 @@
import { Plugin, PluginInstance, PluginParameter } from "@fnndsc/chrisapi";
+import ChrisAPIClient from "../../api/chrisapiclient";
+import { InputType } from "../AddNode/types";
import { unpackParametersIntoObject } from "../AddNode/utils";
import { CreateFeedData } from "./types/feed";
import { PipelineData } from "./types/pipeline";
-import ChrisAPIClient from "../../api/chrisapiclient";
-import { InputType } from "../AddNode/types";
import {
catchError,
@@ -15,9 +15,11 @@ import {
export function getName(selectedConfig: string) {
if (selectedConfig === "fs_plugin") {
return "Analysis Creation using an FS Plugin";
- } else if (selectedConfig === "file_select") {
+ }
+ if (selectedConfig === "file_select") {
return "Analysis Creation using File Select";
- } else return "Analysis Creation";
+ }
+ return "Analysis Creation";
}
export const createFeed = async (
diff --git a/src/components/CreateFeed/types/pipeline.ts b/src/components/CreateFeed/types/pipeline.ts
index 01808b9d9..339946f96 100644
--- a/src/components/CreateFeed/types/pipeline.ts
+++ b/src/components/CreateFeed/types/pipeline.ts
@@ -1,7 +1,7 @@
import {
- PluginPiping,
Pipeline,
PipelinePipingDefaultParameterList,
+ PluginPiping,
} from "@fnndsc/chrisapi";
type ActionMap
= {
@@ -224,6 +224,10 @@ export interface ConfiguartionPageProps {
currentPipelineId: number,
newParamDict: any[],
) => void;
+ handleSetGeneralCompute: (
+ currentPipelineId: number,
+ computeEnv: string,
+ ) => void;
justDisplay?: boolean;
}
diff --git a/src/components/FeedTree/FeedTree.tsx b/src/components/FeedTree/FeedTree.tsx
index c9fcb6b6d..267a01d22 100644
--- a/src/components/FeedTree/FeedTree.tsx
+++ b/src/components/FeedTree/FeedTree.tsx
@@ -1,57 +1,29 @@
-import React, { useRef, useContext } from "react";
-import { useDispatch } from "react-redux";
-import { isEqual } from "lodash";
-import { Switch, Alert, TextInput } from "@patternfly/react-core";
-import { tree, hierarchy, HierarchyPointLink } from "d3-hierarchy";
-import { select, event } from "d3-selection";
-import { zoom as d3Zoom, zoomIdentity } from "d3-zoom";
import { PluginInstance } from "@fnndsc/chrisapi";
+import { Alert, Switch, TextInput } from "@patternfly/react-core";
import RotateLeft from "@patternfly/react-icons/dist/esm/icons/angle-double-left-icon";
import RotateRight from "@patternfly/react-icons/dist/esm/icons/angle-double-right-icon";
-import useSize from "./useSize";
-import Link from "./Link";
-import NodeWrapper from "./Node";
-import { ThemeContext } from "../DarkTheme/useTheme";
-import { TreeNodeDatum, Point, treeAlgorithm } from "./data";
-import TransitionGroupWrapper from "./TransitionGroupWrapper";
-import { TSID } from "./ParentComponent";
-import { useTypedSelector } from "../../store/hooks";
+import { HierarchyPointLink, hierarchy, tree } from "d3-hierarchy";
+import { event, select } from "d3-selection";
+import { zoom as d3Zoom, zoomIdentity } from "d3-zoom";
+import { isEqual } from "lodash";
+import React, { useRef, useContext } from "react";
+import { useDispatch } from "react-redux";
import {
setFeedLayout,
setSearchFilter,
setTranslate,
} from "../../store/feed/actions";
-import { FeedTreeScaleType, NodeScaleDropdown } from "./Controls";
+import type { FeedTreeProp } from "../../store/feed/types";
+import { useTypedSelector } from "../../store/hooks";
import { getNodeOperations } from "../../store/plugin/actions";
import { switchTreeMode } from "../../store/tsplugins/actions";
-import type { FeedTreeProp } from "../../store/feed/types";
-
-interface Separation {
- siblings: number;
- nonSiblings: number;
-}
-
-interface OwnProps {
- tsIds?: TSID;
- data: TreeNodeDatum[];
- onNodeClick: (node: any) => void;
- onNodeClickTs: (node: PluginInstance) => void;
- translate?: Point;
- scaleExtent: {
- min: number;
- max: number;
- };
- zoom: number;
- nodeSize: {
- x: number;
- y: number;
- };
- separation: Separation;
- orientation: "horizontal" | "vertical";
- changeOrientation: (orientation: string) => void;
-}
-
-type AllProps = OwnProps;
+import { ThemeContext } from "../DarkTheme/useTheme";
+import { FeedTreeScaleType, NodeScaleDropdown } from "./Controls";
+import Link from "./Link";
+import NodeWrapper from "./Node";
+import TransitionGroupWrapper from "./TransitionGroupWrapper";
+import TreeNodeDatum, { Point, treeAlgorithm, OwnProps } from "./data";
+import useSize from "./useSize";
type FeedTreeState = {
d3: {
@@ -68,7 +40,7 @@ type FeedTreeState = {
search: boolean;
};
-function calculateD3Geometry(nextProps: AllProps, feedTreeProp: FeedTreeProp) {
+function calculateD3Geometry(nextProps: OwnProps, feedTreeProp: FeedTreeProp) {
let scale;
if (nextProps.zoom > nextProps.scaleExtent.max) {
scale = nextProps.scaleExtent.max;
@@ -84,7 +56,7 @@ function calculateD3Geometry(nextProps: AllProps, feedTreeProp: FeedTreeProp) {
}
function getInitialState(
- props: AllProps,
+ props: OwnProps,
feedTreeProp: FeedTreeProp,
): FeedTreeState {
return {
@@ -102,7 +74,7 @@ function getInitialState(
const svgClassName = "feed-tree__svg";
const graphClassName = "feed-tree__graph";
-const FeedTree = (props: AllProps) => {
+const FeedTree = (props: OwnProps) => {
const { isDarkTheme } = useContext(ThemeContext);
const dispatch = useDispatch();
@@ -232,6 +204,7 @@ const FeedTree = (props: AllProps) => {
const [feedState, setFeedState] = React.useState(
getInitialState(props, feedTreeProp),
);
+
const { scale } = feedState.d3;
const { changeOrientation, zoom, scaleExtent } = props;
@@ -495,7 +468,7 @@ const FeedTree = (props: AllProps) => {
const FeedTreeMemoed = React.memo(
FeedTree,
- (prevProps: AllProps, nextProps: AllProps) => {
+ (prevProps: OwnProps, nextProps: OwnProps) => {
if (
!isEqual(prevProps.data, nextProps.data) ||
prevProps.zoom !== nextProps.zoom ||
diff --git a/src/components/FeedTree/Marker.tsx b/src/components/FeedTree/Marker.tsx
index 14bc6dd8c..2d6ce393f 100644
--- a/src/components/FeedTree/Marker.tsx
+++ b/src/components/FeedTree/Marker.tsx
@@ -1,5 +1,5 @@
-import React, { useRef, useEffect } from "react";
import { select } from "d3-selection";
+import React, { useRef, useEffect } from "react";
const Marker = () => {
const markerRef = useRef(null);
@@ -18,7 +18,7 @@ const Marker = () => {
return (
-
+
);
};
diff --git a/src/components/FeedTree/Node.tsx b/src/components/FeedTree/Node.tsx
index ea702b641..d58d6b127 100644
--- a/src/components/FeedTree/Node.tsx
+++ b/src/components/FeedTree/Node.tsx
@@ -1,13 +1,13 @@
-import React, { Fragment, useRef, useContext } from "react";
-import { ThemeContext } from "../DarkTheme/useTheme";
-import { select } from "d3-selection";
-import { HierarchyPointNode } from "d3-hierarchy";
-import { Datum, TreeNodeDatum, Point } from "./data";
import { PluginInstance } from "@fnndsc/chrisapi";
-import { useTypedSelector } from "../../store/hooks";
-import { FeedTreeScaleType } from "./Controls";
+import { HierarchyPointNode } from "d3-hierarchy";
+import { select } from "d3-selection";
+import React, { Fragment, useRef, useContext } from "react";
import { useDispatch } from "react-redux";
+import { useTypedSelector } from "../../store/hooks";
import { getSelectedD3Node } from "../../store/pluginInstance/actions";
+import { ThemeContext } from "../DarkTheme/useTheme";
+import { FeedTreeScaleType } from "./Controls";
+import TreeNodeDatum, { Datum, Point } from "./data";
type NodeWrapperProps = {
tsNodes?: PluginInstance[];
@@ -76,7 +76,7 @@ const Node = (props: NodeProps) => {
React.useEffect(() => {
const nodeTransform = setNodeTransform(orientation, position);
applyNodeTransform(nodeTransform);
- }, [orientation, position]);
+ }, [orientation, position, applyNodeTransform]);
let statusClass = "";
let tsClass = "";
@@ -171,7 +171,7 @@ const Node = (props: NodeProps) => {
strokeWidth: currentId ? "3px" : "1px",
}}
r={DEFAULT_NODE_CIRCLE_RADIUS}
- >
+ />
{overlaySize && (
{
const currentId = useTypedSelector((state) => {
if (state.instance.selectedPlugin?.data.id === data.id) return true;
- else return false;
+ return false;
});
React.useEffect(() => {
if (currentId) dispatch(getSelectedD3Node(data));
}, [currentId, data, dispatch]);
- let scale; // undefined scale is treated as no indvidual scaling
+ let scale: number | undefined; // undefined scale is treated as no indvidual scaling
if (overlayScale === "time") {
const instanceData = props.data.item?.data;
if (instanceData) {
@@ -214,8 +214,6 @@ const NodeWrapper = (props: NodeWrapperProps) => {
const end = new Date(instanceData?.end_date);
scale = Math.log10(end.getTime() - start.getTime()) / 2;
}
- } else if (overlayScale === "size") {
- // props.data.item?.
}
return (
diff --git a/src/components/FeedTree/ParentComponent.tsx b/src/components/FeedTree/ParentComponent.tsx
index a4a7b5d52..7d002df77 100644
--- a/src/components/FeedTree/ParentComponent.tsx
+++ b/src/components/FeedTree/ParentComponent.tsx
@@ -4,7 +4,7 @@ import { useDispatch } from "react-redux";
import { PluginInstance } from "@fnndsc/chrisapi";
import { setFeedTreeProp } from "../../store/feed/actions";
import FeedTree from "./FeedTree";
-import { getFeedTree, TreeNodeDatum, getTsNodes } from "./data";
+import TreeNodeDatum, { getFeedTree, getTsNodes } from "./data";
import { useTypedSelector } from "../../store/hooks";
import { SpinContainer } from "../Common";
import "./FeedTree.css";
diff --git a/src/components/FeedTree/data.ts b/src/components/FeedTree/data.ts
index 4285807de..63c6337c0 100644
--- a/src/components/FeedTree/data.ts
+++ b/src/components/FeedTree/data.ts
@@ -1,9 +1,11 @@
import {
+ PipelinePipingDefaultParameterList,
PluginInstance,
PluginParameter,
PluginPiping,
} from "@fnndsc/chrisapi";
import { fetchResource } from "../../api/common";
+import { TSID } from "./ParentComponent";
export interface Datum {
id?: number;
@@ -18,7 +20,7 @@ export interface Point {
y: number;
}
-export interface TreeNodeDatum extends Datum {
+export default interface TreeNodeDatum extends Datum {
children: TreeNodeDatum[];
__rd3t: {
id: string;
@@ -27,13 +29,38 @@ export interface TreeNodeDatum extends Datum {
};
}
+export interface Separation {
+ siblings: number;
+ nonSiblings: number;
+}
+
+export interface OwnProps {
+ tsIds?: TSID;
+ data: TreeNodeDatum[];
+ onNodeClick: (node: any) => void;
+ onNodeClickTs: (node: PluginInstance) => void;
+ translate?: Point;
+ scaleExtent: {
+ min: number;
+ max: number;
+ };
+ zoom: number;
+ nodeSize: {
+ x: number;
+ y: number;
+ };
+ separation: Separation;
+ orientation: "horizontal" | "vertical";
+ changeOrientation: (orientation: string) => void;
+}
+
export const getFeedTree = (items: PluginInstance[]) => {
- const tree = [],
- mappedArr: {
- [key: string]: TreeNodeDatum;
- } = {};
+ const tree = [];
+ const mappedArr: {
+ [key: string]: TreeNodeDatum;
+ } = {};
- items.forEach((item) => {
+ for (const item of items) {
const id = item.data.id;
mappedArr[id] = {
@@ -48,7 +75,7 @@ export const getFeedTree = (items: PluginInstance[]) => {
collapsed: false,
},
};
- });
+ }
for (const id in mappedArr) {
const mappedElem = mappedArr[id];
@@ -96,7 +123,7 @@ export const getTsNodes = async (items: PluginInstance[]) => {
export const getTsNodesWithPipings = async (
items: PluginPiping[],
- pluginParameters?: any[],
+ pluginParameters?: PipelinePipingDefaultParameterList,
) => {
const parentIds: {
[key: string]: number[];
diff --git a/src/components/Feeds/FeedListView.tsx b/src/components/Feeds/FeedListView.tsx
index e13258eae..5adb42d83 100644
--- a/src/components/Feeds/FeedListView.tsx
+++ b/src/components/Feeds/FeedListView.tsx
@@ -1,48 +1,48 @@
-import React, { useContext } from "react";
-import { useNavigate } from "react-router";
-import { useDispatch } from "react-redux";
-import { format } from "date-fns";
-import { useQuery } from "@tanstack/react-query";
+import type { Feed } from "@fnndsc/chrisapi";
import { ChartDonutUtilization } from "@patternfly/react-charts";
-import { Table, Thead, Tr, Th, Tbody, Td } from "@patternfly/react-table";
import {
- Tooltip,
- Checkbox,
- PageSection,
- Pagination,
Bullseye,
+ Button,
+ Checkbox,
EmptyState,
- EmptyStateVariant,
- EmptyStateIcon,
EmptyStateHeader,
+ EmptyStateIcon,
+ EmptyStateVariant,
+ PageSection,
+ Pagination,
Skeleton,
ToggleGroup,
ToggleGroupItem,
ToggleGroupItemProps,
- Button,
+ Tooltip,
} from "@patternfly/react-core";
import SearchIcon from "@patternfly/react-icons/dist/esm/icons/search-icon";
+import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
+import { useQuery } from "@tanstack/react-query";
import { Typography } from "antd";
import { cujs } from "chris-utility";
-import { useTypedSelector } from "../../store/hooks";
-import { usePaginate, useSearchQueryParams } from "./usePaginate";
+import { format } from "date-fns";
+import React, { useContext } from "react";
+import { useDispatch } from "react-redux";
+import { useNavigate } from "react-router";
import {
- setBulkSelect,
- removeBulkSelect,
removeAllSelect,
- toggleSelectAll,
+ removeBulkSelect,
setAllSelect,
+ setBulkSelect,
+ toggleSelectAll,
} from "../../store/feed/actions";
+import { useTypedSelector } from "../../store/hooks";
import { setSidebarActive } from "../../store/ui/actions";
-import type { Feed } from "@fnndsc/chrisapi";
+import { AddNodeProvider } from "../AddNode/context";
+import { DataTableToolbar, InfoIcon } from "../Common";
import CreateFeed from "../CreateFeed/CreateFeed";
-import IconContainer from "../IconContainer";
-import WrapperConnect from "../Wrapper";
-import { InfoIcon, DataTableToolbar } from "../Common";
import { CreateFeedProvider, PipelineProvider } from "../CreateFeed/context";
-import { AddNodeProvider } from "../AddNode/context";
import { ThemeContext } from "../DarkTheme/useTheme";
-import { fetchPublicFeeds, fetchFeeds } from "./utilties";
+import IconContainer from "../IconContainer";
+import WrapperConnect from "../Wrapper";
+import { usePaginate, useSearchQueryParams } from "./usePaginate";
+import { fetchFeeds, fetchPublicFeeds } from "./utilties";
const { Paragraph } = Typography;
diff --git a/src/components/Feeds/FeedView.tsx b/src/components/Feeds/FeedView.tsx
index 26d5c096e..25f718eb9 100644
--- a/src/components/Feeds/FeedView.tsx
+++ b/src/components/Feeds/FeedView.tsx
@@ -1,40 +1,44 @@
-import * as React from "react";
-import { useNavigate, useParams } from "react-router";
-import { useQuery } from "@tanstack/react-query";
+import type { Feed, PluginInstance } from "@fnndsc/chrisapi";
import {
Drawer,
- DrawerPanelContent,
DrawerContent,
DrawerContentBody,
+ DrawerPanelContent,
} from "@patternfly/react-core";
+import { useQuery } from "@tanstack/react-query";
+import * as React from "react";
import { useDispatch } from "react-redux";
-import { useTypedSelector } from "../../store/hooks";
-import { DrawerActionButton } from "./DrawerUtils";
-import { handleMaximize, handleMinimize } from "./utilties";
-import type { DestroyActiveResources } from "../../store/resources/types";
-import { setIsNavOpen, setSidebarActive } from "../../store/ui/actions";
+import { useNavigate, useParams } from "react-router";
+import { clearSelectedFile } from "../../store/explorer/actions";
import {
getFeedSuccess,
resetFeed,
setShowToolbar,
} from "../../store/feed/actions";
+import { useTypedSelector } from "../../store/hooks";
import {
getPluginInstancesRequest,
getSelectedD3Node,
getSelectedPlugin,
resetPluginInstances,
} from "../../store/pluginInstance/actions";
-import { clearSelectedFile } from "../../store/explorer/actions";
+import { resetActiveResources } from "../../store/resources/actions";
+import type { DestroyActiveResources } from "../../store/resources/types";
import { addTSNodes, resetTsNodes } from "../../store/tsplugins/actions";
-import ParentComponent from "../FeedTree/ParentComponent";
-import type { PluginInstance, Feed } from "@fnndsc/chrisapi";
+import { setIsNavOpen, setSidebarActive } from "../../store/ui/actions";
+import FeedOutputBrowser from "../FeedOutputBrowser/FeedOutputBrowser";
import FeedGraph from "../FeedTree/FeedGraph";
+import ParentComponent from "../FeedTree/ParentComponent";
import NodeDetails from "../NodeDetails/NodeDetails";
import WrapperConnect from "../Wrapper";
-import { resetActiveResources } from "../../store/resources/actions";
-import FeedOutputBrowser from "../FeedOutputBrowser/FeedOutputBrowser";
-import { fetchAuthenticatedFeed, fetchPublicFeed } from "./utilties";
+import { DrawerActionButton } from "./DrawerUtils";
import { useSearchQueryParams } from "./usePaginate";
+import {
+ fetchAuthenticatedFeed,
+ fetchPublicFeed,
+ handleMaximize,
+ handleMinimize,
+} from "./utilties";
export default function FeedView() {
const query = useSearchQueryParams();
diff --git a/src/components/NodeDetails/NodeDetails.tsx b/src/components/NodeDetails/NodeDetails.tsx
index c439486dc..b508debe2 100644
--- a/src/components/NodeDetails/NodeDetails.tsx
+++ b/src/components/NodeDetails/NodeDetails.tsx
@@ -1,34 +1,34 @@
-import React, { Fragment, ReactNode } from "react";
-import {
- Button,
- Grid,
- GridItem,
- ExpandableSection,
-} from "@patternfly/react-core";
import {
Plugin,
PluginInstance,
PluginInstanceDescendantList,
PluginParameterList,
} from "@fnndsc/chrisapi";
-import { useNavigate } from "react-router";
-import { ErrorBoundary } from "react-error-boundary";
+import {
+ Button,
+ ExpandableSection,
+ Grid,
+ GridItem,
+} from "@patternfly/react-core";
import CalendarAlt from "@patternfly/react-icons/dist/esm/icons/calendar-alt-icon";
+import React, { Fragment, ReactNode } from "react";
+import { ErrorBoundary } from "react-error-boundary";
+import { useNavigate } from "react-router";
+import { useTypedSelector } from "../../store/hooks";
import AddNodeConnect from "../AddNode/AddNode";
+import { AddNodeProvider } from "../AddNode/context";
+import AddPipeline from "../AddPipeline/AddPipeline";
+import GraphNodeContainer from "../AddTsNode";
+import { SpinContainer } from "../Common";
+import { PipelineProvider } from "../PipelinesCopy/context";
import DeleteNode from "../DeleteNode";
+import FeedNote from "../FeedDetails/FeedNote";
+import "./NodeDetails.css";
import PluginLog from "./PluginLog";
+import PluginTitle from "./PluginTitle";
import Status from "./Status";
import StatusTitle from "./StatusTitle";
-import PluginTitle from "./PluginTitle";
-import GraphNodeContainer from "../AddTsNode";
-import AddPipeline from "../AddPipeline/AddPipeline";
-import FeedNote from "../FeedDetails/FeedNote";
-import { useTypedSelector } from "../../store/hooks";
import { getErrorCodeMessage } from "./utils";
-import { SpinContainer } from "../Common";
-import { PipelineProvider } from "../CreateFeed/context";
-import { AddNodeProvider } from "../AddNode/context";
-import "./NodeDetails.css";
interface INodeState {
plugin?: Plugin;
@@ -128,7 +128,7 @@ const NodeDetails: React.FC = () => {
fallback={
);
-};
+}
export default GeneralCompute;
diff --git a/src/components/Pipelines/ListCompute.tsx b/src/components/Pipelines/ListCompute.tsx
index c567f0130..cf9539730 100644
--- a/src/components/Pipelines/ListCompute.tsx
+++ b/src/components/Pipelines/ListCompute.tsx
@@ -11,43 +11,44 @@ const ListCompute = ({
dispatchFn: (item: any) => void;
}) => {
return (
- 0 ? computeList : []}
- renderItem={(item: any) => {
- return (
-
-
- {
- dispatchFn(item);
- }}
- />
-
-
- >
- }
- title={item.name}
- description={item.description}
- />
-
- );
- }}
- />
+ <>
+ 0 ? computeList : []}
+ renderItem={(item: any) => {
+ return (
+
+
+ {
+ dispatchFn(item);
+ }}
+ />
+
+ >
+ }
+ title={item.name}
+ description={item.description}
+ />
+
+ );
+ }}
+ />
+ >
);
};
diff --git a/src/components/Pipelines/NodeData.tsx b/src/components/Pipelines/NodeData.tsx
index 5d4d0ecde..a873fb025 100644
--- a/src/components/Pipelines/NodeData.tsx
+++ b/src/components/Pipelines/NodeData.tsx
@@ -1,10 +1,9 @@
-import React, { useRef, useContext } from "react";
-
import { HierarchyPointNode } from "d3-hierarchy";
import { select } from "d3-selection";
+import React, { useContext, useRef } from "react";
import { TreeNode } from "../../api/common";
-import { fetchComputeInfo, stringToColour } from "../CreateFeed/utils";
import { SinglePipeline } from "../CreateFeed/types/pipeline";
+import { fetchComputeInfo, stringToColour } from "../CreateFeed/utils";
import { ThemeContext } from "../DarkTheme/useTheme";
export interface Point {
@@ -62,7 +61,7 @@ const NodeData = (props: NodeProps) => {
} = props;
const { computeEnvs, title, currentNode, pluginPipings } = state;
- const root = pluginPipings && pluginPipings[0];
+ const root = pluginPipings?.[0];
let currentId = NaN;
if (data.previous_id && root) {
@@ -72,18 +71,25 @@ const NodeData = (props: NodeProps) => {
}
let currentComputeEnv = "";
- if (computeEnvs && computeEnvs[data.id]) {
+ if (computeEnvs?.[data.id]) {
currentComputeEnv = computeEnvs[data.id].currentlySelected;
}
- const titleName = title && title[data.id];
+ const titleName = title?.[data.id];
const applyNodeTransform = (transform: string, opacity = 1) => {
select(nodeRef.current)
.attr("transform", transform)
.style("opacity", opacity);
+
+ select(textRef.current).attr("transform", "translate(-30, 30)");
};
+ React.useEffect(() => {
+ const nodeTransform = setNodeTransform(orientation, position);
+ applyNodeTransform(nodeTransform);
+ }, [orientation, position, applyNodeTransform]);
+
const handleSetComputeEnvironmentsWrap = React.useCallback(
(computeEnvData: {
[x: number]: {
@@ -107,13 +113,8 @@ const NodeData = (props: NodeProps) => {
fetchComputeEnvironments();
}, [data, handleSetComputeEnvironmentsWrap]);
- React.useEffect(() => {
- const nodeTransform = setNodeTransform(orientation, position);
- applyNodeTransform(nodeTransform);
- }, [orientation, position]);
-
const textLabel = (
-
+
{
return (
{
@@ -147,7 +145,7 @@ const NodeData = (props: NodeProps) => {
}}
id={`node_${data.id}`}
r={DEFAULT_NODE_CIRCLE_RADIUS}
- >
+ />
{textLabel}
);
diff --git a/src/components/Pipelines/TitleChange.tsx b/src/components/Pipelines/TitleChange.tsx
index 23dd5004a..a9e12fae2 100644
--- a/src/components/Pipelines/TitleChange.tsx
+++ b/src/components/Pipelines/TitleChange.tsx
@@ -39,14 +39,11 @@ const TitleChange = ({
display: "flex",
alignItems: "center",
marginBottom: "1rem",
+ marginRight: "1rem",
}}
>
void;
+
+ translate?: Point;
+ scaleExtent: {
+ min: number;
+ max: number;
+ };
+ zoom?: number;
+ nodeSize?: {
+ x: number;
+ y: number;
+ };
+ separation?: Separation;
+ orientation?: "horizontal" | "vertical";
}
const Tree = (props: TreeProps) => {
@@ -62,7 +72,6 @@ const Tree = (props: TreeProps) => {
const size = useSize(divRef);
const { currentPipelineId, state, handleSetCurrentNode } = props;
const { pluginPipings, pipelinePlugins, pluginParameters } = state;
-
const [loading, setLoading] = React.useState(false);
const {
handleNodeClick,
@@ -72,7 +81,7 @@ const Tree = (props: TreeProps) => {
const [data, setData] = React.useState();
const [tsIds, setTsIds] = React.useState();
-
+ const { zoom, scaleExtent } = props;
const bindZoomListener = React.useCallback(() => {
const svg = select(`.${svgClassName}`);
const g = select(`.${graphClassName}`);
@@ -91,7 +100,7 @@ const Tree = (props: TreeProps) => {
g.attr("transform", event.transform);
}),
);
- }, [translate.x, translate.y]);
+ }, [zoom, scaleExtent, translate.x, translate.y]);
React.useEffect(() => {
bindZoomListener();
@@ -211,15 +220,22 @@ const Tree = (props: TreeProps) => {
return (
<>
{loading ? (
-
Fetching Pipeline.....
+
) : translate.x > 0 && translate.y > 0 ? (
-
} />
- )}
-
- {isLoading ? (
-
- ) : pipelines.length > 0 ? (
- pipelines.map((pipeline: Pipeline) => {
- return (
- {
- handleOnExpand(pipeline);
- }}
- key={pipeline.data.id}
- items={[
- {
- key: pipeline.data.id,
- label: (
-
-
- {pipeline.data.name}
-
-
-
-
- {showDelete && (
-
- )}
-
-
- ),
- children:
- (expanded?.[pipeline.data.id] ||
- state.pipelineData[pipeline.data.id]) &&
- !isResourcesLoading &&
- !isResourceError ? (
- <>
-
-
-
-
-
-
-
- >
- ) : (
-
- ),
- },
- ]}
- />
- );
- })
- ) : (
-
- )}
-
- {/*
-
-
- */}
-
-
- {Object.keys(errors).length > 0 && (
-
setErrors({})} />
- )}
-
- {isResourceError && (
-
- )}
-
- >
- );
-};
-
-export default Pipelines;
diff --git a/src/components/CreateFeed/Review.tsx b/src/components/CreateFeed/Review.tsx
index d51169ba6..c36a699f0 100644
--- a/src/components/CreateFeed/Review.tsx
+++ b/src/components/CreateFeed/Review.tsx
@@ -1,7 +1,8 @@
import { useCallback, useContext, useEffect } from "react";
import { Grid, WizardContext, Split, SplitItem } from "@patternfly/react-core";
import { ChartDonutUtilization } from "@patternfly/react-charts";
-import { CreateFeedContext, PipelineContext } from "./context";
+import { CreateFeedContext } from "./context";
+import { PipelineContext } from "../PipelinesCopy/context";
import { unpackParametersIntoString } from "../AddNode/utils";
import { PluginDetails } from "../AddNode/ReviewGrid";
import { ChrisFileDetails, LocalFileDetails } from "./HelperComponent";
@@ -24,6 +25,8 @@ const Review = ({ handleSave }: { handleSave: () => void }) => {
selectedComputeEnv,
} = addNodeState;
+ const { pipelineToAdd } = pipelineState;
+
// the installed version of @patternfly/react-core doesn't support read-only chips
const tagList = tags.map((tag: any) => (
@@ -125,7 +128,7 @@ const Review = ({ handleSave }: { handleSave: () => void }) => {
);
};
- const feedErrorMessage = (feedError && feedError["error_message"]) || "";
+ const feedErrorMessage = feedError?.error_message || "";
return (
@@ -161,9 +164,7 @@ const Review = ({ handleSave }: { handleSave: () => void }) => {
title={
Selected Pipeline:}
subTitle={
- {pipelineState.pipelineName
- ? pipelineState.pipelineName
- : "None Selected"}
+ {pipelineToAdd ? pipelineToAdd.data.name : "None Selected"}
}
/>
diff --git a/src/components/CreateFeed/context/index.tsx b/src/components/CreateFeed/context/index.tsx
index 8598fbad6..be85a149a 100644
--- a/src/components/CreateFeed/context/index.tsx
+++ b/src/components/CreateFeed/context/index.tsx
@@ -1,10 +1,6 @@
import React, { createContext, useContext, useReducer } from "react";
import { MainRouterContext } from "../../../routes";
import { createFeedReducer, getInitialState } from "../reducer/feedReducer";
-import {
- pipelineReducer,
- getInitialPipelineState,
-} from "../reducer/pipelineReducer";
import { CreateFeedState } from "../types/feed";
const CreateFeedContext = createContext<{
@@ -15,14 +11,6 @@ const CreateFeedContext = createContext<{
dispatch: () => null,
});
-const PipelineContext = createContext<{
- state: any;
- dispatch: any;
-}>({
- state: getInitialPipelineState(),
- dispatch: () => null,
-});
-
interface CreateFeedProviderProps {
children: React.ReactNode;
}
@@ -40,19 +28,4 @@ const CreateFeedProvider: React.FC
= ({
);
};
-const PipelineProvider = ({ children }: CreateFeedProviderProps) => {
- const initialpipelineState = getInitialPipelineState();
- const [state, dispatch] = useReducer(pipelineReducer, initialpipelineState);
- return (
-
- {children}
-
- );
-};
-
-export {
- CreateFeedContext,
- CreateFeedProvider,
- PipelineProvider,
- PipelineContext,
-};
+export { CreateFeedContext, CreateFeedProvider };
diff --git a/src/components/CreateFeed/createFeedHelper.ts b/src/components/CreateFeed/createFeedHelper.ts
index 1eeb2d1fa..2633db222 100644
--- a/src/components/CreateFeed/createFeedHelper.ts
+++ b/src/components/CreateFeed/createFeedHelper.ts
@@ -1,9 +1,13 @@
-import { Plugin, PluginInstance, PluginParameter } from "@fnndsc/chrisapi";
+import {
+ Plugin,
+ PluginInstance,
+ PluginParameter,
+ Feed,
+} from "@fnndsc/chrisapi";
import ChrisAPIClient from "../../api/chrisapiclient";
import { InputType } from "../AddNode/types";
import { unpackParametersIntoObject } from "../AddNode/utils";
import { CreateFeedData } from "./types/feed";
-import { PipelineData } from "./types/pipeline";
import {
catchError,
@@ -11,6 +15,7 @@ import {
limitConcurrency,
uploadWrapper,
} from "../../api/common";
+import { PipelineState } from "../PipelinesCopy/context";
export function getName(selectedConfig: string) {
if (selectedConfig === "fs_plugin") {
@@ -28,17 +33,16 @@ export const createFeed = async (
requiredInput: InputType,
selectedPlugin: Plugin | undefined,
username: string | null | undefined,
- pipelineData: PipelineData,
setUploadFileCallback: (status: number) => void,
setErrorCallback: (error: any) => void,
selectedConfig: string[],
- selectedPipeline?: number,
+ state: PipelineState,
) => {
/**
* Dircopy requires a path from the ChRIS object storage
* as in input
*/
- let feed;
+ let feed: Feed | undefined | null;
if (
selectedConfig.includes("local_select") ||
@@ -47,11 +51,10 @@ export const createFeed = async (
feed = await createFeedInstanceWithDircopy(
data,
username,
- pipelineData,
setUploadFileCallback,
setErrorCallback,
selectedConfig,
- selectedPipeline,
+ state,
);
} else if (selectedConfig.includes("fs_plugin")) {
feed = await createFeedInstanceWithFS(
@@ -67,16 +70,15 @@ export const createFeed = async (
export const createFeedInstanceWithDircopy = async (
data: CreateFeedData,
username: string | null | undefined,
- pipelineData: PipelineData,
setUploadFileCallback: (value: number) => void,
errorCallback: (error: any) => void,
selectedConfig: string[],
- selectedPipeline?: number,
+ state: PipelineState,
) => {
const { chrisFiles, localFiles } = data;
let dirpath: string[] = [];
- let feed;
+ let feed: Feed;
if (selectedConfig.includes("swift_storage")) {
dirpath = chrisFiles.map((path: string) => path);
@@ -108,56 +110,46 @@ export const createFeedInstanceWithDircopy = async (
dir: dirpath.join(","),
},
);
+ const { pipelineToAdd, computeInfo, titleInfo, selectedPipeline } =
+ state;
+ const id = pipelineToAdd?.data.id;
+ const resources = selectedPipeline?.[id];
if (createdInstance) {
- if (selectedPipeline) {
- const pipeline = pipelineData[selectedPipeline];
- if (
- pipeline.pluginPipings &&
- pipeline.pluginParameters &&
- pipeline.pipelinePlugins &&
- pipeline.pluginPipings.length > 0
- ) {
- const { pluginParameters, computeEnvs, parameterList } = pipeline;
-
- const nodes_info = client.computeWorkflowNodesInfo(
- //@ts-ignore
- pluginParameters.data,
- );
-
- nodes_info.forEach((node) => {
- if (computeEnvs && computeEnvs[node["piping_id"]]) {
- const compute_node =
- computeEnvs[node["piping_id"]]["currentlySelected"];
-
- const title =
- pipeline.title && pipeline.title[node["piping_id"]];
- if (title) {
- node.title = title;
- }
- if (compute_node) {
- node.compute_resource_name = compute_node;
- }
- }
-
- if (parameterList && parameterList[node["piping_id"]]) {
- const params = parameterList[node["piping_id"]];
- node["plugin_parameter_defaults"] = params;
- }
- });
-
- await client.createWorkflow(selectedPipeline, {
- previous_plugin_inst_id: createdInstance.data.id,
- nodes_info: JSON.stringify(nodes_info),
- });
+ if (resources) {
+ const { parameters } = resources;
+
+ const nodes_info = client.computeWorkflowNodesInfo(parameters.data);
+
+ for (const node of nodes_info) {
+ // Set compute info
+ const activeNode = computeInfo?.[id][node.piping_id];
+ // Set Title
+ const titleSet = titleInfo?.[id][node.piping_id];
+
+ if (activeNode) {
+ const compute_node = activeNode.currentlySelected;
+ node.compute_resource_name = compute_node;
+ }
+
+ if (titleSet) {
+ node.title = titleSet;
+ }
}
+
+ await client.createWorkflow(id, {
+ previous_plugin_inst_id: createdInstance.data.id,
+ nodes_info: JSON.stringify(nodes_info),
+ });
}
- feed = await createdInstance.getFeed();
+ feed = (await createdInstance.getFeed()) as Feed;
+ return feed;
}
} catch (error) {
console.log("Error", error);
}
+ return null;
//when the `post` finishes, the dircopyInstances's internal collection is updated
}
@@ -165,8 +157,6 @@ export const createFeedInstanceWithDircopy = async (
const errorObj = catchError(error);
errorCallback(errorObj);
}
-
- return feed;
};
export const createFeedInstanceWithFS = async (
diff --git a/src/components/CreateFeed/reducer/pipelineReducer.ts b/src/components/CreateFeed/reducer/pipelineReducer.ts
deleted file mode 100644
index 61530ac94..000000000
--- a/src/components/CreateFeed/reducer/pipelineReducer.ts
+++ /dev/null
@@ -1,228 +0,0 @@
-import {
- PipelineActions,
- PipelineState,
- PipelineTypes,
-} from "../types/pipeline";
-import { merge } from "lodash";
-
-export function getInitialPipelineState() {
- return {
- pipelineData: {},
- pipelineName: "",
- pipelines: [],
- selectedPipeline: undefined,
- };
-}
-
-export const pipelineReducer = (
- state: PipelineState,
- action: PipelineActions,
-) => {
- switch (action.type) {
- case PipelineTypes.DeselectPipeline: {
- return {
- ...state,
- selectedPipeline: undefined,
- };
- }
- case PipelineTypes.SetPipelines: {
- return {
- ...state,
- pipelines: action.payload.pipelines,
- };
- }
-
- case PipelineTypes.AddPipeline: {
- return {
- ...state,
- pipelines: [...state.pipelines, action.payload.pipeline],
- };
- }
- case PipelineTypes.SetPipelineResources: {
- const { pipelineId, pluginPipings, parameters, pipelinePlugins } =
- action.payload;
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [pipelineId]: {
- pluginPipings,
- pluginParameters: parameters,
- pipelinePlugins,
- currentNode: undefined,
- computeEnvs: undefined,
- },
- },
- };
- }
-
- case PipelineTypes.SetCurrentComputeEnvironment: {
- const { item, currentNode, currentPipelineId, computeEnvList } =
- action.payload.computeEnv;
-
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [currentPipelineId]: {
- ...state.pipelineData[currentPipelineId],
- computeEnvs: {
- ...state.pipelineData[currentPipelineId].computeEnvs,
- [currentNode]: {
- computeEnvs: computeEnvList,
- currentlySelected: item.name,
- },
- },
- },
- },
- };
- }
-
- case PipelineTypes.SetGeneralCompute: {
- const { currentPipelineId, computeEnv } = action.payload;
-
- if (state.pipelineData[currentPipelineId].computeEnvs) {
- const computeEnvs = state.pipelineData[currentPipelineId].computeEnvs;
-
- if (computeEnvs) {
- for (const id in computeEnvs) {
- const currentComputeEnvs = computeEnvs[id].computeEnvs;
- const names = currentComputeEnvs.map((env) => env.name);
- if (names.includes(computeEnv)) {
- computeEnvs[id].currentlySelected = computeEnv;
- }
- }
- }
-
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [currentPipelineId]: {
- ...state.pipelineData[currentPipelineId],
- computeEnvs,
- generalCompute: computeEnv,
- },
- },
- };
- } else {
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [currentPipelineId]: {
- ...state.pipelineData[currentPipelineId],
- generalCompute: computeEnv,
- },
- },
- };
- }
- }
-
- case PipelineTypes.SetPipelineEnvironments: {
- const { computeEnvData, pipelineId } = action.payload;
- if (state.pipelineData[pipelineId].computeEnvs) {
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [pipelineId]: {
- ...state.pipelineData[pipelineId],
- computeEnvs: merge(
- state.pipelineData[pipelineId].computeEnvs,
- computeEnvData,
- ),
- },
- },
- };
- } else {
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [pipelineId]: {
- ...state.pipelineData[pipelineId],
- computeEnvs: computeEnvData,
- },
- },
- };
- }
- }
-
- case PipelineTypes.SetCurrentNode: {
- const { pipelineId, currentNode } = action.payload;
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [pipelineId]: {
- ...state.pipelineData[pipelineId],
- currentNode,
- },
- },
- };
- }
-
- case PipelineTypes.SetCurrentPipeline: {
- const { pipelineId } = action.payload;
- return {
- ...state,
- selectedPipeline: pipelineId,
- };
- }
-
- case PipelineTypes.SetPipelineName: {
- const { pipelineName } = action.payload;
-
- return {
- ...state,
- pipelineName,
- };
- }
-
- case PipelineTypes.SetCurrentNodeTitle: {
- const { currentPipelineId, currentNode, title } = action.payload;
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [currentPipelineId]: {
- ...state.pipelineData[currentPipelineId],
- title: {
- ...state.pipelineData[currentPipelineId].title,
- [currentNode]: title,
- },
- },
- },
- };
- }
-
- case PipelineTypes.SetFormParameters: {
- const { currentPipelineId, currentNode, params } = action.payload;
- return {
- ...state,
- pipelineData: {
- ...state.pipelineData,
- [currentPipelineId]: {
- ...state.pipelineData[currentPipelineId],
- parameterList: {
- ...state.pipelineData[currentPipelineId].parameterList,
- [currentNode]: params,
- },
- },
- },
- };
- }
-
- case PipelineTypes.ResetState: {
- return {
- pipelineData: {},
- pipelineName: "",
- pipelines: [],
- selectedPipeline: undefined,
- };
- }
- default:
- return state;
- }
-};
diff --git a/src/components/CreateFeed/types/pipeline.ts b/src/components/CreateFeed/types/pipeline.ts
deleted file mode 100644
index 339946f96..000000000
--- a/src/components/CreateFeed/types/pipeline.ts
+++ /dev/null
@@ -1,239 +0,0 @@
-import {
- Pipeline,
- PipelinePipingDefaultParameterList,
- PluginPiping,
-} from "@fnndsc/chrisapi";
-
-type ActionMap = {
- [Key in keyof M]: M[Key] extends undefined
- ? {
- type: Key;
- }
- : {
- type: Key;
- payload: M[Key];
- };
-};
-
-export enum PipelineTypes {
- SetPipelines = "SET_PIPELINES",
- SetPipelineResources = "SET_PIPELINE_RESOURCES",
- SetCurrentComputeEnvironment = "SET_CURRENT_COMPUTE_ENVIRONMENT",
- SetCurrentNode = "SET_CURRENT_NODE",
- AddPipeline = "ADD_PIPELINE",
- SetCurrentPipeline = "SET_CURRENT_PIPELINE",
- SetPipelineName = "SET_PIPELINE_NAME",
- SetPipelineEnvironments = "SET_PIPELINE_ENVIRONMENTS",
- SetCurrentNodeTitle = "SET_CURRENT_NODE_TITLE",
- SetDefaultParameters = "SET_DEFAULT_PARAMETERS",
- SetGeneralCompute = "SET_GENERAL_COMPUTE",
- SetFormParameters = "SET_FORM_PARAMETERS",
- DeselectPipeline = "DESELECT_PIPELINE",
- ResetState = "RESET_STATE",
-}
-
-export interface ComputeEnvData {
- [key: string]: { computeEnvs: any[]; currentlySelected: any };
-}
-
-type PipelinePayload = {
- [PipelineTypes.SetPipelines]: {
- pipelines: any[];
- };
-
- [PipelineTypes.SetFormParameters]: {
- currentNode: number;
- currentPipelineId: string;
- params: any[];
- };
-
- [PipelineTypes.SetPipelineResources]: {
- pipelineId: number;
- parameters: any[];
- pluginPipings: PluginPiping[];
- pipelinePlugins: any[];
- };
-
- [PipelineTypes.SetCurrentComputeEnvironment]: {
- computeEnv: {
- item: any;
- currentNode: number;
- currentPipelineId: string;
- computeEnvList: any[];
- };
- };
-
- [PipelineTypes.SetCurrentNode]: {
- pipelineId: number;
- currentNode: number;
- };
-
- [PipelineTypes.AddPipeline]: {
- pipeline: any;
- };
-
- [PipelineTypes.SetCurrentPipeline]: {
- pipelineId: number;
- };
-
- [PipelineTypes.SetPipelineName]: {
- pipelineName: string;
- };
-
- [PipelineTypes.SetPipelineEnvironments]: {
- pipelineId: number;
- computeEnvData: {
- [key: string]: {
- computeEnvs: any[];
- currentlySelected: any;
- };
- };
- };
-
- [PipelineTypes.SetCurrentNodeTitle]: {
- currentPipelineId: string;
- currentNode: number;
- title: string;
- };
-
- [PipelineTypes.SetDefaultParameters]: {
- pipelineId: string;
- defaultParameters: [];
- };
-
- [PipelineTypes.DeselectPipeline]: Record;
-
- [PipelineTypes.SetGeneralCompute]: {
- currentPipelineId: number;
- computeEnv: string;
- };
-
- [PipelineTypes.ResetState]: Record;
-};
-
-export type PipelineActions =
- ActionMap[keyof ActionMap];
-
-export interface PipelineState {
- pipelineData: PipelineData;
- pipelineName: string;
- selectedPipeline?: number;
- pipelines: any[];
-}
-
-export interface SinglePipeline {
- pluginParameters?: any[];
- defaultParameters?: any[];
- pluginPipings?: PluginPiping[];
- pipelinePlugins?: any[];
- computeEnvs?: ComputeEnvData;
- currentNode?: number;
- generalCompute?: string;
- title: {
- [id: number]: string;
- };
- parameterList: {
- [id: number]: any[];
- };
-}
-
-export type UploadJsonProps = Resources & PipelineInstanceResource;
-
-export interface Resources {
- parameters: PipelinePipingDefaultParameterList;
- pluginPipings: any[];
- pipelinePlugins: any[];
- pipelineId?: number;
-}
-
-export interface PipelineInstanceResource {
- pipelineInstance: Pipeline;
-}
-
-export interface PipelineData {
- [key: string]: SinglePipeline;
-}
-
-export interface PipelinesProps {
- justDisplay?: boolean;
- handleDispatchPipelines: (registeredPipelines: any) => void;
- handleSetPipelineResources: (result: Resources) => void;
- handleUploadDispatch: (result: UploadJsonProps) => void;
- handleSetCurrentNode: (pipelineId: number, currentNode: number) => void;
- handleCleanResources: () => void;
- handlePipelineSecondaryResource: (pipeline: Pipeline) => void;
- handleSetCurrentNodeTitle: (
- currentPipelineId: number,
- currentNode: number,
- title: string,
- ) => void;
- handleSetPipelineEnvironments: (
- pipelineId: number,
- computeEnvData: {
- [x: number]: {
- computeEnvs: any[];
- currentlySelected: any;
- };
- },
- ) => void;
- handleSetGeneralCompute: (
- currentPipelineId: number,
- computeEnv: string,
- ) => void;
-
- handleSetCurrentComputeEnv: (
- item: {
- name: string;
- description: string;
- },
- currentNode: number,
- currentPipelineId: number,
- computeEnvList: any[],
- ) => void;
-
- handleFormParameters: (
- currentNode: number,
- currentPipelineId: number,
- newParamDict: any[],
- ) => void;
- state: any;
-}
-
-export interface ConfiguartionPageProps {
- pipelines: any;
- currentPipelineId: number;
- pipeline: Pipeline;
- state: SinglePipeline;
- handleSetCurrentNodeTitle: (
- currentPipelineId: number,
- currentNode: number,
- title: string,
- ) => void;
- handleDispatchPipelines: (registeredPipelines: any) => void;
- handleSetCurrentComputeEnv: (
- item: {
- name: string;
- description: string;
- },
- currentNode: number,
- currentPipelineId: number,
- computeEnvList: any[],
- ) => void;
- handleFormParameters: (
- currentNode: number,
- currentPipelineId: number,
- newParamDict: any[],
- ) => void;
- handleSetGeneralCompute: (
- currentPipelineId: number,
- computeEnv: string,
- ) => void;
- justDisplay?: boolean;
-}
-
-export interface CreatePipelineProps {
- pipelines: any;
- pipeline: Pipeline;
- state: SinglePipeline;
- handleDispatchPipelines: (registeredPipelines: any) => void;
-}
diff --git a/src/components/Feeds/FeedListView.tsx b/src/components/Feeds/FeedListView.tsx
index 5adb42d83..7a07b5a7f 100644
--- a/src/components/Feeds/FeedListView.tsx
+++ b/src/components/Feeds/FeedListView.tsx
@@ -37,7 +37,8 @@ import { setSidebarActive } from "../../store/ui/actions";
import { AddNodeProvider } from "../AddNode/context";
import { DataTableToolbar, InfoIcon } from "../Common";
import CreateFeed from "../CreateFeed/CreateFeed";
-import { CreateFeedProvider, PipelineProvider } from "../CreateFeed/context";
+import { CreateFeedProvider } from "../CreateFeed/context";
+import { PipelineProvider } from "../PipelinesCopy/context";
import { ThemeContext } from "../DarkTheme/useTheme";
import IconContainer from "../IconContainer";
import WrapperConnect from "../Wrapper";
diff --git a/src/components/Pipelines/ClipboardCopyCommand.tsx b/src/components/Pipelines/ClipboardCopyCommand.tsx
deleted file mode 100644
index 24e7b90f0..000000000
--- a/src/components/Pipelines/ClipboardCopyCommand.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import React from "react";
-import {
- CodeBlock,
- CodeBlockCode,
- ClipboardCopyButton,
- CodeBlockAction,
- clipboardCopyFunc,
-} from "@patternfly/react-core";
-import { SinglePipeline } from "../CreateFeed/types/pipeline";
-
-const ClipboardCopyCommand = ({ state }: { state: SinglePipeline }) => {
- const [copied, setCopied] = React.useState(false);
-
- const { currentNode, parameterList } = state;
-
- const params = parameterList && currentNode && parameterList[currentNode];
- const pluginPiping = state?.pluginPipings?.filter((piping) => {
- if (currentNode && piping.data.id === currentNode) {
- return piping;
- }
- });
-
- let generatedCommand = "";
-
- if (params && params.length > 0) {
- for (const input in params) {
- //@ts-ignore
- const name = params[input].name;
- //@ts-ignore
- const defaultValue =
- params[input].default === false || params[input].default === true
- ? ""
- : params[input].default.length === 0
- ? "' '"
- : params[input].default;
- generatedCommand += ` --${name} ${defaultValue}`;
- }
- }
-
- const onClick = (event: any, text: any) => {
- clipboardCopyFunc(event, text);
- setCopied(true);
- };
-
- const actions = (
-
-
-
- {pluginPiping && pluginPiping.length > 0
- ? `${pluginPiping[0].data.plugin_name}:${pluginPiping[0].data.plugin_version}`
- : "N/A"}
-
- onClick(e, generatedCommand)}
- exitDelay={600}
- maxWidth="110px"
- variant="plain"
- >
- {copied ? "Successfully copied to clipboard" : "Copy to clipboard"}
-
-
-
- );
-
- return (
-
- {generatedCommand}
-
- );
-};
-export default ClipboardCopyCommand;
diff --git a/src/components/Pipelines/ConfigurationPage.tsx b/src/components/Pipelines/ConfigurationPage.tsx
deleted file mode 100644
index afbb308c7..000000000
--- a/src/components/Pipelines/ConfigurationPage.tsx
+++ /dev/null
@@ -1,224 +0,0 @@
-import { PluginPiping } from "@fnndsc/chrisapi";
-import {
- ActionGroup,
- Button,
- ExpandableSection,
- Form,
- FormGroup,
- Grid,
- GridItem,
- TextInput,
-} from "@patternfly/react-core";
-import React from "react";
-import { PipelineContext } from "../CreateFeed/context";
-import type { ConfiguartionPageProps } from "../CreateFeed/types/pipeline";
-import ClipboardCopyCommand from "./ClipboardCopyCommand";
-import ListCompute from "./ListCompute";
-import TitleChange from "./TitleChange";
-
-const ConfigurationPage = (props: ConfiguartionPageProps) => {
- const [isExpanded, setIsExpanded] = React.useState(false);
- const {
- currentPipelineId,
- state,
- handleSetCurrentNodeTitle,
- handleSetCurrentComputeEnv,
- handleFormParameters,
- justDisplay,
- } = props;
-
- const { currentNode, computeEnvs, pluginPipings, pluginParameters } = state;
- const computeEnvList =
- computeEnvs && currentNode && computeEnvs[currentNode]
- ? computeEnvs[currentNode].computeEnvs
- : [];
- const [selectedPlugin, setSelectedPlugin] = React.useState();
-
- const onToggle = (_event: React.MouseEvent, isExpanded: boolean) => {
- setIsExpanded(isExpanded);
- };
-
- React.useEffect(() => {
- async function fetchResources() {
- if (pluginPipings && currentNode && pluginParameters) {
- const pluginPiping = pluginPipings.filter((piping: any) => {
- return piping.data.id === currentNode;
- });
-
- const selectedPlugin = await pluginPiping[0].getPlugin();
- setSelectedPlugin(pluginPiping[0]);
-
- const params = await selectedPlugin.getPluginParameters({
- limit: 1000,
- });
-
- const paramDict: {
- [key: string]: string;
- } = {};
- //@ts-ignore
- const filteredParameters = pluginParameters?.data.filter(
- (param: any) => {
- return param.plugin_piping_id === pluginPiping[0].data.id;
- },
- );
-
- for (const param of filteredParameters) {
- paramDict[param.param_name] = param;
- }
-
- const paramItems = params.getItems();
-
- if (paramItems) {
- const newParamDict: any[] = [];
-
- for (const param of paramItems) {
- if (paramDict[param.data.name]) {
- const defaultParam = paramDict[param.data.name];
- //@ts-ignore
- const newParam = {
- name: param.data.name,
- default: param.data.default,
- };
- //@ts-ignore
- newParam.default = defaultParam.value;
- newParamDict.push(newParam);
- }
- }
-
- handleFormParameters(currentNode, currentPipelineId, newParamDict);
- }
- }
- }
-
- fetchResources();
- }, [
- currentNode,
- pluginPipings,
- pluginParameters,
- handleFormParameters,
- currentPipelineId,
- ]);
-
- const generalCompute =
- computeEnvs &&
- currentNode &&
- computeEnvs[currentNode] &&
- computeEnvs[currentNode].currentlySelected;
-
- const dispatchFn = (item: any) => {
- if (currentNode)
- handleSetCurrentComputeEnv(
- item,
- currentNode,
- currentPipelineId,
- computeEnvList,
- );
- };
-
- return (
- <>
-
- {!justDisplay && (
-
- )}
-
- {!justDisplay && (
-
-
-
-
-
-
-
- )}
- >
- );
-};
-
-export default ConfigurationPage;
-
-export const ConfigurePipelineParameters = ({
- currentPipelineId,
- handleFormParameters,
-}: {
- handleFormParameters: (
- currentNode: number,
- currentPipelineId: number,
- paramDict: any[],
- ) => void;
- currentPipelineId: number;
-}) => {
- const { state } = React.useContext(PipelineContext);
- const { pipelineData } = state;
- const { parameterList, currentNode } = pipelineData[currentPipelineId];
- const params = parameterList && currentNode && parameterList[currentNode];
-
- const onFinish = (values: any) => {
- const newParams = params.map((param: any) => {
- const newValue = values[param.name];
- if (newValue) {
- param.default =
- newValue === "true" || newValue === "false"
- ? Boolean(newValue)
- : values[param.name];
- }
- return param;
- });
- handleFormParameters(currentNode, currentPipelineId, newParams);
- };
-
- return (
-
- );
-};
diff --git a/src/components/Pipelines/CreatePipeline.tsx b/src/components/Pipelines/CreatePipeline.tsx
deleted file mode 100644
index b197479fd..000000000
--- a/src/components/Pipelines/CreatePipeline.tsx
+++ /dev/null
@@ -1,140 +0,0 @@
-import React from "react";
-import ReactJson from "react-json-view";
-import { Spin } from "antd";
-import { Button, TextInput } from "@patternfly/react-core";
-import { CreatePipelineProps } from "../CreateFeed/types/pipeline";
-import { generatePipelineWithData } from "../CreateFeed/utils";
-
-const CreatingPipeline = ({
- pipelines,
- pipeline,
- state,
- handleDispatchPipelines,
-}: CreatePipelineProps) => {
- const { pluginParameters, pluginPipings, title, parameterList } = state;
- const [creatingPipeline, setCreatingPipeline] = React.useState({
- loading: false,
- error: {},
- pipelineName: "",
- });
- const handlePipelineCreate = async () => {
- setCreatingPipeline({
- ...creatingPipeline,
- loading: true,
- });
- const mappedArr: any[] = [];
- try {
- pluginPipings?.forEach((piping: any) => {
- const defaults = pluginParameterDefaults(
- //@ts-ignore
- pluginParameters.data,
- piping.data.id,
- parameterList,
- );
-
- const id = pluginPipings.findIndex(
- (pipe: any) => pipe.data.id === piping.data.previous_id,
- );
-
- let titleChange = piping.data.title;
- if (title && title[piping.data.id]) {
- titleChange = title[piping.data.id];
- }
-
- const treeObl = {
- plugin_name: piping.data.plugin_name,
- plugin_version: piping.data.plugin_version,
- previous_index: id === -1 ? null : id,
- title: titleChange,
- plugin_parameter_defaults: defaults,
- };
- mappedArr.push(treeObl);
- });
-
- const result = {
- name: `${creatingPipeline.pipelineName}`,
- authors: pipeline.data.authors,
- locked: pipeline.data.locked,
- description: pipeline.data.description,
- plugin_tree: JSON.stringify(mappedArr),
- };
-
- const { pipelineInstance } = await generatePipelineWithData(result);
- setCreatingPipeline({
- ...creatingPipeline,
- loading: false,
- });
- if (pipelineInstance) {
- handleDispatchPipelines([pipelineInstance, ...pipelines]);
- }
- } catch (error: any) {
- setCreatingPipeline({
- ...creatingPipeline,
- error: error.response.data,
- loading: false,
- });
- }
- };
- return (
-
- {
- event.key === "Enter" && handlePipelineCreate();
- }}
- onChange={(_event, value) =>
- setCreatingPipeline({
- ...creatingPipeline,
- pipelineName: value,
- error: {},
- })
- }
- />
-
-
- {creatingPipeline.loading && }
- {Object.keys(creatingPipeline.error).length > 0 && (
-
-
-
- )}
-
- );
-};
-
-export default CreatingPipeline;
-
-const pluginParameterDefaults = (parameters: any[], id: number, input: any) => {
- const currentInput = input[id];
-
- const defaults = [];
-
- if (currentInput && currentInput.length > 0) {
- defaults.push(...currentInput);
- } else {
- for (let i = 0; i < parameters.length; i++) {
- const parameter = parameters[i];
- if (parameter.plugin_piping_id === id) {
- defaults.push({
- name: parameter.param_name,
- default: parameter.value,
- });
- }
- }
- }
-
- return defaults;
-};
diff --git a/src/components/Pipelines/GeneralCompute.tsx b/src/components/Pipelines/GeneralCompute.tsx
deleted file mode 100644
index 608f75a70..000000000
--- a/src/components/Pipelines/GeneralCompute.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React, { useContext } from "react";
-import ChrisAPIClient from "../../api/chrisapiclient";
-import { PipelineContext } from "../CreateFeed/context";
-import { PipelineTypes } from "../CreateFeed/types/pipeline";
-import ListCompute from "./ListCompute";
-
-type NewType = {
- currentPipelineId: number;
- handleSetGeneralCompute: (
- currentPipelineId: number,
- computeEnv: string,
- ) => void;
-};
-
-function GeneralCompute({ currentPipelineId }: NewType) {
- const { state, dispatch } = useContext(PipelineContext);
- const [computes, setComputes] = React.useState([]);
-
- const generalCompute = state.pipelineData[currentPipelineId].generalCompute;
-
- React.useEffect(() => {
- async function fetchCompute() {
- const client = ChrisAPIClient.getClient();
- const computeResourceList = await client.getComputeResources({
- limit: 100,
- offset: 0,
- });
- setComputes(computeResourceList.data);
- }
-
- fetchCompute();
- }, []);
-
- const dispatchFn = (item: any) => {
- dispatch({
- type: PipelineTypes.SetGeneralCompute,
- payload: { currentPipelineId, computeEnv: item.name },
- });
- };
-
- return (
-
-
-
- );
-}
-
-export default GeneralCompute;
diff --git a/src/components/Pipelines/ListCompute.tsx b/src/components/Pipelines/ListCompute.tsx
deleted file mode 100644
index cf9539730..000000000
--- a/src/components/Pipelines/ListCompute.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import { List, Avatar, Checkbox } from "antd";
-import { stringToColour } from "../CreateFeed/utils";
-
-const ListCompute = ({
- computeList,
- generalCompute,
- dispatchFn,
-}: {
- computeList: any[];
- generalCompute?: string;
- dispatchFn: (item: any) => void;
-}) => {
- return (
- <>
- 0 ? computeList : []}
- renderItem={(item: any) => {
- return (
-
-
- {
- dispatchFn(item);
- }}
- />
-
- >
- }
- title={item.name}
- description={item.description}
- />
-
- );
- }}
- />
- >
- );
-};
-
-export default ListCompute;
diff --git a/src/components/Pipelines/NodeData.tsx b/src/components/Pipelines/NodeData.tsx
deleted file mode 100644
index a873fb025..000000000
--- a/src/components/Pipelines/NodeData.tsx
+++ /dev/null
@@ -1,154 +0,0 @@
-import { HierarchyPointNode } from "d3-hierarchy";
-import { select } from "d3-selection";
-import React, { useContext, useRef } from "react";
-import { TreeNode } from "../../api/common";
-import { SinglePipeline } from "../CreateFeed/types/pipeline";
-import { fetchComputeInfo, stringToColour } from "../CreateFeed/utils";
-import { ThemeContext } from "../DarkTheme/useTheme";
-
-export interface Point {
- x: number;
- y: number;
-}
-
-type NodeProps = {
- state: SinglePipeline;
- data: TreeNode;
- parent: HierarchyPointNode | null;
- position: Point;
- orientation: string;
- handleNodeClick: (
- pluginName: number,
- pipelineId: number,
- plugin_id: number,
- ) => void;
- currentPipelineId: number;
- handleSetCurrentNodeTitle: (
- currentPipelineId: number,
- currentNode: number,
- title: string,
- ) => void;
- handleSetPipelineEnvironments: (
- pipelineId: number,
- computeEnvData: {
- [x: number]: {
- computeEnvs: any[];
- currentlySelected: any;
- };
- },
- ) => void;
-};
-
-const setNodeTransform = (orientation: string, position: Point) => {
- return orientation === "horizontal"
- ? `translate(${position.y},${position.x})`
- : `translate(${position.x}, ${position.y})`;
-};
-const DEFAULT_NODE_CIRCLE_RADIUS = 12;
-
-const NodeData = (props: NodeProps) => {
- const { isDarkTheme } = useContext(ThemeContext);
- const nodeRef = useRef(null);
- const textRef = useRef(null);
- const {
- data,
- position,
- orientation,
- handleNodeClick,
- currentPipelineId,
- state,
- handleSetPipelineEnvironments,
- } = props;
- const { computeEnvs, title, currentNode, pluginPipings } = state;
-
- const root = pluginPipings?.[0];
-
- let currentId = NaN;
- if (data.previous_id && root) {
- currentId = data.id - root.data.id;
- } else {
- currentId = 0;
- }
-
- let currentComputeEnv = "";
- if (computeEnvs?.[data.id]) {
- currentComputeEnv = computeEnvs[data.id].currentlySelected;
- }
-
- const titleName = title?.[data.id];
-
- const applyNodeTransform = (transform: string, opacity = 1) => {
- select(nodeRef.current)
- .attr("transform", transform)
- .style("opacity", opacity);
-
- select(textRef.current).attr("transform", "translate(-30, 30)");
- };
-
- React.useEffect(() => {
- const nodeTransform = setNodeTransform(orientation, position);
- applyNodeTransform(nodeTransform);
- }, [orientation, position, applyNodeTransform]);
-
- const handleSetComputeEnvironmentsWrap = React.useCallback(
- (computeEnvData: {
- [x: number]: {
- computeEnvs: any[];
- currentlySelected: any;
- };
- }) => {
- handleSetPipelineEnvironments(currentPipelineId, computeEnvData);
- },
- [currentPipelineId, handleSetPipelineEnvironments],
- );
-
- React.useEffect(() => {
- async function fetchComputeEnvironments() {
- const computeEnvData = await fetchComputeInfo(data.plugin_id, data.id);
- if (computeEnvData) {
- handleSetComputeEnvironmentsWrap(computeEnvData);
- }
- }
-
- fetchComputeEnvironments();
- }, [data, handleSetComputeEnvironmentsWrap]);
-
- const textLabel = (
-
-
- {currentId}:{data.id}:{titleName ? titleName : data.title}
-
-
- );
-
- const strokeColor = isDarkTheme ? "white" : "#F0AB00";
-
- return (
- {
- if (data) handleNodeClick(data.id, currentPipelineId, data.plugin_id);
- }}
- >
-
- {textLabel}
-
- );
-};
-
-export default NodeData;
diff --git a/src/components/Pipelines/TitleChange.tsx b/src/components/Pipelines/TitleChange.tsx
deleted file mode 100644
index a9e12fae2..000000000
--- a/src/components/Pipelines/TitleChange.tsx
+++ /dev/null
@@ -1,102 +0,0 @@
-import { TextInput } from "@patternfly/react-core";
-import React from "react";
-import { SinglePipeline } from "../CreateFeed/types/pipeline";
-import Check from "@patternfly/react-icons/dist/esm/icons/check-icon";
-import Edit from "@patternfly/react-icons/dist/esm/icons/edit-icon";
-import Close from "@patternfly/react-icons/dist/esm/icons/close-icon";
-import { PluginPiping } from "@fnndsc/chrisapi";
-
-const TitleChange = ({
- currentPipelineId,
- state,
- handleSetCurrentNodeTitle,
- selectedPlugin,
-}: {
- currentPipelineId: number;
- state: SinglePipeline;
- handleSetCurrentNodeTitle: (
- currentPipelineId: number,
- currentNode: number,
- title: string,
- ) => void;
- selectedPlugin?: PluginPiping;
-}) => {
- const iconFontSize = {
- fontSize: "1.25rem",
- };
- const [edit, setEdit] = React.useState(false);
- const [value, setValue] = React.useState("");
- const { title, currentNode } = state;
- const handleCorrectInput = () => {
- setEdit(false);
- if (currentNode)
- handleSetCurrentNodeTitle(currentPipelineId, currentNode, value);
- };
-
- return (
-
- {
- setValue(value);
- }}
- onKeyDown={(event) => {
- if (event.key === "Enter") {
- handleCorrectInput();
- }
- }}
- />
- {!edit && (
- {
- setEdit(true);
- }}
- />
- )}
- {edit && (
- <>
-
- {
- setEdit(false);
- }}
- style={{
- ...iconFontSize,
- }}
- />
- >
- )}
-
- );
-};
-export default TitleChange;
diff --git a/src/components/Pipelines/Tree.tsx b/src/components/Pipelines/Tree.tsx
deleted file mode 100644
index d593f14c3..000000000
--- a/src/components/Pipelines/Tree.tsx
+++ /dev/null
@@ -1,362 +0,0 @@
-import { Spin } from "antd";
-import { hierarchy, tree } from "d3-hierarchy";
-import { event, select } from "d3-selection";
-import { linkVertical } from "d3-shape";
-import { zoom as d3Zoom, zoomIdentity } from "d3-zoom";
-import React, {
- Fragment,
- useEffect,
- useContext,
- useRef,
- useState,
-} from "react";
-import { TreeNode, getFeedTree } from "../../api/common";
-import { SpinContainer } from "../Common";
-import { SinglePipeline } from "../CreateFeed/types/pipeline";
-import { ThemeContext } from "../DarkTheme/useTheme";
-import TransitionGroupWrapper from "../FeedTree/TransitionGroupWrapper";
-import { getTsNodesWithPipings } from "../FeedTree/data";
-import { type Point, type Separation } from "../FeedTree/data";
-import useSize from "../FeedTree/useSize";
-import NodeData from "./NodeData";
-
-const nodeSize = { x: 200, y: 80 };
-const svgClassName = "feed-tree__svg";
-const graphClassName = "feed-tree__graph";
-const scale = 1;
-
-export interface TreeProps {
- state: SinglePipeline;
- currentPipelineId: number;
- handleSetCurrentNode: (pipelineId: number, currentNode: number) => void;
- handleNodeClick: (
- nodeName: number,
- pipelineId: number,
- plugin_id: number,
- ) => void;
- handleSetCurrentNodeTitle: (
- currentPipelineId: number,
- currentNode: number,
- title: string,
- ) => void;
- handleSetPipelineEnvironments: (
- pipelineId: number,
- computeEnvData: {
- [x: number]: {
- computeEnvs: any[];
- currentlySelected: any;
- };
- },
- ) => void;
-
- translate?: Point;
- scaleExtent: {
- min: number;
- max: number;
- };
- zoom?: number;
- nodeSize?: {
- x: number;
- y: number;
- };
- separation?: Separation;
- orientation?: "horizontal" | "vertical";
-}
-
-const Tree = (props: TreeProps) => {
- const divRef = useRef(null);
- const [translate, setTranslate] = React.useState({
- x: 0,
- y: 0,
- });
- const size = useSize(divRef);
- const { currentPipelineId, state, handleSetCurrentNode } = props;
- const { pluginPipings, pipelinePlugins, pluginParameters } = state;
- const [loading, setLoading] = React.useState(false);
- const {
- handleNodeClick,
- handleSetCurrentNodeTitle,
- handleSetPipelineEnvironments,
- } = props;
-
- const [data, setData] = React.useState();
- const [tsIds, setTsIds] = React.useState();
- const { zoom, scaleExtent } = props;
- const bindZoomListener = React.useCallback(() => {
- const svg = select(`.${svgClassName}`);
- const g = select(`.${graphClassName}`);
-
- svg.call(
- ///@ts-ignore
- d3Zoom().transform,
- zoomIdentity.translate(translate.x, translate.y).scale(zoom),
- );
-
- svg.call(
- //@ts-ignore
- d3Zoom()
- .scaleExtent([scaleExtent.min, scaleExtent.max])
- .on("zoom", () => {
- g.attr("transform", event.transform);
- }),
- );
- }, [zoom, scaleExtent, translate.x, translate.y]);
-
- React.useEffect(() => {
- bindZoomListener();
- }, [bindZoomListener]);
-
- const handleSetCurrentNodeCallback = React.useCallback(
- (id: number) => {
- handleSetCurrentNode(currentPipelineId, id);
- },
- [currentPipelineId, handleSetCurrentNode],
- );
-
- React.useEffect(() => {
- if (pluginPipings) {
- setLoading(true);
- const tree = getFeedTree(pluginPipings);
- getTsNodesWithPipings(pluginPipings, pluginParameters).then((tsIds) => {
- setTsIds(tsIds);
- });
- setData(tree);
- }
- if (pipelinePlugins) {
- const defaultPlugin = pipelinePlugins[0];
- const defaultPluginId = pluginPipings?.filter((piping: any) => {
- if (piping.data.plugin_id === defaultPlugin.data.id) {
- return piping.data.id;
- }
- });
-
- if (defaultPluginId) {
- handleSetCurrentNodeCallback(defaultPluginId[0].data.id);
- }
- }
- setLoading(false);
- }, [
- pluginPipings,
- pipelinePlugins,
- pluginParameters,
- currentPipelineId,
- handleSetCurrentNodeCallback,
- pipelinePlugins?.[0],
- ]);
-
- React.useEffect(() => {
- //@ts-ignore
- if (size?.width) {
- setTranslate({
- //@ts-ignore
- x: size.width / 2.5,
- //@ts-ignore
- y: size.height / 3,
- });
- }
- }, [size]);
-
- const generateTree = () => {
- const d3Tree = tree().nodeSize([nodeSize.x, nodeSize.y]);
- let nodes;
- let links: any[] = [];
- let newLinks: any[] = [];
- if (data) {
- const rootNode = d3Tree(hierarchy(data[0]));
- nodes = rootNode.descendants();
- links = rootNode.links();
- const newLinksToAdd: any[] = [];
-
- if (tsIds) {
- for (const link of links) {
- const targetId = link.target.data.id;
- const sourceId = link.target.data.id;
-
- if (targetId && sourceId && (tsIds[targetId] || tsIds[sourceId])) {
- // tsPlugin found
- let topologicalLink: any;
-
- if (tsIds[targetId]) {
- topologicalLink = link.target;
- } else {
- topologicalLink = link.source;
- }
-
- const parents = tsIds[topologicalLink.data.id];
- const dict: any = {};
-
- for (const link of links) {
- for (let i = 0; i < parents.length; i++) {
- if (
- link.source.data.id === parents[i] &&
- !dict[link.source.data.id]
- ) {
- dict[link.source.data.id] = link.source;
- } else if (
- link.target.data.id === parents[i] &&
- !dict[link.target.data.id]
- ) {
- dict[link.target.data.id] = link.target;
- }
- }
- }
-
- for (const i in dict) {
- newLinksToAdd.push({
- source: dict[i],
- target: topologicalLink,
- });
- }
- }
- }
- }
- newLinks = [...links, ...newLinksToAdd];
- }
- return { nodes, newLinks: newLinks };
- };
-
- const { nodes, newLinks: links } = generateTree();
-
- return (
- <>
-
- {loading ? (
-
- ) : translate.x > 0 && translate.y > 0 ? (
-
- Pipeline Tree
-
- {links?.map((linkData, i) => {
- return (
-
- );
- })}
- {nodes?.map(({ data, x, y, parent }, i) => {
- return (
-
- );
- })}
-
-
- ) : (
- Drawing out the pipelines tree
- )}
-
- >
- );
-};
-
-Tree.defaultProps = {
- orientation: "vertical",
- scaleExtent: { min: 0.1, max: 1 },
- zoom: 1,
- nodeSize: { x: 120, y: 80 },
-};
-
-interface LinkProps {
- linkData: any;
- key: string;
- orientation: "vertical";
-}
-
-type LinkState = {
- initialStyle: {
- opacity: number;
- };
-};
-
-const LinkData: React.FC = ({ linkData }) => {
- const { isDarkTheme } = useContext(ThemeContext);
- const linkRef = useRef(null);
- const [initialStyle] = useState({ opacity: 1 });
- const nodeRadius = 12;
-
- useEffect(() => {
- applyOpacity(1);
- }, []);
-
- const applyOpacity = (
- opacity: number,
- done = () => {
- return null;
- },
- ) => {
- select(linkRef.current).style("opacity", opacity).on("end", done);
- };
-
- const { source, target } = linkData;
-
- const drawPath = (ts: boolean) => {
- const deltaX = target.x - source.x;
- const deltaY = target.y - source.y;
- const dist = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- const normX = deltaX / dist;
- const normY = deltaY / dist;
- const sourcePadding = nodeRadius;
- const targetPadding = nodeRadius + 4;
- const sourceX = source.x + sourcePadding * normX;
- const sourceY = source.y + sourcePadding * normY;
- const targetX = target.x - targetPadding * normX;
- const targetY = target.y - targetPadding * normY;
-
- if (ts) {
- return linkVertical()({
- source: [sourceX, sourceY],
- target: [targetX, targetY],
- });
- }
- return `M${sourceX} ${sourceY} L${targetX} ${targetY}`;
- };
-
- const ts = target.data.plugin_name === "pl-topologicalcopy";
-
- const strokeWidthColor = isDarkTheme ? "#F2F9F9" : "#6A6E73";
-
- return (
-
-
-
- );
-};
-
-export default Tree;
diff --git a/src/components/Pipelines/UploadJson.tsx b/src/components/Pipelines/UploadJson.tsx
deleted file mode 100644
index 51312e575..000000000
--- a/src/components/Pipelines/UploadJson.tsx
+++ /dev/null
@@ -1,141 +0,0 @@
-import React from "react";
-import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
-import ReactJSON from "react-json-view";
-import { Alert, Button } from "@patternfly/react-core";
-import { PipelineList } from "@fnndsc/chrisapi";
-import { generatePipelineWithData } from "../CreateFeed/utils";
-import ChrisAPIClient from "../../api/chrisapiclient";
-import { UploadJsonProps } from "../CreateFeed/types/pipeline";
-
-export const UploadJson = ({
- handleDispatch,
-}: {
- handleDispatch: (result: UploadJsonProps) => void;
-}) => {
- const fileOpen = React.useRef(null);
- const [fileName, setFileName] = React.useState("");
- const [error, setError] = React.useState({});
- const [pipelineWarning, setPipelineWarning] = React.useState("");
- const [showSuccessIcon, setShowSuccessIcon] = React.useState(false);
-
- const showOpenFile = () => {
- setPipelineWarning("");
- if (fileOpen.current) {
- fileOpen.current.click();
- }
- };
-
- const cleanUp = (event: any) => {
- event.target.value = null;
- if (fileOpen.current) {
- fileOpen.current.value = "";
- }
- };
-
- const readFile = (file: any, event: any) => {
- const reader = new FileReader();
-
- reader.onloadend = async () => {
- try {
- if (reader.result) {
- const client = ChrisAPIClient.getClient();
- const result = JSON.parse(reader.result as string);
- result["plugin_tree"] = JSON.stringify(result["plugin_tree"]);
- setFileName(result.name);
- const pipelineInstanceList: PipelineList = await client.getPipelines({
- name: result.name,
- });
- if (!pipelineInstanceList.data) {
- const { resources, pipelineInstance } =
- await generatePipelineWithData(result);
- const { parameters, pluginPipings, pipelinePlugins } = resources;
-
- handleDispatch({
- parameters,
- pluginPipings,
- pipelinePlugins,
- pipelineInstance,
- });
- setShowSuccessIcon(true);
- cleanUp(event);
- } else {
- setPipelineWarning(
- `pipeline with the name ${result.name} already exists`,
- );
- cleanUp(event);
- }
- }
- } catch (error) {
- //@ts-ignore
- const errorMessage = error.response.data;
- cleanUp(event);
- setError(errorMessage);
- }
- };
- if (file) {
- reader.readAsText(file);
- }
- };
-
- const handleUpload = (event: any) => {
- const file = event?.target.files[0];
- setError({});
- readFile(file, event);
- };
-
- const keys = Object.keys(error).length;
-
- const alertStyle = {
- marginTop: "1em",
- };
-
- return (
- <>
-
-
}>
- Upload a JSON spec{" "}
-
-
{fileName}
- {showSuccessIcon && (
-
- )}
-
- {pipelineWarning && (
-
- )}
- {keys > 0 && (
-
-
-
- )}
-
-
- >
- );
-};
-
-export default UploadJson;
diff --git a/src/components/Pipelines/index.ts b/src/components/Pipelines/index.ts
deleted file mode 100644
index f04b306de..000000000
--- a/src/components/Pipelines/index.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import NodeData from "./NodeData";
-import Tree from "./Tree";
-import UploadJson from "./UploadJson";
-import ConfigurationPage from "./ConfigurationPage";
-import GeneralCompute from "./GeneralCompute";
-
-export { NodeData, Tree, UploadJson, ConfigurationPage, GeneralCompute };
diff --git a/src/components/PipelinesCopy/GeneralCompute.tsx b/src/components/PipelinesCopy/GeneralCompute.tsx
index cd390a3bf..b27941561 100644
--- a/src/components/PipelinesCopy/GeneralCompute.tsx
+++ b/src/components/PipelinesCopy/GeneralCompute.tsx
@@ -50,7 +50,9 @@ function GeneralCompute() {
isExpanded={isExpanded}
onToggle={onToggle}
toggleText={
- isExpanded ? "Hide All Compute" : "Show All the registered to ChRIS"
+ isExpanded
+ ? "Hide All Compute"
+ : "Show all the compute registered to ChRIS"
}
>
diff --git a/src/components/PipelinesCopy/NodeData.tsx b/src/components/PipelinesCopy/NodeData.tsx
index 456b65d47..876c2b050 100644
--- a/src/components/PipelinesCopy/NodeData.tsx
+++ b/src/components/PipelinesCopy/NodeData.tsx
@@ -1,4 +1,5 @@
import { useQuery } from "@tanstack/react-query";
+import { Alert } from "antd";
import { HierarchyPointNode } from "d3-hierarchy";
import { select } from "d3-selection";
import React, { useContext, useEffect, useRef } from "react";
@@ -129,7 +130,7 @@ const NodeData = (props: NodeProps) => {
return (
<>
- {isError && {error.message}}
+ {isError && }
{isLoading && (
Fetching the compute environments for this node...
)}
diff --git a/src/components/PipelinesCopy/Pipelines.css b/src/components/PipelinesCopy/Pipelines.css
new file mode 100644
index 000000000..7132a15f2
--- /dev/null
+++ b/src/components/PipelinesCopy/Pipelines.css
@@ -0,0 +1,4 @@
+
+.ant-form-item-label label {
+ color: #73bcf7 !important;
+}
\ No newline at end of file
diff --git a/src/components/PipelinesCopy/Pipelines.module.css b/src/components/PipelinesCopy/Pipelines.module.css
deleted file mode 100644
index 81c804e23..000000000
--- a/src/components/PipelinesCopy/Pipelines.module.css
+++ /dev/null
@@ -1,4 +0,0 @@
-
- label {
- color:#1fa7f8 !important;
- }
diff --git a/src/components/PipelinesCopy/PipelinesComponent.tsx b/src/components/PipelinesCopy/PipelinesComponent.tsx
index faa0d334b..73695802b 100644
--- a/src/components/PipelinesCopy/PipelinesComponent.tsx
+++ b/src/components/PipelinesCopy/PipelinesComponent.tsx
@@ -1,7 +1,7 @@
import { Pipeline } from "@fnndsc/chrisapi";
+import { Grid, GridItem } from "@patternfly/react-core";
import CodeBlockComponent from "./CodeBlockComponent";
import ComputeListForSingleCompute from "./ComputeListForSingleCompute";
-import { Grid, GridItem } from "@patternfly/react-core";
import GeneralCompute from "./GeneralCompute";
import TitleChange from "./TitleChange";
import Tree from "./Tree";
@@ -15,21 +15,22 @@ function PipelinesComponent(props: OwnProps) {
return (
<>
+
-
+
-
+
-
+
diff --git a/src/components/PipelinesCopy/TitleChange.tsx b/src/components/PipelinesCopy/TitleChange.tsx
index ba1956ff5..471f02308 100644
--- a/src/components/PipelinesCopy/TitleChange.tsx
+++ b/src/components/PipelinesCopy/TitleChange.tsx
@@ -1,8 +1,7 @@
import { Pipeline, PluginPiping } from "@fnndsc/chrisapi";
-import { Alert, Button, Input, Space, Form } from "antd";
+import { Alert, Button, Form, Input, Space } from "antd";
import { useContext, useEffect, useState } from "react";
import { PipelineContext, Types } from "./context";
-import styles from "./Pipelines.module.css";
type OwnProps = {
currentPipeline: Pipeline;
@@ -59,10 +58,7 @@ function TitleChange({ currentPipeline }: OwnProps) {
return (
<>
-
+
setValue(e.target.value)} value={value} />