Added statistics to both backend and frontend + cloud sync
This commit is contained in:
+181
-121
@@ -6,6 +6,7 @@ import { makeStyles, } from "@mui/styles";
|
||||
import classNames from "classnames";
|
||||
import theme from '../theme.jsx';
|
||||
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||
import WorkflowTemplatePopup from "../components/WorkflowTemplatePopup.jsx";
|
||||
|
||||
// react plugin used to create charts
|
||||
//import { Line, Bar } from "react-chartjs-2";
|
||||
@@ -90,7 +91,7 @@ const useStyles = makeStyles({
|
||||
},
|
||||
});
|
||||
|
||||
const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
|
||||
const UsecaseListComponent = ({userdata, keys, isCloud, globalUrl, frameworkData, isLoggedIn, workflows, setWorkflows}) => {
|
||||
const [expandedIndex, setExpandedIndex] = useState(-1);
|
||||
const [expandedItem, setExpandedItem] = useState(-1);
|
||||
const [inputUsecase, setInputUsecase] = useState({});
|
||||
@@ -103,17 +104,69 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
|
||||
const [selectedWorkflows, setSelectedWorkflows] = useState([])
|
||||
const [firstLoad, setFirstLoad] = useState(true)
|
||||
const [apps, setApps] = useState([])
|
||||
|
||||
const classes = useStyles();
|
||||
const classes = useStyles();
|
||||
let navigate = useNavigate();
|
||||
|
||||
const [mitreTags, setMitreTags] = useState([]);
|
||||
|
||||
const loadApps = () => {
|
||||
fetch(`${globalUrl}/api/v1/apps`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
credentials: "include",
|
||||
})
|
||||
.then((response) => {
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
if (responseJson === null) {
|
||||
console.log("null-response from server")
|
||||
const pretend_apps = [{
|
||||
"name": "TBD",
|
||||
"app_name": "TBD",
|
||||
"app_version": "TBD",
|
||||
"description": "TBD",
|
||||
"version": "TBD",
|
||||
"large_image": "",
|
||||
}]
|
||||
|
||||
setApps(pretend_apps)
|
||||
return
|
||||
}
|
||||
|
||||
if (responseJson.success === false) {
|
||||
console.log("error loading apps: ", responseJson)
|
||||
return
|
||||
}
|
||||
|
||||
setApps(responseJson);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("App loading error: " + error.toString());
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadApps()
|
||||
}, [])
|
||||
|
||||
if (keys === undefined || keys === null || keys.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
const getUsecase = (name, index, subindex) => {
|
||||
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(name.replaceAll(" ", "_"))}`, {
|
||||
const parseUsecase = (parsedUsecase, subcase) => {
|
||||
console.log("parseUsecase: ", parsedUsecase, subcase)
|
||||
}
|
||||
|
||||
const getUsecase = (subcase, index, subindex) => {
|
||||
console.log(subcase)
|
||||
|
||||
fetch(`${globalUrl}/api/v1/workflows/usecases/${escape(subcase.name.replaceAll(" ", "_"))}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -129,14 +182,26 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
return response.json();
|
||||
})
|
||||
.then((responseJson) => {
|
||||
var parsedUsecase = responseJson
|
||||
if (responseJson.success === false) {
|
||||
setInputUsecase({
|
||||
"name": name,
|
||||
})
|
||||
parsedUsecase = subcase
|
||||
|
||||
//img1={inputUsecase.srcimg}
|
||||
//srcapp={inputUsecase.srcapp}
|
||||
//img2={inputUsecase.dstimg}
|
||||
//dstapp={inputUsecase.dstapp}
|
||||
//title={inputUsecase.name}
|
||||
parsedUsecase = parseUsecase(parsedUsecase, subcase)
|
||||
} else {
|
||||
setInputUsecase(responseJson)
|
||||
parsedUsecase = responseJson
|
||||
|
||||
parsedUsecase = parseUsecase(parsedUsecase, responseJson)
|
||||
}
|
||||
|
||||
// Look for the type of app and fill in img1, srcapp...
|
||||
|
||||
|
||||
setInputUsecase(parsedUsecase)
|
||||
setExpandedIndex(index)
|
||||
setExpandedItem(subindex)
|
||||
|
||||
@@ -289,6 +354,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
if (selectedItem && subcase.matches.length > 0 && selectedWorkflows.length === 0 && firstLoad === true) {
|
||||
setFirstLoad(false)
|
||||
setSelectedWorkflows(subcase.matches)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,10 +382,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
}
|
||||
}
|
||||
|
||||
//const backgroundColor = selectedItem ? "inherit" : finished ? "inherit" : usecase.color
|
||||
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("_", " ")
|
||||
@@ -330,14 +394,14 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
//setSelectedWorkflows([])
|
||||
if (selectedItem) {
|
||||
} else {
|
||||
getUsecase(subcase.name, index, subindex)
|
||||
getUsecase(subcase, index, subindex)
|
||||
navigate(`/usecases?selected_object=${fixedName}`)
|
||||
|
||||
//const newitem = removeParam("selected_object", cursearch);
|
||||
//navigate(curpath + newitem)
|
||||
}
|
||||
}}>
|
||||
<Paper style={{padding: 25, minHeight: 75, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
|
||||
<Paper style={{padding: 25, minHeight: isCloud ? 75 : 122, cursor: !selectedItem ? "pointer" : "default", border: itemBorder, backgroundColor: backgroundColor,}} onClick={() => {
|
||||
}}>
|
||||
{!selectedItem ?
|
||||
<div style={{textAlign: "left", position: "relative",}}>
|
||||
@@ -649,12 +713,12 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
: null}
|
||||
|
||||
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
|
||||
<Autocomplete
|
||||
multiple
|
||||
<Autocomplete
|
||||
multiple
|
||||
id="workflow_matching"
|
||||
options={workflows}
|
||||
autoHighlight
|
||||
value={selectedWorkflows}
|
||||
value={selectedWorkflows}
|
||||
classes={{ inputRoot: classes.inputRoot }}
|
||||
ListboxProps={{
|
||||
style: {
|
||||
@@ -662,7 +726,7 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
color: "white",
|
||||
},
|
||||
}}
|
||||
getOptionSelected={(option, value) => option.id === value.id}
|
||||
getOptionSelected={(option, value) => option.id === value.id}
|
||||
getOptionLabel={(option) => {
|
||||
|
||||
if (
|
||||
@@ -685,120 +749,120 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
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)
|
||||
// }
|
||||
//}
|
||||
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])
|
||||
}
|
||||
}
|
||||
// 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
|
||||
}
|
||||
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])
|
||||
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])
|
||||
} 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)
|
||||
setWorkflows(workflows)
|
||||
console.log("New: ", newValue)
|
||||
setSelectedWorkflows(newValue)
|
||||
//setUpdate(Math.random())
|
||||
}}
|
||||
renderOption={(props, option) => {
|
||||
//console.log("In options?: ", props, option)
|
||||
renderOption={(props, data, state) => {
|
||||
var newname = data.name
|
||||
if (newname === undefined || newname === null) {
|
||||
newname = "placeholder"
|
||||
}
|
||||
|
||||
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>
|
||||
)
|
||||
}}
|
||||
if (newname.length > 2) {
|
||||
newname = newname.charAt(0).toUpperCase() + newname.substring(1)
|
||||
}
|
||||
return (
|
||||
<li {...props}>
|
||||
<Tooltip arrow placement="left" title={
|
||||
<span style={{}}>
|
||||
{data.image !== undefined && data.image !== null && data.image.length > 0 ?
|
||||
<img src={data.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={selectedWorkflows.find(wf => wf.id === data.id) !== undefined}
|
||||
/>
|
||||
{newname}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</li>
|
||||
)
|
||||
}}
|
||||
renderInput={(params) => {
|
||||
return (
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
{...params}
|
||||
label="Find your workflows"
|
||||
variant="outlined"
|
||||
<TextField
|
||||
style={{
|
||||
backgroundColor: theme.palette.inputColor,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
}}
|
||||
{...params}
|
||||
label="Find your workflows"
|
||||
variant="outlined"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
: null}
|
||||
: null}
|
||||
<span style={{top: 30, position: "relative",}}>
|
||||
<Typography variant="body1" style={{marginTop: 0,}} onClick={() => {}}>
|
||||
Try it out
|
||||
</Typography>
|
||||
<WorkflowTemplatePopup
|
||||
userdata={userdata}
|
||||
|
||||
globalUrl={globalUrl}
|
||||
img1={inputUsecase.srcimg}
|
||||
srcapp={inputUsecase.srcapp}
|
||||
img2={inputUsecase.dstimg}
|
||||
dstapp={inputUsecase.dstapp}
|
||||
title={inputUsecase.name}
|
||||
description={inputUsecase.description}
|
||||
|
||||
apps={apps}
|
||||
/>
|
||||
</span>
|
||||
{/*
|
||||
|
||||
{/*subcase.matches.length > 0 ?
|
||||
<Grid container style={{maxWidth: 325, marginTop: 10, }}>
|
||||
{subcase.matches.map((workflow, workflowindex) => {
|
||||
return (
|
||||
<Grid key={workflowindex} item index={workflowindex} xs={12}>
|
||||
<WorkflowPaper key={workflowindex} data={workflow} />
|
||||
</Grid>
|
||||
)
|
||||
})}
|
||||
</Grid>
|
||||
:
|
||||
<div>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
No workflow selected yet.
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
{subcase.extra_buttons !== undefined && subcase.extra_buttons !== null && subcase.extra_buttons.length > 0 ?
|
||||
<div style={{marginTop: 25, }}>
|
||||
@@ -852,15 +916,9 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
<Typography variant="body1" style={{marginTop: 15, cursor: "pointer",}} onClick={() => {}}>
|
||||
See other Public Workflows for {} <OpenInNewIcon style={{marginTop: 5, marginLeft: 15, }}/>
|
||||
</Typography>
|
||||
{/*
|
||||
<div>
|
||||
<Typography variant="body1" color="textSecondary">
|
||||
No workflows yet.
|
||||
</Typography>
|
||||
</div>
|
||||
*/}
|
||||
</a>
|
||||
</div>
|
||||
*/}
|
||||
</div>
|
||||
}
|
||||
<div style={{
|
||||
@@ -868,6 +926,8 @@ const UsecaseListComponent = ({keys, isCloud, globalUrl, frameworkData, isLogged
|
||||
width: 350,
|
||||
borderRadius: theme.palette.borderRadius,
|
||||
border: "1px solid rgba(255,255,255,0.3)",
|
||||
padding: 5,
|
||||
backgroundColor: theme.palette.backgroundColor,
|
||||
}}>
|
||||
<AppFramework
|
||||
inputUsecase={inputUsecase}
|
||||
|
||||
Reference in New Issue
Block a user