Skip to content

Commit

Permalink
Merge pull request #1100 from PintoGideon/Update-Pipelines
Browse files Browse the repository at this point in the history
feat: Add a pipeline for the user to allow for zipping files
  • Loading branch information
PintoGideon authored Mar 11, 2024
2 parents e4284e4 + acf8e81 commit 0ef7581
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 33 deletions.
20 changes: 14 additions & 6 deletions src/components/AddPipeline/AddPipeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ const AddPipeline = () => {
(state) => state.plugin.nodeOperations,
);

const alreadyAvailableInstances = useTypedSelector(
(state) => state.instance.pluginInstances.data,
const { pluginInstances, selectedPlugin } = useTypedSelector(
(state) => state.instance,
);

const alreadyAvailableInstances = pluginInstances.data;

const handleToggle = () => {
if (childPipeline) {
dispatch({
Expand All @@ -38,14 +40,11 @@ const AddPipeline = () => {
reactDispatch(getNodeOperations("childPipeline"));
};

const feed = useTypedSelector((state) => state.feed.currentFeed.data);
const { selectedPlugin } = useTypedSelector((state) => state.instance);

const addPipeline = async () => {
const id = pipelineToAdd?.data.id;
const resources = selectedPipeline?.[id];

if (selectedPlugin && feed && resources) {
if (selectedPlugin && resources) {
const { parameters } = resources;
const client = ChrisAPIClient.getClient();

Expand Down Expand Up @@ -73,6 +72,7 @@ const AddPipeline = () => {
nodes_info: JSON.stringify(nodes_info),
});

// Use the pagination helper here
const pluginInstances = await workflow.getPluginInstances({
limit: 1000,
});
Expand Down Expand Up @@ -100,6 +100,14 @@ const AddPipeline = () => {
mutationFn: () => addPipeline(),
});

React.useEffect(() => {
if (mutation.isSuccess) {
setTimeout(() => {
handleToggle();
}, 1000);
}
}, [mutation.isSuccess]);

React.useEffect(() => {
const el = document.querySelector("#indicators");

Expand Down
145 changes: 145 additions & 0 deletions src/components/DownloadNode/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { Button } from "@patternfly/react-core";
import FaDownloadIcon from "@patternfly/react-icons/dist/esm/icons/download-icon";
import { useMutation } from "@tanstack/react-query";
import { Alert } from "antd";
import { useEffect } from "react";
import { useDispatch } from "react-redux";
import ChrisAPIClient from "../../api/chrisapiclient";
import { fetchComputeInfo, fetchResources } from "../../api/common";
import { useTypedSelector } from "../../store/hooks";
import {
getPluginInstancesSuccess,
getSelectedPlugin,
} from "../../store/pluginInstance/actions";
import { getPluginInstanceStatusRequest } from "../../store/resources/actions";
import { SpinContainer } from "../Common";
import { PerPipelinePayload } from "../PipelinesCopy/context";

function DownloadNode() {
const { pluginInstances, selectedPlugin } = useTypedSelector(
(state) => state.instance,
);
const reactDispatch = useDispatch();

const alreadyAvailableInstances = pluginInstances.data;

async function fetchPipelines() {
const client = ChrisAPIClient.getClient();

try {
const pipelineList = await client.getPipelines({
name: "zip v20240311",
});

const pipelines = pipelineList.getItems();

if (pipelines && pipelines.length > 0) {
const pipeline = pipelines[0];
const { id } = pipeline.data;

const data: PerPipelinePayload = await fetchResources(pipeline);
const { parameters, pluginPipings } = data;

const nodes_info = client.computeWorkflowNodesInfo(parameters.data);

// This is an assumption as I know the zip file will only have on pluginPiping
const piping = pluginPipings[0];
const computeEnvPayload = await fetchComputeInfo(
piping.data.plugin_id,
`${piping.data.id}`,
);

for (const node of nodes_info) {
const activeNode = computeEnvPayload?.[node.piping_id];

if (activeNode) {
const compute_node = activeNode.currentlySelected;
node.compute_resource_name = compute_node;
}
}

const workflow = await client.createWorkflow(id, {
previous_plugin_inst_id: selectedPlugin?.data.id, // Ensure selectedPlugin is defined
nodes_info: JSON.stringify(nodes_info),
});

const pluginInstances = await workflow.getPluginInstances({
limit: 1000,
});

const instanceItems = pluginInstances.getItems();

if (
instanceItems &&
instanceItems.length > 0 &&
alreadyAvailableInstances
) {
const firstInstance = instanceItems[instanceItems.length - 1];
const completeList = [...alreadyAvailableInstances, ...instanceItems];

// Assuming reactDispatch, getSelectedPlugin, getPluginInstanceStatusSuccess, and getPluginInstanceStatusRequest are defined elsewhere
reactDispatch(getSelectedPlugin(firstInstance));

const pluginInstanceObj = {
selected: firstInstance,
pluginInstances: completeList,
};

reactDispatch(getPluginInstancesSuccess(pluginInstanceObj));
reactDispatch(getPluginInstanceStatusRequest(pluginInstanceObj));
}
} else {
throw new Error(
"The pipeline to zip is not registered. Please contact an admin",
);
}
return pipelines;
} catch (error) {
throw error;
}
}

const mutation = useMutation({
mutationFn: () => fetchPipelines(),
});

useEffect(() => {
if (mutation.isSuccess) {
setTimeout(() => {
mutation.reset();
}, 1000);
}
}, [mutation.isSuccess]);

return (
<>
<Button
onClick={() => {
mutation.mutate();
}}
icon={<FaDownloadIcon />}
>
Zip
</Button>
{mutation.isError || mutation.isSuccess || mutation.isPending ? (
<div
style={{
marginTop: "1rem",
}}
>
{mutation.isError && (
<Alert type="error" description={mutation.error.message} />
)}
{mutation.isSuccess && (
<Alert type="success" description="Zipping process started..." />
)}
{mutation.isPending && (
<SpinContainer title="Preparing to initiate the zipping process..." />
)}
</div>
) : null}
</>
);
}

export default DownloadNode;
10 changes: 5 additions & 5 deletions src/components/FeedOutputBrowser/FileBrowser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const FileBrowser = (props: FileBrowserProps) => {
} else {
toggleAnimation();
dispatch(setSelectedFile(item));
!drawerState["preview"].open && dispatch(setFilePreviewPanel());
!drawerState.preview.open && dispatch(setFilePreviewPanel());
}
};

Expand Down Expand Up @@ -239,10 +239,10 @@ const FileBrowser = (props: FileBrowserProps) => {
) : (
<Tbody>
{items.map((item: string | FeedFile, index) => {
let type;
let icon;
let fsize;
let fileName;
let type: string;
let icon: React.ReactNode;
let fsize: string;
let fileName: string;
type = "UNKNOWN FORMAT";
const isPreviewing = selectedFile === item;
let currentStatus = 0;
Expand Down
12 changes: 6 additions & 6 deletions src/components/IconContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const IconContainer = () => {
let prefix = "";
if (action === "merge") {
prefix = "Merge of ";
} else if (action === "download") {
} else if (action === "") {
prefix = "archive-";
} else {
prefix = "";
Expand Down Expand Up @@ -208,7 +208,7 @@ const IconContainer = () => {
let newFeedName = feedNames.toString().replace(/[, ]+/g, "_");
let createdFeed: Feed | null = null;

if (operation === "download") {
if (operation === "archive") {
newFeedName = `archive-${newFeedName}`;
newFeedName = newFeedName.substring(0, 100);
newFeedName = feedName === "" ? newFeedName : feedName;
Expand Down Expand Up @@ -286,11 +286,11 @@ const IconContainer = () => {
currentAction === "share" &&
shareFeedMutation.mutate({ bulkSelect, sharePublically, feedName });
currentAction === "delete" && deleteFeedMutation.mutate(bulkSelect);
currentAction === "download" &&
currentAction === "archive" &&
handleDownloadMutation.mutate({
feedList: bulkSelect,
feedName,
operation: "download",
operation: "archive",
});
currentAction === "merge" &&
handleDownloadMutation.mutate({
Expand All @@ -304,7 +304,7 @@ const IconContainer = () => {

return (
<ToggleGroup aria-label="Feed Action Bar">
{["download", "merge", "duplicate", "share", "delete"].map((action) => {
{["archive", "merge", "duplicate", "share", "delete"].map((action) => {
return (
<React.Fragment key={action}>
<ToolGroupContainer
Expand Down Expand Up @@ -413,7 +413,7 @@ export default IconContainer;
const actionMap: {
[key: string]: ReactElement;
} = {
download: <FaDownload />,
archive: <FaDownload />,
merge: <ShareButtonIcon />,
duplicate: <MdCallSplit />,
share: <MdIosShare />,
Expand Down
17 changes: 13 additions & 4 deletions src/components/NodeDetails/NodeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
Grid,
GridItem,
} from "@patternfly/react-core";
import { EyeIcon, CalendarAltIcon } from "@patternfly/react-icons";
import { CalendarAltIcon, EyeIcon } from "@patternfly/react-icons";
import React, { Fragment, ReactNode } from "react";
import { ErrorBoundary } from "react-error-boundary";
import { useNavigate } from "react-router";
Expand All @@ -20,16 +20,17 @@ import { AddNodeProvider } from "../AddNode/context";
import AddPipeline from "../AddPipeline/AddPipeline";
import GraphNodeContainer from "../AddTsNode";
import { SpinContainer } from "../Common";
import { PipelineProvider } from "../PipelinesCopy/context";
import { isPlVisualDataset } from "../DatasetRedirect/getDatasets";
import DeleteNode from "../DeleteNode";
import DownloadNode from "../DownloadNode";
import FeedNote from "../FeedDetails/FeedNote";
import { PipelineProvider } from "../PipelinesCopy/context";
import "./NodeDetails.css";
import PluginLog from "./PluginLog";
import PluginTitle from "./PluginTitle";
import Status from "./Status";
import StatusTitle from "./StatusTitle";
import { getErrorCodeMessage } from "./utils";
import { isPlVisualDataset } from "../DatasetRedirect/getDatasets";

interface INodeState {
plugin?: Plugin;
Expand All @@ -55,7 +56,7 @@ const NodeDetails: React.FC = () => {
const drawerState = useTypedSelector((state) => state.drawers);

const { plugin, instanceParameters, pluginParameters } = nodeState;
const [isExpanded, setIsExpanded] = React.useState(true);
const [isExpanded, setIsExpanded] = React.useState(false);
const [isErrorExpanded, setisErrorExpanded] = React.useState(false);

React.useEffect(() => {
Expand Down Expand Up @@ -253,6 +254,14 @@ const NodeDetails: React.FC = () => {
)}
</Grid>

<Grid hasGutter={true}>
<RenderButtonGridItem>
<PipelineProvider>
<DownloadNode />
</PipelineProvider>
</RenderButtonGridItem>
</Grid>

{
// Jennings: hastily adding an extra button here.
// IMO the Node Details pane should be cleaned up.
Expand Down
2 changes: 2 additions & 0 deletions src/components/Pacs/pfdcmClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ class PfdcmClient {
!imagestatus.push &&
images.pushed === 0 &&
requestedFiles &&
requestedFiles > 0 &&
images.packed === +requestedFiles;

newImageStatus[1].icon = showPushDetails && <Spin />;
Expand All @@ -327,6 +328,7 @@ class PfdcmClient {

const showRegisterDetails =
requestedFiles &&
requestedFiles > 0 &&
images.pushed === +requestedFiles &&
!imagestatus.register &&
images.registered === 0;
Expand Down
26 changes: 14 additions & 12 deletions src/store/pluginInstance/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ const reducer: Reducer<IPluginInstanceState> = (
},
selectedPlugin: action.payload,
};
} else return { ...state };
}
return { ...state };
}

case PluginInstanceTypes.ADD_NODE_REQUEST: {
Expand All @@ -118,16 +119,16 @@ const reducer: Reducer<IPluginInstanceState> = (
},
loadingAddNode: false,
};
} else
return {
...state,
pluginInstances: {
data: action.payload,
error: "",
loading: false,
},
loadingAddNode: false,
};
}
return {
...state,
pluginInstances: {
data: action.payload,
error: "",
loading: false,
},
loadingAddNode: false,
};
}

case PluginInstanceTypes.ADD_SPLIT_NODES_SUCCESS: {
Expand All @@ -145,7 +146,8 @@ const reducer: Reducer<IPluginInstanceState> = (
loading: false,
},
};
} else return state;
}
return state;
}

case PluginInstanceTypes.DELETE_NODE_SUCCESS: {
Expand Down

0 comments on commit 0ef7581

Please sign in to comment.