+
{
- setActionInput(e.target.value)
- }}
- InputProps={{
- endAdornment: (
- agentRequestLoading ?
-
- :
-
-
-
-
-
- ),
- }}
+ id="copy_element_shuffle"
+ style={{ display: "none" }}
/>
-
-
-
} label="Select Apps"
- style={chipStyle}
- onClick={() => {
- setAppPickerAnchor(document.getElementById("add_app_chip"))
+ {showAgentStarter ?
+
{
+ e.preventDefault();
+ submitInput(actionInput);
+ }}
+ >
+ {/*
+
+ */}
+
+
+
+
- {
- setAppPickerAnchor(null)
+
+ What do you want to do?
+
+ {
+ setActionInput(e.target.value)
}}
- anchorOrigin={{
- vertical: 'bottom',
- horizontal: 'left',
+ InputProps={{
+ style: {
+ borderRadius: 30,
+ },
+ endAdornment: (
+ agentRequestLoading ?
+
+ :
+
+
+
+
+
+ ),
}}
- >
-
+
+
+
+
} label="Select Apps / MCPs"
+ style={chipStyle}
+ onClick={() => {
+ setAppPickerAnchor(document.getElementById("add_app_chip"))
+ }}
/>
-
+
{
+ setAppPickerAnchor(null)
+ }}
+ anchorOrigin={{
+ vertical: 'bottom',
+ horizontal: 'left',
+ }}
+ >
+
+
+
+
+ {chosenApps.map((app, index) => {
+ var chosenName = (app?.name?.charAt(0).toUpperCase() + app?.name?.slice(1))?.replaceAll("_", " ").replaceAll("-", " ")
+ if (chosenName === "API") {
+ chosenName = "default"
+ }
+
+ const chosenImagePath = app?.image === undefined || app?.image === null || app?.image === "" ? app?.large_image === undefined || app?.large_image === null || app?.large_image === "" ? theme.palette.singulBlackWhite : app.large_image : app.image
+ const chosenImage =
+
+ return (
+
{
+ const newChosenApps = chosenApps.filter((a, i) => i !== index)
+ setChosenApps(newChosenApps)
+ }}
+ />
+ )
+ })}
+
+
+
+ {execution === undefined || execution === null || execution?.execution_id === undefined || execution?.execution_id === null ? null : typeButtonGroup}
+
+
+ {/*
+
+ */}
+
+ :
+
+
+
+ {typeButtonGroup}
+
+
+
+
+ {
+ GetExecution(execution?.execution_id, agentActionResult?.action?.id, execution?.authorization)
+ }}
+ >
+
+
+
+
+
+ {execution?.status === "EXECUTING" ?
+
+
+ {
+ toast.warn("Not implemented. Should run abort.")
+ }}
+ >
+
+
+
+
+ : null}
+
+
+
+
+
+ {chosenApps?.map((app, index) => {
+ return(
+
+ {
+ window.open(`/apps/${app.id}`, '_blank', 'noopener,noreferrer');
+ }}
+ style={{
+ cursor: "pointer",
+ width: 30,
+ height: 30,
+ }}
+ />
+
+ )
+ })}
+
+
+
+
+ {buttonState === "timeline" ?
+
+ :
+ null
+ }
-
- {chosenApps.map((app, index) => {
- const chosenName = (app?.name?.charAt(0).toUpperCase() + app?.name?.slice(1))?.replaceAll("_", " ").replaceAll("-", " ")
- const chosenImagePath = app?.image
- const chosenImage =
-
- return (
-
{
- const newChosenApps = chosenApps.filter((a, i) => i !== index)
- setChosenApps(newChosenApps)
- }}
- />
- )
- })}
-
-
- :
-
-
- {
- setButtonState("default");
- }}
- >
- Default
-
- {
- setButtonState("timeline");
- }}
- >
- Timeline
-
-
-
-
-
- {
- GetExecution(execution.execution_id, agentActionResult.action.id, execution.authorization)
- }}
- >
-
-
-
-
-
- {buttonState === "timeline" ?
-
- :
- null
}
- }
+
)
}
diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx
index d6e33cef..b39f22dd 100755
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -72,6 +72,8 @@ import {
Radio,
ButtonGroup,
Box,
+ ToggleButton,
+ ToggleButtonGroup,
} from "@mui/material";
@@ -150,11 +152,11 @@ import ShuffleCodeEditor from "../components/ShuffleCodeEditor1.jsx";
import LineChartWrapper from "../components/LineChartWrapper.jsx";
import WorkflowValidationTimeline from "../components/WorkflowValidationTimeline.jsx"
-import { validateJson, collapseField, GetIconInfo, handleReactJsonClipboard, HandleJsonCopy, } from "../views/Workflows2.jsx";
+import { validateJson, collapseField, GetIconInfo, buildIconSvgPath, handleReactJsonClipboard, HandleJsonCopy, } from "../views/Workflows2.jsx";
import { GetParsedPaths, internalIds, } from "../views/Apps.jsx";
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
-import ParsedAction from "../components/ParsedAction.jsx";
+import ParsedAction from "../components/ParsedActionNew.jsx";
import PaperComponent from "../components/PaperComponent.jsx"
import ExtraApps from "../components/ExtraApps.jsx"
import EditWorkflow from "../components/EditWorkflow.jsx"
@@ -203,7 +205,7 @@ export const triggers = [
trigger_type: "WEBHOOK",
errors: null,
large_image:
- "data:image/png;base64,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",
+ "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4IiByeD0iOCIgZmlsbD0iIzIxQTBCRCIvPgo8cGF0aCBkPSJNMjMuOTYxNyAxOC4wOTk0QzI1LjAwMDQgMTguMDY5NiAyNS42ODE3IDE5LjE3NTIgMjUuMTg4MiAyMC4wODk2TDI1LjE3NDYgMjAuMTE1TDI1LjE5MDIgMjAuMTM5NEwyNy45ODMyIDI0LjY4MDRMMjguMDA0NiAyNC43MTU2TDI4LjA0MzcgMjQuN0MyOC41MzgzIDI0LjUwMDcgMjkuMDY3MSAyNC4zOTgyIDI5LjYwMDMgMjQuMzk4MkMzMS4wODE0IDI0LjM5ODkgMzIuNDQ5OSAyNS4xODkyIDMzLjE5MTIgMjYuNDcxNEMzNC43ODk2IDI5LjIzNzMgMzIuNzk0OCAzMi42OTY1IDI5LjYwMDMgMzIuNjk4QzI5LjM2ODEgMzIuNjk4IDI5LjE1MzkgMzIuNTczOSAyOS4wMzc4IDMyLjM3MjhDMjguNzg3NyAzMS45Mzk1IDI5LjEgMzEuMzk4MiAyOS42MDAzIDMxLjM5ODJDMzEuMjA2NyAzMS4zOTg4IDMyLjQ5NjEgMzAuMDcyMyAzMi40NSAyOC40NjY2QzMyLjM4NjcgMjYuMjczNiAyOS45NzM3IDI0Ljk3MTYgMjguMTA2MiAyNi4xMjI4QzI3LjgwMDggMjYuMzEwOCAyNy40MDAxIDI2LjIxNSAyNy4yMTE3IDI1LjkwOTlIMjcuMjEyNkwyNC4wODE4IDIwLjgyMkwyNC4wNjcxIDIwLjc5ODZIMjQuMDAwN0MyMy41MzIzIDIwLjc5ODYgMjMuMDk3MSAyMC41NTU4IDIyLjg1MTMgMjAuMTU3QzIyLjMwNjIgMTkuMjcyMyAyMi45MjMgMTguMTI5MyAyMy45NjE3IDE4LjA5OTRaTTE1LjA4MDggMjYuMDU3NEMxNS4zODE0IDI1LjY1NzIgMTYuMDAyNiAyNS43MzI4IDE2LjE5OSAyNi4xOTMxQzE2LjI3ODcgMjYuMzgwMSAxNi4yNjU3IDI2LjU5MTkgMTYuMTY3NyAyNi43NjY0TDE2LjEyMDggMjYuODM4NkMxNS43NDkxIDI3LjMzMSAxNS41NDg1IDI3LjkzMTYgMTUuNTUwNSAyOC41NDg2QzE1LjU1MDcgMzAuNzQyMyAxNy45MjYxIDMyLjExMzIgMTkuODI1OSAzMS4wMTY0QzIwLjcwNzUgMzAuNTA3MyAyMS4yNTA2IDI5LjU2NjYgMjEuMjUwNyAyOC41NDg2QzIxLjI1MDcgMjguMTg5NyAyMS41NDE0IDI3Ljg5ODQgMjEuOTAwMSAyNy44OTgySDI4LjQxNzdMMjguNDMyNCAyNy44NzM4QzI4Ljk1MiAyNi45NzM4IDMwLjI1MTYgMjYuOTczOCAzMC43NzEyIDI3Ljg3MzhDMzEuMjkwMyAyOC43NzM3IDMwLjY0MDMgMjkuODk4MiAyOS42MDEzIDI5Ljg5ODJDMjkuMTE5MiAyOS44OTgxIDI4LjY3MzUgMjkuNjQwOSAyOC40MzI0IDI5LjIyMzRMMjguNDE3NyAyOS4xOThIMjIuNDk4OEwyMi40OTE5IDI5LjI0QzIxLjk1OTcgMzIuMzg5NyAxOC4yMTc0IDMzLjc4MjIgMTUuNzU1NiAzMS43NDY4QzE0LjA0ODEgMzAuMzM0NyAxMy43NTA4IDI3LjgyOTYgMTUuMDgwOCAyNi4wNTc0Wk0yMC42NjA5IDE2Ljk5QzIyLjU1NTQgMTQuNDE3OSAyNi41MjQxIDE0Ljg2MTIgMjcuODA0NCAxNy43ODc4QzI3Ljg5NzMgMTguMDAwOCAyNy44NjkxIDE4LjI0NzQgMjcuNzMxMiAxOC40MzQzQzI3LjQzNCAxOC44MzY0IDI2LjgxMzQgMTguNzY2NCAyNi42MTMgMTguMzA4M1YxOC4zMDc0QzI1Ljk0NTQgMTYuNzc5MyAyNC4xMTM0IDE2LjE0ODUgMjIuNjQ2MiAxNi45NDEyQzIwLjcxNjIgMTcuOTg0IDIwLjYzODYgMjAuNzI1NiAyMi41MDY2IDIxLjg3NTdDMjIuODEyIDIyLjA2MzkgMjIuOTA3MyAyMi40NjM3IDIyLjcxOTUgMjIuNzY5M0wxOS41ODk2IDI3Ljg1NjJMMTkuNTc1IDI3Ljg4MDZMMTkuNTg4NiAyNy45MDZDMjAuMDc1IDI4LjgwNTUgMTkuNDIzNiAyOS44OTgzIDE4LjQwMTEgMjkuODk4MkMxNy45MTk2IDI5Ljg5NzggMTcuNDc0MyAyOS42NDEyIDE3LjIzMzIgMjkuMjI0NEMxNi43MTI5IDI4LjMyNDggMTcuMzYxOSAyNy4xOTg4IDE4LjQwMTEgMjcuMTk4SDE4LjQ2NzVMMTguNDgyMiAyNy4xNzQ2TDIxLjI3NjEgMjIuNjM1NUwyMS4yOTg2IDIyLjU5OTRMMjEuMjY2NCAyMi41NzFDMTkuNjQ2MSAyMS4xNTAxIDE5LjM4MjkgMTguNzI1MiAyMC42NjA5IDE2Ljk5WiIgZmlsbD0id2hpdGUiIHN0cm9rZT0iIzIxQTBCRCIgc3Ryb2tlLXdpZHRoPSIwLjEiLz4KPC9zdmc+Cg==",
is_valid: true,
label: "Webhook",
environment: "onprem",
@@ -229,8 +231,7 @@ export const triggers = [
status: "uninitialized",
trigger_type: "SCHEDULE",
errors: null,
- large_image:
- "data:image/png;base64,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",
+ large_image: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4IiByeD0iOCIgZmlsbD0iIzIxQTBCRCIvPgo8Y2lyY2xlIGN4PSIyNCIgY3k9IjI0IiByPSI4Ljc1IiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lkdGg9IjEuNSIvPgo8cGF0aCBkPSJNMjguNSAyNEgyNC4yNUMyNC4xMTE5IDI0IDI0IDIzLjg4ODEgMjQgMjMuNzVWMjAuNSIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K",
label: "Schedule",
is_valid: true,
environment: "onprem",
@@ -258,8 +259,7 @@ export const triggers = [
status: "uninitialized",
trigger_type: "SUBFLOW",
errors: null,
- large_image:
- "data:image/png;base64,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",
+ large_image: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4IiByeD0iOCIgZmlsbD0idXJsKCNwYWludDBfbGluZWFyXzMxN181OTcpIi8+CjxwYXRoIGQ9Ik0xNS45OTk4IDE2LjAwMTVMMTUuOTk5OCAyNS43NDA2TDE5LjIwMDEgMjUuNzQwNkwxOS4yMDAxIDE5LjI0ODVMMzEuOTk5OCAxOS4yNDg1TDMxLjk5OTggMTYuMDAxNUwxNS45OTk4IDE2LjAwMTVaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjguNzk5NCAyMi4yNjE3TDI4Ljc5OTQgMjguNzUzOEwxNS45OTk4IDI4Ljc1MzhMMTUuOTk5OCAzMi4wMDA4TDMxLjk5OTggMzIuMDAwOEwzMS45OTk4IDIyLjI2MTdMMjguNzk5NCAyMi4yNjE3WiIgZmlsbD0id2hpdGUiLz4KPHBhdGggZD0iTTI1LjczOSAyMi4yNjE3TDIyLjI2MDcgMjIuMjYxN0wyMi4yNjA3IDI1Ljc0TDI1LjczOSAyNS43NEwyNS43MzkgMjIuMjYxN1oiIGZpbGw9IndoaXRlIi8+CjxkZWZzPgo8bGluZWFyR3JhZGllbnQgaWQ9InBhaW50MF9saW5lYXJfMzE3XzU5NyIgeDE9Ii03LjcwNzc2ZS0wOSIgeTE9IjI3LjA3NjkiIHgyPSI0OC4wMDE0IiB5Mj0iMjYuOTM3NyIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPgo8c3RvcCBzdG9wLWNvbG9yPSIjRkY4NDQ0Ii8+CjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI0YyNjQzQiIvPgo8L2xpbmVhckdyYWRpZW50Pgo8L2RlZnM+Cjwvc3ZnPgo=",
is_valid: true,
label: "Subflow",
environment: "onprem",
@@ -303,7 +303,7 @@ export const triggers = [
}
],
status: "running",
- large_image: "/images/workflows/UserInput2.svg",
+ large_image: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDgiIGhlaWdodD0iNDgiIHZpZXdCb3g9IjAgMCA0OCA0OCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHJlY3Qgd2lkdGg9IjQ4IiBoZWlnaHQ9IjQ4IiByeD0iOCIgZmlsbD0iIzg2MzZCNCIvPgo8cGF0aCBkPSJNMjEuMjgyMiAxNi43VjE0LjdNMTYuNzgyMiAyMS4ySDE0Ljc4MjJNMTcuOTc5MSAyNC41MDMyTDE2LjU2NDkgMjUuOTE3NE0yNS45OTk3IDE2LjQ4MjRMMjQuNTg1NCAxNy44OTY2TTE2LjU2NDggMTYuNDgyNUwxNy45NzkgMTcuODk2N00yNS4yODk4IDMyLjM1MDRMMjYuNzc3NyAyOC40NTc4QzI2Ljk3OTYgMjcuOTI5NSAyNy40NDggMjcuNTQ5IDI4LjAwNjUgMjcuNDU5N0wzMS42MjY0IDI2Ljg4MDVDMzMuMTkwOSAyNi42MzAyIDMzLjQ1ODUgMjQuNDkxNiAzMi4wMDQgMjMuODYzNEwyMi4zNDUyIDE5LjY5MjdDMjEuMTc1MSAxOS4xODc0IDE5LjkxNzkgMjAuMjAxMyAyMC4xNjQgMjEuNDUxOUwyMi4yNTczIDMyLjA5MDhDMjIuNTY0MyAzMy42NTEgMjQuNzIyMSAzMy44MzU4IDI1LjI4OTggMzIuMzUwNFoiIHN0cm9rZT0id2hpdGUiIHN0cm9rZS13aWR0aD0iMS4yNSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=",
description: "Wait for user input trigger",
trigger_type: "USERINPUT",
is_valid: true,
@@ -312,7 +312,7 @@ export const triggers = [
environment: "cloud",
long_description: "Take user input to continue execution",
id: "",
- },
+ }
];
// Adds specific text to items
@@ -406,7 +406,7 @@ export function SetJsonDotnotation(jsonInput, inputKey) {
//export const green = "#86c142";
export const green = "#2BC07E"
-export const yellow = "#FECC00";
+export const yellow = "#FFC633";
export const red = "#F53434";
export const grey = "#b0b0b0";
@@ -438,6 +438,66 @@ export function removeParam(key, sourceURL) {
return rtn;
}
+const ACTION_STATES_STORAGE_KEY = "shuffle_action_tab_states";
+
+export function getActionState(actionId, workflowId = null) {
+ const defaultState = {
+ tab: "setup",
+ showOptionalParams: false,
+ userSelectedTab: false,
+ };
+
+ try {
+ const stored = localStorage.getItem(ACTION_STATES_STORAGE_KEY);
+ if (!stored) return defaultState;
+
+ const allStates = JSON.parse(stored);
+
+ // Handle both old flat structure and new nested structure for backward compatibility
+ let actionState = {};
+ if (workflowId && allStates[workflowId] && allStates[workflowId][actionId]) {
+ // New nested structure: workflowId -> actionId -> state
+ actionState = allStates[workflowId][actionId];
+ }
+
+ // Validate tab value
+ const validTabs = ["setup", "configuration"];
+ const tab = validTabs.includes(actionState.tab) ? actionState.tab : defaultState.tab;
+
+ return {
+ tab,
+ showOptionalParams: actionState.showOptionalParams === true,
+ userSelectedTab: actionState.userSelectedTab === true,
+ };
+ } catch (e) {
+ return defaultState;
+ }
+}
+
+export function setActionState(actionId, updates, workflowId = null) {
+ if (!actionId || !updates) return;
+
+ try {
+ const stored = localStorage.getItem(ACTION_STATES_STORAGE_KEY);
+ const allStates = stored ? JSON.parse(stored) : {};
+
+ if (workflowId) {
+ // New nested structure: workflowId -> actionId -> state
+ if (!allStates[workflowId]) {
+ allStates[workflowId] = {};
+ }
+ if (!allStates[workflowId][actionId]) {
+ allStates[workflowId][actionId] = {};
+ }
+ Object.assign(allStates[workflowId][actionId], updates);
+ }
+
+ localStorage.setItem(ACTION_STATES_STORAGE_KEY, JSON.stringify(allStates));
+ } catch (e) {
+ console.error("Failed to save action state:", e);
+ }
+}
+
const splitter = "|~|";
const svgSize = 24;
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
@@ -463,9 +523,9 @@ const AngularWorkflow = (defaultprops) => {
var to_be_copied = "";
const [firstrequest, setFirstrequest] = React.useState(true);
- const cystyle = useMemo(() => defaultCytoscapeStyle(theme), [themeMode]);
- // const cystyle = useMemo(() => defaultCytoscapeStyle, [themeMode]);
+ const [apps, setApps] = React.useState([]);
+ const cystyle = useMemo(() => defaultCytoscapeStyle(theme, apps), [themeMode, apps]);
const [cy, setCy] = React.useState();
const useStyles = makeStyles({
@@ -593,7 +653,6 @@ const AngularWorkflow = (defaultprops) => {
const [showDropdown, setShowDropdown] = React.useState(false);
const [triggerActionList, setTriggerActionList] = React.useState([]);
- const [apps, setApps] = React.useState([]);
const [filteredApps, setFilteredApps] = React.useState([]);
const [prioritizedApps, setPrioritizedApps] = React.useState([])
@@ -670,7 +729,7 @@ const AngularWorkflow = (defaultprops) => {
})
const [executionArgumentModalOpen, setExecutionArgumentModalOpen] = React.useState(false);
const [searchModalOpen, setSearchModalOpen] = React.useState(false);
-
+ const [buildDebugMode, setBuildDebugMode] = useState("build"); // "build" or "debug"
useEffect(() => {
if (!firstrequest && isLoaded && isLoggedIn && editWorkflowModalOpen === false) {
@@ -974,6 +1033,7 @@ const AngularWorkflow = (defaultprops) => {
"id": "shuffle_agent",
"name": "AI Agent",
"type": "ACTION",
+ "is_valid": true,
"app_version": "1.0.0",
"loop_versions": ["1.0.0"],
"authentication": {
@@ -1001,7 +1061,7 @@ const AngularWorkflow = (defaultprops) => {
*/
{
"name": "input",
- "value": "Take the data below and run the LLM query\n\n$exec",
+ "value": "What are you able to do?\n\n$exec",
"required": true,
"multiline": true,
"description": "The input data for the LLM query",
@@ -1311,7 +1371,7 @@ const AngularWorkflow = (defaultprops) => {
if (appId === "integration" || appId === "shuffle_agent") {
if (appId === "shuffle_agent") {
- // Get the apps for OpenAI, Gemini, Mistral, DeepSeek
+ // Get sample apps for OpenAI, Gemini, Mistral, DeepSeek...
loadAppConfig("1275a420a6a8b8d782483ac0c22f492c") // Shuffle AI
loadAppConfig("5d19dd82517870c68d40cacad9b5ca91") // OpenAI
//loadAppConfig("5d19dd82517870c68d40cacad9b5ca91") // Gemini
@@ -1656,8 +1716,40 @@ const AngularWorkflow = (defaultprops) => {
cy.on("mouseout", "node", (e) => onNodeHoverOut(e));
// Handles dragging
- cy.on("drag", "node", (e) => onNodeDrag(e, selectedAction));
- cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction));
+ cy.on("drag", "node", (e) => {
+ const node = e.target;
+ // This is used to calculate the movement deltas for group/multi-drag.
+ if (!node.data("dragStartPos")) {
+ node.data("dragStartPos", { ...node.position() });
+ }
+
+ // Move all selected nodes together when Ctrl is held
+ handleMultiDrag(e);
+
+ // Continuously update orientation while dragging (including neighbors)
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDrag(e, selectedAction);
+ });
+
+ cy.on("free", "node", (e) => {
+ const node = e.target;
+ const startPos = node.data("dragStartPos");
+
+ if (startPos) {
+ node.removeData("dragStartPos");
+ }
+
+ // Clear multidrag state
+ if (cy) {
+ cy.nodes().forEach((n) => n.removeData("multiDragStartPos"));
+ }
+
+ // Update orientation after drag ends (including neighbors)
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDragStop(e, selectedAction);
+ });
cy.on("cxttap", "node", (e) => onCtxTap(e));
@@ -1675,6 +1767,10 @@ const AngularWorkflow = (defaultprops) => {
return false
},
+ handlePosition: (node) => {
+ const orientation = node.data("flowOrientation");
+ return orientation === "vertical" ? "middle top" : "right middle";
+ },
preview: true,
toggleOffOnLeave: true,
loopAllowed: function (node) {
@@ -2560,7 +2656,7 @@ const AngularWorkflow = (defaultprops) => {
// Center and zoom to the node with smooth animation if requested
if (config.center) {
- cy.animate({
+ cy.stop().animate({
center: {
eles: cyNode
},
@@ -3318,13 +3414,13 @@ const AngularWorkflow = (defaultprops) => {
foundnode.data("errors", [error])
const parsedStyle = {
- "border-width": "10px",
+ "border-width": "2px",
"border-opacity": ".9",
"border-color": red,
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -3445,6 +3541,18 @@ const AngularWorkflow = (defaultprops) => {
return
}
+ for (var i = 0; i < workflowExecutions.length; i++) {
+ const exec = workflowExecutions[i]
+ if (exec.execution_id === curAction.source_execution) {
+ if (exec?.execution_argument === undefined || exec?.execution_argument === null || exec?.execution_argument.length === 0) {
+ break
+ }
+
+ setExecutionText(exec.execution_argument)
+ break
+ }
+ }
+
setExecutionRunning(true)
setExecutionRequestStarted(true)
var headers = {
@@ -3676,6 +3784,60 @@ const AngularWorkflow = (defaultprops) => {
})
};
+ useEffect(() => {
+
+ const handleDebugKeyDown = (event) => {
+ if ((event.metaKey || event.ctrlKey) && event.key === '/') {
+ event.preventDefault(); // Prevent default browser behavior (like opening search bar)
+ if (!workflow.public && !executionRequestStarted) {
+ executeWorkflow(executionText, workflow.start, lastSaved);
+ }
+ }
+ if ((event.ctrlKey || event.metaKey) && event.key === "'") {
+ // Check if Ctrl (Windows/Linux) or Command (Mac) key is pressed along with '/'
+ if (!workflow.public && !executionModalOpen) {
+ setExecutionModalOpen(true);
+ getWorkflowExecution(props.match.params.key, "");
+ } else if (!workflow.public && executionModalOpen) {
+ setExecutionModalOpen(false);
+ }
+ }
+
+ if ((event.ctrlKey || event.metaKey) && event.key === "]") {
+ console.log("Show workflow revisions key pressed")
+ if (!workflow.public) {
+ setShowWorkflowRevisions(true)
+ //setOriginalWorkflow(workflow)
+ }
+ }
+
+ if ((event.ctrlKey || event.metaKey) && event.key === ";") {
+ if (!workflow.public && executionModalOpen) {
+ getWorkflowExecution(props.match.params.key, "");
+ }
+ }
+
+ /*
+ if (( event.ctrlKey || event.metaKey ) && event.shiftKey) {
+ console.log("Shift key pressed")
+ if (!workflow.public && executionModalOpen) {
+ setExecutionRunning(false);
+ stop()
+ const newitem = removeParam("execution_id", cursearch);
+ navigate(curpath + newitem)
+ setExecutionModalView(0);
+ }
+ }
+ */
+ };
+
+ document.addEventListener('keydown', handleDebugKeyDown);
+
+ return () => {
+ document.removeEventListener('keydown', handleDebugKeyDown);
+ }
+ }, [executeWorkflow, executionText, workflow, lastSaved, executionRequestStarted])
+
// This can be used to only show prioritzed ones later
// Right now, it can prioritize authenticated ones
//"Testing",
@@ -3830,7 +3992,7 @@ const AngularWorkflow = (defaultprops) => {
} else {
console.log("Closing auth modal? FAIL")
- toast("Failed to find new authentication. See details in Oauth2 popup window where auth was attempted.");
+ toast.error("Failed to find new authentication. See details in Oauth2 popup window where auth was attempted.");
shouldClose = false
}
} else {
@@ -4184,7 +4346,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4201,7 +4363,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": "#81c784",
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4250,7 +4412,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4267,7 +4429,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": "#81c784",
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4298,7 +4460,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4314,7 +4476,7 @@ const AngularWorkflow = (defaultprops) => {
"line-gradient-stop-colors": ["grey", "grey"],
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4346,7 +4508,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4363,7 +4525,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": color,
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4394,7 +4556,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4450,7 +4612,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4484,7 +4646,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -5406,6 +5568,13 @@ const AngularWorkflow = (defaultprops) => {
};
const onEdgeSelect = (event) => {
+
+ const selectedNodes = cy.$(':selected');
+ if (selectedNodes && selectedNodes.length > 1) {
+ event.target.unselect();
+ return;
+ }
+
ReactDOM.unstable_batchedUpdates(() => {
setRightSideBarOpen(true);
setLastSaved(false);
@@ -7096,8 +7265,20 @@ const AngularWorkflow = (defaultprops) => {
cy.removeListener("drag");
cy.removeListener("free");
- cy.on("drag", "node", (e) => onNodeDrag(e, curaction));
- cy.on("free", "node", (e) => onNodeDragStop(e, curaction));
+ cy.on("drag", "node", (e) => {
+ const node = e.target;
+
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDrag(e, curaction);
+ });
+
+ cy.on("free", "node", (e) => {
+ const node = e.target;
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDragStop(e, curaction);
+ });
}
if (environments !== undefined && environments !== null && (typeof environments === "array" || typeof environments === "object")) {
@@ -7697,6 +7878,153 @@ const AngularWorkflow = (defaultprops) => {
return dstdata;
};
+ // Dynamic Label Positioning - Core Logic Function
+ // This looks at all edges connected to a node and figures out if the workflow
+ // is flowing horizontally (left-to-right) or vertically (top-to-bottom)
+ // Based on that, it sets the node's "flowOrientation" which controls where the label appears
+ const updateNodeLabelOrientation = (node) => {
+
+ if (!node || typeof node.position !== "function") {
+ return
+ }
+
+ // Get all edges (connections) attached to this node
+ const edges = node.connectedEdges()
+
+ // If node has no edges, default to horizontal layout (label at bottom)
+ if (!edges || edges.length === 0) {
+ node.data("flowOrientation", "horizontal") // Set the orientation data
+ return
+ }
+
+ // Get the current position of this node (x, y coordinates)
+ const nodePos = node.position()
+
+ let hasHorizontalOutgoing = false
+ let hasStrongVertical = false
+
+ // Loop through each edge connected to this node
+ edges.forEach((edge) => {
+ // Check if this node is the source (start) of the edge
+ const isSource = edge.source().id() === node.id()
+ // Get the other node connected by this edge (target if we're source, source if we're target)
+ const other = isSource ? edge.target() : edge.source()
+
+ if (!other || typeof other.position !== "function") {
+ return
+ }
+
+ const otherPos = other.position()
+ // Calculating the distance between the nodes
+ const dx = Math.abs(otherPos.x - nodePos.x)
+ const dy = Math.abs(otherPos.y - nodePos.y)
+
+ // Ignore edges that are too small
+ if (dx < 2 && dy < 2) {
+ return
+ }
+
+ // Determine if edge is mostly vertical (going up/down)
+ const isVerticalish = dx < 30 && dy > 30
+
+ // Determine if edge is mostly horizontal (going left/right)
+ const isHorizontalish = dy < 30 && dx > 30
+
+ if (isSource && isHorizontalish) {
+ hasHorizontalOutgoing = true
+ }
+
+ if (isVerticalish) {
+ hasStrongVertical = true
+ }
+ })
+
+ // Decision: Choose the orientation based on what we found
+ // Priority order:
+ // 1) If we have a horizontal OUTGOING edge → stay horizontal (label at bottom)
+ // (This is the default workflow style - left to right)
+ // 2) Else if we have any strong vertical edge → go vertical (label on right)
+ // (This prevents labels from being cut by vertical edges)
+ // 3) Else → default to horizontal (label at bottom)
+ let newOrientation = "horizontal"
+ if (!hasHorizontalOutgoing && hasStrongVertical) {
+ newOrientation = "vertical"
+ }
+
+ // Save the orientation to the node's data
+ // This will trigger the CSS rules we defined in defaultCytoscapeStyle.jsx
+ node.data("flowOrientation", newOrientation)
+ }
+
+ // This updates node orientation and its connected neighbors
+ const updateNodeAndNeighborsOrientation = (node) => {
+ updateNodeLabelOrientation(node);
+
+ const edges = node.connectedEdges();
+ if (edges && edges.length > 0) {
+ edges.forEach((edge) => {
+ const source = edge.source();
+ const target = edge.target();
+
+ if (source && source.id() !== node.id()) {
+ updateNodeLabelOrientation(source);
+ }
+
+ if (target && target.id() !== node.id()) {
+ updateNodeLabelOrientation(target);
+ }
+ });
+ }
+ };
+
+ // Multi-Node Dragging
+ const handleMultiDrag = (e) => {
+
+ const node = e.target
+ const ev = e.originalEvent
+
+ if (!ev || !ev.ctrlKey) {
+ return;
+ }
+
+ const start = node.data("multiDragStartPos")
+
+ if (!start) {
+ const selectedNodes = cy.$(":selected")
+
+ selectedNodes.forEach((n) => {
+ n.data("multiDragStartPos", { ...n.position() })
+ })
+ return
+ }
+
+ // SUBSEQUENT DRAG EVENTS: Move all selected nodes together
+ // Calculate how far the dragged node has moved
+ const cur = node.position()
+ const dx = cur.x - start.x
+ const dy = cur.y - start.y
+
+ // Get all selected nodes again
+ const selectedNodes = cy.$(":selected")
+
+ // Move each selected node by the same distance (dx, dy)
+ selectedNodes.forEach((n) => {
+ const s = n.data("multiDragStartPos")
+
+ // Skip if no starting position saved, or if this is the node being dragged
+ // (the dragged node is already being moved by Cytoscape automatically)
+ if (!s || n.id() === node.id()) {
+ return
+ }
+
+ // Move this node to: original position + how far the dragged node moved
+ n.position({
+ x: s.x + dx, // Original x + horizontal movement
+ y: s.y + dy, // Original y + vertical movement
+ })
+ })
+ }
+
// Checks for errors in edges when they're added
const onEdgeAdded = (event) => {
setLastSaved(false);
@@ -7721,6 +8049,8 @@ const AngularWorkflow = (defaultprops) => {
if (sourcenode === undefined || sourcenode === null || destinationnode === undefined || destinationnode === null) {
console.log("Source or destination node is undefined or null: ", sourcenode, destinationnode)
} else {
+ updateNodeLabelOrientation(sourcenode)
+ updateNodeLabelOrientation(destinationnode)
if (sourcenode.data("name") === "switch") {
event.target.remove()
return
@@ -7938,6 +8268,11 @@ const AngularWorkflow = (defaultprops) => {
const node = event.target;
const nodedata = JSON.parse(JSON.stringify(event.target.data()))
+ // Default to horizontal layout for new nodes if not explicitly set
+ if (node.data("flowOrientation") === undefined) {
+ node.data("flowOrientation", "horizontal");
+ }
+
if (nodedata.finished === false || (nodedata.id !== undefined && nodedata.is_valid === undefined)) {
return
}
@@ -8002,7 +8337,8 @@ const AngularWorkflow = (defaultprops) => {
if (nodedata.app_name === "Shuffle Tools") {
const iconInfo = GetIconInfo(nodedata);
- const svg_pin = `
`;
+ const iconViewBox = iconInfo.svgViewBox || `0 0 ${svgSize} ${svgSize}`;
+ const svg_pin = `
${buildIconSvgPath(iconInfo, "white")} `;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
nodedata.large_image = svgpin_Url;
nodedata.fillGradient = iconInfo.fillGradient;
@@ -8242,8 +8578,40 @@ const AngularWorkflow = (defaultprops) => {
setWorkflow(workflow);
}
+ // Check if user is typing in an input field, textarea, or contenteditable element
+ var isInputField = function(target) {
+ if (!target) return false
+ const tagName = target.localName || target.tagName?.toLowerCase()
+ const isInput = tagName === "input" || tagName === "textarea"
+ const isContentEditable = target.isContentEditable === true || target.contentEditable === "true"
+ const isEditable = target.getAttribute && (target.getAttribute("contenteditable") === "true" || target.getAttribute("contenteditable") === "")
+ return isInput || isContentEditable || isEditable
+ }
+
//var previouskey = 0
const handleKeyDown = (event) => {
+
+ // Check if any modal or sidebar is open - if so, disable custom shortcuts
+ var isAnyModalOrSidebarOpen =
+ variablesModalOpen ||
+ aiQueryModalOpen ||
+ workflowGenerationModalOpen ||
+ executionVariablesModalOpen ||
+ authenticationModalOpen ||
+ conditionsModalOpen ||
+ authgroupModalOpen ||
+ codeModalOpen ||
+ executionModalOpen ||
+ editWorkflowModalOpen ||
+ tenzirConfigModalOpen ||
+ codeEditorModalOpen ||
+ executionArgumentModalOpen ||
+ searchModalOpen ||
+ rightSideBarOpen ||
+ leftSideBarOpenByClick ||
+ selectionOpen ||
+ (suggestionBox && suggestionBox.open)
+
switch (event.keyCode) {
case 27:
if (configureWorkflowModalOpen === true) {
@@ -8271,58 +8639,97 @@ const AngularWorkflow = (defaultprops) => {
}
break;
+ // FEATURE: Multi-Node Copy (Cmd+C / Ctrl+C)
case 67:
- if (event.ctrlKey && !event.shiftKey) {
- if (
- event.path !== undefined &&
- event.path !== null &&
- event.path.length > 0
- ) {
- if (event.path[0].localName !== "body") {
- console.log("Skipping because body is not targeted");
- return;
- }
+ if ((event.ctrlKey || event.metaKey) && !event.shiftKey) {
+
+ // If any modal/sidebar is open, let browser handle normal copy
+ if (isAnyModalOrSidebarOpen) {
+ return
}
- if (
- event.target !== undefined &&
- event.target !== null
- ) {
- if (event.target.localName !== "body") {
- console.log("Skipping because body is not targeted")
- return;
- }
+ // Do not enter if it's an input field, textarea, or contenteditable element
+ // (we don't want to interfere with normal text copying)
+ if (isInputField(event.target) || isInputField(document.activeElement)) {
+ return;
}
- console.log("CTRL+C");
+ // Make sure Cytoscape is initialized
if (cy !== undefined && cy !== null) {
- var cydata = cy.$(":selected").jsons();
- if (cydata !== undefined && cydata !== null && cydata.length > 0) {
- console.log(cydata);
- const elementName = "copy_element_shuffle";
- var copyText = document.getElementById(elementName);
- if (copyText !== null && copyText !== undefined) {
- const clipboard = navigator.clipboard;
- if (clipboard === undefined) {
- toast("Can only copy over HTTPS (port 3443)");
- return;
- }
+ // Get all selected nodes (this includes decorator nodes, buttons, nodes etc.)
+ const allSelected = cy.$(":selected").filter("node");
+
+ // Filter to get only actual workflow nodes (not UI elements)
+ const selectedNodes = allSelected.filter(node => {
+ const data = node.data();
+ // Only copy nodes that are:
+ // - Not decorator nodes (small icon nodes attached to main nodes)
+ // - Not descriptor nodes (UI elements)
+ // - Not button nodes (delete/copy buttons)
+ // - Either ACTION or TRIGGER type (actual workflow nodes)
+ return data.decorator !== true &&
+ data.isDescriptor !== true &&
+ data.isButton !== true &&
+ (data.type === "ACTION" || data.type === "TRIGGER");
+ });
- navigator.clipboard.writeText(JSON.stringify(cydata));
- copyText.select();
- copyText.setSelectionRange(0, 99999); /* For mobile devices */
- document.execCommand("copy");
- toast(`Copied ${cydata.length} element(s)`);
- }
+ // Only proceed if we have valid nodes to copy
+ if (selectedNodes.length > 0) {
+
+ const nodeIds = selectedNodes.map(n => n.id());
+
+ // Prepare node data for clipboard
+ // We save: node data, position, and original ID (for remapping later)
+ const nodesData = selectedNodes.map(n => ({
+ data: n.data(),
+ position: n.position(),
+ originalId: n.id()
+ }));
+
+ const internalBranches = workflow.branches.filter(branch =>
+ nodeIds.includes(branch.source_id) && // Source node is selected
+ nodeIds.includes(branch.destination_id) // Destination node is selected
+ );
+
+ const clipboardData = {
+ type: "copy_nodes_shuffle",
+ nodes: nodesData,
+ branches: internalBranches
+ };
+
+ // Write to clipboard as JSON string
+ navigator.clipboard.writeText(JSON.stringify(clipboardData))
+ .then(() => toast(`Copied ${selectedNodes.length} node(s) with ${internalBranches.length} branch(es)`))
+ .catch(() => toast("Failed to copy to clipboard"));
+
+ // Prevent browser's default copy behavior
+ event.preventDefault();
}
}
}
break;
+ // FEATURE: Multi-Node Paste (Cmd+V / Ctrl+V)
case 86:
- console.log("CTRL+V? ctrl: ", event.ctrlKey)
- if (event.ctrlKey) {
- // Paste is handled in the handlePaste() function.
+ // Check if Ctrl (Windows/Linux) or Cmd (Mac) is pressed
+ if (event.ctrlKey || event.metaKey) {
+
+ // If any modal/sidebar is open, let browser handle normal paste
+ if (isAnyModalOrSidebarOpen) {
+ return
+ }
+
+ // Don't paste if it's an input field, textarea, or contenteditable element
+ if (isInputField(event.target) || isInputField(document.activeElement)) {
+ return;
+ }
+
+ // Make sure Cytoscape is initialized
+ if (cy !== undefined && cy !== null) {
+ handlePaste(event);
+ }
+ // Prevent browser's default paste behavior
+ event.preventDefault();
}
break;
case 88:
@@ -8338,6 +8745,56 @@ const AngularWorkflow = (defaultprops) => {
// As a poweruser myself, I found myself hitting this a few
// too many times to just edit text. Need a better bind, which does NOT work while inside a field
break;
+ // FEATURE: Multi-Selection Delete (Delete / Backspace keys)
+ // Key code 46 = Delete key (Mac/Windows)
+ // Key code 8 = Backspace key (Windows)
+ case 46: // Delete key
+ case 8: // Backspace key
+ // If any modal/sidebar is open, let browser handle normal delete
+ if (isAnyModalOrSidebarOpen) {
+ return
+ }
+
+ // Don't delete if user is typing in an input field, textarea, or contenteditable element
+ // (we don't want to interfere with normal text deletion)
+ if (isInputField(event.target) || isInputField(document.activeElement)) {
+ return; // Exit early - let the browser handle normal deletion
+ }
+
+ // Make sure Cytoscape is initialized
+ if (cy !== undefined && cy !== null) {
+ // Get all selected nodes
+ const selectedNodes = cy.$(":selected").filter("node");
+
+ // Only proceed if we have nodes selected
+ if (selectedNodes.length > 0) {
+ // IMPORTANT: Collect node IDs first before deleting
+ // This prevents issues if the selection changes while we're deleting
+ const nodeIdsToDelete = [];
+
+ // Loop through selected nodes and collect their IDs
+ selectedNodes.forEach(node => {
+ const nodeData = node.data();
+ // Skip decorator nodes (small icon nodes) - they shouldn't be deleted directly
+ // Exception: COMMENT type decorators can be deleted
+ if (nodeData.decorator === true && nodeData.type !== "COMMENT") {
+ return; // Skip this node
+ }
+ // Add this node's ID to our delete list
+ nodeIdsToDelete.push(nodeData.id);
+ });
+
+ // Delete each node using the existing removeNode function
+ // This function handles proper cleanup (triggers, workflow updates, history, etc.)
+ nodeIdsToDelete.forEach(nodeId => {
+ removeNode(nodeId); // This will trigger onNodeRemoved and clean up properly
+ });
+
+ // Prevent browser's default delete behavior
+ event.preventDefault();
+ }
+ }
+ break;
default:
break;
}
@@ -8345,35 +8802,90 @@ const AngularWorkflow = (defaultprops) => {
//previouskey = event.keyCode
};
- const handlePaste = (event) => {
+ const handlePaste = async (event) => {
if (event.path !== undefined && event.path !== null && event.path.length > 0) {
if (event.path[0].localName !== "body") {
- console.log("Skipping paste because body is not targeted")
- return;
+ return;
}
}
if (event.target !== undefined && event.target !== null) {
- // If it's an input area, skip paste
- if (event.target.localName === "input" || event.target.localName === "textarea") {
- console.log("Skipping paste because body is not targeted (1). Target: ", event?.target?.localName)
- return;
- }
+ if (event.target.localName === "input" || event.target.localName === "textarea") {
+ return;
+ }
}
- // Does this stop things?
- //event.preventDefault()
- const clipboard = (event.originalEvent || event).clipboardData.getData("text/plain")
- console.log("CLIPBOARD TO PASTE: ", clipboard)
+ if (cy === undefined || cy === null) return;
try {
- const allnodes = cy.nodes().jsons()
- var parsedjson = JSON.parse(clipboard);
- if (!Array.isArray(parsedjson)) {
- console.log("Not array! Adding to array.")
- parsedjson = [parsedjson]
+ let clipboardText;
+ if (event.clipboardData) {
+ clipboardText = event.clipboardData.getData("text/plain");
+ } else {
+ clipboardText = await navigator.clipboard.readText();
}
+ const clipboardData = JSON.parse(clipboardText);
+
+ // Handle new multi-node copy format - use same logic as individual copy button
+ if (clipboardData.type === "copy_nodes_shuffle" && clipboardData.nodes && clipboardData.branches) {
+ const idMap = {};
+ clipboardData.nodes.forEach(node => {
+ idMap[node.originalId] = uuidv4();
+ });
+
+ clipboardData.nodes.forEach(node => {
+ const newNodeData = JSON.parse(JSON.stringify(node.data));
+ const newId = idMap[node.originalId];
+ newNodeData.id = newId;
+ if (newNodeData.position !== undefined) {
+ newNodeData.position = {
+ x: node.position.x + 450,
+ y: node.position.y + 450,
+ }
+ }
+
+ newNodeData.isStartNode = false;
+ newNodeData.errors = [];
+ newNodeData.is_valid = true;
+ newNodeData.isValid = true;
+ newNodeData.label = newNodeData.label + "_copy";
+
+ cy.add({
+ group: "nodes",
+ data: newNodeData,
+ position: newNodeData.position,
+ });
+
+ workflow.actions.push(newNodeData);
+ });
+
+ // Copy internal branches (between pasted nodes only - no connections to old nodes)
+ clipboardData.branches.forEach(branch => {
+ const newbranch = JSON.parse(JSON.stringify(branch));
+ newbranch.id = uuidv4();
+ newbranch.source_id = idMap[branch.source_id];
+ newbranch.destination_id = idMap[branch.destination_id];
+ newbranch._id = newbranch.id;
+ newbranch.source = newbranch.source_id;
+ newbranch.target = newbranch.destination_id;
+ cy.add({
+ group: "edges",
+ data: newbranch,
+ });
+ });
+
+ // Clear clipboard after successful paste
+ navigator.clipboard.writeText("").catch(() => {});
+
+ event.preventDefault();
+ return;
+ }
+
+ // Fallback to old format for backward compatibility
+ const allnodes = cy.nodes().jsons();
+ var parsedjson = Array.isArray(clipboardData) ? clipboardData : [clipboardData];
+
for (let jsonkey in parsedjson) {
var item = parsedjson[jsonkey];
@@ -8416,10 +8928,10 @@ const AngularWorkflow = (defaultprops) => {
group: item.group,
data: item.data,
position: {
- x: item.position.x+20,
- y: item.position.y+20,
- },
- })
+ x: (item.position?.x || 0) + 20,
+ y: (item.position?.y || 0) + 20,
+ },
+ });
}
} catch (e) {
console.log("Error pasting: ", e);
@@ -8615,19 +9127,19 @@ const AngularWorkflow = (defaultprops) => {
}
var parsedStyle = {
- "border-width": "1px",
+ "border-width": "2px",
"font-size": "18px",
//"cursor": "default",
}
if ((nodedata.app_name === "Testing" || nodedata.app_name === "Shuffle Tools") && !nodedata.isStartNode) {
parsedStyle = {
- "border-width": "1px",
+ "border-width": "2px",
"font-size": "0px",
};
}
- event.target.animate(
+ event.target.stop().animate(
{
style: parsedStyle,
},
@@ -8657,8 +9169,14 @@ const AngularWorkflow = (defaultprops) => {
return;
}
- const px = parentNode.position("x") - 65;
- const py = parentNode.position("y") - 45;
+ var xDiff = 0
+ var yDiff = 0
+ if (parentNode.data("app_id") === "shuffle_agent") {
+ xDiff = 70
+ }
+
+ const px = parentNode.position("x") - 65 - xDiff;
+ const py = parentNode.position("y") - 45 - yDiff;
const circleId = (newNodeId = uuidv4());
parentNode.data("circleId", circleId);
@@ -9367,7 +9885,7 @@ const AngularWorkflow = (defaultprops) => {
if (nodedata.type === "TRIGGER") {
if (nodedata.trigger_type === "SUBFLOW" || nodedata.trigger_type === "USERINPUT") {
addCopyButton(event);
- } else {
+ } else {
// Check how many executions from the source
addRunCountButton(event);
}
@@ -9375,9 +9893,9 @@ const AngularWorkflow = (defaultprops) => {
addCopyButton(event);
- if (nodedata.app_id !== "shuffle_agent") {
- addStartnodeButton(event);
- }
+ // if (nodedata.app_id !== "shuffle_agent") {
+ addStartnodeButton(event);
+ // }
}
// autocomplete
@@ -9393,14 +9911,14 @@ const AngularWorkflow = (defaultprops) => {
}
}
- if (nodedata.name === "switch" || nodedata.app_id === "shuffle_agent") {
+ if (nodedata.name === "switch") {
return
}
var parsedStyle = {
- "border-width": "7px",
+ "border-width": "6px",
"border-opacity": ".7",
- "font-size": "25px",
+ "font-size": nodedata.app_id !== "shuffle_agent" && "25px",
//"cursor": "pointer",
}
@@ -9413,7 +9931,7 @@ const AngularWorkflow = (defaultprops) => {
const item = typeIds[idkey]
if (item.data.id === nodedata.id) {
//console.log("items: ", item.data.id, nodedata.id)
- parsedStyle["border-width"] = "7px"
+ parsedStyle["border-width"] = "6px"
break
}
}
@@ -9423,7 +9941,7 @@ const AngularWorkflow = (defaultprops) => {
}
if (event.target !== undefined && event.target !== null) {
- event.target.animate(
+ event.target.stop().animate(
{
style: parsedStyle,
},
@@ -9632,7 +10150,65 @@ const AngularWorkflow = (defaultprops) => {
}
}
- const setupGraph = (inputworkflow) => {
+ function roundBase64Image(base64, radius = 12) {
+ if (!base64 || typeof base64 !== "string") {
+ return Promise.resolve(base64);
+ }
+
+ return new Promise((resolve) => {
+ const img = new Image();
+ if (!base64.startsWith("data:")) {
+ img.crossOrigin = "anonymous";
+ }
+
+ img.onload = () => {
+ const size = Math.min(img.width, img.height);
+ if (size === 0) {
+ resolve(base64);
+ return;
+ }
+
+ const canvas = document.createElement("canvas");
+ canvas.width = size;
+ canvas.height = size;
+
+ const ctx = canvas.getContext("2d");
+
+ // Draw rounded rect mask
+ ctx.beginPath();
+ ctx.moveTo(radius, 0);
+ ctx.lineTo(size - radius, 0);
+ ctx.quadraticCurveTo(size, 0, size, radius);
+ ctx.lineTo(size, size - radius);
+ ctx.quadraticCurveTo(size, size, size - radius, size);
+ ctx.lineTo(radius, size);
+ ctx.quadraticCurveTo(0, size, 0, size - radius);
+ ctx.lineTo(0, radius);
+ ctx.quadraticCurveTo(0, 0, radius, 0);
+ ctx.closePath();
+ ctx.clip();
+
+ // Draw image centered & cropped square
+ const sx = (img.width - size) / 2;
+ const sy = (img.height - size) / 2;
+ ctx.drawImage(img, sx, sy, size, size, 0, 0, size, size);
+
+ try {
+ resolve(canvas.toDataURL("image/png"));
+ } catch (e) {
+ resolve(base64);
+ }
+ };
+
+ img.onerror = () => {
+ resolve(base64);
+ };
+
+ img.src = base64;
+ });
+ }
+
+ const setupGraph = async (inputworkflow) => {
// Reset cytoscape nodes and branches
if (cy !== undefined && cy !== null) {
if (inputworkflow.actions !== undefined && inputworkflow.actions !== null && inputworkflow.actions.length > 0) {
@@ -9660,12 +10236,13 @@ const AngularWorkflow = (defaultprops) => {
inputworkflow.visual_branches = []
}
- const actions = inputworkflow.actions.map((action) => {
+ const actions = await Promise.all(inputworkflow.actions.map(async (action) => {
const node = {};
if (!action.isStartNode && action.app_name === "Shuffle Tools") {
const iconInfo = GetIconInfo(action)
- const svg_pin = `
`;
+ const iconViewBox = iconInfo.svgViewBox || `0 0 ${svgSize} ${svgSize}`;
+ const svg_pin = `
${buildIconSvgPath(iconInfo, "white")} `;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
action.large_image = svgpin_Url;
action.fillGradient = iconInfo.fillGradient;
@@ -9686,6 +10263,12 @@ const AngularWorkflow = (defaultprops) => {
action.iconBackground = iconInfo.iconBackgroundColor
action.fillstyle = "linear-gradient"
}
+ }else if(!action.isStartNode) {
+ // This is to round the corners of the image
+ const originalBase64 = action.large_image !== undefined && action.large_image !== null && action.large_image !== "" ? action.large_image : theme.palette.defaultImage
+ const roundedImage = await roundBase64Image(originalBase64, 16);
+ action = {...action, large_image: roundedImage}
+
}
node.position = action.position;
@@ -9734,14 +10317,14 @@ const AngularWorkflow = (defaultprops) => {
const foundnode = cy.getElementById(action.id)
if (foundnode !== undefined && foundnode !== null) {
const parsedStyle = {
- "border-width": "3px",
+ "border-width": "2px",
"border-opacity": "1",
"border-color": "#40E0D0",
"opacity": "0.4",
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -9755,7 +10338,7 @@ const AngularWorkflow = (defaultprops) => {
}
return node
- })
+ }))
// What are these again? Where are they used?
const decoratorNodes = []
@@ -9903,14 +10486,14 @@ const AngularWorkflow = (defaultprops) => {
const foundnode = cy.getElementById(trigger.id)
if (foundnode !== undefined && foundnode !== null) {
const parsedStyle = {
- "border-width": "3px",
+ "border-width": "2px",
"border-opacity": "1",
"border-color": "#40E0D0",
"opacity": "0.4",
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -10651,6 +11234,10 @@ const AngularWorkflow = (defaultprops) => {
return false
},
+ handlePosition: (node) => {
+ const orientation = node.data("flowOrientation");
+ return orientation === "vertical" ? "middle top" : "right middle";
+ },
preview: false,
toggleOffOnLeave: true,
loopAllowed: function (node) {
@@ -10674,7 +11261,20 @@ const AngularWorkflow = (defaultprops) => {
console.log("Error fitting cytoscape (4): ", error)
}
-
+ // Ensure all nodes have correct initial orientation based on edges
+ // after graph is rendered / fitted.
+ try {
+ cy.nodes().forEach((node) => {
+ if (node.data("flowOrientation") === undefined) {
+ node.data("flowOrientation", "horizontal")
+ }
+
+ updateNodeLabelOrientation(node)
+ })
+ } catch (error) {
+ console.log("Error setting initial flowOrientation: ", error)
+ }
+
cy.on("boxselect", "node", (e) => {
e.preventDefault()
e.stopPropagation()
@@ -10749,8 +11349,19 @@ const AngularWorkflow = (defaultprops) => {
});
// Handles dragging
- cy.on("drag", "node", (e) => onNodeDrag(e, selectedAction));
- cy.on("free", "node", (e) => onNodeDragStop(e, selectedAction));
+ cy.on("drag", "node", (e) => {
+ const node = e.target;
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDrag(e, selectedAction);
+ });
+
+ cy.on("free", "node", (e) => {
+ const node = e.target;
+ updateNodeAndNeighborsOrientation(node);
+
+ onNodeDragStop(e, selectedAction);
+ });
cy.on("cxttap", "node", (e) => onCtxTap(e));
@@ -11005,6 +11616,7 @@ const AngularWorkflow = (defaultprops) => {
marginLeft: 5,
marginRight: 5,
display: "flex",
+ backgroundColor: theme.palette.backgroundColor,
flexDirection: "column",
minHeight: isMobile ? bodyHeight - appBarSize * 4 : parsedHeight,
maxHeight: isMobile ? bodyHeight - appBarSize * 4 : parsedHeight,
@@ -11353,17 +11965,13 @@ const AngularWorkflow = (defaultprops) => {
orientation={isMobile ? "vertical" : "horizontal"}
style={{
display: "flex",
+ width: "100%",
}}
>
-
-
-
- {isMobile ? null : Apps }
-
+ "Apps"
}
style={tabStyle}
/>
@@ -11390,12 +11998,7 @@ const AngularWorkflow = (defaultprops) => {
-
-
-
- {isMobile ? null : Vars }
-
+ "Vars"
}
style={tabStyle}
/>
@@ -11645,7 +12248,8 @@ const AngularWorkflow = (defaultprops) => {
if (newAppData.app_name === "Shuffle Tools") {
const iconInfo = GetIconInfo(newAppData)
- const svg_pin = ` `;
+ const iconViewBox = iconInfo.svgViewBox || `0 0 ${svgSize} ${svgSize}`;
+ const svg_pin = `${buildIconSvgPath(iconInfo, "white")} `;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin)
newAppData.large_image = svgpin_Url
@@ -11778,7 +12382,7 @@ const AngularWorkflow = (defaultprops) => {
zoom: 0.9,
}
- const handleAppDrag = (e, app) => {
+ const handleAppDrag = async (e, app) => {
if (cy === undefined || cy === null) {
return
}
@@ -11935,6 +12539,10 @@ const AngularWorkflow = (defaultprops) => {
}
}
+ const originalBase64 = app.large_image !== undefined && app.large_image !== null && app.large_image !== "" ? app.large_image : app.palette.defaultImage
+ const roundedImage = await roundBase64Image(originalBase64, 16);
+
+
const newAppData = {
name: app.actions[actionIndex].name,
label: actionLabel,
@@ -11953,7 +12561,7 @@ const AngularWorkflow = (defaultprops) => {
type: actionType,
parameters: parameters,
isStartNode: false,
- large_image: app.large_image,
+ large_image: roundedImage,
run_magic_output: false,
authentication: [],
execution_variable: undefined,
@@ -12151,7 +12759,16 @@ const AngularWorkflow = (defaultprops) => {
// Change the Large Image
const iconInfo = GetIconInfo(action)
- const svg_pin = ` `;
+ const bgColor = iconInfo.iconBackgroundColor || "#f76b1c";
+ var pathElement;
+ if (iconInfo.svgViewBox === "0 0 48 48") {
+ pathElement = buildIconSvgPath(iconInfo, iconInfo.iconColor);
+ } else if (iconInfo.useStroke) {
+ pathElement = ` `;
+ } else {
+ pathElement = ` `;
+ }
+ const svg_pin = ` ${pathElement} `;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
app.large_image = svgpin_Url
app.fillGradient = iconInfo.fillGradient
@@ -12199,7 +12816,8 @@ const AngularWorkflow = (defaultprops) => {
// If action is set, look for the icon of it with the normal setup
}
- newAppStyle.backgroundColor = theme.palette.backgroundColor
+ newAppStyle.backgroundColor = hover ? theme.palette.parsedAppPaperColor : "transparent"
+
return (
{
@@ -12223,6 +12841,7 @@ const AngularWorkflow = (defaultprops) => {
>
{
if (!dragRef.current) {
@@ -12330,9 +12949,9 @@ const AngularWorkflow = (defaultprops) => {
-
+
{
userDrag: "none",
userSelect: "none",
borderRadius: theme.palette?.borderRadius,
- height: isMobile ? 40 : 45,
- width: isMobile ? 40 : 45,
-
+ height: isMobile ? 40 : (small === true || app.type === "TRIGGER") ? 52 : 45,
+ width: isMobile ? 40 : (small === true || app.type === "TRIGGER") ? 52 : 45,
background: `linear-gradient(to right, ${app.fillGradient})`,
}}
/>
@@ -12487,7 +13105,7 @@ const AngularWorkflow = (defaultprops) => {
//}
safeRefine(event.currentTarget.value)
}}
- limit={5}
+ limit={15}
/>
{/*isSearchStalled ? 'My search is stalled' : ''*/}
@@ -12692,7 +13310,7 @@ const AngularWorkflow = (defaultprops) => {
{title}
@@ -12704,15 +13322,15 @@ const AngularWorkflow = (defaultprops) => {
// Popular Shuffle Tools actions
const popularActions = [
- ["repeat_back_to_me", "filter_list", "execute_python", "parse_ioc"],
- ["set_cache_value", "get_file_meta", "merge_lists", "send_sms_shuffle"]
+ ["repeat_back_to_me", "execute_python", "get_file_value", "set_cache_value"],
+ ["get_file_meta", "send_sms_shuffle", "filter_list", "merge_lists"],
];
return (
{
InputProps={{
style: {
height: 40,
+ borderRadius: theme.palette?.borderRadius,
+ backgroundColor: theme.palette.usecaseCardColor,
},
startAdornment: (
@@ -12782,7 +13402,7 @@ const AngularWorkflow = (defaultprops) => {
)}
{visibleApps.length > extraApps.length ?
-
+
Your Apps
: null}
@@ -12798,9 +13418,9 @@ const AngularWorkflow = (defaultprops) => {
return null
}
- if ((app.id === "shuffle_agent") && userdata.support !== true) {
- return null
- }
+ //if ((app.id === "shuffle_agent") && userdata.support !== true) {
+ // return null
+ //}
if (viewedApps.includes(app.id)) {
return null
@@ -13034,7 +13654,8 @@ const AngularWorkflow = (defaultprops) => {
if (newSelectedAction.app_name === "Shuffle Tools") {
const iconInfo = GetIconInfo(newSelectedAction);
- const svg_pin = ` `;
+ const iconViewBox = iconInfo.svgViewBox || `0 0 ${svgSize} ${svgSize}`;
+ const svg_pin = `${buildIconSvgPath(iconInfo, "white")} `;
const svgpin_Url = encodeURI("data:image/svg+xml;utf-8," + svg_pin);
newSelectedAction.large_image = svgpin_Url;
newSelectedAction.fillGradient = iconInfo.fillGradient;
@@ -14360,8 +14981,7 @@ const AngularWorkflow = (defaultprops) => {
padding: 30,
pointerEvents: "auto",
color: theme.palette.text.primary,
- minWidth: isMobile ? "90%" : 650,
- border: theme.palette.defaultBorder,
+ minWidth: isMobile ? "90%" : 750,
borderRadius: theme.palette.borderRadius,
backgroundColor: "black",
@@ -14474,18 +15094,24 @@ const AngularWorkflow = (defaultprops) => {
{
setExecutionText(data)
- executeWorkflow(data, workflow.start, lastSaved);
+ executeWorkflow(data, workflow.start, lastSaved)
setExecutionArgumentModalOpen(false)
}}
>Select
{
return collapseField(jsonField)
}}
@@ -14499,10 +15125,11 @@ const AngularWorkflow = (defaultprops) => {
}
return (
- {
setExecutionText(data)
- executeWorkflow(data, workflow.start, lastSaved);
+ //executeWorkflow(data, workflow.start, lastSaved);
setExecutionArgumentModalOpen(false)
}}
@@ -14759,6 +15386,7 @@ const AngularWorkflow = (defaultprops) => {
color: theme.palette.textColor,
backgroundColor: 'inherit',
zIndex: 10000,
+ fontSize: 12,
}}
>
PS: Conditions can't be used for loops [ .# ]. Use the filters list action.{" "}
@@ -15110,7 +15738,9 @@ const AngularWorkflow = (defaultprops) => {
key={condition.condition.id}
square
style={paperVariableStyle}
- onClick={() => { }}
+ onClick={() => {
+ setLastSaved(false)
+ }}
>
{
return
}
+ setLastSaved(false)
setSourceValue({
name: "source",
value: "",
@@ -15384,17 +16015,15 @@ const AngularWorkflow = (defaultprops) => {
// Change Direction of the branch target/source
const foundBranch = cy.getElementById(selectedEdge.id)
if (foundBranch !== undefined && foundBranch !== null) {
- console.log("BRANCH: ", foundBranch)
const source = foundBranch.data("source")
const target = foundBranch.data("target")
var branchdata = JSON.parse(JSON.stringify(foundBranch.data()))
- console.log("BEFORE: ", branchdata)
- console.log("Start node", workflow.start)
const startNode = workflow.start
if (source === startNode) {
toast("Can't point to Start Node")
} else {
+ setLastSaved(false)
const newid = uuidv4()
branchdata.source = target
branchdata.target = source
@@ -19229,27 +19858,25 @@ const AngularWorkflow = (defaultprops) => {
const cytoscapeViewWidths = isMobile ? 50 : 950;
const bottomBarStyle = {
position: "absolute",
- transition: "all 0.3s ease",
- minWidth: windowWidth < 1600 && leftSideBarOpenByClick ? 800 : cytoscapeViewWidths,
- maxWidth: windowWidth < 1600 && leftSideBarOpenByClick ? 800 : cytoscapeViewWidths,
- marginLeft: 20,
- marginBottom: 30,
+ left: `${leftBarSize + (cytoscapeWidth / 2)}px`,
+ transform: "translateX(-50%)",
+ bottom: 20,
zIndex: 10,
- transform: isMobile
- ? `translateX(20px)`
- : `translateX(${leftBarSize}px)`,
- top: isMobile ? appBarSize + 55 : undefined,
- bottom: isMobile ? undefined : 0,
+ display: "flex",
+ justifyContent: "center",
+ alignItems: "center",
};
const topBarStyle = {
position: "absolute",
-
- top: isMobile ? 30 : isSafari ? 15 : 25,
- transform: isMobile ? "translateX(20px)" : `translateX(${leftBarSize}px)`,
+ top: 10,
+ transform: `translateX(${leftBarSize}px)`,
+ width: bodyWidth - leftBarSize + 25,
transition: "all 0.3s ease",
+ paddingLeft : 30,
zoom: isSafari ? undefined : 0.9,
- }
+ overflow: "hidden",
+ }
const changeOrg = () => {
@@ -19298,7 +19925,7 @@ const AngularWorkflow = (defaultprops) => {
}, 2000);
}
- toast.info("Successfully changed active organisation - refreshing!");
+ toast.success("Successfully changed active organisation - refreshing!");
} else {
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
toast(responseJson.reason);
@@ -19316,6 +19943,38 @@ const AngularWorkflow = (defaultprops) => {
const TopCytoscapeBar = (props) => {
const [hovered, setHovered] = useState(false)
+ const toggleButtonSx = {
+ textTransform: "none",
+ backgroundColor: "transparent",
+ color: theme.palette.text.primary,
+ height: 36,
+ minWidth: 90,
+ padding: "8px 44px",
+ display: "flex",
+ alignItems: "center",
+ gap: 1,
+ fontSize: "16px",
+ fontWeight: 400,
+ boxShadow: "none",
+ fontFamily: theme?.typography?.fontFamily,
+ "&.Mui-selected": {
+ backgroundColor: themeMode === "dark" ? "#1e1e1e" : "#CCCCCC",
+ color: theme.palette.text.primary,
+ fontWeight: 600,
+ "&:hover": {
+ backgroundColor: themeMode === "dark" ? "rgba(0,0,0,0.3)" : "rgba(0,0,0,0.1)",
+ },
+ },
+ "&:hover": {
+ backgroundColor: themeMode === "dark" ? "rgba(255,255,255,0.05)" : "rgba(0,0,0,0.05)",
+ },
+ }
+
+ const toggleOptions = [
+ { value: "build", label: "Build", icon: "/icons/workflow-page/buildIcon.svg", darkIcon: "/icons/workflow-page/buildIcon-dark.svg"},
+ { value: "debug", label: "Debug", icon: "/icons/workflow-page/runningMan.svg", darkIcon: "/icons/workflow-page/run-dark.svg"},
+ ]
+
if (workflow?.public === true) {
return null
}
@@ -19328,678 +19987,761 @@ const AngularWorkflow = (defaultprops) => {
return (
+
+ {/* Top Row: Workflow Name | Build/Debug Toggle | Right Side Buttons */}
-
{
- setHovered(true)
+ {/* Left: Workflow Name Container */}
+
+ {
- setHovered(false)
- }}
- onClick={() => {
- setEditWorkflowModalOpen(true)
- setLastSaved(false)
- }}
- >
- {workflow?.name !== undefined && workflow?.name !== null && workflow?.name?.length > 0 ?
-
- :
- null
- }
- {workflow.name}
-
- {workflowAsCode && (
+ onMouseEnter={() => {
+ setHovered(true)
+ }}
+ onMouseLeave={() => {
+ setHovered(false)
+ }}
+ onClick={() => {
+ setEditWorkflowModalOpen(true)
+ setLastSaved(false)
+ }}
+ >
+ {workflow?.name !== undefined && workflow?.name !== null && workflow?.name?.length > 0 ?
+
+ :
+ null
+ }
+ {workflow.name}
+
+
+
+ {/* Center: Build/Debug Toggle */}
+ {workflow.public === true ? null : (
+
+
{
+ if (newMode !== null) {
+ setBuildDebugMode(newMode)
+ if (newMode === "debug") {
+ setExecutionModalOpen(true);
+ getWorkflowExecution(workflow.id, "", executionFilter, workflow.org_id)
+ }
+ }
+ }}
+ sx={{
+ backgroundColor: themeMode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.05)",
+ borderRadius: "8px",
+ padding: "3px",
+ border: "none",
+ "& .MuiToggleButtonGroup-grouped": {
+ border: "none",
+ "&:not(:first-of-type)": {
+ borderRadius: "6px",
+ borderTopLeftRadius: "0px",
+ borderBottomLeftRadius: "0px",
+ },
+ "&:first-of-type": {
+ borderRadius: "6px",
+ borderTopRightRadius: "0px",
+ borderBottomRightRadius: "0px",
+ },
+ },
+ }}
+ >
+ {toggleOptions.map(({ value, label, icon, darkIcon }) => (
+
+
+ {label}
+
+ ))}
+
+
)}
+
+ {/* Right: Buttons Container */}
+
+ {originalWorkflow?.suborg_distribution === undefined || originalWorkflow?.suborg_distribution === null || originalWorkflow?.suborg_distribution?.length === 0 || originalWorkflow?.suborg_distribution.includes("none") ?
+ <>
+ {originalWorkflow?.parentorg_workflow !== undefined && originalWorkflow?.parentorg_workflow !== null && originalWorkflow?.parentorg_workflow?.length > 0 || workflow?.parentorg_workflow !== undefined && workflow?.parentorg_workflow !== null && workflow?.parentorg_workflow?.length > 0 ?
+ null
+
+ /*
+ * Disabled because redirects occurred anyway
+ *
+
{
+ //changeOrg()
+
+ // Reload the page
+ navigate(`/workflows/${workflow.parentorg_workflow}`)
+ window.location.reload()
+ }}
+ >
+ Go to parent org workflow
+
+ */
+
+ : null}
+
+ {userdata !== undefined && userdata !== null && userdata?.orgs !== undefined && userdata?.orgs !== null && userdata?.orgs?.length > 1 && workflow?.id !== undefined && workflow?.id && workflow?.id?.length > 0 && userdata?.active_org?.creator_org?.length === 0 && userdata?.active_org?.id == workflow?.org_id ?
+
{
+ setEditWorkflowModalOpen(true)
+ }}
+ >
+ Enable Suborg Distribution
+
+ : null}
+ >
+ :
+
+ Save the workflow first
+
+ : null} arrow placement="right">
+
+
+ Select an Org ({originalWorkflow?.suborg_distribution?.length})
+
+ {
+ if (cy !== undefined && cy !== null) {
+ cy.nodes().unselect()
+ }
+
+ if (lastSaved === false && originalWorkflow.id === workflow.id) {
+ setSuborgWorkflows([])
+ saveWorkflow(workflow, undefined, undefined, e.target.value)
+
+ /* Standard re-loads */
+ setAllTriggers(undefined)
+ setSelectedTriggerIndex(-1)
+ getEnvironments(e.target.value)
+ getAppAuthentication(undefined, undefined, undefined, e.target.value)
+ getFiles(e.target.value)
+ listOrgCache(e.target.value)
+ /* Standard re-loads */
+
+ toast.warn(`Saving workflow first due to detected changes.`, {
+ autoClose: 2000,
+ })
+ return
+ }
+
+ if (workflow.org_id === e.target.value) {
+ console.log("Same org selected. No change.")
+ return
+ } else {
+ //if (savingState === 0) {
+ // saveWorkflow(workflow, undefined, undefined, undefined)
+ // return
+ //}
+ }
+
+ navigate(`?org_id=${e.target.value}`)
+
+ // Unselect in cy
+ if (cy !== undefined && cy !== null) {
+ cy.nodes().unselect()
+ cy.edges().unselect()
+ }
+
+ ReactDOM.unstable_batchedUpdates(() => {
+ /* Standard re-loads */
+ setAllTriggers(undefined)
+ setSelectedTriggerIndex(-1)
+ getEnvironments(e.target.value)
+ getAppAuthentication(undefined, undefined, undefined, e.target.value)
+ getFiles(e.target.value)
+ listOrgCache(e.target.value)
+ /* Standard re-loads */
+
+ // Reset the save button to ensure random saves don't occur during move
+ setLastSaved(true)
+
+ // FIXME: There is a timing problem here.
+ // For events to have the data they need, they
+ // need to be registered with setupGraph()
+ // AFTER all the APIs are done
+
+ // Should look through childorg workflow
+ setTimeout(() => {
+ if (e.target.value === originalWorkflow.org_id) {
+ updateCurrentWorkflow(originalWorkflow)
+ return
+ } else {
+ // Load environments, auth, auth groups
+ //toast("Loading correct info for suborg")
+ }
+
+ if (originalWorkflow?.childorg_workflow_ids === undefined || originalWorkflow?.childorg_workflow_ids === null || originalWorkflow?.childorg_workflow_ids?.length === 0) {
+ //console.log("Childorg doesn't exist (?). Suborgworkflows: ", suborgWorkflows)
+
+ if (suborgWorkflows !== undefined && suborgWorkflows !== null && suborgWorkflows?.length > 0) {
+ var found = false
+ for (var suborgkey in suborgWorkflows) {
+ const suborgWorkflow = suborgWorkflows[suborgkey]
+ if (suborgWorkflow.org_id === e.target.value) {
+ found = true
+ updateCurrentWorkflow(suborgWorkflow)
+ break
+ }
+ }
+
+ if (!found) {
+ toast("(3) Creating new workflow for this org. Please wait a second while we duplicate.")
+ //console.log("No workflow found out of suborg workflows.")
+
+ //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
+ }
+ } else {
+ console.log("Suborgworkflows: ", suborgWorkflows)
+ toast("(1) Loading NEW workflow for this org (?). Please wait a second.")
+ saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
+ }
+ } else {
+ console.log("In childorg EXIST!")
+ var workflowFound = false
+ for (var childorgidkey in originalWorkflow.childorg_workflow_ids) {
+ const childworkflowid = originalWorkflow.childorg_workflow_ids[childorgidkey]
+ for (var suborgWorkflowKey in suborgWorkflows) {
+ const suborgWorkflow = suborgWorkflows[suborgWorkflowKey]
+ if (suborgWorkflow.org_id === e.target.value) {
+ workflowFound = true
+ updateCurrentWorkflow(suborgWorkflow)
+ break
+ }
+ }
+
+ if (workflowFound) {
+ break
+ }
+ }
+
+ if (!workflowFound) {
+ console.log("No workflow found.")
+ toast("(2) Creating new workflow for this org. Please wait a few seconds while we prepare it for you.")
+ //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
+ }
+ }
+ }, 500)
+ })
+ }}
+ label="Suborg Distribution"
+ fullWidth
+ >
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ }}
+ /> {userdata.active_org.large_image}{" "}
+
+ {userdata.active_org.name}
+
+
+
+ {originalWorkflow.suborg_distribution.map((org_id, index) => {
+ var data = {}
+ for (var key in userdata.orgs) {
+ if (userdata.orgs[key].id === org_id) {
+ data = userdata.orgs[key]
+ break
+ }
+ }
+
+ if (data.id === undefined || data.id === null) {
+ return null
+ }
+
+ var skipOrg = false;
+ const imagesize = 22
+ const imageStyle = {
+ width: imagesize,
+ height: imagesize,
+ pointerEvents: "none",
+ marginRight: 10,
+ marginLeft:
+ data.creator_org !== undefined &&
+ data.creator_org !== null &&
+ data.creator_org?.length > 0
+ ? data?.id === userdata?.active_org?.id
+ ? 0
+ : 0
+ : 0,
+ }
+
+ const image =
+ data.image === "" ? (
+
+ ) : (
+
+ )
+
+ var orgDiff = {
+ different: false,
+ }
+
+ const foundMatchingWorkflow = suborgWorkflows?.find((workflow) => workflow.org_id === data.id)
+ if (foundMatchingWorkflow !== undefined && foundMatchingWorkflow !== null && foundMatchingWorkflow.diff !== undefined && foundMatchingWorkflow.diff !== null) {
+ orgDiff = foundMatchingWorkflow.diff
+ }
+
+ //console.log("DIFF: ", orgDiff)
+
+ return (
+
+
+ {image}{" "}
+
+ {data.name}
+
+
+
+ {foundMatchingWorkflow !== undefined && foundMatchingWorkflow !== null && foundMatchingWorkflow?.errors !== undefined && foundMatchingWorkflow?.errors !== null && foundMatchingWorkflow?.errors?.length > 0 &&
+
+
+ {foundMatchingWorkflow?.errors?.length} Workflow Issue{foundMatchingWorkflow?.errors?.length > 1 ? "s" : ""}
+
+
+ }
+ >
+
+
+ }
+
+ {orgDiff.different === true ?
+
+
+ Diff (beta):
+
+
+ {orgDiff.environment === true &&
+ - Environment
+ }
+
+ {orgDiff?.actions?.length > 0 &&
+ - Actions ({orgDiff.actions?.length}):
+ {orgDiff.actions.map((orgDiffAction, index) => {
+ //console.log("DIFF2: ", orgDiffAction)
+ var formattedError = ""
+ var paramchanges = ""
+ for (var diffActionKey in orgDiffAction) {
+ if (diffActionKey !== "id" && diffActionKey !== "label" && diffActionKey !== "parameters" && diffActionKey !== "params" && diffActionKey !== "large_image") {
+ if (formattedError?.length > 0) {
+ formattedError += ", "
+ }
+ formattedError += diffActionKey
+ }
+
+ if (diffActionKey === "parameters") {
+ paramchanges = orgDiffAction[diffActionKey].join(", ")
+ }
+ }
+
+ if (paramchanges?.length > 0) {
+ formattedError += paramchanges
+ }
+
+ return (
+
+
+
+
+ {formattedError}
+
+ )
+ })}
+
+ }
+
+
+ }>
+
+
+ : null}
+
+ )
+ })}
+
+
+
+ }
+
+ {showEnvironment === true && environments?.length > 0 ?
+
0 && Object.getOwnPropertyNames(selectedActionEnvironment || {})?.length !== 0 && selectedActionEnvironment?.Name !== "Cloud" && savingState === 0 ? (
+
+
+ 0}
+ onChange={(event) => {
+ toast("Opening in new tab. Refresh this page after adding it.")
+
+ setTimeout(() => {
+ window.open(`/admin?tab=locations`, "_blank", "noopener,noreferrer")
+ }, 1500)
+ //selectedActionEnvironment.suborg_distribution = event.target.checked ? userdata.orgs.map((org) => org.id) : []
+ //changeDistribution(selectedAction?.selectedAuthentication)
+ }}
+ name="distributeAuth"
+ color="primary"
+ />
+ }
+ label={
+
+ Distribute location
+
+ }
+ />
+
+
+ ) : null
+ } placement="right">
+
+
+ Runtime Location
+
+ {
+ getEnvironments(workflow.org_id)
+ }}
+ onChange={(e) => {
+ setLastSaved(false)
+ const env = environments.find((a) => a.Name === e.target.value)
+ setSelectedActionEnvironment(env)
+ selectedAction.environment = env.Name
+ setSelectedAction(selectedAction)
+
+ for (let actionkey in workflow.actions) {
+ workflow.actions[actionkey].environment = env.Name
+ }
+
+ setWorkflow(workflow)
+ //toast.success("Set execution location for ALL actions to " + env.Name)
+ }}
+ style={{
+ pointerEvents: "auto",
+ color: theme.palette.text.primary,
+ borderRadius: theme.palette?.borderRadius,
+ backgroundColor: theme.palette.platformColor,
+ height: 40,
+ }}
+ >
+ {environments.map((data, index) => {
+ if (data.archived === true) {
+ return null
+ }
+
+ const isRunning = data.running_ip !== ""
+
+ return (
+
+ {data.Name === "cloud" || data.Name === "Cloud" ? null : !isRunning ?
+
+
+ {
+ e.preventDefault()
+ e.stopPropagation()
+ window.open(`/admin?tab=locations&env=${data.Name}`, "_blank", "noopener,noreferrer")
+ }}
+ />
+
+
+ :
+ {
+ }}
+ variant="outlined"
+ color="primary"
+ />
+ }
+ {data.default === true ?
+
+ : null}
+ {data.Name}
+
+ );
+ })}
+
+
+
+ : null}
+
+ {workflowAsCode && (
- }
- variant="outlined"
+ {
window.location.href = `/workflows/${workflow.id}/code`
}}
style={{
- marginTop: 10,
- marginLeft: 5,
height: 40,
+ borderRadius: theme.palette?.borderRadius,
+ color: theme.palette.text.primary,
+ textTransform: "none",
pointerEvents: "auto",
+ width: "100%",
}}
>
Build this workflow as code
- )}
-
- {!distributedFromParent || userdata?.support === true ?
- isCorrectOrg ? null :
-
- Warning : {
- toast("Changing to correct organisation. Please wait a few seconds.")
-
- changeOrg()
-
-
-
- }}
- >Change Active Organization to edit this Workflow.
-
- :
-
- suborgWorkflows?.length === 0 ?
-
- Warning: This workflow is controlled by your parent org and may not be editable.
-
- :
- null
- }
-
- {originalWorkflow?.suborg_distribution === undefined || originalWorkflow?.suborg_distribution === null || originalWorkflow?.suborg_distribution?.length === 0 || originalWorkflow?.suborg_distribution.includes("none") ?
-
-
- {originalWorkflow?.parentorg_workflow !== undefined && originalWorkflow?.parentorg_workflow !== null && originalWorkflow?.parentorg_workflow?.length > 0 || workflow?.parentorg_workflow !== undefined && workflow?.parentorg_workflow !== null && workflow?.parentorg_workflow?.length > 0 ?
-
- null
-
- /*
- * Disabled because redirects occurred anyway
-
- {
- //changeOrg()
-
- // Reload the page
- navigate(`/workflows/${workflow.parentorg_workflow}`)
- window.location.reload()
- }}
- >
- Go to parent org workflow
-
- */
-
- : null}
-
- {userdata !== undefined && userdata !== null && userdata?.orgs !== undefined && userdata?.orgs !== null && userdata?.orgs?.length > 1 && workflow?.id !== undefined && workflow?.id && workflow?.id?.length > 0 && userdata?.active_org?.creator_org?.length === 0 && userdata?.active_org?.id == workflow?.org_id ?
- {
- setEditWorkflowModalOpen(true)
- }}
- >
- Enable Suborg Distribution
-
- : null}
-
- :
-
-
- Save the workflow first
-
- : null} arrow placement="right">
-
-
-
-
- Select an Org ({originalWorkflow?.suborg_distribution?.length})
-
- {
- if (cy !== undefined && cy !== null) {
- cy.nodes().unselect()
- }
-
- if (lastSaved === false && originalWorkflow.id === workflow.id) {
- setSuborgWorkflows([])
-
- saveWorkflow(workflow, undefined, undefined, e.target.value)
-
- /* Standard re-loads */
- setAllTriggers(undefined)
- setSelectedTriggerIndex(-1)
-
- getEnvironments(e.target.value)
- getAppAuthentication(undefined, undefined, undefined, e.target.value)
- getFiles(e.target.value)
- listOrgCache(e.target.value)
- /* Standard re-loads */
-
- toast.warn(`Saving workflow first due to detected changes.`, {
- autoClose: 2000,
- })
-
-
- return
- }
-
- if (workflow.org_id === e.target.value) {
- console.log("Same org selected. No change.")
- return
- } else {
- //if (savingState === 0) {
- // saveWorkflow(workflow, undefined, undefined, undefined)
- // return
- //}
- }
-
-
- navigate(`?org_id=${e.target.value}`)
-
- // Unselect in cy
- if (cy !== undefined && cy !== null) {
- cy.nodes().unselect()
- cy.edges().unselect()
- }
-
- ReactDOM.unstable_batchedUpdates(() => {
- /* Standard re-loads */
- setAllTriggers(undefined)
- setSelectedTriggerIndex(-1)
- getEnvironments(e.target.value)
- getAppAuthentication(undefined, undefined, undefined, e.target.value)
- getFiles(e.target.value)
- listOrgCache(e.target.value)
- /* Standard re-loads */
-
- // Reset the save button to ensure random saves don't occur during move
- setLastSaved(true)
-
- // FIXME: There is a timing problem here.
- // For events to have the data they need, they
- // need to be registered with setupGraph()
- // AFTER all the APIs are done
-
- // Should look through childorg workflow
- setTimeout(() => {
- if (e.target.value === originalWorkflow.org_id) {
- updateCurrentWorkflow(originalWorkflow)
- return
- } else {
- // Load environments, auth, auth groups
- //toast("Loading correct info for suborg")
- }
-
- if (originalWorkflow?.childorg_workflow_ids === undefined || originalWorkflow?.childorg_workflow_ids === null || originalWorkflow?.childorg_workflow_ids?.length === 0) {
- //console.log("Childorg doesn't exist (?). Suborgworkflows: ", suborgWorkflows)
-
- if (suborgWorkflows !== undefined && suborgWorkflows !== null && suborgWorkflows?.length > 0) {
- var found = false
- for (var suborgkey in suborgWorkflows) {
- const suborgWorkflow = suborgWorkflows[suborgkey]
- if (suborgWorkflow.org_id === e.target.value) {
- found = true
- updateCurrentWorkflow(suborgWorkflow)
- break
- }
- }
-
- if (!found) {
- toast("(3) Creating new workflow for this org. Please wait a second while we duplicate.")
- //console.log("No workflow found out of suborg workflows.")
-
- //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
- }
- } else {
- console.log("Suborgworkflows: ", suborgWorkflows)
- toast("(1) Loading NEW workflow for this org (?). Please wait a second.")
- saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
- }
- } else {
- console.log("In childorg EXIST!")
-
- var workflowFound = false
- for (var childorgidkey in originalWorkflow.childorg_workflow_ids) {
- const childworkflowid = originalWorkflow.childorg_workflow_ids[childorgidkey]
- for (var suborgWorkflowKey in suborgWorkflows) {
- const suborgWorkflow = suborgWorkflows[suborgWorkflowKey]
- if (suborgWorkflow.org_id === e.target.value) {
- workflowFound = true
-
- updateCurrentWorkflow(suborgWorkflow)
- break
- }
- }
-
- if (workflowFound) {
- break
- }
- }
-
- if (!workflowFound) {
- console.log("No workflow found.")
- toast("(2) Creating new workflow for this org. Please wait a few seconds while we prepare it for you.")
- //saveWorkflow(originalWorkflow, undefined, undefined, e.target.value)
- }
- }
- }, 500)
- })
- }}
- label="Suborg Distribution"
- fullWidth
- >
-
-
- {
- e.preventDefault()
- e.stopPropagation()
- }}
- /> {userdata.active_org.large_image}{" "}
-
-
- {userdata.active_org.name}
-
-
-
-
-
- {originalWorkflow.suborg_distribution.map((org_id, index) => {
- var data = {}
- for (var key in userdata.orgs) {
- if (userdata.orgs[key].id === org_id) {
- data = userdata.orgs[key]
- break
- }
- }
-
- if (data.id === undefined || data.id === null) {
- return null
- }
-
- var skipOrg = false;
-
- const imagesize = 22
- const imageStyle = {
- width: imagesize,
- height: imagesize,
- pointerEvents: "none",
- marginRight: 10,
- marginLeft:
- data.creator_org !== undefined &&
- data.creator_org !== null &&
- data.creator_org?.length > 0
- ? data?.id === userdata?.active_org?.id
- ? 0
- : 0
- : 0,
- }
-
- const image =
- data.image === "" ? (
-
- ) : (
-
- )
-
- var orgDiff = {
- different: false,
- }
-
- const foundMatchingWorkflow = suborgWorkflows?.find((workflow) => workflow.org_id === data.id)
- if (foundMatchingWorkflow !== undefined && foundMatchingWorkflow !== null && foundMatchingWorkflow.diff !== undefined && foundMatchingWorkflow.diff !== null) {
- orgDiff = foundMatchingWorkflow.diff
- }
-
- //console.log("DIFF: ", orgDiff)
-
- return (
-
-
- {image}{" "}
-
- {data.name}
-
-
-
- {foundMatchingWorkflow !== undefined && foundMatchingWorkflow !== null && foundMatchingWorkflow?.errors !== undefined && foundMatchingWorkflow?.errors !== null && foundMatchingWorkflow?.errors?.length > 0 &&
-
-
- {foundMatchingWorkflow?.errors?.length} Workflow Issue{foundMatchingWorkflow?.errors?.length > 1 ? "s" : ""}
-
-
- }
- >
-
-
- }
-
- {orgDiff.different === true ?
-
-
- Diff (beta):
-
-
- {orgDiff.environment === true &&
- - Environment
- }
-
- {orgDiff?.actions?.length > 0 &&
- - Actions ({orgDiff.actions?.length}):
- {orgDiff.actions.map((orgDiffAction, index) => {
- //console.log("DIFF2: ", orgDiffAction)
- var formattedError = ""
-
- var paramchanges = ""
- for (var diffActionKey in orgDiffAction) {
- if (diffActionKey !== "id" && diffActionKey !== "label" && diffActionKey !== "parameters" && diffActionKey !== "params" && diffActionKey !== "large_image") {
- if (formattedError?.length > 0) {
- formattedError += ", "
- }
- formattedError += diffActionKey
- }
-
- if (diffActionKey === "parameters") {
- paramchanges = orgDiffAction[diffActionKey].join(", ")
- }
- }
-
- if (paramchanges?.length > 0) {
- formattedError += paramchanges
- }
-
- return (
-
-
-
-
- {formattedError}
-
- )
- })}
-
- }
-
-
-
- }>
-
-
- : null}
-
- )
- })}
-
-
-
- }
-
-
- {showEnvironment === true && environments?.length > 0 && selectedActionEnvironment !== undefined && selectedActionEnvironment !== null && selectedActionEnvironment.Name !== undefined && selectedActionEnvironment.Name !== null ?
- 0 && Object.getOwnPropertyNames(selectedActionEnvironment).length !== 0 && selectedActionEnvironment?.Name !== "Cloud" && savingState === 0 ? (
-
-
- 0}
- onChange={(event) => {
- toast("Opening in new tab. Refresh this page after adding it.")
-
- setTimeout(() => {
- window.open(`/admin?tab=locations`, "_blank", "noopener,noreferrer")
- }, 1500)
- //selectedActionEnvironment.suborg_distribution = event.target.checked ? userdata.orgs.map((org) => org.id) : []
- //changeDistribution(selectedAction?.selectedAuthentication)
- }}
- name="distributeAuth"
- color="primary"
- />
- }
- label={
-
- Distribute location
-
- }
- />
-
-
- ) : null
- } placement="right">
-
-
-
-
- Runtime Location
-
- {
- getEnvironments(workflow.org_id)
- }}
- onChange={(e) => {
- setLastSaved(false)
- const env = environments.find((a) => a.Name === e.target.value)
- setSelectedActionEnvironment(env)
- selectedAction.environment = env.Name
- setSelectedAction(selectedAction)
-
- for (let actionkey in workflow.actions) {
- workflow.actions[actionkey].environment = env.Name
- }
-
- setWorkflow(workflow)
- //toast.success("Set execution location for ALL actions to " + env.Name)
- }}
- style={{
- pointerEvents: "auto",
- color: theme.palette.text.primary,
- maxWidth: 250,
- minWidth: 250,
- borderRadius: theme.palette?.borderRadius,
- marginLeft: 35,
-
- backgroundColor: "transparent",
- height: 40,
- }}
- >
- {environments.map((data, index) => {
- if (data.archived === true) {
- return null
- }
-
- const isRunning = data.running_ip !== ""
-
- return (
-
-
- {data.Name === "cloud" || data.Name === "Cloud" ? null : !isRunning ?
-
-
-
- {
- e.preventDefault()
- e.stopPropagation()
-
- window.open(`/admin?tab=locations&env=${data.Name}`, "_blank", "noopener,noreferrer")
- }}
-
-
- />
-
-
- :
- {
- //handleChipClick
- }}
- variant="outlined"
- color="primary"
- />
- }
-
- {data.default === true ?
-
- : null}
-
- {data.Name}
-
- );
- })}
-
-
-
- : null}
-
-
- {parentWorkflows === undefined || parentWorkflows === null || parentWorkflows.length === 0 ? null :
-
+
+
+ {/* Warning Messages */}
+ {!distributedFromParent || userdata?.support === true ?
+ isCorrectOrg ? null :
+
+ Warning : {
+ toast("Changing to correct organisation. Please wait a few seconds.")
+ changeOrg()
+ }}
+ >Change Active Organization to edit this Workflow.
+
+ :
+
+ suborgWorkflows?.length === 0 ?
+
+ Warning: This workflow is controlled by your parent org and may not be editable.
+
+ :
+ null
}
-
+
+
+ {parentWorkflows === undefined || parentWorkflows === null || parentWorkflows.length === 0 ? null :
+
+ }
+
);
};
@@ -20648,303 +21390,472 @@ const AngularWorkflow = (defaultprops) => {
return null;
}
- const buttonHeights = 45
- const boxSize = buttonHeights
+ const saveIcon = (
+
+
+
+ );
+
+ const toolbarHeight = 40;
+ const buttonSize = 40;
+ const borderRadius = "8px";
+
+ const iconSvgSize = 21;
+
+ // Play/Stop button
const executionButton = executionRunning ? (
-
- {
- abortExecution();
- }}
- >
-
-
-
-
- ) : (
-
{
- executeWorkflow(executionText, workflow.start, lastSaved);
+ onClick={() => abortExecution()}
+ sx={{
+ minWidth: buttonSize,
+ width: buttonSize,
+ height: buttonSize,
+ borderRadius: "8px",
+ backgroundColor: "#FF8544",
+ color: "#ffffff",
+ padding: 0,
+ "&:hover": {
+ backgroundColor: "#FF955C",
+ },
}}
>
-
+
-
- )
+
+ ) : (
+
+ executeWorkflow(executionText, workflow.start, lastSaved)}
+ sx={{
+ minWidth: buttonSize,
+ width: buttonSize,
+ height: buttonSize,
+ borderRadius: "8px",
+ backgroundColor: theme.palette.accentColor,
+ color: theme.palette.text.primary,
+ padding: 0,
+ paddingLeft: 0.2,
+ "&:hover": {
+ backgroundColor: "#FF955C",
+ },
+ "&:disabled": {
+ backgroundColor: "#494949",
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
+
+ );
return (
-
-
- {executionButton}
- {
+ setExecutionModalOpen(true);
+ getWorkflowExecution(workflow.id, "", executionFilter, workflow.org_id);
+ }}
>
- {
- setExecutionModalOpen(true);
- getWorkflowExecution(workflow.id, "", executionFilter, workflow.org_id)
- }}
- >
-
-
-
-
- {
- setExecutionText(e.target.value);
- }}
-
- // Start adornment
- />
-
-
-
- {/*userdata.avatar === creatorProfile.github_avatar ? null :*/}
-
+
+
+
-
-
- {
- saveWorkflow(workflow)
+ setExecutionText(e.target.value)}
+ sx={{
+ minWidth: 160,
+ maxHeight: 38,
+ height: toolbarHeight,
+ marginLeft: "8px",
+ "& .MuiOutlinedInput-root": {
+ height: toolbarHeight,
+ borderRadius: borderRadius,
+ backgroundColor: theme.palette.backgroundColor,
+ color: theme.palette.text.primary,
+ maxHeight: 38,
+ "& fieldset": {
+ borderColor: "transparent",
+ },
+ "&:hover fieldset": {
+ borderColor: "transparent",
+ },
+ "&.Mui-focused fieldset": {
+ borderColor: "transparent",
+ },
+ "&.Mui-disabled": {
+ backgroundColor: "#212121",
+ color: "#9E9E9E",
+ },
+ },
+ "& .MuiInputBase-input": {
+ padding: "0 12px",
+ maxHeight: 38,
+ fontSize: 14,
+ "&::placeholder": {
+ color: theme.palette.text.primary,
+ opacity: 0.7,
+ paddingLeft: 1,
+ },
+ },
+ }}
+ />
+
- if (workflow.public === true) {
- console.log("Public!")
+ {/*userdata.avatar === creatorProfile.github_avatar ? null :*/}
- const tmpurl = new URL(window.location.href)
- const searchParams = tmpurl.searchParams
- const queryID = searchParams.get('queryID')
-
- if (queryID !== undefined && queryID !== null) {
- aa('init', {
- appId: "JNSS5CFDZZ",
- apiKey: "c8f882473ff42d41158430be09ec2b4e",
- })
-
- const timestamp = new Date().getTime()
- aa('sendEvents', [
- {
- eventType: 'conversion',
- eventName: 'Public Workflow Saved',
- index: 'workflows',
- objectIDs: [workflow.id],
- timestamp: timestamp,
- queryID: queryID,
- userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
- }
- ])
- } else {
- console.log("No query to handle")
- }
+
+
+ {
+ saveWorkflow(workflow)
+ if (workflow.public === true) {
+ console.log("Public!");
+ const tmpurl = new URL(window.location.href);
+ const searchParams = tmpurl.searchParams;
+ const queryID = searchParams.get('queryID');
+ if (queryID !== undefined && queryID !== null) {
+ aa('init', {
+ appId: "JNSS5CFDZZ",
+ apiKey: "c8f882473ff42d41158430be09ec2b4e",
+ })
+ const timestamp = new Date().getTime();
+ aa('sendEvents', [
+ {
+ eventType: 'conversion',
+ eventName: 'Public Workflow Saved',
+ index: 'workflows',
+ objectIDs: [workflow.id],
+ timestamp: timestamp,
+ queryID: queryID,
+ userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
- }}
- >
- {savingState === 2 ? (
-
- ) : savingState === 1 ? (
-
- ) : (
-
- )}
-
-
-
- {workflow.public || userdata.support == true ?
+ ])
+ }
+ } else {
+ console.log("No query to handle")
+ }
+ }}
+ sx={{
+ height: toolbarHeight,
+ borderRadius: borderRadius,
+ fontFamily: theme?.typography?.fontFamily,
+ backgroundColor: !(lastSaved && !workflow.public) ? "rgba(255, 133, 68, 0.2)" : theme.palette.slateGrayColor,
+ color: "#ffffff",
+ fontSize: "12px",
+ textTransform: "none",
+ padding: "0px 14px",
+ marginLeft: "8px",
+ maxHeight: 35,
+ display: "flex",
+ alignItems: "center",
+ gap: "6px",
+ "& .MuiTypography-root": {
+ fontSize: "14px",
+ color: !(lastSaved && !workflow.public) ? "#ff8544" : theme.palette.text.primary
+ },
+ "& .MuiSvgIcon-root": {
+ color: !(lastSaved && !workflow.public) ? "#ff8544" : theme.palette.text.primary
+ },
+ "&:hover": {
+ backgroundColor: "rgba(255, 133, 68, 0.2)",
+ border: "0.5px solid #ff8544",
+ },
+ "&:disabled": {
+ backgroundColor: "#494949",
+ color: "#9E9E9E",
+ "& .MuiSvgIcon-root": {
+ color: "#9E9E9E",
+ },
+ "& .MuiTypography-root": {
+ color: "#9E9E9E",
+ },
+ },
+ }}
+ >
+ {savingState === 2 ? (
+
+ ) : savingState === 1 ? (
+
+ ) : (
+
+ {saveIcon}
+
+ )}
+
+ Save
+
+
+
+
+
+ {/* Separator */}
+
+
+
+ {/* Download */}
-
- {
- const data = workflow;
- let exportFileDefaultName = data.name + ".json";
-
- let dataStr = JSON.stringify(data);
- let dataUri =
- "data:application/json;charset=utf-8," +
- encodeURIComponent(dataStr);
- let linkElement = document.createElement("a");
- linkElement.setAttribute("href", dataUri);
- linkElement.setAttribute("download", exportFileDefaultName);
- linkElement.click();
- }}
- >
-
-
-
-
- : null}
-
- {/*
-
-
- cy.fit(null, 50)}
- >
-
-
-
-
- */}
-
-
-
- {
- handleHistoryUndo(history);
+ {
+ const data = workflow;
+ let exportFileDefaultName = data.name + ".json";
+ let dataStr = JSON.stringify(data);
+ let dataUri =
+ "data:application/json;charset=utf-8," + encodeURIComponent(dataStr);
+ let linkElement = document.createElement("a");
+ linkElement.setAttribute("href", dataUri);
+ linkElement.setAttribute("download", exportFileDefaultName);
+ linkElement.click();
+ }}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
}}
>
-
-
-
+
+
+
+
+ {/* Undo */}
+
+ handleHistoryUndo(history)}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ "&:disabled": {
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
+
+ {/* Fit to Screen */}
+
+ cy.fit(null, 50)}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ }}
+ >
+
+
+
+
+ {/* Delete/Trash */}
-
- {
- const selectedNode = cy.$(":selected");
- if (selectedNode.data() === undefined) {
- return
- }
-
- removeNode(selectedNode.data("id"))
- }}
- >
-
-
-
+ {
+ const selectedNode = cy.$(":selected");
+ if (selectedNode.data() === undefined) {
+ return;
+ }
+ removeNode(selectedNode.data("id"));
+ }}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ "&:disabled": {
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
-
-
- {
- addCommentNode();
- }}
- >
-
-
-
+ {/* Separator */}
+
+
+ {/* History */}
+
+ setShowWorkflowRevisions(true)}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ "&:disabled": {
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
+ {/* Add */}
+
+ addCommentNode()}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ "&:disabled": {
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
+
+
+ {/* WorkflowMenu - was conditionally rendered in old code */}
{workflow.configuration !== null &&
workflow.configuration !== undefined &&
workflow.configuration.exit_on_error !== undefined ? (
@@ -20974,78 +21885,78 @@ const AngularWorkflow = (defaultprops) => {
- */}
+ */}
-
-
- {
- setShowWorkflowRevisions(true)
- }}
- >
-
-
-
-
+ {userdata.support === true && (
+
+ )}
-
- {userdata?.support === true ?
-
-
- {
- setupWorkflowYaml(workflow)
- }}
- >
-
-
-
-
- : null}
-
- {userdata.support == true || !isCloud ?
+ {userdata?.support === true && (
-
- {
- setWorkflowGenerationModalOpen(!workflowGenerationModalOpen)
- }}
- >
-
-
-
+ setupWorkflowYaml(workflow)}
+ sx={{
+ width: toolbarHeight,
+ height: toolbarHeight,
+ color: theme.palette.text.primary,
+ "&:hover": {
+ backgroundColor: "rgba(255, 255, 255, 0.05)",
+ },
+ "&:disabled": {
+ color: "#9E9E9E",
+ },
+ }}
+ >
+
+
- : null}
+ )}
+
-
-
-
+ {/* AI Button with Gradient */}
+ {(userdata.support == true || !isCloud) && (
+
+ setWorkflowGenerationModalOpen(!workflowGenerationModalOpen)}
+ variant="aiButton"
+ color="secondary"
+ sx={{
+ minWidth: buttonSize,
+ width: buttonSize,
+ borderRadius: "8px",
+ height: buttonSize,
+ marginLeft: "4px",
+ }}
+ >
+
+
+
+ )}
+
);
};
@@ -21383,7 +22294,7 @@ const AngularWorkflow = (defaultprops) => {
return (
{
@@ -21644,6 +22557,8 @@ const AngularWorkflow = (defaultprops) => {
minWidth: leftBarSize,
maxWidth: leftBarSize,
borderRight: "1px solid rgb(91, 96, 100)",
+ transition: "min-width 0.3s ease, max-width 0.3s ease",
+ overflow: "hidden",
}}
>
@@ -21654,6 +22569,8 @@ const AngularWorkflow = (defaultprops) => {
minWidth: leftBarSize,
maxWidth: leftBarSize,
borderRight: "1px solid rgb(91, 96, 100)",
+ transition: "min-width 0.3s ease, max-width 0.3s ease",
+ overflow: "hidden",
}}
>
{
return (
-
+
{
onSelect={(select) => {
HandleJsonCopy(validate.result, select, "exec");
}}
- name={false}
+ name={"$exec"}
/>
)
@@ -21787,7 +22704,26 @@ const AngularWorkflow = (defaultprops) => {
)
}
- if (execution.execution_source === "authgroups") {
+ if (execution.execution_source?.startsWith("datastore")) {
+ const iconMargin = 7
+ return (
+
+
+
+ )
+ } else if (execution.execution_source === "authgroups") {
const iconMargin = 7
return (
{
open={executionModalOpen}
onClose={() => {
setExecutionModalOpen(false)
-
+ setBuildDebugMode("build")
//const newitem = removeParam("execution_id", cursearch);
//navigate(curpath + newitem)
}}
@@ -22290,6 +23226,8 @@ const AngularWorkflow = (defaultprops) => {
borderLeft: theme.palette.defaultBorder,
borderRadius: theme.palette.borderRadius,
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
backgroundColor: themeMode === "dark" ? "black" : theme.palette.drawer.backgroundColor,
},
}}
@@ -22943,6 +23881,7 @@ const AngularWorkflow = (defaultprops) => {
) : null}
+
{executionData.execution_source !== undefined &&
executionData.execution_source !== null &&
executionData.execution_source.length > 0 &&
@@ -22954,8 +23893,17 @@ const AngularWorkflow = (defaultprops) => {
-
- {executionData.execution_source === "authgroups" || (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ?
+ {executionData?.execution_source?.startsWith("datastore") ?
+ 2 ? "&category="+executionData.execution_source.split("|")[1]+"&key="+executionData.execution_source.split("|")[2] : ""}`}
+ target="_blank"
+ style={{ textDecoration: "none", color: theme.palette.linkColor }}
+ >
+ Datastore Automation
+
+ :
+ executionData.execution_source === "authgroups" || (executionData.authgroup !== undefined && executionData.authgroup !== null && executionData.authgroup.length > 0) ?
{
{data?.action?.name === "run_schemaless" || data?.action?.name === "run_singul" || data?.action?.name === "singul" && data?.action?.parameters?.length > 4 ?
: null}
@@ -23614,7 +24576,7 @@ const AngularWorkflow = (defaultprops) => {
HandleJsonCopy(showResult, select, data.action.label);
console.log("SELECTED!: ", select);
}}
- name={"Results for " + data.action.label}
+ name={`$${data?.action?.label?.toLowerCase()}`}
/>
@@ -23627,19 +24589,23 @@ const AngularWorkflow = (defaultprops) => {
whiteSpace: "pre-wrap",
}}
>
-
- Result
-
-
- {data.result}
-
+ {validate?.result?.length > 0 ?
+
+
+ Result
+
+
+ {data.result}
+
+
+ : null}
)}
@@ -24108,7 +25074,11 @@ const AngularWorkflow = (defaultprops) => {
/>
) : (
-
Result
+ {validate?.result?.length > 0 ?
+
+ Result
+
+ : null}
{
>
{/*isMobile ? null : leftView*/}
{leftView}
+
+ {userdata.support === true && (
+
+
{
+ console.log("Toggle sidebar!")
+ setLeftBarSize(leftViewOpen ? 0 : 235)
+ setLeftViewOpen(!leftViewOpen)
+ }}
+ style={{
+ position: "absolute",
+ left: 0,
+ top: "50%",
+ transform: "translateY(-50%)",
+ zIndex: 1000,
+ backgroundColor: theme.palette.surfaceColor,
+ border: `1px solid ${theme.palette.defaultBorder}`,
+ borderLeft: "none",
+ borderTopRightRadius: "8px",
+ borderBottomRightRadius:"8px",
+ borderTopLeftRadius: "0",
+ borderBottomLeftRadius: "0",
+ width: leftViewOpen ? 24 : 32,
+ height: 48,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ transition: "left 0.3s ease, width 0.3s ease, border-radius 0.3s ease",
+ cursor: "pointer",
+ }}
+ >
+ {leftViewOpen ?
+
:
+
+ }
+
+
+ )}
{workflow.id === undefined || workflow.id === null || appsLoaded === false ? (
{
style={{
width: workflow?.public && !isLoggedIn ? cytoscapeWidth + 50 : cytoscapeWidth,
height: workflow?.public && !isLoggedIn ? (bodyHeight - 50) : bodyHeight - 2,
- backgroundColor: theme.palette.surfaceColor,
+ backgroundColor: theme.palette.cytoscapeBackgroundColor,
}}
stylesheet={cystyle}
boxSelectionEnabled={true}
@@ -24266,7 +25274,101 @@ const AngularWorkflow = (defaultprops) => {
{executionModal}
- {
+
+ {/* New parsedaction in new release */}
+
0 &&
+ rightSideBarOpen &&
+ Object.getOwnPropertyNames(selectedTrigger || {}).length === 0 &&
+ Object.getOwnPropertyNames(selectedComment || {}).length === 0
+ }
+ hideBackdrop={true}
+ transitionDuration={{ enter: 180, exit: 0 }}
+ onClose={() => {
+ setRightSideBarOpen(false);
+ }}
+ ModalProps={{
+ keepMounted: true,
+ }}
+ sx={{
+ pointerEvents: "none",
+ "& .MuiDrawer-paper": {
+ pointerEvents: "auto",
+ },
+ }}
+ PaperProps={{
+ style: {
+ width: rightsidebarStyle.width,
+ minWidth: rightsidebarStyle.minWidth,
+ maxWidth: rightsidebarStyle.maxWidth,
+ overflow: "hidden",
+ },
+ }}
+ >
+
+
+
+
+ {/* old code just for backup */}
+ {/* {
rightSideBarOpen && Object.getOwnPropertyNames(selectedAction).length > 0 ?
@@ -24331,7 +25433,7 @@ const AngularWorkflow = (defaultprops) => {
: null
- }
+ } */}
{/* Looks for triggers" */}
{/* Only fixed the ones that require scrolling on a small screen */}
{/* Most important: Actions. But these are a lot more complex */}
@@ -24401,7 +25503,7 @@ const AngularWorkflow = (defaultprops) => {
{shownErrors}
-
+ {/*
*/}
}
diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx
index bb08e468..6ff6793b 100755
--- a/frontend/src/views/AppCreator.jsx
+++ b/frontend/src/views/AppCreator.jsx
@@ -563,7 +563,7 @@ const AppCreator = (defaultprops) => {
};
- const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (import.meta.env.VITE_IS_SSR === "true");
+ const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
useEffect(() => {
if (window.location.pathname.includes("apps/edit")) {
@@ -699,20 +699,20 @@ const AppCreator = (defaultprops) => {
// This is the data FROM the database, not what's being saved
const parseIncomingOpenapiData = (data) => {
- var parsedDecoded = ""
- try {
- const decoded = base64_decode(data.openapi)
- parsedDecoded = decoded
+ var parsedDecoded = ""
+ try {
+ const decoded = base64_decode(data.openapi)
+ parsedDecoded = decoded
} catch (e) {
- console.log("Failed JSON parsing: ", e)
- parsedDecoded = data
- }
+ console.log("Failed JSON parsing: ", e)
+ parsedDecoded = data
+ }
- if (data.openapi === null) {
- toast("Failed to load OpenAPI for app. Please contact support if this persists.")
- setIsAppLoaded(true);
- return
- }
+ if (data.openapi === null) {
+ toast("Failed to load OpenAPI for app. Please contact support if this persists.")
+ setIsAppLoaded(true);
+ return
+ }
//console.log("Decoded: ", parsedDecoded)
const parsedapp =
@@ -791,6 +791,9 @@ const AppCreator = (defaultprops) => {
}
if (data.info["x-categories"] !== undefined && data.info["x-categories"].length > 0) {
+ if (typeof data.info["x-categories"] === "array") {
+ } else {
+ }
setNewWorkflowCategories(data.info["x-categories"]);
}
}
@@ -913,36 +916,41 @@ const AppCreator = (defaultprops) => {
body: "",
errors: [],
example_response: "",
- action_label: "No Label",
+ action_label: ["No Label"],
required_bodyfields: [],
};
if (methodvalue["x-label"] !== undefined && methodvalue["x-label"] !== null) {
- console.log("LABEL: ", methodvalue["x-label"])
+ const labels = typeof methodvalue["x-label"] === 'object' || Array.isArray(methodvalue["x-label"]) ? methodvalue["x-label"] : (typeof methodvalue["x-label"] === 'string' ? methodvalue["x-label"].split(",") : [])
- var correctlabel = ""
- const labels = methodvalue["x-label"].split(",")
+ var correctlabels = []
+ console.log("LABEL1: ", methodvalue["x-label"])
for (let labelkey in labels) {
- var label = labels[labelkey].trim()
- if (label.toLowerCase() === "no label") {
+ var label = labels[labelkey]?.trim()
+ if (label?.toLowerCase() === "no label") {
continue
}
// Remove quotes and escapes
- label = label.replace(/['"]+/g, '')
- label = label.replace(/\\/g, '')
+ label = label?.replace(/['"]+/g, '')
+ label = label?.replace(/\\/g, '')
- //label = label.replace("_", " ", -1)
- //label = label.charAt(0).toUpperCase() + label.slice(1)
+ // Uppercase first
+ if (label === undefined || label === null || label?.length === 0 || label?.toLowerCase().replaceAll(" ", "_") === "no_label") {
+ label = "No Label"
+ }
- correctlabel = label
- break
+ label = label?.replace("_", " ")
+ label = label?.charAt(0).toUpperCase() + label?.slice(1)
+
+ correctlabels?.push(label)
}
- console.log("LABEL: ", correctlabel)
+ console.log("LABEL: ", correctlabels)
+
// FIX: Map labels only if they're actually in the category list
//newaction.action_label = methodvalue["x-label"]
- newaction.action_label = correctlabel
+ newaction.action_label = correctlabels
}
if (methodvalue["x-required-fields"] !== undefined && methodvalue["x-required-fields"] !== null) {
@@ -1678,7 +1686,7 @@ const AppCreator = (defaultprops) => {
}
}
- //newaction.action_label = "No Label"
+ //newaction.action_label = ["No Label"]
newActions.push(newaction);
}
}
@@ -1961,9 +1969,9 @@ const AppCreator = (defaultprops) => {
setProjectCategories(all_categories);
// Rearrange them by which has action_label
- const firstActions = newActions.filter(data => data.action_label !== undefined && data.action_label !== null && data.action_label !== "No Label")
+ const firstActions = newActions.filter(data => data.action_label !== undefined && data.action_label !== null && data.action_label[0] !== "No Label")
console.log("First actions: ", firstActions)
- const secondActions = newActions.filter(data => data.action_label === undefined || data.action_label === null || data.action_label === "No Label")
+ const secondActions = newActions.filter(data => data.action_label === undefined || data.action_label === null || data.action_label[0] === "No Label")
newActions = firstActions.concat(secondActions)
setActions(newActions);
//data.paths[item.url][item.method.toLowerCase()]["x-label"] = item.action_label
@@ -2114,17 +2122,16 @@ const AppCreator = (defaultprops) => {
},
};
- if (item.action_label !== undefined && item.action_label !== "" && item.action_label !== "No Label") {
- //console.log("Action label: ", item.action_label)
- data.paths[item.url][item.method.toLowerCase()]["x-label"] = item.action_label
- }
+ if (item.action_label !== undefined && item.action_label !== "" && item.action_label[0] !== "No Label") {
+ data.paths[item.url][item.method.toLowerCase()]["x-label"] = item.action_label
+ }
- if (item.required_bodyfields !== undefined && item.required_bodyfields !== null && item.required_bodyfields.length > 0) {
- console.log("Required bodyfields: ", item.required_bodyfields)
- data.paths[item.url][item.method.toLowerCase()]["x-required-fields"] = item.required_bodyfields
- }
+ if (item.required_bodyfields !== undefined && item.required_bodyfields !== null && item.required_bodyfields.length > 0) {
+ console.log("Required bodyfields: ", item.required_bodyfields)
+ data.paths[item.url][item.method.toLowerCase()]["x-required-fields"] = item.required_bodyfields
+ }
- //console.log("ACTION: ", item)
+ //console.log("ACTION: ", item)
if (item.example_response !== undefined && item.example_response !== null && item.example_response.length > 0) {
@@ -3448,7 +3455,7 @@ const AppCreator = (defaultprops) => {
errors: [],
example_response: "",
method: actionNonBodyRequest[0],
- action_label: "No Label",
+ action_label: ["No Label"],
required_bodyfields: [],
});
@@ -4450,6 +4457,31 @@ const AppCreator = (defaultprops) => {
const url = data.url;
const hasFile = (data["file_field"] !== undefined && data["file_field"] !== null && data["file_field"].length > 0) || data["example_response"] === "shuffle_file_download"
+ if (data?.action_label[0] !== 'No Label') {
+ console.log("Action label: ", data?.name, data?.action_label)
+ }
+
+ var currentActionLabels = JSON.parse(JSON.stringify(actionLabels))
+ for (var labelKey in data?.action_label) {
+ const label = data?.action_label[labelKey]
+ if (label.toLowerCase().replaceAll(" ", "_") === "no_label") {
+ continue
+ }
+
+ var found = false
+ for (var acatKey in currentActionLabels) {
+ const acat = currentActionLabels[acatKey]
+ if (acat === label) {
+ found = true
+ break
+ }
+ }
+
+ if (!found) {
+ console.log(`Not found: '${label}' in ${currentActionLabels}`)
+ currentActionLabels.push(data?.action_label[labelKey])
+ }
+ }
return (
@@ -4532,23 +4564,38 @@ const AppCreator = (defaultprops) => {
*/}
{/* From 2023: Example of handling action labels */}
- {actionLabels.length > 0 && newWorkflowCategories !== undefined && newWorkflowCategories !== null && newWorkflowCategories.length > 0 && categories.length > 0 ?
+ {currentActionLabels.length > 0 && newWorkflowCategories !== undefined && newWorkflowCategories !== null && newWorkflowCategories.length > 0 && categories.length > 0 ?
{
- console.log("Should change: ", e.target.value, " Index: ", index)
+ if (e.target.value === undefined || e.target.value === null) {
+ return
+ }
+
+ if (e.target.value.length === 0) {
+ e.target.value = ["No Label"]
+ }
const foundIndex = actions.findIndex((action) => action.name === data.name)
- console.log("Found index: ", foundIndex)
if (foundIndex !== undefined && foundIndex !== null && foundIndex >= 0) {
+ if (e.target.value.includes("no_label") || e.target.value.includes("No_Label") || e.target.value.includes("No Label")) {
+ actions[foundIndex].action_label = ["No Label"]
+ setActions(actions)
+ setUpdate(Math.random())
+
+ return
+ }
+
+ console.log("Should change: ", e.target.value, " Index: ", index)
actions[foundIndex].action_label = e.target.value
setActions(actions)
setUpdate(Math.random())
}
}}
- value={data?.action_label?.replace(" ", "_").toLowerCase()}
+ value={data?.action_label}
style={{
- border: data.action_label === undefined || data.action_label === "No Label" ? "" : `2px solid ${bgColor}`,
+ border: data.action_label === undefined || data.action_label[0] === "No Label" ? "" : `2px solid ${bgColor}`,
borderRadius: theme.shape.borderRadius,
backgroundColor: theme.palette.backgroundColor,
paddingLeft: 10,
@@ -4563,12 +4610,15 @@ const AppCreator = (defaultprops) => {
name: "Method",
id: "method-option",
}}
+ onClick={(e) => {
+ console.log("Current labels: ", data?.action_label)
+ }}
>
- {actionLabels.map((label, labelindex) => {
+ {currentActionLabels.map((label, labelindex) => {
return (
@@ -4633,7 +4683,7 @@ const AppCreator = (defaultprops) => {
body: "",
errors: [],
method: actionNonBodyRequest[0],
- action_label: "No Label",
+ action_label: ["No Label"],
required_bodyfields: [],
});
setActionsModalOpen(true);
@@ -5385,15 +5435,15 @@ const AppCreator = (defaultprops) => {
body: "",
errors: [],
method: actionNonBodyRequest[0],
- action_label: "No Label",
- required_bodyfields: [],
+ action_label: ["No Label"],
+ required_bodyfields: [],
});
- console.log("Added: ", actions)
+ console.log("Added: ", actions)
setActions(actions)
- setFilteredActions(actions)
+ setFilteredActions(actions)
setActionAmount(50);
- setUpdate(Math.random());
+ setUpdate(Math.random());
}}
>
New action
@@ -5417,7 +5467,7 @@ const AppCreator = (defaultprops) => {
// body: "",
// errors: [],
// method: actionNonBodyRequest[0],
- // action_label: "No Label",
+ // action_label: ["No Label"],
// required_bodyfields: [],
//})
//setActions(actions)
diff --git a/frontend/src/views/AppExplorer.jsx b/frontend/src/views/AppExplorer.jsx
index 1db7e20c..5cbe502e 100644
--- a/frontend/src/views/AppExplorer.jsx
+++ b/frontend/src/views/AppExplorer.jsx
@@ -65,6 +65,7 @@ import { Context } from "../context/ContextApi.jsx";
import {
SearchBox,
+ StaticRefinementList,
RefinementList,
InstantSearch,
connectSearchBox,
@@ -72,14 +73,14 @@ import {
Index,
} from "react-instantsearch-dom";
import AppStats from "../components/AppStats.jsx";
-import ParsedAction from "../components/ParsedAction.jsx";
+import ParsedAction from "../components/ParsedActionNew.jsx";
import { validateJson, GetIconInfo } from "../views/Workflows2.jsx";
import { base64_decode, appCategories } from "../views/AppCreator.jsx";
import { triggers as workflowTriggers } from "../views/AngularWorkflow.jsx";
import AuthenticationOauth2 from "../components/Oauth2Auth.jsx";
import AuthenticationWindow from "../components/AuthenticationWindow.jsx";
import { CodeHandler, Img, OuterLink, CopyToClipboard, } from "../views/Docs.jsx";
-import { useStyles, } from "../components/ParsedAction.jsx";
+import { useStyles, } from "../components/ParsedActionNew.jsx";
import { sortByKey } from "../views/AngularWorkflow.jsx";
import { v4 as uuidv4 } from "uuid";
@@ -240,13 +241,14 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
const [triggers, setTriggers] = useState([])
const [selectedOrganization, setSelectedOrganization] = React.useState(undefined)
const [selectedValidationAction, setSelectedValidationAction] = React.useState({})
+ const [settingValidationAction, setSettingValidationAction] = React.useState(false)
const [selectedMeta, setSelectedMeta] = React.useState({
link: "https://github.com/Shuffle/openapi-apps/new/master/docs",
read_time: 1,
})
- const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (import.meta.env.VITE_IS_SSR === "true");
+ const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
// FIXME: This is used, as useEffect() creates an issue with apps not loading at all
@@ -453,6 +455,7 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
rel="noopener noreferrer"
target="_blank"
href={data.url}
+ target="_blank"
style={{ textDecoration: "none", color: "#f85a3e" }}
>
@@ -1163,8 +1166,8 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
if (methodvalue["x-label"] !== undefined && methodvalue["x-label"] !== null) {
// Check if there are commas in it then loop and find the correct one
// Should ignore 'No Label' and 'No label'
- var correctlabel = ""
- const labels = methodvalue["x-label"].split(",")
+ const labels = typeof methodvalue["x-label"] === 'object' || Array.isArray(methodvalue["x-label"]) ? methodvalue["x-label"] : methodvalue["x-label"].split(",")
+ var correctlabels = []
for (let labelkey in labels) {
var label = labels[labelkey].trim()
if (label.toLowerCase() === "no label") {
@@ -1178,12 +1181,14 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
//label = label.replace("_", " ", -1)
//label = label.charAt(0).toUpperCase() + label.slice(1)
- correctlabel = label
- break
+ correctlabels.push(label)
+ if (label === "app_validation") {
+ setSelectedValidationAction(newaction)
+ }
}
// FIX: Map labels only if they're actually in the category list
- newaction.action_label = correctlabel
+ newaction.action_label = correctlabels
}
if (methodvalue["x-required-fields"] !== undefined && methodvalue["x-required-fields"] !== null) {
@@ -2931,7 +2936,7 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
}
const ActionSelectOption = (actionprops) => {
- const { option, newActionname, newActiondescription, useIcon, extraDescription, } = actionprops;
+ const { option, newActionname, newActiondescription, useIcon, extraDescription, selected, } = actionprops;
const [hover, setHover] = React.useState(false);
return (
@@ -2945,14 +2950,18 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
padding: 8,
paddingLeft: 14,
paddingBottom: 4,
- backgroundColor: hover ? theme.palette.surfaceColor : theme.palette.inputColor,
+ backgroundColor: selected === true ? theme.palette.platformColor : hover ? theme.palette.surfaceColor : theme.palette.inputColor,
+ border: selected === true ? `2px solid ${theme.palette.platformColor}` : `2px solid ${theme.palette.inputColor}`,
}} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
onClick={(event) => {
console.log("Clicked on action: ", option)
if (option !== undefined && option !== null) {
+ // FIXME: Add removal of app_validation from others
setSelectedValidationAction(option)
+ toast.info(`Selecting validation action...`)
+ setSettingValidationAction(true)
const labelData = {
"app_id": app.id,
@@ -2973,12 +2982,20 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
})
.then((response) => response.json())
.then((responseJson) => {
- if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
- toast(responseJson.reason)
+ setSettingValidationAction(false)
+
+ if (responseJson.success === true) {
+ toast.success("Validation action selected")
+ } else if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) {
+ toast.error(responseJson.reason)
+ } else {
+ toast.error("Failed selecting validation action")
}
})
.catch((error) => {
console.log("Error: ", error)
+ setSettingValidationAction(false)
+ toast.error("Failed selecting validation action")
})
// Update the app itself?
@@ -3104,13 +3121,15 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
: } label={appType === 0 || appType === 2 ? "Try the API" : "Try it out"} />
} style={{color: theme.palette.text.primary, textTransform: "none", }} label="Stats & Downloads" />
- } style={{color: theme.palette.text.secondary, textTransform: "none", }} disabled label="Integrations" />
+ } style={{color: theme.palette.text.primary, textTransform: "none", }} disabled style={{color: theme.palette.text.secondary}} label="Integrations" />
} disabled={userdata.support !== true} style={{color: userdata.support !== true ? theme.palette.text.secondary: theme.palette.text.primary, textTransform: "none", }} label="Creator" value={4} />
@@ -3481,222 +3500,280 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
The validation action is the action that is used to validate the app. This is used both when a user wants to validate their auth, as well as when Shuffle runs automatic tests of the app. It is recommended that the action should be a GET request. Validation is decided based on whether the action is ran successfully in a workflow.
-
{
- // Most popular
- // Is categorized
- // Uncategorized
- return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions";
- }}
- renderGroup={(params) => {
+
+
{
+ // Most popular
+ // Is categorized
+ // Uncategorized
+ return option.category_label !== undefined && option.category_label !== null && option.category_label.length > 0 ? "Most used" : "All Actions";
+ }}
+ renderGroup={(params) => {
- return (
-
- {params.group}
- {params.children}
-
- )
- }}
- options={renderedActionOptions}
- ListboxProps={{
- style: {
- backgroundColor: theme.palette.surfaceColor,
- color: "white",
- },
- }}
- filterOptions={(options, { inputValue }) => {
- const lowercaseValue = inputValue === null ? "" : inputValue.toLowerCase()
- options = options.filter((x) => {
- if (x.name === undefined || x.name === null) {
- x.name = ""
- }
-
- if (x.description === undefined || x.description === null) {
- x.description = ""
- }
-
- if (x.method !== "GET") {
- return null
- }
-
- return x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)
- })
-
- return options
- }}
- getOptionLabel={(option) => {
- if (option === undefined || option === null || option.name === undefined || option.name === null ) {
- return null;
- }
-
- const newname = (
- option.name.charAt(0).toUpperCase() + option.name.substring(1)
- ).replaceAll("_", " ");
-
- return newname;
- }}
- fullWidth
- style={{
- backgroundColor: theme.palette.inputColor,
- height: 50,
- borderRadius: theme.palette?.borderRadius,
- }}
- onChange={(event, newValue) => {
- // Workaround with event lol
- console.log("Changed to: ", event, newValue)
- toast("Changed validation action")
- if (newValue !== undefined && newValue !== null) {
- /*
- setNewSelectedAction({
- target: {
- value: newValue.name
- }
- })
- */
- }
- }}
- renderOption={(props, option, state) => {
- var newActionname = option.name;
- if (option.label !== undefined && option.label !== null && option.label.length > 0) {
- newActionname = option.label;
- }
-
- var newActiondescription = option.description;
- //console.log("DESC: ", newActiondescription)
- if (option.description === undefined || option.description === null) {
- newActiondescription = "Description: No description defined for this action"
- } else {
- newActiondescription = "Description: "+newActiondescription
- }
-
- const iconInfo = GetIconInfo({ name: option.name });
- const useIcon = iconInfo.originalIcon;
-
- if (newActionname === undefined || newActionname === null) {
- newActionname = "No name"
- option.name = "No name"
- option.label = "No name"
- }
-
- newActionname = (newActionname.charAt(0).toUpperCase() + newActionname.substring(1)).replaceAll("_", " ");
-
- var method = ""
- var extraDescription = ""
- if (option.name.includes("get_")) {
- method = "GET"
- } else if (option.name.includes("post_")) {
- method = "POST"
- } else if (option.name.includes("put_")) {
- method = "PUT"
- } else if (option.name.includes("patch_")) {
- method = "PATCH"
- } else if (option.name.includes("delete_")) {
- method = "DELETE"
- } else if (option.name.includes("options_")) {
- method = "OPTIONS"
- } else if (option.name.includes("connect_")) {
- method = "CONNECT"
- }
-
- // FIXME: Should it require a base URL?
- if (method.length > 0 && option.description !== undefined && option.description !== null && option.description.includes("http")) {
- var extraUrl = ""
- const descSplit = option.description.split("\n")
- // Last line of descSplit
- if (descSplit.length > 0) {
- extraUrl = descSplit[descSplit.length-1]
- }
-
- if (extraUrl.length > 0) {
- if (extraUrl.includes(" ")) {
- extraUrl = extraUrl.split(" ")[0]
+ return (
+
+ {params.group}
+ {params.children}
+
+ )
+ }}
+ options={renderedActionOptions}
+ ListboxProps={{
+ style: {
+ backgroundColor: theme.palette.surfaceColor,
+ color: "white",
+ },
+ }}
+ filterOptions={(options, { inputValue }) => {
+ const lowercaseValue = inputValue === null ? "" : inputValue.toLowerCase()
+ options = options.filter((x) => {
+ if (x.name === undefined || x.name === null) {
+ x.name = ""
}
- if (extraUrl.includes("#")) {
- extraUrl = extraUrl.split("#")[0]
+ if (x.description === undefined || x.description === null) {
+ x.description = ""
}
- extraDescription = `${method} ${extraUrl}`
- } else {
- //console.log("No url found. Check again :)")
- }
- }
+ if (x.method !== "GET") {
+ return null
+ }
- return (
-
- );
- }}
- renderInput={(params) => {
- if (params.inputProps?.value) {
- const prefixes = ["Post", "Put", "Patch"];
- for (let prefix of prefixes) {
- if (params.inputProps.value.startsWith(prefix)) {
- let newValue = params.inputProps.value.replace(prefix + " ", "");
- if (newValue.length > 1) {
- newValue = newValue.charAt(0).toUpperCase() + newValue.substring(1);
+ return x.name.replaceAll("_", " ").toLowerCase().includes(lowercaseValue) || x.description.toLowerCase().includes(lowercaseValue)
+ })
+
+ return options
+ }}
+ getOptionLabel={(option) => {
+ if (option === undefined || option === null || option.name === undefined || option.name === null ) {
+ return null;
+ }
+
+ const newname = (
+ option.name.charAt(0).toUpperCase() + option.name.substring(1)
+ ).replaceAll("_", " ");
+
+ return newname;
+ }}
+ fullWidth
+ style={{
+ backgroundColor: theme.palette.inputColor,
+ height: 50,
+ borderRadius: theme.palette?.borderRadius,
+ }}
+ onChange={(event, newValue) => {
+ // Workaround with event lol
+ console.log("Changed to: ", event, newValue)
+ toast("Changed validation action")
+ if (newValue !== undefined && newValue !== null) {
+ /*
+ setNewSelectedAction({
+ target: {
+ value: newValue.name
+ }
+ })
+ */
+ }
+ }}
+ renderOption={(props, option, state) => {
+ var newActionname = option.name;
+ if (option.label !== undefined && option.label !== null && option.label.length > 0) {
+ newActionname = option.label;
+ }
+
+ var newActiondescription = option.description;
+ //console.log("DESC: ", newActiondescription)
+ if (option.description === undefined || option.description === null) {
+ newActiondescription = "Description: No description defined for this action"
+ } else {
+ newActiondescription = "Description: "+newActiondescription
+ }
+
+ const iconInfo = GetIconInfo({ name: option.name });
+ const useIcon = iconInfo.originalIcon;
+
+ if (newActionname === undefined || newActionname === null) {
+ newActionname = "No name"
+ option.name = "No name"
+ option.label = "No name"
+ }
+
+ newActionname = (newActionname.charAt(0).toUpperCase() + newActionname.substring(1)).replaceAll("_", " ");
+
+ var method = ""
+ var extraDescription = ""
+ if (option.name.includes("get_")) {
+ method = "GET"
+ } else if (option.name.includes("post_")) {
+ method = "POST"
+ } else if (option.name.includes("put_")) {
+ method = "PUT"
+ } else if (option.name.includes("patch_")) {
+ method = "PATCH"
+ } else if (option.name.includes("delete_")) {
+ method = "DELETE"
+ } else if (option.name.includes("options_")) {
+ method = "OPTIONS"
+ } else if (option.name.includes("connect_")) {
+ method = "CONNECT"
+ }
+
+ // FIXME: Should it require a base URL?
+ if (method.length > 0 && option.description !== undefined && option.description !== null && option.description.includes("http")) {
+ var extraUrl = ""
+ const descSplit = option.description.split("\n")
+ // Last line of descSplit
+ if (descSplit.length > 0) {
+ extraUrl = descSplit[descSplit.length-1]
+ }
+
+ if (extraUrl.length > 0) {
+ if (extraUrl.includes(" ")) {
+ extraUrl = extraUrl.split(" ")[0]
}
- // Set the new value without mutating inputProps
- params = { ...params, inputProps: { ...params.inputProps, value: newValue } };
- break;
+
+ if (extraUrl.includes("#")) {
+ extraUrl = extraUrl.split("#")[0]
+ }
+
+ extraDescription = `${method} ${extraUrl}`
+ } else {
+ //console.log("No url found. Check again :)")
}
}
- // Check if it starts with "Get List" and method is "Get"
- if (params.inputProps.value.startsWith("Get List")) {
- console.log("Get List")
- }
- }
- const actionDescription = ""
- const isIntegration = false
+ const isSelected = selectedValidationAction !== undefined && selectedValidationAction !== null && selectedValidationAction?.name === option.name
return (
-
-
-
- )
+ selected={isSelected}
+ />
+ );
}}
- />
+ renderInput={(params) => {
+ if (params.inputProps?.value) {
+ const prefixes = ["Post", "Put", "Patch"];
+ for (let prefix of prefixes) {
+ if (params.inputProps.value.startsWith(prefix)) {
+ let newValue = params.inputProps.value.replace(prefix + " ", "");
+ if (newValue.length > 1) {
+ newValue = newValue.charAt(0).toUpperCase() + newValue.substring(1);
+ }
+ // Set the new value without mutating inputProps
+ params = { ...params, inputProps: { ...params.inputProps, value: newValue } };
+ break;
+ }
+ }
+ // Check if it starts with "Get List" and method is "Get"
+ if (params.inputProps.value.startsWith("Get List")) {
+ console.log("Get List")
+ }
+ }
+
+ const actionDescription = ""
+ const isIntegration = false
+
+ return (
+
+
+
+ )
+ }}
+ />
+ {
+ if (app === null || app === undefined || app.id === undefined || app.name === undefined) {
+ toast.error("App not found");
+ return;
+ }
+
+ // Check if validation action is selected
+ if (selectedValidationAction === null || selectedValidationAction === undefined) {
+ toast.error("Please select a validation action first");
+ return;
+ }
+
+ setExecuting(true);
+ fetch(`${globalUrl}/api/v1/apps/${app.id}/test`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Accept: "application/json",
+ },
+ credentials: "include",
+ })
+ .then((response) => {
+ return response.json();
+ })
+ .then((responseJson) => {
+ if (responseJson.success === true) {
+ toast.success("Test executed successfully");
+ } else {
+ if (responseJson.reason && responseJson.reason.includes("No validation action found")) {
+ toast.error("No validation action found. Please select a validation action from the dropdown above and try again.");
+ } else {
+ toast.error(responseJson.reason || "Test failed");
+ }
+ }
+ setExecuting(false);
+ })
+ .catch((error) => {
+ console.log("Error:", error);
+ toast.error("Request failed");
+ setExecuting(false);
+ });
+ }}
+ variant="outlined"
+ style={{
+ marginLeft: 20,
+ }}
+ >
+ {executing ? "Testing..." : "Run Test"}
+
+
diff --git a/frontend/src/views/Apps2.jsx b/frontend/src/views/Apps2.jsx
index afb9d25d..d095c1a9 100644
--- a/frontend/src/views/Apps2.jsx
+++ b/frontend/src/views/Apps2.jsx
@@ -1360,6 +1360,13 @@ const Apps2 = (props) => {
console.log("Failed to set apps in localstorage: ", e)
}
}
+
+ const userId = userdata?.id;
+ if (userId !== undefined && userId !== null) {
+ const filteredUserApps = privateapps.filter((app) => app.owner === userId);
+ setUserApps(filteredUserApps);
+ }
+
})
.catch((error) => {
console.log("Failed to get apps: ", error.toString());
@@ -1368,6 +1375,14 @@ const Apps2 = (props) => {
});
};
+ useEffect(() => {
+ const userId = userdata?.id;
+ if (userId !== undefined && userId !== null && userId.length > 0 && apps.length > 0) {
+ const filteredUserApps = apps.filter((app) => app.owner === userId);
+ setUserApps(filteredUserApps);
+ }
+ }, [userdata, apps]);
+
// Locally hotloads app from folder
const hotloadApps = () => {
toast("Hotloading apps from location in .env");
diff --git a/frontend/src/views/GettingStarted.jsx b/frontend/src/views/GettingStarted.jsx
index a87101c5..2066c0ed 100644
--- a/frontend/src/views/GettingStarted.jsx
+++ b/frontend/src/views/GettingStarted.jsx
@@ -972,7 +972,7 @@ const GettingStarted = (props) => {
const [open, setOpen] = React.useState(false);
const [anchorEl, setAnchorEl] = React.useState(null);
- var boxColor = "#FECC00";
+ var boxColor = "#FFC633";
if (data.is_valid) {
boxColor = "#86c142";
}
@@ -1562,7 +1562,7 @@ const GettingStarted = (props) => {
renderCell: (params) => {
const data = params.row.record;
- var boxColor = "#FECC00";
+ var boxColor = "#FFC633";
if (data.is_valid) {
boxColor = "#86c142";
}
diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx
index f94b38b5..443181b5 100644
--- a/frontend/src/views/Workflows2.jsx
+++ b/frontend/src/views/Workflows2.jsx
@@ -103,6 +103,9 @@ import {
Publish as PublishIcon,
GetApp as GetAppIcon,
Image as ImageIcon,
+ Shield as ShieldIcon,
+ Warning as WarningIcon,
+ ChevronRight as ChevronRightIcon,
} from "@mui/icons-material";
// Additional Components
@@ -120,6 +123,7 @@ import { debounce } from "lodash";
import { removeQuery } from "../components/ScrollToTop.jsx";
import {green, yellow, red, grey, triggers as wfTriggers, } from "../views/AngularWorkflow.jsx"
+import Licensed from "../components/Licensed.jsx";
const searchClient = algoliasearch("JNSS5CFDZZ", "c8f882473ff42d41158430be09ec2b4e");
@@ -255,6 +259,18 @@ export const handleReactJsonClipboard = (copy) => {
// Takes an action in Shuffle and
// Returns information about the icon, the color etc to be used
// This can be used for actions of all types
+// PARSED ICON PROPERTIES:
+// icon - SVG d attribute string
+// iconColor - path fill/stroke color (used in cytoscape node SVGs; "white" on colored bg)
+// iconBackgroundColor - solid bg color for the node
+// fillGradient - [color1, color2] for gradient bg; if set, fillstyle = "linear-gradient"
+// originalIcon - React element (22x22, currentColor) used in ParsedActionNew dropdown
+// svgViewBox - viewBox for the SVG; "0 0 48 48" for 48-coord paths, defaults to "0 0 24 24"
+// dropdownViewBox - tighter crop viewBox for dropdown rendering (auto: "10 10 28 28" for 48x48)
+// useStroke - true → render path with stroke (no fill); for outline-style icons
+// useFill - true + useStroke → render with BOTH fill and stroke
+// fillRule - "evenodd" for complex filled shapes (e.g. filter); default "nonzero"
+//
export const GetIconInfo = (action) => {
// Finds the icon based on the action. Should be verbs.
const iconList = [
@@ -263,6 +279,7 @@ export const GetIconInfo = (action) => {
{ key: "cache_get", values: ["get_cache"] },
{ key: "filter", values: ["filter"] },
{ key: "merge", values: ["join", "merge", "route", "router"] },
+ {key: "get_file_value", values: ["get_file_value"]},
{
key: "search",
values: ["search", "find", "locate", "index", "analyze", "anal", "match", "check cache", "check", "verify", "validate", "siem", ],
@@ -343,7 +360,7 @@ export const GetIconInfo = (action) => {
"protect",
],
},
- { key: "intel", values: ["intel", "feed", "threat intel", "threat intelligence", "ti", "t.i.", "t.i", "ti.", "rule", "technique", "tactic", "techniques", "tactics", "ioc", "indicator", "hash", "ip", "url", "domain", ] },
+ { key: "intel", values: ["intel", "feed", "threat intel", "threat intelligence", "ti", "t.i.", "t.i", "ti.", "rule", "technique", "tactic", "techniques", "tactics", "ioc", "indicator", "hash", "ip", "url", "domain", "sha", "md5",] },
];
var selectedKey = ""
@@ -392,57 +409,132 @@ export const GetIconInfo = (action) => {
originalIcon: "",
fillGradient: ["#8acc3f", "#459622"],
},
- cache_add: {
- icon: "M11 3C6.58 3 3 4.79 3 7C3 9.21 6.58 11 11 11C15.42 11 19 9.21 19 7C19 4.79 15.42 3 11 3ZM3 9V12C3 14.21 6.58 16 11 16C15.42 16 19 14.21 19 12V9C19 11.21 15.42 13 11 13C6.58 13 3 11.21 3 9ZM3 14V17C3 19.21 6.58 21 11 21C12.41 21 13.79 20.81 15 20.46V17.46C13.79 17.81 12.41 18 11 18C6.58 18 3 16.21 3 14ZM20 14V17H17V19H20V22H22V19H25V17H22V14",
+ // cache_add: {
+ // icon: "M11 3C6.58 3 3 4.79 3 7C3 9.21 6.58 11 11 11C15.42 11 19 9.21 19 7C19 4.79 15.42 3 11 3ZM3 9V12C3 14.21 6.58 16 11 16C15.42 16 19 14.21 19 12V9C19 11.21 15.42 13 11 13C6.58 13 3 11.21 3 9ZM3 14V17C3 19.21 6.58 21 11 21C12.41 21 13.79 20.81 15 20.46V17.46C13.79 17.81 12.41 18 11 18C6.58 18 3 16.21 3 14ZM20 14V17H17V19H20V22H22V19H25V17H22V14",
+ // iconColor: "white",
+ // iconBackgroundColor: "#8acc3f",
+ // originalIcon: "",
+ // fillGradient: ["#8acc3f", "#459622"],
+ // },
+ get_file_value: {
+ icon: "M25.8332 14.8335H18.4998C18.0136 14.8335 17.5473 15.0267 17.2035 15.3705C16.8597 15.7143 16.6665 16.1806 16.6665 16.6668V31.3335C16.6665 31.8197 16.8597 32.286 17.2035 32.6299C17.5473 32.9737 18.0136 33.1668 18.4998 33.1668H29.4998C29.9861 33.1668 30.4524 32.9737 30.7962 32.6299C31.14 32.286 31.3332 31.8197 31.3332 31.3335V20.3335L25.8332 14.8335Z M25.8335 14.8335V20.3335H31.3335 M24 29.5V24 M21.25 26.75H26.75",
iconColor: "white",
- iconBackgroundColor: "#8acc3f",
+ iconBackgroundColor: "rgba(43, 189, 160, 1)",
originalIcon: "",
- fillGradient: ["#8acc3f", "#459622"],
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
+ fillGradient: ["rgba(43, 189, 160, 1)", "rgba(43, 189, 160, 1)"],
},
- cache_get: {
- icon: "M12 2C7.58 2 4 3.79 4 6C4 8.06 7.13 9.74 11.15 9.96C12.45 8.7 14.19 8 16 8C16.8 8 17.59 8.14 18.34 8.41C19.37 7.74 20 6.91 20 6C20 3.79 16.42 2 12 2ZM4 8V11C4 12.68 6.08 14.11 9 14.71C9.06 13.7 9.32 12.72 9.77 11.82C6.44 11.34 4 9.82 4 8ZM15.93 9.94C14.75 9.95 13.53 10.4 12.46 11.46C8.21 15.71 13.71 22.5 18.75 19.17L23.29 23.71L24.71 22.29L20.17 17.75C22.66 13.97 19.47 9.93 15.93 9.94ZM15.9 12C17.47 11.95 19 13.16 19 15C19 15.7956 18.6839 16.5587 18.1213 17.1213C17.5587 17.6839 16.7956 18 16 18C13.33 18 12 14.77 13.88 12.88C14.47 12.29 15.19 12 15.9 12ZM4 13V16C4 18.05 7.09 19.72 11.06 19.95C10.17 19.07 9.54 17.95 9.22 16.74C6.18 16.17 4 14.72 4 13Z",
+ cache_add: {
+ icon: "M24 20.6667C28.1421 20.6667 31.5 19.5475 31.5 18.1667C31.5 16.786 28.1421 15.6667 24 15.6667C19.8579 15.6667 16.5 16.786 16.5 18.1667C16.5 19.5475 19.8579 20.6667 24 20.6667Z M31.5 24C31.5 25.3833 28.1667 26.5 24 26.5C19.8333 26.5 16.5 25.3833 16.5 24 M16.5 18.1667V29.8334C16.5 31.2167 19.8333 32.3334 24 32.3334C28.1667 32.3334 31.5 31.2167 31.5 29.8334V18.1667 M32 35C34.2091 35 36 33.2091 36 31C36 28.7909 34.2091 27 32 27C29.7909 27 28 28.7909 28 31C28 33.2091 29.7909 35 32 35Z M32 29V33 M30 31H34",
iconColor: "white",
- iconBackgroundColor: "#8acc3f",
+ iconBackgroundColor: "rgba(43, 189, 160, 1)",
+ fillGradient: ["rgba(43, 189, 160, 1)", "rgba(43, 189, 160, 1)"],
originalIcon: "",
- fillGradient: ["#8acc3f", "#459622"],
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
+ },
+ // cache_get: {
+ // icon: "M12 2C7.58 2 4 3.79 4 6C4 8.06 7.13 9.74 11.15 9.96C12.45 8.7 14.19 8 16 8C16.8 8 17.59 8.14 18.34 8.41C19.37 7.74 20 6.91 20 6C20 3.79 16.42 2 12 2ZM4 8V11C4 12.68 6.08 14.11 9 14.71C9.06 13.7 9.32 12.72 9.77 11.82C6.44 11.34 4 9.82 4 8ZM15.93 9.94C14.75 9.95 13.53 10.4 12.46 11.46C8.21 15.71 13.71 22.5 18.75 19.17L23.29 23.71L24.71 22.29L20.17 17.75C22.66 13.97 19.47 9.93 15.93 9.94ZM15.9 12C17.47 11.95 19 13.16 19 15C19 15.7956 18.6839 16.5587 18.1213 17.1213C17.5587 17.6839 16.7956 18 16 18C13.33 18 12 14.77 13.88 12.88C14.47 12.29 15.19 12 15.9 12ZM4 13V16C4 18.05 7.09 19.72 11.06 19.95C10.17 19.07 9.54 17.95 9.22 16.74C6.18 16.17 4 14.72 4 13Z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#8acc3f",
+ // originalIcon: "",
+ // fillGradient: ["#8acc3f", "#459622"],
+ // },
+ cache_get: {
+ icon: "M22.25 14C24.379 14 26.3377 14.2865 27.79 14.7705C28.5123 15.0113 29.1516 15.3144 29.625 15.6875C30.09 16.054 30.5 16.5766 30.5 17.25V25.0889C30.4172 25.0848 30.3338 25.083 30.25 25.083C29.8184 25.083 29.3995 25.1374 29 25.2402V25.0537C28.6427 25.2475 28.2369 25.4175 27.7998 25.5635C26.3499 26.0475 24.3907 26.333 22.25 26.333C20.1093 26.333 18.1501 26.0475 16.7002 25.5635C16.2631 25.4175 15.8573 25.2475 15.5 25.0537V28.917C15.5002 28.9389 15.5137 29.0744 15.8018 29.3027C16.085 29.5272 16.542 29.7623 17.1748 29.9736C18.4332 30.3937 20.2243 30.667 22.25 30.667C23.3382 30.667 24.3581 30.5844 25.2646 30.4463C25.3016 30.9605 25.4159 31.4527 25.5967 31.9121C24.5747 32.0741 23.4408 32.167 22.25 32.167C20.1092 32.167 18.1502 31.8805 16.7002 31.3965C15.9791 31.1558 15.342 30.8524 14.8701 30.4785C14.4059 30.1106 14.0002 29.5883 14 28.917V17.25C14 16.5766 14.41 16.054 14.875 15.6875C15.3484 15.3144 15.9877 15.0113 16.71 14.7705C18.1623 14.2865 20.121 14 22.25 14ZM29 19.2168C28.64 19.4118 28.2306 19.5826 27.79 19.7295C26.3377 20.2135 24.379 20.5 22.25 20.5C20.121 20.5 18.1623 20.2135 16.71 19.7295C16.2694 19.5826 15.86 19.4118 15.5 19.2168V23.083C15.5001 23.1039 15.5122 23.2403 15.8018 23.4697C16.0851 23.6941 16.5421 23.9294 17.1748 24.1406C18.4332 24.5607 20.2243 24.833 22.25 24.833C24.2757 24.833 26.0668 24.5607 27.3252 24.1406C27.9579 23.9294 28.4149 23.6941 28.6982 23.4697C28.9878 23.2403 28.9999 23.1039 29 23.083V19.2168ZM22.25 15.5C20.2371 15.5 18.4456 15.7727 17.1836 16.1934C16.5488 16.405 16.0893 16.6412 15.8037 16.8662C15.5099 17.0978 15.5 17.2331 15.5 17.25C15.5001 17.2679 15.5111 17.4032 15.8037 17.6338C16.0893 17.8588 16.5488 18.095 17.1836 18.3066C18.4456 18.7273 20.2371 19 22.25 19C24.2628 19 26.0544 18.7273 27.3164 18.3066C27.9512 18.095 28.4107 17.8588 28.6963 17.6338C28.9889 17.4032 28.9999 17.2679 29 17.25C29 17.2331 28.9901 17.0978 28.6963 16.8662C28.4107 16.6412 27.9512 16.405 27.3164 16.1934C26.0544 15.7727 24.2629 15.5 22.25 15.5Z M29.9166 32.4164C31.3893 32.4164 32.5831 31.2225 32.5831 29.7497C32.5831 28.2769 31.3893 27.083 29.9166 27.083C28.4439 27.083 27.25 28.2769 27.25 29.7497C27.25 31.2225 28.4439 32.4164 29.9166 32.4164Z M33.2505 33.0828L31.8005 31.6328",
+ iconColor: "white",
+ iconBackgroundColor: "rgba(43, 189, 160, 1)",
+ fillGradient: ["rgba(43, 189, 160, 1)", "rgba(43, 189, 160, 1)"],
+ originalIcon: "",
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
repeat: {
- icon: "M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z",
+ icon: "M7.417 8.667V11.167H9.917 M16.583 15.333V12.833H14.083 M15.538 10.75C15.326 10.153 14.967 9.619 14.494 9.198C14.020 8.777 13.448 8.483 12.830 8.343C12.212 8.204 11.569 8.223 10.960 8.399C10.352 8.575 9.798 8.902 9.350 9.35L7.417 11.167M16.583 12.833L14.650 14.65C14.202 15.098 13.648 15.425 13.040 15.601C12.431 15.777 11.788 15.796 11.170 15.657C10.552 15.517 9.980 15.223 9.507 14.802C9.033 14.381 8.674 13.847 8.463 13.25",
iconColor: "white",
- iconBackgroundColor: defaultColor,
+ iconBackgroundColor: "rgba(242, 101, 59, 1)",
+ fillGradient: ["rgba(242, 101, 59, 1)", "rgba(242, 101, 59, 1)"],
originalIcon: ,
+ useStroke: true,
+ dropdownViewBox: "5 7 14 10",
},
+ // repeat: {
+ // icon: "M19 8l-4 4h3c0 3.31-2.69 6-6 6-1.01 0-1.97-.25-2.8-.7l-1.46 1.46C8.97 19.54 10.43 20 12 20c4.42 0 8-3.58 8-8h3l-4-4zM6 12c0-3.31 2.69-6 6-6 1.01 0 1.97.25 2.8.7l1.46-1.46C15.03 4.46 13.57 4 12 4c-4.42 0-8 3.58-8 8H1l4 4 4-4H6z",
+ // iconColor: "white",
+ // iconBackgroundColor: defaultColor,
+ // originalIcon: ,
+ // },
+
add: {
icon: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z",
iconColor: "white",
iconBackgroundColor: defaultColor,
originalIcon: ,
},
+ // edit: {
+ // icon: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z",
+ // iconColor: "white",
+ // iconBackgroundColor: defaultColor,
+ // originalIcon: ,
+ // },
edit: {
- icon: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z",
+ icon: "M27.75 17.25C27.947 17.053 28.1808 16.8967 28.4382 16.7901C28.6956 16.6835 28.9714 16.6287 29.25 16.6287C29.5286 16.6287 29.8044 16.6835 30.0618 16.7901C30.3192 16.8967 30.553 17.053 30.75 17.25C30.947 17.447 31.1032 17.6808 31.2098 17.9382C31.3165 18.1956 31.3713 18.4714 31.3713 18.75C31.3713 19.0286 31.3165 19.3044 31.2098 19.5618C31.1032 19.8191 30.947 20.053 30.75 20.25L20.625 30.375L16.5 31.5L17.625 27.375L27.75 17.25Z",
iconColor: "white",
- iconBackgroundColor: defaultColor,
+ iconBackgroundColor: "rgba(242, 101, 59, 1)",
+ fillGradient: ["rgba(242, 101, 59, 1)", "rgba(242, 101, 59, 1)"],
originalIcon: ,
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
- filter: {
- icon: "M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39c.51-.66.04-1.61-.79-1.61H5.04c-.83 0-1.3.95-.79 1.61z",
+ // filter: {
+ // icon: "M4.25 5.61C6.27 8.2 10 13 10 13v6c0 .55.45 1 1 1h2c.55 0 1-.45 1-1v-6s3.72-4.8 5.74-7.39c.51-.66.04-1.61-.79-1.61H5.04c-.83 0-1.3.95-.79 1.61z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#f5515f",
+ // originalIcon: "",
+ // fillGradient: ["#f5515f", "#a1051d"],
+ // },
+ filter: {
+ icon: "M31.25 17C31.25 16.8619 31.1381 16.75 31 16.75H17C16.8619 16.75 16.75 16.8619 16.75 17V18.5859C16.75 18.6522 16.7764 18.7158 16.8232 18.7627L21.2373 23.1768C21.5655 23.5049 21.75 23.95 21.75 24.4141V30.958L26.25 29.459V24.4141C26.25 23.95 26.4345 23.5049 26.7627 23.1768L31.1768 18.7627C31.2236 18.7158 31.25 18.6522 31.25 18.5859V17ZM32.75 18.5859C32.75 19.05 32.5655 19.4951 32.2373 19.8232L27.8232 24.2373C27.7764 24.2842 27.75 24.3478 27.75 24.4141V29.6396C27.75 30.1769 27.4066 30.6558 26.8955 30.8262L21.8955 32.4922C21.0874 32.7615 20.2509 32.1611 20.25 31.3076V24.4141C20.25 24.3478 20.2236 24.2842 20.1768 24.2373L15.7627 19.8232C15.4345 19.4951 15.25 19.05 15.25 18.5859V17C15.25 16.0335 16.0335 15.25 17 15.25H31C31.9665 15.25 32.75 16.0335 32.75 17V18.5859Z",
iconColor: "white",
- iconBackgroundColor: "#f5515f",
+ iconBackgroundColor: "rgba(217, 56, 136, 1)",
originalIcon: "",
- fillGradient: ["#f5515f", "#a1051d"],
- },
+ fillGradient: ["rgba(217, 56, 136, 1)", "rgba(217, 56, 136, 1)"],
+ fillRule: "evenodd",
+ svgViewBox: "0 0 48 48",
+ },
+ // merge: {
+ // icon: "M17 20.41 18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#f5515f",
+ // originalIcon: "",
+ // fillGradient: ["#f5515f", "#a1051d"],
+ // },
merge: {
- icon: "M17 20.41 18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z",
+ icon: "M23.4692 16.2696C23.7621 15.9768 24.2369 15.9769 24.5298 16.2696L29.3032 21.0421C29.5961 21.335 29.5961 21.8107 29.3032 22.1036C29.0103 22.3963 28.5345 22.3964 28.2417 22.1036L24.7495 18.6104V23.0802C24.7497 23.0867 24.7505 23.0932 24.7505 23.0997V24.0001C24.7507 28.0592 28.0409 31.3497 32.1001 31.3497C32.5141 31.3498 32.85 31.6857 32.8501 32.0997C32.8501 32.5138 32.5142 32.8496 32.1001 32.8497C28.4809 32.8497 25.3708 30.6766 23.9995 27.5645C22.6281 30.6765 19.519 32.8497 15.8999 32.8497C15.4857 32.8497 15.1499 32.5139 15.1499 32.0997C15.15 31.6856 15.4858 31.3497 15.8999 31.3497C19.9591 31.3497 23.2493 28.0592 23.2495 24.0001V18.6104L19.7573 22.1036C19.4644 22.3963 18.9886 22.3964 18.6958 22.1036C18.4032 21.8108 18.4032 21.3349 18.6958 21.0421L23.4692 16.2696Z",
iconColor: "white",
- iconBackgroundColor: "#f5515f",
+ iconBackgroundColor: "rgba(217, 56, 136, 1)",
originalIcon: "",
- fillGradient: ["#f5515f", "#a1051d"],
+ fillGradient: ["rgba(217, 56, 136, 1)", "rgba(217, 56, 136, 1)"],
+ useStroke: false,
+ useFill: true,
+ svgViewBox: "0 0 48 48",
},
+ // compare: {
+ // icon: "M10 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h5v2h2V1h-2v2zm0 15H5l5-6v6zm9-15h-5v2h5v13l-5-6v9h5c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z",
+ // iconColor: "white",
+ // iconBackgroundColor: defaultColor,
+ // originalIcon: ,
+ // },
compare: {
- icon: "M10 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h5v2h2V1h-2v2zm0 15H5l5-6v6zm9-15h-5v2h5v13l-5-6v9h5c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2z",
+ icon: "M19 15.75H23.7832V32.25H19C17.7574 32.25 16.75 31.2426 16.75 30V18C16.75 16.8352 17.6352 15.8771 18.7695 15.7617L19 15.75Z M26.667 16.125H29.0003C30.6572 16.125 32.0003 17.4681 32.0003 19.125V28.875C32.0003 30.5319 30.6572 31.875 29.0003 31.875H26.667",
iconColor: "white",
- iconBackgroundColor: defaultColor,
- originalIcon: ,
+ iconBackgroundColor: "rgba(242, 101, 59, 1)",
+ originalIcon: "",
+ fillGradient: ["rgba(242, 101, 59, 1)", "rgba(242, 101, 59, 1)"],
+ useStroke: true,
+ useFill: true,
+ svgViewBox: "0 0 48 48",
},
extract: {
icon: "M3 3h18v2H3z",
@@ -462,18 +554,36 @@ export const GetIconInfo = (action) => {
iconBackgroundColor: defaultColor,
originalIcon: ,
},
+ // execute: {
+ // icon: "M8 5v14l11-7z",
+ // iconColor: "white",
+ // iconBackgroundColor: defaultColor,
+ // originalIcon: ,
+ // },
execute: {
- icon: "M8 5v14l11-7z",
+ icon: "M17.3335 28.1667L22.3335 23.1667L17.3335 18.1667 M24 29.8333H30.6667",
iconColor: "white",
- iconBackgroundColor: defaultColor,
+ iconBackgroundColor: "rgba(242, 101, 59, 1)",
+ fillGradient: ["rgba(242, 101, 59, 1)", "rgba(242, 101, 59, 1)"],
originalIcon: ,
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
+ // delete: {
+ // icon: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#03030e",
+ // originalIcon: ,
+ // fillGradient: ["#03030e", "#205d66"],
+ // },
delete: {
- icon: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z",
+ icon: "M15 18.5H33C31.5955 18.5 30.8933 18.5 30.3889 18.8371C30.1705 18.983 29.983 19.1705 29.8371 19.3889C29.5 19.8933 29.5 20.5955 29.5 22V27.5C29.5 29.3856 29.5 30.3284 28.9142 30.9142C28.3284 31.5 27.3856 31.5 25.5 31.5H22.5C20.6144 31.5 19.6716 31.5 19.0858 30.9142C18.5 30.3284 18.5 29.3856 18.5 27.5V22C18.5 20.5955 18.5 19.8933 18.1629 19.3889C18.017 19.1705 17.8295 18.983 17.6111 18.8371C17.1067 18.5 16.4045 18.5 15 18.5Z M21.5 15.5002C21.5 15.5002 22 14.5 24 14.5C26 14.5 26.5 15.5 26.5 15.5",
iconColor: "white",
- iconBackgroundColor: "#03030e",
- originalIcon: ,
- fillGradient: ["#03030e", "#205d66"],
+ iconBackgroundColor: "rgba(98, 98, 98, 1)",
+ originalIcon: "",
+ fillGradient: ["rgba(98, 98, 98, 1)", "rgba(98, 98, 98, 1)"],
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
close: {
icon: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",
@@ -482,19 +592,37 @@ export const GetIconInfo = (action) => {
originalIcon: ,
fillGradient: ["#03030e", "#205d66"],
},
+ // send: {
+ // icon: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#0373da",
+ // originalIcon: ,
+ // fillGradient: ["#0bc8bf", "#0373da"],
+ // },
send: {
- icon: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z",
+ icon: "M31.3332 16.6667L22.1665 25.8334 M31.3332 16.6667L25.4998 33.3334L22.1665 25.8334L14.6665 22.5001L31.3332 16.6667Z",
iconColor: "white",
- iconBackgroundColor: "#0373da",
- originalIcon: ,
- fillGradient: ["#0bc8bf", "#0373da"],
+ iconBackgroundColor: "rgba(128, 107, 255, 1)",
+ originalIcon: "",
+ fillGradient: ["rgba(128, 107, 255, 1)", "rgba(128, 107, 255 , 1)"],
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
+ // download: {
+ // icon: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z",
+ // iconColor: "white",
+ // iconBackgroundColor: "#0373da",
+ // originalIcon: ,
+ // fillGradient: ["#0bc8bf", "#0373da"],
+ // },
download: {
- icon: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z",
+ icon: "M18 22L24 28M24 28L30 22M24 28L24 16 M17 33H31",
iconColor: "white",
- iconBackgroundColor: "#0373da",
- originalIcon: ,
- fillGradient: ["#0bc8bf", "#0373da"],
+ iconBackgroundColor: "rgba(128, 107, 255, 1)",
+ originalIcon: "",
+ fillGradient: ["rgba(128, 107, 255, 1)", "rgba(128, 107, 255, 1)"],
+ useStroke: true,
+ svgViewBox: "0 0 48 48",
},
search: {
icon: "M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
@@ -537,7 +665,7 @@ export const GetIconInfo = (action) => {
iconColor: "white",
iconBackgroundColor: "green",
originalIcon: ,
- }
+ },
}
/*
@@ -568,28 +696,59 @@ export const GetIconInfo = (action) => {
}
if (
- (selectedItem.originalIcon === undefined ||
- selectedItem.originalIcon === "") &&
selectedItem.icon !== "" &&
selectedItem.icon !== undefined
) {
- const svg_pin = (
-
-
-
- );
+ const iconViewBox = selectedItem.svgViewBox || `0 0 ${svgSize} ${svgSize}`;
+ // Use a tighter viewBox for dropdown icons so 48x48 centered content appears larger
+ const dropdownViewBox = selectedItem.dropdownViewBox || (iconViewBox === "0 0 48 48" ? "10 10 28 28" : iconViewBox);
+ const strokeW = iconViewBox === "0 0 48 48" ? "1.5" : "1";
+ // Build dropdown React SVG using the same stroke/fill logic as buildIconSvgPath
+ var svg_pin;
+ if (selectedItem.useStroke && selectedItem.useFill) {
+ svg_pin = (
+
+
+
+ );
+ } else if (selectedItem.useStroke) {
+ svg_pin = (
+
+
+
+ );
+ } else {
+ svg_pin = (
+
+
+
+ );
+ }
selectedItem.originalIcon = svg_pin;
}
return selectedItem;
};
+// Builds the SVG string for an icon with the proper fill/stroke attributes.
+// color: the fill/stroke color (e.g. "white" for cytoscape nodes, "currentColor" for React)
+// Returns an SVG path element string ready to embed inside an tag.
+export const buildIconSvgPath = (iconInfo, color) => {
+ const iconViewBox = iconInfo.svgViewBox || "0 0 24 24";
+ // For stroke icons: use proportional stroke width (0.75 for 24x24, 1.5 for 48x48)
+ // This ensures consistent visual appearance across different viewBox sizes
+ const strokeW = iconInfo.useStroke
+ ? (iconViewBox === "0 0 48 48" ? "1.5" : "0.75")
+ : (iconInfo.useFill ? "0" : "1.5");
+ if (iconInfo.useStroke && iconInfo.useFill) {
+ return ` `;
+ } else if (iconInfo.useStroke) {
+ return ` `;
+ } else {
+ return ` `;
+ }
+};
+
export const collapseField = (field, inputdata) => {
if (field === undefined || field === null) {
return true
@@ -625,7 +784,7 @@ export const validateJson = (showResult) => {
if (showResult === undefined || showResult === null) {
return {
valid: false,
- result: "",
+ result: showResult,
}
}
@@ -638,7 +797,10 @@ export const validateJson = (showResult) => {
}
if (typeof showResult === "object" || typeof showResult === "array") {
- return {
+ //console.log("Valid!: ", showResult)
+ // FIXME: Not returning as we want to recurse.
+
+ return {
valid: true,
result: showResult,
}
@@ -720,64 +882,85 @@ export const validateJson = (showResult) => {
}
// This is where we start recursing
+ // Problem: Loops aren't recursed properly.
if (jsonvalid) {
// Check fields if they can be parsed too
try {
for (const [key, value] of Object.entries(result)) {
- if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
- //console.log("CHECKING STRING: ", value)
+ if (value === null || value === undefined) {
+ continue
+ }
- const inside_result = validateJson(value)
- if (inside_result.valid) {
- //console.log("INSIDE RESULT: ", inside_result.result)
+ try {
+ if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
+ //console.log("CHECKING STRING: ", value)
- if (typeof inside_result.result === "string") {
- const newres = JSON.parse(inside_result.result)
+ const inside_result = validateJson(value)
+ if (inside_result.valid) {
+ if (typeof inside_result.result === "string") {
+ const newres = JSON.parse(inside_result.result)
- result[key] = newres
- } else {
- result[key] = inside_result.result
- }
- }
- } else {
+ result[key] = newres
+ } else {
+ result[key] = inside_result.result
+ }
+ }
+ } else {
+ // Usually only reaches here if raw array > dict > value
+ if (typeof showResult !== "array") {
+ for (const [subkey, subvalue] of Object.entries(value)) {
+ if (typeof subvalue === "string" && (subvalue.startsWith("{") || subvalue.startsWith("["))) {
+ const inside_result = validateJson(subvalue)
+ if (inside_result.valid) {
+ if (typeof inside_result.result === "string") {
+ const newres = JSON.parse(inside_result.result)
+ result[key][subkey] = newres
+ } else {
+ result[key][subkey] = inside_result.result
+ }
+ }
+ }
- // Usually only reaches here if raw array > dict > value
- if (typeof showResult !== "array") {
- for (const [subkey, subvalue] of Object.entries(value)) {
- if (typeof subvalue === "string" && (subvalue.startsWith("{") || subvalue.startsWith("["))) {
- const inside_result = validateJson(subvalue)
- if (inside_result.valid) {
- if (typeof inside_result.result === "string") {
- const newres = JSON.parse(inside_result.result)
- result[key][subkey] = newres
- } else {
- result[key][subkey] = inside_result.result
- }
- }
- }
-
- }
- }
- }
+ }
+ } else {
+ console.log("Skip array: ", value)
+ }
+ }
+ } catch (e) {
+ console.log(`Failed to parse '${key}': '${value}': `, e, JSON.stringify(result))
+ }
}
} catch (e) {
- //console.log("Failed parsing inside json subvalues: ", e)
+ console.log("Failed parsing inside json subvalues: ", e, result)
}
}
- return {
- valid: jsonvalid,
+ //console.log("Result: ", result)
+
+ try {
+ const stringified = JSON.stringify(result)
+ if ((stringified.startsWith("{") && stringified.endsWith("}")) || (stringified.startsWith("[") && stringified.endsWith("]"))) {
+ result = JSON.parse(stringified)
+ jsonvalid = true
+ }
+ } catch(e) {
+ jsonvalid = false
+ }
+
+ const toReturn = {
result: result,
- };
+ valid: jsonvalid,
+ }
+
+ return toReturn
};
//Custom hook for handling styling of the dropzone
const useDropzoneStyles = () => {
- const { leftSideBarOpenByClick } = useContext(Context);
- const { themeMode, brandColor } = useContext(Context);
+ const { leftSideBarOpenByClick, themeMode, brandColor } = useContext(Context);
const theme = getTheme(themeMode, brandColor);
- return {
+ return React.useMemo(() => ({
paddingTop: 70,
// minHeight: 1000,
backgroundColor: theme.palette.backgroundColor,
@@ -785,7 +968,7 @@ const useDropzoneStyles = () => {
// maxWidth: window.innerWidth > 1366 ? 1366 : isMobile ? "100%" : 1200,
paddingLeft: leftSideBarOpenByClick ? 200 : 0,
transition: "padding-left 0.3s ease",
- };
+ }), [leftSideBarOpenByClick, theme]);
};
//Wrapper for the dropzone component
@@ -798,8 +981,6 @@ const DropzoneWrapper = memo(({ onDrop, WorkflowView }) => {
);
});
-
-
const Workflows2 = (props) => {
const { globalUrl, isLoggedIn, isLoaded, userdata, checkLogin } = props;
const location = useLocation();
@@ -891,7 +1072,7 @@ const Workflows2 = (props) => {
const [field1, setField1] = React.useState("");
const [field2, setField2] = React.useState("");
const [downloadUrl, setDownloadUrl] = React.useState("https://github.com/shuffle/workflows")
- const [downloadBranch, setDownloadBranch] = React.useState("master");
+ const [downloadBranch, setDownloadBranch] = React.useState("main");
const [loadWorkflowsModalOpen, setLoadWorkflowsModalOpen] =
React.useState(false);
const [exportModalOpen, setExportModalOpen] = React.useState(false);
@@ -2903,7 +3084,7 @@ const Workflows2 = (props) => {
const [open, setOpen] = React.useState(false);
const [anchorEl, setAnchorEl] = React.useState(null);
- var boxColor = "#FECC00";
+ var boxColor = "#FFC633";
if (data.is_valid) {
boxColor = "#86c142";
}
@@ -3346,7 +3527,7 @@ const Workflows2 = (props) => {
}
style={{
textDecoration: "none",
- color: "inherit",
+ color: theme.palette.text.primary,
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
@@ -3891,7 +4072,7 @@ const Workflows2 = (props) => {
renderCell: (params) => {
const data = params.row.record;
- var boxColor = "#FECC00";
+ var boxColor = "#FFC633";
if (data.is_valid) {
boxColor = "#86c142";
}
@@ -5097,7 +5278,7 @@ const Workflows2 = (props) => {
margin: "auto",
}}>
- {currTab === 0 ? "Org" : currTab === 1 ? "Your" : "Discover"} Workflows
+ {currTab === 0 ? "Org" : currTab === 1 ? "Your" : currTab === 2 ? "Discover" : "Security Bundle" } Workflows
@@ -5149,7 +5330,7 @@ const Workflows2 = (props) => {
{backgroundWorkflows.length > 0 &&
{
exportAllWorkflows(workflows)}
>
+
+ setLoadWorkflowsModalOpen(true)}
+ disabled={currTab === 2}
+ >
+
+
+
{
}
- {!isCloud && currentOrg?.old_org ? (
+ {!isCloud && (currentOrg?.old_org || isProdStatusOn) ? (
{
- navigate("/admin?admin_tab=billingstats")
- }}
>
-
-
- {isProdStatusOn ? "Production" : "NOT Production"}
-
) : null}
@@ -5812,15 +5972,15 @@ const Workflows2 = (props) => {
const parsedData = {
url: url,
- field_3: downloadBranch || "master",
+ branch: downloadBranch || "master",
};
if (field1.length > 0) {
- parsedData["field_1"] = field1;
+ parsedData["username"] = field1;
}
if (field2.length > 0) {
- parsedData["field_2"] = field2;
+ parsedData["password"] = field2;
}
toast("Getting specific workflows from your URL.");
@@ -5867,17 +6027,28 @@ const Workflows2 = (props) => {
open={loadWorkflowsModalOpen}
onClose={() => { }}
PaperProps={{
- style: {
- backgroundColor: theme.palette.surfaceColor,
- color: "white",
- minWidth: "800px",
- minHeight: "320px",
- },
+ sx: {
+ borderRadius: theme?.palette?.DialogStyle?.borderRadius,
+ border: theme?.palette?.DialogStyle?.border,
+ minWidth: '440px',
+ fontFamily: theme?.typography?.fontFamily,
+ backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
+ zIndex: 1000,
+ '& .MuiDialogContent-root': {
+ backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
+ },
+ '& .MuiDialogTitle-root': {
+ backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
+ },
+ '& .MuiDialogActions-root': {
+ backgroundColor: theme?.palette?.DialogStyle?.backgroundColor,
+ },
+ }
}}
>
-
- Load workflows from github repo
+
+ Load workflows from a remote repository
{
-
- Repository (supported: github, gitlab, bitbucket)
+
+ Repository (supported: github, gitlab, bitbucket, azure devops):
{
setDownloadBranch(e.target.value)}
- placeholder="master"
+ placeholder="main"
fullWidth
/>
- Authentication (optional - private repos etc):
+ Authentication for private repositories (optional):
{
fullWidth
/>
{
Cancel
{
handleGithubValidation();
}}
- color="primary"
>
Submit
diff --git a/functions/onprem/orborus/go.mod b/functions/onprem/orborus/go.mod
index a5a20284..b4aeeeae 100644
--- a/functions/onprem/orborus/go.mod
+++ b/functions/onprem/orborus/go.mod
@@ -10,7 +10,7 @@ require (
github.com/docker/docker v28.3.3+incompatible
github.com/docker/go-connections v0.5.0
github.com/satori/go.uuid v1.2.0
- github.com/shuffle/shuffle-shared v0.9.82
+ github.com/shuffle/shuffle-shared v0.9.84
k8s.io/api v0.34.2
k8s.io/apimachinery v0.34.2
)
@@ -48,6 +48,7 @@ require (
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
+ github.com/coreos/go-oidc/v3 v3.17.0 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
@@ -63,13 +64,14 @@ require (
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
- github.com/go-git/go-git/v5 v5.16.1 // indirect
- github.com/go-jose/go-jose/v4 v4.0.5 // indirect
+ github.com/go-git/go-git/v5 v5.16.5 // indirect
+ github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
diff --git a/functions/onprem/orborus/go.sum b/functions/onprem/orborus/go.sum
index 461ef234..cf6deddb 100644
--- a/functions/onprem/orborus/go.sum
+++ b/functions/onprem/orborus/go.sum
@@ -93,6 +93,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
+github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
@@ -142,12 +144,12 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
-github.com/go-git/go-git/v5 v5.16.1 h1:TuxMBWNL7R05tXsUGi0kh1vi4tq0WfXNLlIrAkXG1k8=
-github.com/go-git/go-git/v5 v5.16.1/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
+github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
+github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -165,6 +167,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
+github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -311,8 +315,8 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shuffle/opensearch-go/v4 v4.0.0 h1:Mh85CD1MwOgXiFFYlzS1llnvdqL3CztRdR1ZT/SLIjU=
github.com/shuffle/opensearch-go/v4 v4.0.0/go.mod h1:gVLZKQE5khQWMb68XBtgKrhu78oLGL2zHwAGnFMDwC0=
-github.com/shuffle/shuffle-shared v0.9.79 h1:4E6vrgcBnpqRQfptjnbYqSmOUNpMVeaNjNHFa0Uq2rQ=
-github.com/shuffle/shuffle-shared v0.9.79/go.mod h1:zsRdKLjMyLHg2kNyw06wTbzi2m073lczcurFhiYp6M8=
+github.com/shuffle/shuffle-shared v0.9.84 h1:b77E386LUk63k9dTN735/hcRuH2XY1cNgTvxpx3qS/s=
+github.com/shuffle/shuffle-shared v0.9.84/go.mod h1:AkXajlWWB16WfWjCw9K7y38L8JKABJzVxcX6KI/J1H4=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
diff --git a/functions/onprem/worker/go.mod b/functions/onprem/worker/go.mod
index 7c833001..7bc5fd19 100644
--- a/functions/onprem/worker/go.mod
+++ b/functions/onprem/worker/go.mod
@@ -11,7 +11,7 @@ require (
github.com/docker/docker v28.3.3+incompatible
github.com/gorilla/mux v1.8.1
github.com/satori/go.uuid v1.2.0
- github.com/shuffle/shuffle-shared v0.9.82
+ github.com/shuffle/shuffle-shared v0.9.84
github.com/shuffle/singul v0.0.24
k8s.io/api v0.34.2
k8s.io/apimachinery v0.34.2
@@ -49,6 +49,7 @@ require (
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
+ github.com/coreos/go-oidc/v3 v3.17.0 // indirect
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
@@ -65,13 +66,14 @@ require (
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
- github.com/go-git/go-git/v5 v5.16.1 // indirect
- github.com/go-jose/go-jose/v4 v4.0.5 // indirect
+ github.com/go-git/go-git/v5 v5.16.5 // indirect
+ github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
+ github.com/goccy/go-json v0.10.5 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/golang/protobuf v1.5.4 // indirect
diff --git a/functions/onprem/worker/go.sum b/functions/onprem/worker/go.sum
index 69edddc6..85cfecac 100644
--- a/functions/onprem/worker/go.sum
+++ b/functions/onprem/worker/go.sum
@@ -93,6 +93,8 @@ github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151X
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
+github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
+github.com/coreos/go-oidc/v3 v3.17.0/go.mod h1:wqPbKFrVnE90vty060SB40FCJ8fTHTxSwyXJqZH+sI8=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
@@ -142,12 +144,12 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
-github.com/go-git/go-git/v5 v5.16.1 h1:TuxMBWNL7R05tXsUGi0kh1vi4tq0WfXNLlIrAkXG1k8=
-github.com/go-git/go-git/v5 v5.16.1/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8=
+github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
+github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
-github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
+github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
+github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -165,6 +167,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
+github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
+github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -313,8 +317,8 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shuffle/opensearch-go/v4 v4.0.0 h1:Mh85CD1MwOgXiFFYlzS1llnvdqL3CztRdR1ZT/SLIjU=
github.com/shuffle/opensearch-go/v4 v4.0.0/go.mod h1:gVLZKQE5khQWMb68XBtgKrhu78oLGL2zHwAGnFMDwC0=
-github.com/shuffle/shuffle-shared v0.9.82 h1:JVT5fSE6IJx+ILRgJniHiF66PgqF2El0kModyQDMmKk=
-github.com/shuffle/shuffle-shared v0.9.82/go.mod h1:zsRdKLjMyLHg2kNyw06wTbzi2m073lczcurFhiYp6M8=
+github.com/shuffle/shuffle-shared v0.9.84 h1:b77E386LUk63k9dTN735/hcRuH2XY1cNgTvxpx3qS/s=
+github.com/shuffle/shuffle-shared v0.9.84/go.mod h1:AkXajlWWB16WfWjCw9K7y38L8JKABJzVxcX6KI/J1H4=
github.com/shuffle/singul v0.0.24 h1:e+roPArxMOtO6C45F438O4bDNztECz/mFIhFbI77B6w=
github.com/shuffle/singul v0.0.24/go.mod h1:JkJB6KfllouSklwIAC02t2Sl2awVH9lC8UtP3axUIWw=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=