Fixed usecase linking and added basic priorities to start making a priority system

This commit is contained in:
frikky
2022-05-21 14:31:43 +02:00
parent 2167be32f5
commit 7e42553fee
10 changed files with 413 additions and 86 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ module main
go 1.16 go 1.16
//replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared replace github.com/shuffle/shuffle-shared => ../../../shuffle-shared
//replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi //replace github.com/frikky/kin-openapi => ../../../../git/kin-openapi
//replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch //replace github.com/frikky/go-elasticsearch => ../../../../git/go-elasticsearch
+15
View File
@@ -1038,6 +1038,18 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
chatDisabled = true chatDisabled = true
} }
orgPriorities := org.Priorities
if len(org.Priorities) < 5 {
log.Printf("[WARNING] Should find and add priorities as length is less than 5 for org %s", userInfo.ActiveOrg.Id)
newPriorities, err := shuffle.GetPriorities(ctx, org)
if err != nil {
log.Printf("[WARNING] Failed getting new priorities for org %s: %s", org.Id, err)
//orgPriorities = []shuffle.Priority{}
} else {
orgPriorities = newPriorities
}
}
tutorialsFinished := []string{} tutorialsFinished := []string{}
returnValue := shuffle.HandleInfo{ returnValue := shuffle.HandleInfo{
Success: true, Success: true,
@@ -1056,6 +1068,7 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) {
EthInfo: userInfo.EthInfo, EthInfo: userInfo.EthInfo,
Tutorials: tutorialsFinished, Tutorials: tutorialsFinished,
ChatDisabled: chatDisabled, ChatDisabled: chatDisabled,
Priorities: orgPriorities,
} }
returnData, err := json.Marshal(returnValue) returnData, err := json.Marshal(returnValue)
@@ -5966,7 +5979,9 @@ func initHandlers() {
r.HandleFunc("/api/v1/workflows/collections/{key}", shuffle.HandleGetCollection).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows/collections/{key}", shuffle.HandleGetCollection).Methods("GET", "OPTIONS")
// Related to use-cases that are not directly workflows. // Related to use-cases that are not directly workflows.
r.HandleFunc("/api/v1/workflows/usecases/{key}", shuffle.HandleGetUsecase).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/usecases", shuffle.LoadUsecases).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/workflows/usecases", shuffle.LoadUsecases).Methods("GET", "OPTIONS")
r.HandleFunc("/api/v1/workflows/usecases", shuffle.UpdateUsecases).Methods("POST", "OPTIONS")
// Legacy app things // Legacy app things
r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS")
+2 -1
View File
@@ -2051,8 +2051,9 @@ func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string,
workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 1000, 0) workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 1000, 0)
appCounter := 0 appCounter := 0
if err != nil { if err != nil {
log.Printf("Failed to get existing generated apps") log.Printf("[WARNING] Failed to get existing generated apps for OpenAPI verification: %s", err)
} }
for _, file := range dir { for _, file := range dir {
if len(onlyname) > 0 && file.Name() != onlyname { if len(onlyname) > 0 && file.Name() != onlyname {
continue continue
+2 -5
View File
@@ -64,11 +64,7 @@ const App = (message, props) => {
const [isLoggedIn, setIsLoggedIn] = useState(false) const [isLoggedIn, setIsLoggedIn] = useState(false)
const [dataset, setDataset] = useState(false) const [dataset, setDataset] = useState(false)
const [isLoaded, setIsLoaded] = useState(false) const [isLoaded, setIsLoaded] = useState(false)
const [curpath, setCurpath] = useState( const [curpath, setCurpath] = useState(typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname)
typeof window === "undefined" || window.location === undefined
? ""
: window.location.pathname
)
useEffect(() => { useEffect(() => {
@@ -303,6 +299,7 @@ const App = (message, props) => {
> >
<ScrollToTop <ScrollToTop
getUserNotifications={getUserNotifications} getUserNotifications={getUserNotifications}
curpath={curpath}
setCurpath={setCurpath} setCurpath={setCurpath}
/> />
{!isLoaded ? null : {!isLoaded ? null :
@@ -924,10 +924,7 @@ const Framework = (props) => {
const shiftmodifier = 3*scale const shiftmodifier = 3*scale
//const svgSize = `${40*scale}px` //const svgSize = `${40*scale}px`
const svgSize = `${40}px` const svgSize = `${40}px`
console.log("Size: ", svgSize)
console.log("Framework: ", parsedFrameworkData)
const fontSize = `${12*scale}px` const fontSize = `${12*scale}px`
const defaultSize = `${85*scale}px` const defaultSize = `${85*scale}px`
const iconSize = `${45*scale}px` const iconSize = `${45*scale}px`
@@ -1265,14 +1262,11 @@ const Framework = (props) => {
changeUsecase(selectedUsecase, usecaseType) changeUsecase(selectedUsecase, usecaseType)
if (inputUsecase !== undefined && inputUsecase !== null) { if (inputUsecase !== undefined && inputUsecase !== null) {
console.log("Got usecase: ", inputUsecase)
for (var key in inputUsecase.process) { for (var key in inputUsecase.process) {
if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") { if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") {
continue continue
} }
console.log("Edge: ", inputUsecase.process[key])
inputUsecase.process[key].label = parseInt(key)+1 inputUsecase.process[key].label = parseInt(key)+1
inputUsecase.process[key].id = uuidv4(); inputUsecase.process[key].id = uuidv4();
+7
View File
@@ -183,6 +183,13 @@ const ParsedAction = (props) => {
const [fieldCount, setFieldCount] = React.useState(0); const [fieldCount, setFieldCount] = React.useState(0);
const [hiddenDescription, setHiddenDescription] = React.useState(true); const [hiddenDescription, setHiddenDescription] = React.useState(true);
useEffect(() => {
if (setLastSaved !== undefined) {
setLastSaved(false)
}
}, [expansionModalOpen])
useEffect(() => { useEffect(() => {
if (selectedAction.parameters !== null && selectedAction.parameters !== undefined) { if (selectedAction.parameters !== null && selectedAction.parameters !== undefined) {
const paramcheck = selectedAction.parameters.find(param => param.name === "body") const paramcheck = selectedAction.parameters.find(param => param.name === "body")
+16 -13
View File
@@ -2,23 +2,26 @@ import { useEffect } from "react";
//import { withRouter } from "react-router-dom"; //import { withRouter } from "react-router-dom";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
function ScrollToTop({ getUserNotifications, setCurpath, history }) { // ensures scrolling happens in the right way on different pages and when changing
function ScrollToTop({ getUserNotifications, curpath, setCurpath, history }) {
let location = useLocation(); let location = useLocation();
useEffect(() => { useEffect(() => {
//const unlisten = history.listen(() => { // Custom handler for certain scroll mechanics
window.scroll({ //
top: 0, console.log("OLD: ", curpath, "NeW: ", window.location.pathname)
left: 0, if (curpath === window.location.pathname && curpath === "/usecases") {
behavior: "smooth", } else {
});
setCurpath(window.location.pathname); window.scroll({
getUserNotifications(); top: 0,
//}); left: 0,
//return () => { behavior: "smooth",
// unlisten(); });
//};
setCurpath(window.location.pathname);
getUserNotifications();
}
}, [location]); }, [location]);
return null; return null;
+20 -13
View File
@@ -166,7 +166,7 @@ export function sortByKey(array, key) {
}); });
} }
function removeParam(key, sourceURL) { export function removeParam(key, sourceURL) {
if (sourceURL === undefined) { if (sourceURL === undefined) {
return; return;
} }
@@ -1611,10 +1611,6 @@ const AngularWorkflow = (defaultprops) => {
} }
const getWorkflow = (workflow_id, sourcenode) => { const getWorkflow = (workflow_id, sourcenode) => {
console.log(
//`Getting workflow ${workflow_id} with append value ${sourcenode}`
);
fetch(globalUrl + "/api/v1/workflows/" + workflow_id, { fetch(globalUrl + "/api/v1/workflows/" + workflow_id, {
method: "GET", method: "GET",
headers: { headers: {
@@ -1716,6 +1712,11 @@ const AngularWorkflow = (defaultprops) => {
nodefound = true; nodefound = true;
} }
if (responseJson.public) {
node.data.is_valid = true
node.is_valid = true
}
var example = ""; var example = "";
if ( if (
action.example !== undefined && action.example !== undefined &&
@@ -1757,6 +1758,7 @@ const AngularWorkflow = (defaultprops) => {
return null; return null;
} }
edge.data = { edge.data = {
id: branch.id, id: branch.id,
_id: branch.id, _id: branch.id,
@@ -1769,6 +1771,11 @@ const AngularWorkflow = (defaultprops) => {
source_workflow: responseJson.id, source_workflow: responseJson.id,
}; };
if (responseJson.public) {
edge.data.is_valid = true
edge.is_valid = true
}
return edge; return edge;
}); });
@@ -4124,6 +4131,11 @@ const AngularWorkflow = (defaultprops) => {
node.data.type = "ACTION"; node.data.type = "ACTION";
node.isStartNode = action["id"] === workflow.start; node.isStartNode = action["id"] === workflow.start;
if (workflow.public === true) {
node.data.is_valid = true
node.is_valid = true
}
var example = ""; var example = "";
if ( if (
action.example !== undefined && action.example !== undefined &&
@@ -4431,14 +4443,8 @@ const AngularWorkflow = (defaultprops) => {
} else if ( } else if (
// 2nd load - configures cytoscape // 2nd load - configures cytoscape
// //
!established && !established && cy !== undefined &&
cy !== undefined && ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && authLoaded) {
((apps !== null &&
apps !== undefined &&
apps.length > 0) || workflow.public === true) &&
Object.getOwnPropertyNames(workflow).length > 0 &&
authLoaded
) {
console.log("In POST graph setup!") console.log("In POST graph setup!")
//This part has to load LAST, as it's kind of not async. //This part has to load LAST, as it's kind of not async.
@@ -10824,6 +10830,7 @@ const AngularWorkflow = (defaultprops) => {
x: 300, x: 300,
y: 300, y: 300,
}; };
cy.add({ cy.add({
group: "nodes", group: "nodes",
data: { data: {
+348 -45
View File
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useInterval } from "react-powerhooks"; import { useInterval } from "react-powerhooks";
import DetectionFramework from "../components/DetectionFramework.jsx"; import DetectionFramework from "../components/DetectionFramework.jsx";
import { makeStyles, useTheme } from "@material-ui/core/styles";
// nodejs library that concatenates classes // nodejs library that concatenates classes
import classNames from "classnames"; import classNames from "classnames";
import theme from '../theme'; import theme from '../theme';
@@ -9,6 +10,7 @@ import { useNavigate, Link, useParams } from "react-router-dom";
// react plugin used to create charts // react plugin used to create charts
//import { Line, Bar } from "react-chartjs-2"; //import { Line, Bar } from "react-chartjs-2";
import { useAlert } from "react-alert"; import { useAlert } from "react-alert";
import Autocomplete from "@material-ui/lab/Autocomplete";
import { import {
Tooltip, Tooltip,
@@ -19,6 +21,7 @@ import {
Grid, Grid,
Paper, Paper,
Chip, Chip,
Checkbox,
} from "@material-ui/core"; } from "@material-ui/core";
import { import {
@@ -27,9 +30,13 @@ import {
Description as DescriptionIcon, Description as DescriptionIcon,
PlayArrow as PlayArrowIcon, PlayArrow as PlayArrowIcon,
Edit as EditIcon, Edit as EditIcon,
CheckBox as CheckBoxIcon,
CheckBoxOutlineBlank as CheckBoxOutlineBlankIcon,
OpenInNew as OpenInNewIcon,
} from "@material-ui/icons"; } from "@material-ui/icons";
import WorkflowPaper from "../components/WorkflowPaper.jsx" import WorkflowPaper from "../components/WorkflowPaper.jsx"
import { removeParam } from "../views/AngularWorkflow.jsx"
// core components // core components
//import { //import {
@@ -57,7 +64,33 @@ import {
TreeMapRect, TreeMapRect,
} from 'reaviz'; } from 'reaviz';
const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLoggedIn}) => { const useStyles = makeStyles({
notchedOutline: {
borderColor: "#f85a3e !important",
},
root: {
"& .MuiAutocomplete-listbox": {
border: "2px solid #f85a3e",
color: "white",
fontSize: 18,
"& li:nth-child(even)": {
backgroundColor: "#CCC",
},
"& li:nth-child(odd)": {
backgroundColor: "#FFF",
},
},
},
inputRoot: {
color: "white",
// This matches the specificity of the default styles at https://github.com/mui-org/material-ui/blob/v4.11.3/packages/material-ui-lab/src/Autocomplete/Autocomplete.js#L90
"&:hover .MuiOutlinedInput-notchedOutline": {
borderColor: "#f86a3e",
},
},
});
const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
const [expandedIndex, setExpandedIndex] = useState(-1); const [expandedIndex, setExpandedIndex] = useState(-1);
const [expandedItem, setExpandedItem] = useState(-1); const [expandedItem, setExpandedItem] = useState(-1);
const [inputUsecase, setInputUsecase] = useState({}); const [inputUsecase, setInputUsecase] = useState({});
@@ -67,8 +100,13 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
const [video, setVideo] = useState(""); const [video, setVideo] = useState("");
const [blogpost, setBlogpost] = useState(""); const [blogpost, setBlogpost] = useState("");
const [mitreTags, setMitreTags] = useState([]); const [selectedWorkflows, setSelectedWorkflows] = useState([])
const [firstLoad, setFirstLoad] = useState(true)
const classes = useStyles();
let navigate = useNavigate(); let navigate = useNavigate();
const [mitreTags, setMitreTags] = useState([]);
if (keys === undefined || keys === null || keys.length === 0) { if (keys === undefined || keys === null || keys.length === 0) {
return null return null
} }
@@ -104,7 +142,6 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
setTimeout(() => { setTimeout(() => {
//console.log("Scroll!") //console.log("Scroll!")
const found = document.getElementById("selected_box"); const found = document.getElementById("selected_box");
console.log("Found to scroll: ", found)
if (found !== undefined && found !== null) { if (found !== undefined && found !== null) {
//console.log("FOUND!!") //console.log("FOUND!!")
found.scrollTo({ found.scrollTo({
@@ -112,6 +149,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
behavior: "smooth", behavior: "smooth",
}) })
} }
setFirstLoad(true)
setSelectedWorkflows([])
}, 100); }, 100);
}) })
.catch((error) => { .catch((error) => {
@@ -119,6 +159,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
setInputUsecase({}) setInputUsecase({})
setExpandedIndex(index) setExpandedIndex(index)
setExpandedItem(subindex) setExpandedItem(subindex)
setFirstLoad(true)
setSelectedWorkflows([])
}) })
} }
@@ -178,6 +221,44 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
}) })
} }
const setWorkflow = (workflowdata) => {
const new_url = `${globalUrl}/api/v1/workflows/${workflowdata.id}`
fetch(new_url, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(workflowdata),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for workflows :O!");
return;
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
alert.error("Error updating workflow: ", responseJson.reason)
} else {
alert.error("Error updating workflow.")
}
return
}
return responseJson;
})
.catch((error) => {
alert.error("Problem setting workflow: ", error.toString());
});
};
return ( return (
<div style={{marginTop: 25, minHeight: 1000,}}> <div style={{marginTop: 25, minHeight: 1000,}}>
<Typography variant="h1"> <Typography variant="h1">
@@ -194,14 +275,19 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
</Typography> </Typography>
<Grid container spacing={3} style={{marginTop: 25}}> <Grid container spacing={3} style={{marginTop: 25}}>
{usecase.list.map((subcase, subindex) => { {usecase.list.map((subcase, subindex) => {
const selectedItem = subindex === expandedItem && index === expandedIndex
if (subcase.matches === undefined || subcase.matches === null) { if (subcase.matches === undefined || subcase.matches === null) {
subcase.matches = [] subcase.matches = []
} else {
if (selectedItem && subcase.matches.length > 0 && selectedWorkflows.length === 0 && firstLoad === true) {
setFirstLoad(false)
setSelectedWorkflows(subcase.matches)
}
} }
const selectedItem = subindex === expandedItem && index === expandedIndex
if (selectedItem && subcase.name !== undefined && inputUsecase.name !== undefined) { if (selectedItem && subcase.name !== undefined && inputUsecase.name !== undefined) {
if (subcase.name.toLowerCase().replaceAll(" ", "_") === inputUsecase.name.toLowerCase().replaceAll(" ", "_")) { if (subcase.name.toLowerCase().replaceAll(" ", "_") === inputUsecase.name.toLowerCase().replaceAll(" ", "_")) {
console.log("Input: ", inputUsecase)
if (inputUsecase.description !== undefined && inputUsecase.description !== null) { if (inputUsecase.description !== undefined && inputUsecase.description !== null) {
subcase.description = inputUsecase.description subcase.description = inputUsecase.description
} }
@@ -213,21 +299,32 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
if (inputUsecase.video !== undefined && inputUsecase.video !== null) { if (inputUsecase.video !== undefined && inputUsecase.video !== null) {
subcase.video = inputUsecase.video subcase.video = inputUsecase.video
} }
if (inputUsecase.extra_buttons !== undefined && inputUsecase.extra_buttons !== null) {
subcase.extra_buttons = inputUsecase.extra_buttons
}
} }
} }
const finished = subcase.matches.length > 0
//const backgroundColor = selectedItem ? "inherit" : finished ? "inherit" : usecase.color //const backgroundColor = selectedItem ? "inherit" : finished ? "inherit" : usecase.color
const backgroundColor = "inherit" const finished = subcase.matches.length > 0
const backgroundColor = theme.palette.surfaceColor
//"inherit"
const itemBorder = `${selectedItem ? "3px" : expandedItem >= 0 ? "0px" : "1px"} solid ${usecase.color}` const itemBorder = `${selectedItem ? "3px" : expandedItem >= 0 ? "0px" : "1px"} solid ${usecase.color}`
const fixedName = subcase.name.toLowerCase().replace("_", " ")
return ( return (
<Grid item xs={selectedItem ? 12 : 4} key={subindex} style={{minHeight: 110,}} onClick={() => { <Grid id={fixedName} item xs={selectedItem ? 12 : 4} key={subindex} style={{minHeight: 110,}} onClick={() => {
//setSelectedWorkflows([])
if (selectedItem) { if (selectedItem) {
} else { } else {
//if (subcase.description !== undefined && subcase.description !== null && subcase.description.length > 0) {
getUsecase(subcase.name, index, subindex) getUsecase(subcase.name, index, subindex)
//} navigate(`/usecases?selected_object=${fixedName}`)
//const newitem = removeParam("selected_object", cursearch);
//navigate(curpath + newitem)
} }
}}> }}>
<Paper style={{padding: "30px 30px 30px 30px", minHeight: 75, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => { <Paper style={{padding: "30px 30px 30px 30px", minHeight: 75, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
@@ -307,7 +404,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
: null} : null}
</div> </div>
: :
<div style={{textAlign: "left", position: "relative",}} id="selected_box"> <div style={{textAlign: "left", position: "relative", }} id="selected_box">
<Typography variant="h6"> <Typography variant="h6">
<b>{subcase.name}</b> <b>{subcase.name}</b>
</Typography> </Typography>
@@ -402,7 +499,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</div> </div>
<div style={{marginTop: 25, display: "flex", minHeight: 400, maxHeight: 400, }}> <div style={{marginTop: 25, display: "flex", minHeight: 400, maxHeight: 400, marginRight: 15, }}>
{editing ? {editing ?
<div style={{flex: 1, marginRight: 50, }}> <div style={{flex: 1, marginRight: 50, }}>
<Typography variant="h6"> <Typography variant="h6">
@@ -506,14 +603,149 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
</div> </div>
: :
<div style={{flex: 1, textAlign: "left", marginRight: 10, }}> <div style={{flex: 1, textAlign: "left", marginRight: 10, }}>
<Typography variant="body1"> <Typography variant="body1" color="textSecondary">
{subcase.description} {subcase.description}
</Typography> </Typography>
<Typography variant="h6" style={{marginTop: 15, }}> <Typography variant="body1" style={{marginTop: 15, marginBottom: 10, }}>
Your workflow{subcase.matches.length === 1 ? "" : "s"} ({subcase.matches.length}) Select relevant workflows
</Typography> </Typography>
{subcase.matches.length > 0 ?
<Grid container xs={3} style={{maxWidth: 325, marginTop: 10, }}> {workflows !== undefined && workflows !== null && workflows.length > 0 ?
<Autocomplete
multiple
id="workflow_matching"
options={workflows}
autoHighlight
value={selectedWorkflows}
classes={{ inputRoot: classes.inputRoot }}
ListboxProps={{
style: {
backgroundColor: theme.palette.inputColor,
color: "white",
},
}}
getOptionSelected={(option, value) => option.id === value.id}
getOptionLabel={(option) => {
if (
option === undefined ||
option === null ||
option.name === undefined ||
option.name === null
) {
return "No Workflow Selected";
}
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) => {
console.log("CLICK: ", newValue)
//handleWorkflowSelectionUpdate({ target: { value: newValue} })
//setSelectedWorkflows=
//var newvalue = []
//for (var key in newValue) {
// if (newValue[key].id !== undefined) {
// newvalue.push(newValue[key].id)
// }
//}
// Doing this way as you may want to remove some too
for (var key in workflows) {
if (!newValue.find(data => data.id === workflows[key].id)) {
// Check if it has the one in it
if (workflows[key]["usecase_ids"] !== undefined && workflows[key]["usecase_ids"] !== null && workflows[key]["usecase_ids"].includes(subcase.name)) {
const filtered = workflows[key]["usecase_ids"].filter(data => data !== subcase.name)
if (filtered !== undefined && filtered !== null) {
//console.log("Removing: ", workflows[key].name, workflows[key])
workflows[key]["usecase_ids"] = filtered
setWorkflow(workflows[key])
}
}
continue
}
if (workflows[key]["usecase_ids"] === undefined || workflows[key]["usecase_ids"] === null) {
workflows[key]["usecase_ids"] = [subcase.name]
console.log("Setting: ", workflows[key].name)
setWorkflow(workflows[key])
} else if (!workflows[key]["usecase_ids"].includes(subcase.name)) {
workflows[key]["usecase_ids"].push(subcase.name)
console.log("Adding: ", workflows[key].name)
setWorkflow(workflows[key])
}
}
setWorkflows(workflows)
console.log("New: ", newValue)
setSelectedWorkflows(newValue)
//setUpdate(Math.random())
}}
renderOption={(props, option) => {
//console.log("In options?: ", props, option)
var newname = props.name
if (newname === undefined || newname === null) {
newname = "placeholder"
}
if (newname.length > 2) {
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
}
return (
<li {...props}>
<Tooltip arrow placement="left" title={
<span style={{}}>
{props.image !== undefined && props.image !== null && props.image.length > 0 ?
<img src={props.image} alt={newname} style={{backgroundColor: theme.palette.surfaceColor, maxHeight: 200, minHeigth: 200, borderRadius: theme.palette.borderRadius, }} />
: null}
<Typography>
Choose {newname}
</Typography>
</span>
} placement="bottom">
<span>
<Checkbox
icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
checkedIcon={<CheckBoxIcon fontSize="small" />}
style={{ marginRight: 8 }}
checked={option.selected}
/>
{newname}
</span>
</Tooltip>
</li>
)
}}
renderInput={(params) => {
return (
<TextField
style={{
backgroundColor: theme.palette.inputColor,
borderRadius: theme.palette.borderRadius,
}}
{...params}
label="Find your workflows"
variant="outlined"
/>
);
}}
/>
: null}
{/*subcase.matches.length > 0 ?
<Grid container style={{maxWidth: 325, marginTop: 10, }}>
{subcase.matches.map((workflow, workflowindex) => { {subcase.matches.map((workflow, workflowindex) => {
return ( return (
<Grid key={workflowindex} item index={workflowindex} xs={12}> <Grid key={workflowindex} item index={workflowindex} xs={12}>
@@ -528,13 +760,16 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
No workflow selected yet. No workflow selected yet.
</Typography> </Typography>
</div> </div>
} */}
{isCloud !== false ? <div style={{marginTop: 35}}>
<div> <a
<Typography variant="h6" style={{marginTop: 15, cursor: "pointer",}} onClick={() => { href={`https://shuffler.io/search?tab=workflows&q=${subcase.name}`}
navigate("/search?tab=workflows&q="+subcase.name) rel="noopener noreferrer"
}}> target="_blank"
Public workflows style={{ textDecoration: "none", color: "white", marginRight: 5, }}
>
<Typography variant="body1" style={{marginTop: 15, cursor: "pointer",}} onClick={() => {}}>
See Public Workflows <OpenInNewIcon style={{marginTop: 5, marginLeft: 15, }}/>
</Typography> </Typography>
{/* {/*
<div> <div>
@@ -543,8 +778,40 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
</Typography> </Typography>
</div> </div>
*/} */}
</a>
</div>
<div style={{display: "flex"}}>
{subcase.extra_buttons !== undefined && subcase.extra_buttons !== null && subcase.extra_buttons.length > 0 ?
subcase.extra_buttons.map((subdata, index) => {
var highlight = false
var baseTypeInfo = subcase.type !== undefined ? subcase.type : "communication"
if (frameworkData[baseTypeInfo] !== undefined && frameworkData[baseTypeInfo] !== null && subdata.app !== undefined && subdata.app !== null) {
if (frameworkData[baseTypeInfo].name.toLowerCase().replaceAll("_", " ") === subdata.app.toLowerCase().replaceAll("_", " ")) {
highlight = true
}
}
return (
<a
key={index}
href={subdata.link}
rel="noopener noreferrer"
target="_blank"
style={{ textDecoration: "none", color: "rgba(255,255,255,0.7)", marginRight: 5, }}
>
<div style={{width: 140, display: "flex", borderRadius: theme.palette.borderRadius, cursor: "pointer", border: highlight ? "2px solid #f86a3e" : "1px solid rgba(255,255,255,0.7)", backgroundColor: theme.palette.inputColor, padding: 15, }}>
<img src={subdata.image} style={{width: 40, height: 40, }} />
<Typography variant="body1" style={{marginLeft: 15, marginTop: 6,}}>
{subdata.name}
</Typography>
</div>
</a>
)
})
: null}
</div> </div>
: null}
</div> </div>
} }
<div style={{ <div style={{
@@ -726,10 +993,63 @@ const Dashboard = (props) => {
const [workflows, setWorkflows] = useState([]); const [workflows, setWorkflows] = useState([]);
const [frameworkData, setFrameworkData] = useState(undefined); const [frameworkData, setFrameworkData] = useState(undefined);
let navigate = useNavigate();
const isCloud = const isCloud =
window.location.host === "localhost:3002" || window.location.host === "localhost:3002" ||
window.location.host === "shuffler.io"; window.location.host === "shuffler.io";
useEffect(() => {
if (selectedUsecaseCategory.length === 0) {
setSelectedUsecases(usecases)
} else {
const foundUsecase = usecases.find(data => data.name === selectedUsecaseCategory)
if (foundUsecase !== undefined && foundUsecase !== null) {
setSelectedUsecases([foundUsecase])
}
}
}, [selectedUsecaseCategory])
const checkSelectedParams = () => {
const urlSearchParams = new URLSearchParams(window.location.search)
const params = Object.fromEntries(urlSearchParams.entries())
const curpath = typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname;
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
const foundQuery = params["selected"]
if (foundQuery !== null && foundQuery !== undefined) {
setSelectedUsecaseCategory(foundQuery)
const newitem = removeParam("selected", cursearch);
navigate(curpath + newitem)
}
const foundQuery2 = params["selected_object"]
if (foundQuery2 !== null && foundQuery2 !== undefined) {
console.log("Got selected_object: ", foundQuery2)
const queryName = foundQuery2.toLowerCase().replaceAll("_", " ")
// Waiting a bit for it to render
setTimeout(() => {
const foundItem = document.getElementById(queryName)
if (foundItem !== undefined && foundItem !== null) {
foundItem.click()
} else {
//console.log("Couldn't find item with name ", queryName)
}
}, 100);
}
}
useEffect(() => {
if (usecases.length > 0) {
console.log(usecases)
checkSelectedParams()
}
}, [usecases])
const getFramework = () => { const getFramework = () => {
fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", { fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", {
method: "GET", method: "GET",
@@ -783,10 +1103,8 @@ const Dashboard = (props) => {
.then((responseJson) => { .then((responseJson) => {
fetchUsecases(responseJson) fetchUsecases(responseJson)
console.log("Resp: ", responseJson)
if (responseJson !== undefined) { if (responseJson !== undefined) {
//setWorkflows(responseJson); setWorkflows(responseJson);
//fetchUsecases(responseJson)
} }
}) })
.catch((error) => { .catch((error) => {
@@ -795,18 +1113,6 @@ const Dashboard = (props) => {
}); });
} }
useEffect(() => {
console.log("Changed: ", selectedUsecaseCategory)
if (selectedUsecaseCategory.length === 0) {
setSelectedUsecases(usecases)
} else {
const foundUsecase = usecases.find(data => data.name === selectedUsecaseCategory)
if (foundUsecase !== undefined && foundUsecase !== null) {
console.log("FOUND: ", foundUsecase)
setSelectedUsecases([foundUsecase])
}
}
}, [selectedUsecaseCategory])
document.title = "Shuffle - usecases"; document.title = "Shuffle - usecases";
var dayGraphLabels = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]; var dayGraphLabels = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130];
@@ -846,9 +1152,7 @@ const Dashboard = (props) => {
}) })
.then((responseJson) => { .then((responseJson) => {
if (responseJson.success !== false) { if (responseJson.success !== false) {
console.log("Usecases: ", responseJson)
if (workflows !== undefined && workflows !== null && workflows.length > 0) { if (workflows !== undefined && workflows !== null && workflows.length > 0) {
console.log("Got workflows: ", workflows)
var categorydata = responseJson var categorydata = responseJson
var newcategories = [] var newcategories = []
@@ -866,7 +1170,6 @@ const Dashboard = (props) => {
if (workflow.usecase_ids !== undefined && workflow.usecase_ids !== null) { if (workflow.usecase_ids !== undefined && workflow.usecase_ids !== null) {
for (var usecasekey in workflow.usecase_ids) { for (var usecasekey in workflow.usecase_ids) {
if (workflow.usecase_ids[usecasekey].toLowerCase() === subcategory.name.toLowerCase()) { if (workflow.usecase_ids[usecasekey].toLowerCase() === subcategory.name.toLowerCase()) {
console.log("Got match: ", workflow.usecase_ids[usecasekey])
category.matches.push({ category.matches.push({
"workflow": workflow.id, "workflow": workflow.id,
@@ -888,7 +1191,6 @@ const Dashboard = (props) => {
newcategories.push(category) newcategories.push(category)
} }
console.log("Categories: ", newcategories)
if (newcategories !== undefined && newcategories !== null && newcategories.length > 0) { if (newcategories !== undefined && newcategories !== null && newcategories.length > 0) {
handleKeysetting(newcategories) handleKeysetting(newcategories)
setUsecases(newcategories) setUsecases(newcategories)
@@ -1064,7 +1366,6 @@ const Dashboard = (props) => {
}); });
if (firstRequest) { if (firstRequest) {
console.log("HELO");
setFirstRequest(false); setFirstRequest(false);
//start(); //start();
//runUpdate(); //runUpdate();
@@ -1213,6 +1514,8 @@ const Dashboard = (props) => {
keys={selectedUsecases} keys={selectedUsecases}
isCloud={isCloud} isCloud={isCloud}
globalUrl={globalUrl} globalUrl={globalUrl}
workflows={workflows}
setWorkflows={setWorkflows}
/> />
{treeKeys.length > 0 ? {treeKeys.length > 0 ?
+2 -2
View File
@@ -3038,7 +3038,7 @@ const Workflows = (props) => {
</div> </div>
</div> </div>
} }
<div style={{ flex: 1, textAlign: "right" }}> <div style={{ flex: 1, textAlign: "right", }}>
{workflowButtons} {workflowButtons}
</div> </div>
</div> </div>
@@ -3090,7 +3090,7 @@ const Workflows = (props) => {
}} }}
*/} */}
<div style={{width: "100%",}}> <div style={{width: "100%", minHeight: isMobile ? 0 : 71, maxHeight: isMobile ? 0 : 71, }}>
{!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ? {!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ?
<div style={{ display: "flex", }}> <div style={{ display: "flex", }}>
{usecases.map((usecase, index) => { {usecases.map((usecase, index) => {