diff --git a/backend/go-app/go.mod b/backend/go-app/go.mod index 3f782f4d..083567a1 100644 --- a/backend/go-app/go.mod +++ b/backend/go-app/go.mod @@ -2,7 +2,7 @@ module main 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/go-elasticsearch => ../../../../git/go-elasticsearch diff --git a/backend/go-app/main.go b/backend/go-app/main.go index 3cb02362..433ce6b2 100644 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -1038,6 +1038,18 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { 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{} returnValue := shuffle.HandleInfo{ Success: true, @@ -1056,6 +1068,7 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { EthInfo: userInfo.EthInfo, Tutorials: tutorialsFinished, ChatDisabled: chatDisabled, + Priorities: orgPriorities, } returnData, err := json.Marshal(returnValue) @@ -5966,7 +5979,9 @@ func initHandlers() { r.HandleFunc("/api/v1/workflows/collections/{key}", shuffle.HandleGetCollection).Methods("GET", "OPTIONS") // 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.UpdateUsecases).Methods("POST", "OPTIONS") // Legacy app things r.HandleFunc("/api/v1/workflows/apps/validate", validateAppInput).Methods("POST", "OPTIONS") diff --git a/backend/go-app/walkoff.go b/backend/go-app/walkoff.go index c83fb664..c0f39ecd 100644 --- a/backend/go-app/walkoff.go +++ b/backend/go-app/walkoff.go @@ -2051,8 +2051,9 @@ func iterateOpenApiGithub(fs billy.Filesystem, dir []os.FileInfo, extra string, workflowapps, err := shuffle.GetAllWorkflowApps(ctx, 1000, 0) appCounter := 0 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 { if len(onlyname) > 0 && file.Name() != onlyname { continue diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index e403f7c5..a16a3302 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -64,11 +64,7 @@ const App = (message, props) => { const [isLoggedIn, setIsLoggedIn] = useState(false) const [dataset, setDataset] = useState(false) const [isLoaded, setIsLoaded] = useState(false) - const [curpath, setCurpath] = useState( - typeof window === "undefined" || window.location === undefined - ? "" - : window.location.pathname - ) + const [curpath, setCurpath] = useState(typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname) useEffect(() => { @@ -303,6 +299,7 @@ const App = (message, props) => { > {!isLoaded ? null : diff --git a/frontend/src/components/DetectionFramework.jsx b/frontend/src/components/DetectionFramework.jsx index 6dba209a..4cbb0e7e 100644 --- a/frontend/src/components/DetectionFramework.jsx +++ b/frontend/src/components/DetectionFramework.jsx @@ -924,10 +924,7 @@ const Framework = (props) => { const shiftmodifier = 3*scale //const svgSize = `${40*scale}px` const svgSize = `${40}px` - console.log("Size: ", svgSize) - - console.log("Framework: ", parsedFrameworkData) const fontSize = `${12*scale}px` const defaultSize = `${85*scale}px` const iconSize = `${45*scale}px` @@ -1265,14 +1262,11 @@ const Framework = (props) => { changeUsecase(selectedUsecase, usecaseType) if (inputUsecase !== undefined && inputUsecase !== null) { - console.log("Got usecase: ", inputUsecase) - for (var key in inputUsecase.process) { if (inputUsecase.process[key].source === "" || inputUsecase.process[key].target === "") { continue } - console.log("Edge: ", inputUsecase.process[key]) inputUsecase.process[key].label = parseInt(key)+1 inputUsecase.process[key].id = uuidv4(); diff --git a/frontend/src/components/ParsedAction.jsx b/frontend/src/components/ParsedAction.jsx index 3298c6f0..2e8d79cc 100644 --- a/frontend/src/components/ParsedAction.jsx +++ b/frontend/src/components/ParsedAction.jsx @@ -183,6 +183,13 @@ const ParsedAction = (props) => { const [fieldCount, setFieldCount] = React.useState(0); const [hiddenDescription, setHiddenDescription] = React.useState(true); + + useEffect(() => { + if (setLastSaved !== undefined) { + setLastSaved(false) + } + }, [expansionModalOpen]) + useEffect(() => { if (selectedAction.parameters !== null && selectedAction.parameters !== undefined) { const paramcheck = selectedAction.parameters.find(param => param.name === "body") diff --git a/frontend/src/components/ScrollToTop.jsx b/frontend/src/components/ScrollToTop.jsx index f166cf1f..2e19a282 100644 --- a/frontend/src/components/ScrollToTop.jsx +++ b/frontend/src/components/ScrollToTop.jsx @@ -2,23 +2,26 @@ import { useEffect } from "react"; //import { withRouter } 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(); useEffect(() => { - //const unlisten = history.listen(() => { - window.scroll({ - top: 0, - left: 0, - behavior: "smooth", - }); + // Custom handler for certain scroll mechanics + // + console.log("OLD: ", curpath, "NeW: ", window.location.pathname) + if (curpath === window.location.pathname && curpath === "/usecases") { + } else { - setCurpath(window.location.pathname); - getUserNotifications(); - //}); - //return () => { - // unlisten(); - //}; + window.scroll({ + top: 0, + left: 0, + behavior: "smooth", + }); + + setCurpath(window.location.pathname); + getUserNotifications(); + } }, [location]); return null; diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 45a87c2f..86fd8c33 100644 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -166,7 +166,7 @@ export function sortByKey(array, key) { }); } -function removeParam(key, sourceURL) { +export function removeParam(key, sourceURL) { if (sourceURL === undefined) { return; } @@ -1611,10 +1611,6 @@ const AngularWorkflow = (defaultprops) => { } const getWorkflow = (workflow_id, sourcenode) => { - console.log( - //`Getting workflow ${workflow_id} with append value ${sourcenode}` - ); - fetch(globalUrl + "/api/v1/workflows/" + workflow_id, { method: "GET", headers: { @@ -1716,6 +1712,11 @@ const AngularWorkflow = (defaultprops) => { nodefound = true; } + if (responseJson.public) { + node.data.is_valid = true + node.is_valid = true + } + var example = ""; if ( action.example !== undefined && @@ -1757,6 +1758,7 @@ const AngularWorkflow = (defaultprops) => { return null; } + edge.data = { id: branch.id, _id: branch.id, @@ -1769,6 +1771,11 @@ const AngularWorkflow = (defaultprops) => { source_workflow: responseJson.id, }; + if (responseJson.public) { + edge.data.is_valid = true + edge.is_valid = true + } + return edge; }); @@ -4124,6 +4131,11 @@ const AngularWorkflow = (defaultprops) => { node.data.type = "ACTION"; node.isStartNode = action["id"] === workflow.start; + if (workflow.public === true) { + node.data.is_valid = true + node.is_valid = true + } + var example = ""; if ( action.example !== undefined && @@ -4431,14 +4443,8 @@ const AngularWorkflow = (defaultprops) => { } else if ( // 2nd load - configures cytoscape // - !established && - cy !== undefined && - ((apps !== null && - apps !== undefined && - apps.length > 0) || workflow.public === true) && - Object.getOwnPropertyNames(workflow).length > 0 && - authLoaded - ) { + !established && cy !== undefined && + ((apps !== null && apps !== undefined && apps.length > 0) || workflow.public === true) && Object.getOwnPropertyNames(workflow).length > 0 && authLoaded) { console.log("In POST graph setup!") //This part has to load LAST, as it's kind of not async. @@ -10824,6 +10830,7 @@ const AngularWorkflow = (defaultprops) => { x: 300, y: 300, }; + cy.add({ group: "nodes", data: { diff --git a/frontend/src/views/Dashboard.jsx b/frontend/src/views/Dashboard.jsx index ffe6cea3..87493107 100644 --- a/frontend/src/views/Dashboard.jsx +++ b/frontend/src/views/Dashboard.jsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from "react"; import { useInterval } from "react-powerhooks"; import DetectionFramework from "../components/DetectionFramework.jsx"; +import { makeStyles, useTheme } from "@material-ui/core/styles"; // nodejs library that concatenates classes import classNames from "classnames"; import theme from '../theme'; @@ -9,6 +10,7 @@ import { useNavigate, Link, useParams } from "react-router-dom"; // react plugin used to create charts //import { Line, Bar } from "react-chartjs-2"; import { useAlert } from "react-alert"; +import Autocomplete from "@material-ui/lab/Autocomplete"; import { Tooltip, @@ -19,6 +21,7 @@ import { Grid, Paper, Chip, + Checkbox, } from "@material-ui/core"; import { @@ -27,9 +30,13 @@ import { Description as DescriptionIcon, PlayArrow as PlayArrowIcon, Edit as EditIcon, + CheckBox as CheckBoxIcon, + CheckBoxOutlineBlank as CheckBoxOutlineBlankIcon, + OpenInNew as OpenInNewIcon, } from "@material-ui/icons"; import WorkflowPaper from "../components/WorkflowPaper.jsx" +import { removeParam } from "../views/AngularWorkflow.jsx" // core components //import { @@ -57,7 +64,33 @@ import { TreeMapRect, } 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 [expandedItem, setExpandedItem] = useState(-1); const [inputUsecase, setInputUsecase] = useState({}); @@ -67,8 +100,13 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged const [video, setVideo] = useState(""); const [blogpost, setBlogpost] = useState(""); - const [mitreTags, setMitreTags] = useState([]); + const [selectedWorkflows, setSelectedWorkflows] = useState([]) + const [firstLoad, setFirstLoad] = useState(true) + + const classes = useStyles(); let navigate = useNavigate(); + + const [mitreTags, setMitreTags] = useState([]); if (keys === undefined || keys === null || keys.length === 0) { return null } @@ -104,7 +142,6 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged setTimeout(() => { //console.log("Scroll!") const found = document.getElementById("selected_box"); - console.log("Found to scroll: ", found) if (found !== undefined && found !== null) { //console.log("FOUND!!") found.scrollTo({ @@ -112,6 +149,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged behavior: "smooth", }) } + + setFirstLoad(true) + setSelectedWorkflows([]) }, 100); }) .catch((error) => { @@ -119,6 +159,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged setInputUsecase({}) setExpandedIndex(index) 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 (
@@ -194,14 +275,19 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged {usecase.list.map((subcase, subindex) => { + const selectedItem = subindex === expandedItem && index === expandedIndex + if (subcase.matches === undefined || subcase.matches === null) { 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 (subcase.name.toLowerCase().replaceAll(" ", "_") === inputUsecase.name.toLowerCase().replaceAll(" ", "_")) { - console.log("Input: ", inputUsecase) if (inputUsecase.description !== undefined && inputUsecase.description !== null) { subcase.description = inputUsecase.description } @@ -213,21 +299,32 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged if (inputUsecase.video !== undefined && inputUsecase.video !== null) { 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 = "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 fixedName = subcase.name.toLowerCase().replace("_", " ") + return ( - { + { + + //setSelectedWorkflows([]) if (selectedItem) { } else { - //if (subcase.description !== undefined && subcase.description !== null && subcase.description.length > 0) { getUsecase(subcase.name, index, subindex) - //} + navigate(`/usecases?selected_object=${fixedName}`) + + //const newitem = removeParam("selected_object", cursearch); + //navigate(curpath + newitem) } }}> { @@ -307,7 +404,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged : null}
: -
+
{subcase.name} @@ -402,7 +499,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
-
+
{editing ?
@@ -506,14 +603,149 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
:
- + {subcase.description} - - Your workflow{subcase.matches.length === 1 ? "" : "s"} ({subcase.matches.length}) + + Select relevant workflows - {subcase.matches.length > 0 ? - + + {workflows !== undefined && workflows !== null && workflows.length > 0 ? + 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 ( +
  • + + {props.image !== undefined && props.image !== null && props.image.length > 0 ? + {newname} + : null} + + Choose {newname} + + + } placement="bottom"> + + } + checkedIcon={} + style={{ marginRight: 8 }} + checked={option.selected} + /> + {newname} + + +
  • + ) + }} + renderInput={(params) => { + return ( + + ); + }} + /> + : null} + + {/*subcase.matches.length > 0 ? + {subcase.matches.map((workflow, workflowindex) => { return ( @@ -528,13 +760,16 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged No workflow selected yet.
    - } - {isCloud !== false ? -
    - { - navigate("/search?tab=workflows&q="+subcase.name) - }}> - Public workflows + */} + + + +
    + {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 ( + +
    + + + {subdata.name} + +
    +
    + ) + }) + : null}
    - : null}
    }
    { const [workflows, setWorkflows] = useState([]); const [frameworkData, setFrameworkData] = useState(undefined); + let navigate = useNavigate(); const isCloud = window.location.host === "localhost:3002" || 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 = () => { fetch(globalUrl + "/api/v1/apps/frameworkConfiguration", { method: "GET", @@ -783,10 +1103,8 @@ const Dashboard = (props) => { .then((responseJson) => { fetchUsecases(responseJson) - console.log("Resp: ", responseJson) if (responseJson !== undefined) { - //setWorkflows(responseJson); - //fetchUsecases(responseJson) + setWorkflows(responseJson); } }) .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"; var dayGraphLabels = [60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]; @@ -846,9 +1152,7 @@ const Dashboard = (props) => { }) .then((responseJson) => { if (responseJson.success !== false) { - console.log("Usecases: ", responseJson) if (workflows !== undefined && workflows !== null && workflows.length > 0) { - console.log("Got workflows: ", workflows) var categorydata = responseJson var newcategories = [] @@ -866,7 +1170,6 @@ const Dashboard = (props) => { if (workflow.usecase_ids !== undefined && workflow.usecase_ids !== null) { for (var usecasekey in workflow.usecase_ids) { if (workflow.usecase_ids[usecasekey].toLowerCase() === subcategory.name.toLowerCase()) { - console.log("Got match: ", workflow.usecase_ids[usecasekey]) category.matches.push({ "workflow": workflow.id, @@ -888,7 +1191,6 @@ const Dashboard = (props) => { newcategories.push(category) } - console.log("Categories: ", newcategories) if (newcategories !== undefined && newcategories !== null && newcategories.length > 0) { handleKeysetting(newcategories) setUsecases(newcategories) @@ -1064,7 +1366,6 @@ const Dashboard = (props) => { }); if (firstRequest) { - console.log("HELO"); setFirstRequest(false); //start(); //runUpdate(); @@ -1213,6 +1514,8 @@ const Dashboard = (props) => { keys={selectedUsecases} isCloud={isCloud} globalUrl={globalUrl} + workflows={workflows} + setWorkflows={setWorkflows} /> {treeKeys.length > 0 ? diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index 501a1d01..20658187 100644 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -3038,7 +3038,7 @@ const Workflows = (props) => {
    } -
    +
    {workflowButtons}
    @@ -3090,7 +3090,7 @@ const Workflows = (props) => { }} */} -
    +
    {!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ?
    {usecases.map((usecase, index) => {