Added json changes and local storage

This commit is contained in:
Frikky
2024-05-17 00:59:28 +02:00
parent e364099ac1
commit 5f8f5ab224
12 changed files with 336 additions and 112 deletions
+1 -1
View File
@@ -660,7 +660,7 @@ class AppBase:
break
else:
# FIXME: Add a checker for 403, and Proxy logs failing
self.logger.info(f"[ERROR] Bad resp {ret.status_code} for url {url}")
self.logger.info(f"[ERROR] Bad resp ({ret.status_code}) in send_result for url '{url}'")
time.sleep(sleeptime)
+8 -1
View File
@@ -203,6 +203,11 @@ const Header = (props) => {
window.location.pathname = "/";
localStorage.setItem("globalUrl", "")
// Delete userinfo from localstorage
localStorage.removeItem("apps")
localStorage.removeItem("workflows")
localStorage.removeItem("userinfo")
})
.catch((error) => {
console.log(error);
@@ -476,7 +481,9 @@ const Header = (props) => {
if (response.status !== 200) {
console.log("Error in response");
} else {
localStorage.setItem("apps", [])
localStorage.removeItem("apps")
localStorage.removeItem("workflows")
localStorage.removeItem("userinfo")
}
return response.json();
+2 -4
View File
@@ -70,8 +70,6 @@ const registeredApps = [
"microsoft_teams",
"microsoft_teams_user_access",
"todoist",
"microsoft_sentinel",
"microsoft_365_defender",
"google_chat",
"google_sheets",
"google_drive",
@@ -711,7 +709,7 @@ const AuthenticationOauth2 = (props) => {
</DialogTitle>
<DialogContent>
<span style={{}}>
Oauth2 requires a client ID and secret to authenticate, defined in the remote system. Your redirect URL is <b>{window.location.origin}/set_authentication</b>&nbsp;-&nbsp;
Oauth2 requires a client ID and secret to authenticate, defined in the remote system. {authenticationType.type === "oauth2-app" ? null : <span>Your redirect URL is <b>{window.location.origin}/set_authentication</b>&nbsp;-&nbsp;</span>}
<a
target="_blank"
rel="norefferer"
@@ -808,7 +806,7 @@ const AuthenticationOauth2 = (props) => {
const fieldname = data.name === "url" && authenticationType.grant_type !== undefined && authenticationType.grant_type !== null && authenticationType.grant_type.length > 0 && authenticationType.type === "oauth2-app" ? "Token URL" : data.name
return (
<div key={index} style={{ marginTop: 0, }}>
<div key={index} style={{ marginTop: authenticationType.type === "oauth2-app" ? 10 : 0, }}>
<LockOpenIcon style={{ marginRight: 10 }} />
<b>{fieldname}</b>
-1
View File
@@ -3552,7 +3552,6 @@ const ParsedAction = (props) => {
fullWidth
variant="contained"
onClick={() => {
console.log(authenticationType);
//if (authenticationType.type === "oauth2" && authenticationType.redirect_uri !== undefined && authenticationType.redirect_uri !== null) {
// return null
//}
+10 -1
View File
@@ -26,7 +26,16 @@ const theme = createTheme(adaptV4Theme({
green: "#5cc879",
borderRadius: 10,
defaultBorder: "1px solid rgba(255,255,255,0.3)",
jsonTheme: "brewer",
//jsonTheme: "brewer",
//jsonTheme: "chalk",
//jsonTheme: "monokai",
//jsonTheme: "google",
//jsonTheme: "tomorrow",
jsonIconStyle: "round",
jsonTheme: "summerfruit",
jsonCollapseStringsAfterLength: 75,
reactJsonStyle: {
padding: 5,
width: "98%",
+3 -1
View File
@@ -1609,7 +1609,9 @@ If you're interested, please let me know a time that works for you, or set up a
if (response.status !== 200) {
console.log("Error in response");
} else {
localStorage.setItem("apps", [])
localStorage.removeItem("apps")
localStorage.removeItem("workflows")
localStorage.removeItem("userinfo")
}
return response.json();
+87 -12
View File
@@ -655,6 +655,48 @@ const AngularWorkflow = (defaultprops) => {
// Handle the activation case, as they are NOT in the event management system yet
if (selectedApp.actions === undefined || selectedApp.actions === null || selectedApp.actions.length > 1) {
return
} else {
if (selectedApp.id !== undefined && selectedApp.id !== null && selectedApp.id.length > 0) {
const appUrl = `${globalUrl}/api/v1/apps/${selectedApp.id}/config?openapi=false`
fetch(appUrl, {
headers: {
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
return response.json()
})
.then((responseJson) => {
if (responseJson.success === true && responseJson.app !== undefined && responseJson.app !== null && responseJson.app.length > 0) {
// Base64 decode into json
const foundapp = JSON.parse(atob(responseJson.app))
if (foundapp.actions !== undefined && foundapp.actions !== null && foundapp.actions.length > selectedApp.actions.length) {
setSelectedApp(foundapp)
for (var i = 0; i < apps.length; i++) {
if (apps[i].id !== foundapp.id) {
continue
}
apps[i] = foundapp
setApps(apps)
setFilteredApps(apps)
// Update the local storage
localStorage.setItem("apps", JSON.stringify(apps))
break
}
}
// FIXME: Add it to the existing list AND update the selected app
}
})
.catch((error) => {
console.log(`Failed side-loading app ${selectedApp.name}`)
})
}
}
for (let appkey in apps) {
@@ -2198,7 +2240,9 @@ const AngularWorkflow = (defaultprops) => {
return
}
return response.json();
console.log("Apps loaded. JSON decoding next")
return response.json()
})
.then((responseJson) => {
if (responseJson === null) {
@@ -4178,14 +4222,18 @@ const AngularWorkflow = (defaultprops) => {
// Check local storage has it
const foundapps = localStorage.getItem("apps")
if (foundapps !== null && foundapps !== undefined) {
const parsedapps = JSON.parse(foundapps)
if (parsedapps !== null && parsedapps !== undefined && parsedapps.length > 0) {
for (let appkey in parsedapps) {
if (parsedapps[appkey].name === curaction.app_name) {
curapp = parsedapps[appkey]
break
try {
const parsedapps = JSON.parse(foundapps)
if (parsedapps !== null && parsedapps !== undefined && parsedapps.length > 0) {
for (let appkey in parsedapps) {
if (parsedapps[appkey].name === curaction.app_name) {
curapp = parsedapps[appkey]
break
}
}
}
} catch (e) {
console.log("Problem with parsing apps from local storage", e)
}
} else {
@@ -4193,6 +4241,12 @@ const AngularWorkflow = (defaultprops) => {
}
}
/*
if (curapp && curapp.app_id !== undefined && curapp.app_id !== null && curapp.app_id.length > 0 &&curapp.actions.length <= 1) {
toast(`Side-loading app ${curapp.name} to get actions.`)
}
*/
if (!curapp || curapp === undefined) {
const tmpapp = {
name: curaction.app_name,
@@ -4205,6 +4259,7 @@ const AngularWorkflow = (defaultprops) => {
setSelectedApp(tmpapp)
setSelectedAction(curaction)
} else {
curaction.app_id = curapp.id
setAuthenticationType(
@@ -6810,7 +6865,7 @@ const AngularWorkflow = (defaultprops) => {
}
console.log("Setupgraph done 2!")
};
}
const removeNode = (nodeId) => {
const selectedNode = cy.getElementById(nodeId);
@@ -8082,10 +8137,17 @@ const AngularWorkflow = (defaultprops) => {
return;
}
if (app.actions === undefined || app.actions === null) {
app.actions = []
}
/*
if (app.actions === undefined || app.actions === null || app.actions.length === 0) {
toast("App " + app.name + " currently has no actions to perform. Please go to https://shuffler.io/apps to edit it.")
return
}
*/
newNodeId = uuidv4();
const actionType = "ACTION";
@@ -8610,8 +8672,6 @@ const AngularWorkflow = (defaultprops) => {
</ListItem>
:
hits.map((hit, index) => {
console.log("HIT: ", hit)
const innerlistitemStyle = {
width: positionInfo.width + 35,
overflowX: "hidden",
@@ -15728,6 +15788,9 @@ const AngularWorkflow = (defaultprops) => {
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={true}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
displayArrayKey={false}
enableClipboard={(copy) => {
handleReactJsonClipboard(copy);
}}
@@ -15735,7 +15798,7 @@ const AngularWorkflow = (defaultprops) => {
onSelect={(select) => {
HandleJsonCopy(validate.result, select, "exec");
}}
name={"Execution Argument"}
name={false}
/>
</div>
)
@@ -16034,6 +16097,9 @@ const AngularWorkflow = (defaultprops) => {
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={parsedCollapse}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
displayArrayKey={false}
shouldCollapse={(field) => {
console.log("FIELD: ", field)
}}
@@ -17134,6 +17200,9 @@ const AngularWorkflow = (defaultprops) => {
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={true}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
displayArrayKey={false}
enableClipboard={(copy) => {
handleReactJsonClipboard(copy);
}}
@@ -17263,6 +17332,9 @@ const AngularWorkflow = (defaultprops) => {
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={data.value.length < 10000 ? false : true}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
displayArrayKey={false}
displayDataTypes={false}
name={"Parsed data for variable " + data.name}
/>
@@ -17371,7 +17443,7 @@ const AngularWorkflow = (defaultprops) => {
return "The app's Docker Image is not available in the environment yet. Re-run the app to force a re-download of the app. If the problem persists, contact support"
}
if (result.status !== 200 && (result.url.includes("192.168") || result.url.includes("172.16") || result.url.includes("10.0"))) {
if (result.status !== 200 && result.url !== undefined && result.url !== null && (result.url.includes("192.168") || result.url.includes("172.16") || result.url.includes("10.0"))) {
return "Consider whether your Orborus environment can connect to a local IP or not."
}
@@ -17648,6 +17720,9 @@ const AngularWorkflow = (defaultprops) => {
theme={theme.palette.jsonTheme}
style={theme.palette.reactJsonStyle}
collapsed={selectedResult.result.length < 10000 ? false : true}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
displayArrayKey={false}
enableClipboard={(copy) => {
handleReactJsonClipboard(copy);
}}
+10 -9
View File
@@ -2994,15 +2994,15 @@ const AppCreator = (defaultprops) => {
toast("Auth URL must start with http(s)://");
}
if (tmpstring.includes("?")) {
var newtmp = tmpstring.split("?")
if (tmpstring.length > 1) {
tmpstring = newtmp[0]
}
}
if (tmpstring.includes("?")) {
var newtmp = tmpstring.split("?")
if (tmpstring.length > 1) {
tmpstring = newtmp[0]
}
}
setParameterName(tmpstring)
}}
setParameterName(tmpstring)
}}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
@@ -6054,10 +6054,11 @@ const AppCreator = (defaultprops) => {
<Select
fullWidth
onChange={(e) => {
setOauth2Type(e.target.value);
setOauth2Type(e.target.value)
if (e.target.value === "application" && oauth2GrantType === "") {
setOauth2GrantType("client_credentials")
setParameterName("")
}
if (e.target.value === "delegated") {
+26 -2
View File
@@ -426,6 +426,22 @@ const Apps = (props) => {
};
const getApps = () => {
// Get apps from localstorage
var storageApps = []
try {
const appstorage = localStorage.getItem("apps")
storageApps = JSON.parse(appstorage)
if (storageApps === null || storageApps === undefined || storageApps.length === 0) {
storageApps = []
} else {
setApps(storageApps)
setFilteredApps(storageApps)
setAppSearchLoading(false)
}
} catch (e) {
//console.log("Failed to get apps from localstorage: ", e)
}
fetch(globalUrl + "/api/v1/apps", {
method: "GET",
headers: {
@@ -447,7 +463,6 @@ const Apps = (props) => {
return response.json();
})
.then((responseJson) => {
console.log("Apps: ", responseJson)
//responseJson = sortByKey(responseJson, "large_image")
//responseJson = sortByKey(responseJson, "is_valid")
//setFilteredApps(responseJson.filter(app => !internalIds.includes(app.name) && !(!app.activated && app.generated)))
@@ -505,6 +520,14 @@ const Apps = (props) => {
}
}
if (privateapps.length > 0 && storageApps.length === 0) {
try {
localStorage.setItem("apps", JSON.stringify(privateapps))
} catch (e) {
console.log("Failed to set apps in localstorage: ", e)
}
}
//setTimeout(() => {
// setFirstLoad(false)
//}, 5000)
@@ -2420,8 +2443,9 @@ const Apps = (props) => {
) {
setSelectedAction(responseJson.actions[0]);
} else {
setSelectedAction({});
setSelectedAction({})
}
setSelectedApp(responseJson);
setSharingConfiguration(responseJson.sharing === true ? "public" : "you")
}
+5 -2
View File
@@ -1,4 +1,4 @@
import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
import React, { useEffect, useLayoutEffect, useRef, useState } from "react"
import { toast } from 'react-toastify';
import Markdown from 'react-markdown'
@@ -178,7 +178,10 @@ export const CodeHandler = (props) => {
style={theme.palette.reactJsonStyle}
collapsed={false}
displayDataTypes={false}
name={""}
displayArrayKey={false}
iconStyle={theme.palette.jsonIconStyle}
collapseStringsAfterLength={theme.palette.jsonCollapseStringsAfterLength}
name={false}
/>
:
<div style={{ display: "flex", position: "relative", }}>
+8 -2
View File
@@ -1156,8 +1156,8 @@ const Dashboard = (props) => {
const [selectedUsecaseCategory, setSelectedUsecaseCategory] = useState("");
const [selectedUsecases, setSelectedUsecases] = useState([]);
const [usecases, setUsecases] = useState([]);
const [workflows, setWorkflows] = useState([]);
const [usecases, setUsecases] = useState([])
const [workflows, setWorkflows] = useState([])
const [frameworkData, setFrameworkData] = useState(undefined);
let navigate = useNavigate();
@@ -1359,6 +1359,8 @@ const Dashboard = (props) => {
return
}
console.log("LOADED: ", responseJson)
if (workflows !== undefined && workflows !== null && workflows.length > 0) {
var categorydata = responseJson
var newcategories = []
@@ -1408,6 +1410,10 @@ const Dashboard = (props) => {
setUsecases(responseJson)
setSelectedUsecases(responseJson)
}
} else {
handleKeysetting(responseJson)
setUsecases(responseJson)
setSelectedUsecases(responseJson)
}
})
.catch((error) => {
+176 -76
View File
@@ -601,7 +601,7 @@ const Workflows = (props) => {
const [view, setView] = React.useState("grid");
const [filters, setFilters] = React.useState([]);
const [submitLoading, setSubmitLoading] = React.useState(false);
const [actionImageList, setActionImageList] = React.useState([]);
const [actionImageList, setActionImageList] = React.useState([{"large_image": ""}])
const [firstLoad, setFirstLoad] = React.useState(true);
const [showMoreClicked, setShowMoreClicked] = React.useState(false);
@@ -752,6 +752,14 @@ const Workflows = (props) => {
};
const getApps = () => {
try {
const appstorage = localStorage.getItem("apps")
const privateapps = JSON.parse(appstorage)
setApps(privateapps)
} catch (e) {
//console.log("Failed to get apps from localstorage: ", e)
}
fetch(`${globalUrl}/api/v1/apps`, {
method: "GET",
headers: {
@@ -1106,6 +1114,22 @@ const Workflows = (props) => {
}
const getAvailableWorkflows = () => {
var storageWorkflows = []
try {
const storagewf = localStorage.getItem("workflows")
storageWorkflows = JSON.parse(storagewf)
if (storageWorkflows === null || storageWorkflows === undefined || storageWorkflows.length === 0) {
storageWorkflows = []
} else {
setWorkflows(storageWorkflows)
setFilteredWorkflows(storageWorkflows)
fetchUsecases(storageWorkflows)
setWorkflowDone(true)
}
} catch (e) {
//console.log("Failed to get workflows from localstorage: ", e)
}
fetch(globalUrl + "/api/v1/workflows", {
method: "GET",
headers: {
@@ -1123,65 +1147,71 @@ const Workflows = (props) => {
//}
toast("Failed getting workflows. Are you logged in?");
return;
return
}
return response.json();
})
.then((responseJson) => {
if (responseJson !== undefined) {
var newarray = []
for (var key in responseJson) {
const wf = responseJson[key]
if (wf.public === true) {
continue
}
var newarray = []
for (var key in responseJson) {
const wf = responseJson[key]
if (wf.public === true) {
continue
}
newarray.push(wf)
}
var setProdFilter = false
newarray.push(wf)
}
var setProdFilter = false
var actionnamelist = [];
var parsedactionlist = [];
for (var key in newarray) {
const workflow = newarray[key]
if (workflow.status === "production") {
setProdFilter = true
}
var actionnamelist = [];
var parsedactionlist = [];
for (var key in newarray) {
const workflow = newarray[key]
if (workflow.status === "production") {
setProdFilter = true
}
for (var actionkey in newarray[key].actions) {
const action = newarray[key].actions[actionkey];
//console.log("Action: ", action)
if (actionnamelist.includes(action.app_name)) {
continue;
}
actionnamelist.push(action.app_name);
parsedactionlist.push(action);
}
for (var actionkey in newarray[key].actions) {
const action = newarray[key].actions[actionkey];
//console.log("Action: ", action)
if (actionnamelist.includes(action.app_name)) {
continue;
}
//console.log(parsedactionlist)
setActionImageList(parsedactionlist);
actionnamelist.push(action.app_name);
parsedactionlist.push(action);
}
}
if (setProdFilter === true) {
const newWorkflows = newarray.filter(workflow => workflow.status === "production")
if (newWorkflows !== undefined && newWorkflows !== null) {
setFilteredWorkflows(newWorkflows);
} else {
setFilteredWorkflows(newarray);
}
setFilters(["status:production"]);
} else {
setFilteredWorkflows(newarray);
}
if (newarray.length > 0 && storageWorkflows.length <= newarray.length) {
try {
localStorage.setItem("workflows", JSON.stringify(newarray))
} catch (e) {
console.log("Failed to set workflows in localstorage: ", e)
}
}
// Ensures the zooming happens only once per load
// Ensures the zooming happens only once per load
setTimeout(() => {
fetchUsecases(newarray)
setActionImageList(parsedactionlist);
if (setProdFilter === true) {
const newWorkflows = newarray.filter(workflow => workflow.status === "production")
if (newWorkflows !== undefined && newWorkflows !== null) {
setFilteredWorkflows(newWorkflows);
} else {
setFilteredWorkflows(newarray);
}
setFilters(["status:production"]);
} else {
setFilteredWorkflows(newarray)
}
setFirstLoad(false)
}, 100)
@@ -1265,13 +1295,13 @@ const Workflows = (props) => {
return response.json();
})
.then((responseJson) => {
setWorkflows(workflows);
setWorkflowDone(true);
setWorkflows(workflows);
setWorkflowDone(true);
if (responseJson.success !== false) {
setAllUsecases(responseJson);
handleKeysetting(responseJson, workflows)
}
if (responseJson.success !== false) {
setAllUsecases(responseJson);
handleKeysetting(responseJson, workflows)
}
})
.catch((error) => {
//toast("ERROR: " + error.toString());
@@ -1637,8 +1667,76 @@ const Workflows = (props) => {
})
.catch((error) => {
toast(error.toString());
});
};
})
}
const setEditing = (data) => {
ReactDOM.unstable_batchedUpdates(() => {
setIsEditing(true)
setModalOpen(true);
setNewWorkflowName(data.name);
setNewWorkflowDescription(data.description);
setDefaultReturnValue(data.default_return_value);
if (data.tags !== undefined && data.tags !== null) {
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)));
}
if (data.usecase_ids !== undefined && data.usecase_ids !== null && data.usecase_ids.length > 0) {
setSelectedUsecases(data.usecase_ids)
}
setEditingWorkflow(JSON.parse(JSON.stringify(data)))
})
}
const sideloadWorkflow = (id, openEdit) => {
const storagewf = localStorage.getItem("workflows")
const storageWorkflows = JSON.parse(storagewf)
if (storageWorkflows === null || storageWorkflows === undefined || storageWorkflows.length === 0) {
} else {
for (var i = 0; i < storageWorkflows.length; i++) {
if (storageWorkflows[i].id === id) {
if (storageWorkflows[i].image !== "") {
return
}
}
}
}
fetch(globalUrl + "/api/v1/workflows/" + id, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
}
return response.json()
})
.then((responseJson) => {
if (openEdit) {
setEditing(responseJson)
}
for (var i = 0; i < storageWorkflows.length; i++) {
if (storageWorkflows[i].id === id) {
storageWorkflows[i] = responseJson
localStorage.setItem("workflows", JSON.stringify(storageWorkflows))
break
}
}
setWorkflows(storageWorkflows)
//setFilteredWorkflows(storageWorkflows)
})
.catch((error) => {
console.log(error.toString())
})
}
const deleteWorkflow = (id) => {
fetch(globalUrl + "/api/v1/workflows/" + id, {
@@ -1666,8 +1764,8 @@ const Workflows = (props) => {
})
.catch((error) => {
toast(error.toString());
});
};
})
}
const handleChipClick = (e) => {
addFilter(e.target.innerHTML);
@@ -1796,21 +1894,13 @@ const Workflows = (props) => {
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
onClick={(event) => {
event.stopPropagation()
ReactDOM.unstable_batchedUpdates(() => {
setIsEditing(true)
setModalOpen(true);
setEditingWorkflow(JSON.parse(JSON.stringify(data)));
setNewWorkflowName(data.name);
setNewWorkflowDescription(data.description);
setDefaultReturnValue(data.default_return_value);
if (data.tags !== undefined && data.tags !== null) {
setNewWorkflowTags(JSON.parse(JSON.stringify(data.tags)));
}
if (data.actions !== undefined && data.actions !== null && data.actions.length > 0 && data.image !== "") {
setEditing(data)
if (data.usecase_ids !== undefined && data.usecase_ids !== null && data.usecase_ids.length > 0) {
setSelectedUsecases(data.usecase_ids)
}
})
} else {
//toast("Need to side-load workflow to be edited properly")
sideloadWorkflow(data.id, true)
}
}}
key={"change"}
>
@@ -1986,7 +2076,7 @@ const Workflows = (props) => {
}
return (
<div style={{width: "100%", position: "relative", border: isDistributed ? "2px solid #40E0D0" : "inherit", borderRadius: theme.palette.borderRadius, }}>
<div style={{width: "100%", minWidth: 321, position: "relative", border: isDistributed ? "2px solid #40E0D0" : "inherit", borderRadius: theme.palette.borderRadius, }}>
<Paper square style={paperAppStyle}>
{selectedCategory !== "" ?
<Tooltip title={`Usecase Category: ${selectedCategory}`} placement="bottom">
@@ -1997,7 +2087,7 @@ const Workflows = (props) => {
top: 0,
left: 0,
height: paperAppStyle.minHeight,
width: 2,
width: 3,
backgroundColor: boxColor,
borderRadius: "0 100px 0 0",
}}
@@ -2022,7 +2112,16 @@ const Workflows = (props) => {
{image}
</div>
</Tooltip>
<Tooltip arrow title={
<Tooltip arrow
onMouseEnter={() => {
/*
if (data.image === undefined || data.image === null || data.image === "" && !loadingWorkflows.includes(data.id)) {
sideloadWorkflow(data.id, false)
loadingWorkflows.push(data.id)
}
*/
}}
title={
<div style={{width: "100%", minWidth: 250, maxWidth: 310, }}>
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
<img src={data.image} alt={data.name} style={{backgroundColor: theme.palette.surfaceColor, maxWidth: 300, minWidth: 250, borderRadius: theme.palette.borderRadius, }} />
@@ -3180,6 +3279,7 @@ const Workflows = (props) => {
<Button
color="secondary"
style={{}}
disabled={true}
variant="text"
onClick={() => {
exportAllWorkflows(workflows);
@@ -3418,9 +3518,9 @@ const Workflows = (props) => {
<div style={{ marginTop: 10, marginBottom: 10, }} />
{!isMobile &&
actionImageList !== undefined &&
actionImageList !== null &&
actionImageList.length > 0 ? (
actionImageList !== undefined &&
actionImageList !== null &&
actionImageList.length > 0 ? (
<div
style={{
display: "flex",