+
+
+
+
{
- 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);
+ }}
+ >
+ {/*
+
+ */}
+
+
+
+
+ What do you want to do?
+
+ {
+ setActionInput(e.target.value)
+ }}
+ InputProps={{
+ endAdornment: (
+ agentRequestLoading ?
+
+ :
+
+
+
+
+
+ ),
}}
/>
- {
- setAppPickerAnchor(null)
- }}
- anchorOrigin={{
- vertical: 'bottom',
- horizontal: 'left',
- }}
- >
-
+
+
} label="Select Apps / MCPs"
+ style={chipStyle}
+ onClick={() => {
+ setAppPickerAnchor(document.getElementById("add_app_chip"))
+ }}
/>
-
+
{
+ setAppPickerAnchor(null)
+ }}
+ anchorOrigin={{
+ vertical: 'bottom',
+ horizontal: 'left',
+ }}
+ >
+
+
+
+
+ {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)
+ }}
+ />
+ )
+ })}
+
+
+
+ {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..fcf3e270 100755
--- a/frontend/src/views/AngularWorkflow.jsx
+++ b/frontend/src/views/AngularWorkflow.jsx
@@ -463,9 +463,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 +593,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([])
@@ -2560,7 +2559,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
},
@@ -3324,7 +3323,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -3445,6 +3444,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 = {
@@ -3830,7 +3841,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 +4195,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4201,7 +4212,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": "#81c784",
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4250,7 +4261,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4267,7 +4278,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": "#81c784",
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4298,7 +4309,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4314,7 +4325,7 @@ const AngularWorkflow = (defaultprops) => {
"line-gradient-stop-colors": ["grey", "grey"],
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4346,7 +4357,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4363,7 +4374,7 @@ const AngularWorkflow = (defaultprops) => {
"border-color": color,
}
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4394,7 +4405,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4450,7 +4461,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -4484,7 +4495,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- node.animate(
+ node.stop().animate(
{
style: parsedStyle,
},
@@ -8627,7 +8638,7 @@ const AngularWorkflow = (defaultprops) => {
};
}
- event.target.animate(
+ event.target.stop().animate(
{
style: parsedStyle,
},
@@ -9423,7 +9434,7 @@ const AngularWorkflow = (defaultprops) => {
}
if (event.target !== undefined && event.target !== null) {
- event.target.animate(
+ event.target.stop().animate(
{
style: parsedStyle,
},
@@ -9741,7 +9752,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -9910,7 +9921,7 @@ const AngularWorkflow = (defaultprops) => {
}
const animationDuration = 150
- foundnode.animate(
+ foundnode.stop().animate(
{
style: parsedStyle,
},
@@ -12487,7 +12498,7 @@ const AngularWorkflow = (defaultprops) => {
//}
safeRefine(event.currentTarget.value)
}}
- limit={5}
+ limit={15}
/>
{/*isSearchStalled ? 'My search is stalled' : ''*/}
@@ -14360,8 +14371,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 +14484,24 @@ const AngularWorkflow = (defaultprops) => {
{
setExecutionText(data)
- executeWorkflow(data, workflow.start, lastSaved);
+ executeWorkflow(data, workflow.start, lastSaved)
setExecutionArgumentModalOpen(false)
}}
>Select
{
return collapseField(jsonField)
}}
@@ -14499,10 +14515,11 @@ const AngularWorkflow = (defaultprops) => {
}
return (
- {
setExecutionText(data)
- executeWorkflow(data, workflow.start, lastSaved);
+ //executeWorkflow(data, workflow.start, lastSaved);
setExecutionArgumentModalOpen(false)
}}
@@ -14759,6 +14776,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 +15128,9 @@ const AngularWorkflow = (defaultprops) => {
key={condition.condition.id}
square
style={paperVariableStyle}
- onClick={() => { }}
+ onClick={() => {
+ setLastSaved(false)
+ }}
>
{
return
}
+ setLastSaved(false)
setSourceValue({
name: "source",
value: "",
@@ -15384,17 +15405,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
@@ -19298,7 +19317,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);
@@ -20649,7 +20668,7 @@ const AngularWorkflow = (defaultprops) => {
}
const buttonHeights = 45
- const boxSize = buttonHeights
+ const boxSize = buttonHeights+2
const executionButton = executionRunning ? (
@@ -20737,20 +20756,17 @@ const AngularWorkflow = (defaultprops) => {
>
{
return (
-
+
{
onSelect={(select) => {
HandleJsonCopy(validate.result, select, "exec");
}}
- name={false}
+ name={"$exec"}
/>
)
@@ -21787,7 +21803,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 (
{
) : null}
+
{executionData.execution_source !== undefined &&
executionData.execution_source !== null &&
executionData.execution_source.length > 0 &&
@@ -22954,8 +22990,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) ?
{
HandleJsonCopy(showResult, select, data.action.label);
console.log("SELECTED!: ", select);
}}
- name={"Results for " + data.action.label}
+ name={`$${data?.action?.label?.toLowerCase()}`}
/>
diff --git a/frontend/src/views/AppCreator.jsx b/frontend/src/views/AppCreator.jsx
index d6317b3a..7a954ef2 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 : (process.env.IS_SSR === "true");
+ const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
useEffect(() => {
if (window.location.pathname.includes("apps/edit")) {
diff --git a/frontend/src/views/AppExplorer.jsx b/frontend/src/views/AppExplorer.jsx
index 1e23d70d..54537f7d 100644
--- a/frontend/src/views/AppExplorer.jsx
+++ b/frontend/src/views/AppExplorer.jsx
@@ -247,7 +247,7 @@ const buttonBackground = "linear-gradient(to right, #f86a3e, #f34079)";
read_time: 1,
})
- const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.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
diff --git a/frontend/src/views/Docs.jsx b/frontend/src/views/Docs.jsx
index f5b3bb82..ef933d16 100755
--- a/frontend/src/views/Docs.jsx
+++ b/frontend/src/views/Docs.jsx
@@ -62,7 +62,6 @@ const dividerColor = "rgb(225, 228, 232)";
const hrefStyle = {
color: "rgba(255, 255, 255, 0.8)",
textDecoration: "none",
- marginRight: window.location.pathname.includes("/articles/") ? "0.8em" : undefined,
};
@@ -387,6 +386,7 @@ export const CodeHandler = (props) => {
minWidth: "50%",
maxWidth: "100%",
backgroundColor: theme.palette.inputColor,
+ whiteSpace: "pre-wrap",
overflowY: "auto",
// Have it inline
borderRadius: theme.palette?.borderRadius,
@@ -1020,7 +1020,7 @@ const Docs = (defaultprops) => {
}
const fetchDocList = (resetCache = false) => {
- var url = `${globalUrl}/api/v1/docs`
+ var url = `${globalUrl}/api/v1/docs?resetCache=${resetCache}`
if (location.pathname.includes("/legal")) {
url = `${globalUrl}/api/v1/docs?folder=legal&resetCache=${resetCache}`
} else if (location.pathname.includes("/articles")) {
@@ -1047,16 +1047,16 @@ const Docs = (defaultprops) => {
.catch((error) => { });
};
- const fetchDoc = (docId) => {
+ const fetchDoc = (docId, resetCache = false) => {
if (docId === undefined) {
return
}
- var url = `${globalUrl}/api/v1/docs/${docId}`
+ var url = `${globalUrl}/api/v1/docs/${docId}?resetCache=${resetCache}`
if (location.pathname.includes("/legal")) {
- url = `${globalUrl}/api/v1/docs/${docId}?folder=legal`
+ url = `${globalUrl}/api/v1/docs/${docId}?folder=legal&resetCache=${resetCache}`
} else if (location.pathname.includes("/articles")) {
- url = `${globalUrl}/api/v1/docs/${docId}?folder=articles`
+ url = `${globalUrl}/api/v1/docs/${docId}?folder=articles&resetCache=${resetCache}`
}
fetch(url, {
@@ -1082,7 +1082,7 @@ const Docs = (defaultprops) => {
autoClose: 2000,
});
setTimeout(() => {
- navigate(`/articles/2.0_release`)
+ navigate(`/articles`)
}, 2000)
return
}
@@ -1130,7 +1130,8 @@ const Docs = (defaultprops) => {
const handleResetCache = () => {
fetchDocList(true);
- toast("Cache has been reset");
+ fetchDoc(props.match.params.key, true);
+ toast("Cache and list will be reset in a few seconds");
}
if (firstrequest) {
@@ -1344,6 +1345,21 @@ const Docs = (defaultprops) => {
tr: TableRowRenderer,
th: TableHeaderCellRenderer,
td: TableCellRenderer,
+ ul: ({ children }) => (
+
+ {children}
+
+ ),
+ ol: ({ children }) => (
+
+ {children}
+
+ ),
+ li: ({ children }) => (
+
+ {children}
+
+ ),
}
@@ -1355,7 +1371,6 @@ const Docs = (defaultprops) => {
const activeListItemStyle = {
backgroundColor: "rgba(248, 106, 62, 0.08)", // Slight orange tint
- marginRight: window.location.pathname.includes("/articles/") ? "0.8em" : undefined,
borderLeft: "3px solid #f86a3e",
paddingLeft: "13px", // Compensate for the border
};
@@ -1415,6 +1430,7 @@ const Docs = (defaultprops) => {
{
}
- {userdata?.support && isArticlePage && (
-
- Reset Cache
-
+
+ Reset Cache
+
+
)}
{tocLines.length > 0 ?
(
diff --git a/frontend/src/views/NewDashboard.jsx b/frontend/src/views/NewDashboard.jsx
index bb2add48..f4709a84 100644
--- a/frontend/src/views/NewDashboard.jsx
+++ b/frontend/src/views/NewDashboard.jsx
@@ -111,8 +111,8 @@ const NewDashboard = (props) => {
const STATIC_TIME_PERCENT = 'TBD'
const STATIC_MONEY_PERCENT = 'TBD'
const kpis = [
- { value: timeFmt.display, title: timeFmt.title, label: 'Time saved', icon:
, percentage: STATIC_TIME_PERCENT, color: '#5cc879', disabled: true},
- { value: formatCurrencyCompact(totals.moneySavedDollars), label: 'Money saved', icon:
, percentage: STATIC_MONEY_PERCENT, color: '#5cc879', disabled: true, },
+ //{ value: timeFmt.display, title: timeFmt.title, label: 'Time saved', icon:
, percentage: STATIC_TIME_PERCENT, color: '#5cc879', disabled: true},
+ //{ value: formatCurrencyCompact(totals.moneySavedDollars), label: 'Money saved', icon:
, percentage: STATIC_MONEY_PERCENT, color: '#5cc879', disabled: true, },
{ value: String(unreadCount), label: 'Total errors', icon:
, percentage: "", color: '#f87171' },
{ value: String(readCount), label: 'Errors resolved', icon:
, percentage: "", color: '#5cc879' },
];
@@ -133,12 +133,12 @@ const NewDashboard = (props) => {
useEffect(() => {
const anyLoading =
- loadingSfw ||
- loadingRot ||
+ //loadingSfw ||
+ //loadingRot ||
loadingNoti ||
- loadingSelectedOrgStats ||
+ loadingSelectedOrgStats //||
!selectedOrganization ||
- !selectedOrgForStats;
+ //!selectedOrgForStats;
setShowOverlay(anyLoading);
}, [
loadingSfw,
@@ -399,6 +399,7 @@ const NewDashboard = (props) => {
headerSubtitle="Complete these steps to start seeing insights."
/>
)}
+
{showOverlay && (
@@ -407,6 +408,7 @@ const NewDashboard = (props) => {
)}
+
{/* Header / Greeting */}
{`${getGreeting()}, ${displayName ?? 'User'}!`}
diff --git a/frontend/src/views/UpdateAuthentication.jsx b/frontend/src/views/UpdateAuthentication.jsx
index b55d844b..9f4702ea 100644
--- a/frontend/src/views/UpdateAuthentication.jsx
+++ b/frontend/src/views/UpdateAuthentication.jsx
@@ -25,7 +25,7 @@ const SetAuthentication = (props) => {
const [loadFail, setLoadFail] = useState("");
const [appAuthentication, setAppAuthentication] = React.useState([]);
- const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.IS_SSR === "true");
+ const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
//const alert = useAlert();
const parseIncomingOpenapiData = (data) => {
diff --git a/frontend/src/views/Welcome.jsx b/frontend/src/views/Welcome.jsx
index cb5c24c5..169c58b1 100644
--- a/frontend/src/views/Welcome.jsx
+++ b/frontend/src/views/Welcome.jsx
@@ -47,7 +47,7 @@ const Welcome = (props) => {
}
}, [activeStep])
- const isCloud = (window.location.host === "localhost:3002" || window.location.host === "shuffler.io") ? true : (process.env.IS_SSR === "true");
+ const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
const [steps, setSteps] = useState([
"Help us get to know you",
"Find your Apps",
diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx
index f94b38b5..1cd1cfd3 100644
--- a/frontend/src/views/Workflows2.jsx
+++ b/frontend/src/views/Workflows2.jsx
@@ -343,7 +343,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 = ""
@@ -3346,7 +3346,7 @@ const Workflows2 = (props) => {
}
style={{
textDecoration: "none",
- color: "inherit",
+ color: theme.palette.text.primary,
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
@@ -5149,7 +5149,7 @@ const Workflows2 = (props) => {
{backgroundWorkflows.length > 0 &&