Fixed last material-ui references

This commit is contained in:
Frikky
2023-08-16 02:37:19 +02:00
parent cfe190edc9
commit b693b960cc
33 changed files with 106 additions and 9548 deletions
-1
View File
@@ -1,7 +1,6 @@
import React, { useState, useEffect } from 'react';
import ReactGA from 'react-ga4';
import theme from '../theme';
//import { useTheme } from '@material-ui/core/styles';
import {Link} from 'react-router-dom';
import { useAlert } from "react-alert";
import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@mui/icons-material';
-54
View File
@@ -1,54 +0,0 @@
import React from "react";
//import List from '@material-ui/core/List';
//import ListItem from '@material-ui/core/ListItem';
//borderTop: "1px solid #385F71"
const FooterStyle = {
right: "0",
left: "0",
bottom: "0",
height: "130px",
backgroundColor: "rgba(15, 14, 31, 1)",
};
const FooterInfo = {
maxWidth: "1150px",
minWidth: "768px",
textAlign: "center",
margin: "auto",
};
const hrefStyle = {
color: "#bdbdbd",
textDecoration: "none",
};
const Footer = (props) => {
return (
<div style={FooterStyle}>
<div style={FooterInfo}>
<Box />
</div>
</div>
);
};
const Box = (props) => {
return (
<div style={{ display: "flex" }}>
<div style={{ flex: "1" }}>
<a style={hrefStyle} href="/about">
<h1>About</h1>
</a>
</div>
<div style={{ flex: "1" }}>
<a style={hrefStyle} href="/privacy-policy">
<h1>Privacy Policy</h1>
</a>
</div>
</div>
);
};
export default Footer;
-1
View File
@@ -1,7 +1,6 @@
import React, {useState} from 'react';
import theme from '../theme.jsx';
import {BrowserView, MobileView} from "react-device-detect";
//import { useTheme } from '@material-ui/core/styles';
import { useNavigate, Link } from "react-router-dom";
import ReactGA from 'react-ga4';
-176
View File
@@ -1,176 +0,0 @@
/* eslint-disable react/no-multi-comp */
import React, { useState } from "react";
import DialogTitle from "@material-ui/core/DialogTitle";
import Dialog from "@material-ui/core/Dialog";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
const LoginDialog = (props) => {
const {
classes,
onClose,
open,
globalUrl,
isLoggedIn,
setIsLoggedIn,
...other
} = props;
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
//const [selectedValue, setSelectedValue] = useState(false);
// Used to swap from login to register. True = login, false = register
const [loginCheck, setLoginCheck] = useState(true);
// Error messages etc
const [loginInfo, setLoginInfo] = useState("");
const handleValidateForm = () => {
return username.length > 1 && password.length > 8;
};
const onSubmit = (e) => {
e.preventDefault();
// Just use this one?
var data =
'{"username": "' + username + '", "password": "' + password + '"}';
var baseurl = globalUrl;
if (loginCheck) {
var url = baseurl + "/login";
fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
console.log(responseJson);
//console.log(e)
if (responseJson["success"] === false) {
setLoginInfo(responseJson["reason"]);
} else {
setLoginInfo("Successful login :)");
onClose();
setIsLoggedIn(true);
}
})
)
.catch((error) => {
setLoginInfo("Error in userdata");
});
} else {
url = baseurl + "/register";
fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
setLoginInfo(responseJson["reason"]);
} else {
setLoginInfo("Successful register :)");
onClose();
setIsLoggedIn(true);
}
})
)
.catch((error) => {
setLoginInfo("Error in userdata");
});
}
};
const onChangeUser = (e) => {
setUsername(e.target.value);
};
const onChangePass = (e) => {
setPassword(e.target.value);
};
const onClickRegister = () => {
setLoginCheck(!loginCheck);
};
//var loginChange = loginCheck ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>;
var formButton = loginCheck ? (
<div>Click to Register</div>
) : (
<div>Click to Login</div>
);
return (
<Dialog modal open={open} onClose={onClose} {...other}>
<DialogTitle>{formtitle}</DialogTitle>
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
Username
<div>
<TextField
required
id="standard-required"
autoComplete="username"
margin="normal"
variant="outlined"
onChange={onChangeUser}
/>
</div>
Password
<div>
<TextField
id="outlined-password-input"
type="password"
autoComplete="current-password"
margin="normal"
variant="outlined"
onChange={onChangePass}
/>
</div>
<div style={{ display: "flex", marginTop: "15px" }}>
<Button
color="secondary"
variant="contained"
type="submit"
style={{ flex: "1", marginRight: "5px" }}
disabled={!handleValidateForm()}
>
SUBMIT
</Button>
<Button
color="primary"
variant="contained"
type="button"
style={{ flex: "1" }}
onClick={onClose}
>
Cancel
</Button>
</div>
{loginInfo}
</form>
<div style={{ display: "flex" }}>
<Button
color="secondary"
variant="contained"
onClick={onClickRegister}
type="button"
style={{ flex: "1" }}
>
{formButton}
</Button>
</div>
</Dialog>
);
};
export default LoginDialog;
-213
View File
@@ -1,213 +0,0 @@
import React, { useState, useRef, useImperativeHandle } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Menu, { MenuProps } from "@material-ui/core/Menu";
import MenuItem, { MenuItemProps } from "@material-ui/core/MenuItem";
import ArrowRight from "@material-ui/icons/ArrowRight";
import clsx from "clsx";
//<MenuItemProps, 'button'>
//export interface NestedMenuItemProps {
// /**
// * Open state of parent `<Menu />`, used to close decendent menus when the
// * root menu is closed.
// */
// parentMenuOpen: boolean;
// /**
// * Component for the container element.
// * @default 'div'
// */
// component: React.ElementType;
// /**
// * Effectively becomes the `children` prop passed to the `<MenuItem/>`
// * element.
// */
// label: React.ReactNode;
// /**
// * @default <ArrowRight />
// */
// rightIcon: React.ReactNode;
// /**
// * Props passed to container element.
// */
// ContainerProps: React.HTMLAttributes;
// //<HTMLElement> &React.RefAttributes<HTMLElement | null>
// /**
// * Props passed to sub `<Menu/>` element
// */
// MenuProps: Omit<MenuProps, 'children'>;
// /**
// * @see https://material-ui.com/api/list-item/
// */
// button: true;
//}
const TRANSPARENT = "rgba(0,0,0,0)";
const useMenuItemStyles = makeStyles((theme) => ({
root: (props: any) => ({
backgroundColor: props.open ? theme.palette.action.hover : TRANSPARENT,
}),
}));
/**
* Use as a drop-in replacement for `<MenuItem>` when you need to add cascading
* menu elements as children to this component.
*/
//const NestedMenuItem = React.forwardRef<NestedMenuItemProps>(
const NestedMenuItem = (props, ref) => {
console.log(props, ref);
//function NestedMenuItem(props, ref) {
const {
parentMenuOpen,
component = "div",
label,
rightIcon = <ArrowRight />,
children,
className,
tabIndex: tabIndexProp,
MenuProps = {},
ContainerProps: ContainerPropsProp = {},
...MenuItemProps
} = props;
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);
const { ref: containerRefProp, ...ContainerProps } = ContainerPropsProp;
const menuItemRef = useRef < HTMLLIElement > null;
useImperativeHandle(ref, () => menuItemRef.current);
const containerRef = useRef < HTMLDivElement > null;
useImperativeHandle(containerRefProp, () => containerRef.current);
const menuContainerRef = useRef < HTMLDivElement > null;
console.log(
"PAST THIS: ",
containerRefProp,
menuItemRef,
containerRef,
menuContainerRef,
ContainerProps
);
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
setIsSubMenuOpen(true);
if (ContainerProps?.onMouseEnter) {
ContainerProps.onMouseEnter(event);
}
};
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
setIsSubMenuOpen(false);
if (ContainerProps?.onMouseLeave) {
ContainerProps.onMouseLeave(event);
}
};
// Check if any immediate children are active
const isSubmenuFocused = () => {
const active = containerRef.current?.ownerDocument?.activeElement;
for (const child of menuContainerRef.current?.children ?? []) {
if (child === active) {
return true;
}
}
return false;
};
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
if (event.target === containerRef.current) {
setIsSubMenuOpen(true);
}
if (ContainerProps?.onFocus) {
ContainerProps.onFocus(event);
}
};
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === "Escape") {
return;
}
if (isSubmenuFocused()) {
event.stopPropagation();
}
const active = containerRef.current?.ownerDocument?.activeElement;
if (event.key === "ArrowLeft" && isSubmenuFocused()) {
containerRef.current?.focus();
}
if (
event.key === "ArrowRight" &&
event.target === containerRef.current &&
event.target === active
) {
console.log("MENU: ", menuContainerRef);
const firstChild = menuContainerRef.current.children[0];
console.log("FIRST: ", firstChild);
firstChild.focus();
}
};
const open = isSubMenuOpen && parentMenuOpen;
const menuItemClasses = useMenuItemStyles({ open });
// Root element must have a `tabIndex` attribute for keyboard navigation
let tabIndex;
if (!props.disabled) {
tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1;
}
console.log("PAST 2! ", tabIndex);
return (
<div
{...ContainerProps}
ref={containerRef}
onFocus={handleFocus}
tabIndex={tabIndex}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onKeyDown={handleKeyDown}
>
<MenuItem
{...MenuItemProps}
className={clsx(menuItemClasses.root, className)}
ref={menuItemRef}
>
{label}
{rightIcon}
</MenuItem>
<Menu
// Set pointer events to 'none' to prevent the invisible Popover div
// from capturing events for clicks and hovers
style={{ pointerEvents: "none" }}
anchorEl={menuItemRef.current}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "left",
}}
open={open}
autoFocus={false}
disableAutoFocus
disableEnforceFocus
onClose={() => {
setIsSubMenuOpen(false);
}}
>
<div ref={menuContainerRef} style={{ pointerEvents: "auto" }}>
{children}
</div>
</Menu>
</div>
);
};
export default NestedMenuItem;
-202
View File
@@ -1,202 +0,0 @@
import React, {useState, useRef, useImperativeHandle} from 'react'
import {makeStyles} from '@material-ui/core/styles'
import Menu, {MenuProps} from '@material-ui/core/Menu'
import MenuItem, {MenuItemProps} from '@material-ui/core/MenuItem'
import ArrowRight from '@material-ui/icons/ArrowRight'
import clsx from 'clsx'
export interface NestedMenuItemProps extends Omit<MenuItemProps, 'button'> {
/**
* Open state of parent `<Menu />`, used to close decendent menus when the
* root menu is closed.
*/
parentMenuOpen: boolean
/**
* Component for the container element.
* @default 'div'
*/
component?: React.ElementType
/**
* Effectively becomes the `children` prop passed to the `<MenuItem/>`
* element.
*/
label?: React.ReactNode
/**
* @default <ArrowRight />
*/
rightIcon?: React.ReactNode
/**
* Props passed to container element.
*/
ContainerProps?: React.HTMLAttributes<HTMLElement> &
React.RefAttributes<HTMLElement | null>
/**
* Props passed to sub `<Menu/>` element
*/
MenuProps?: Omit<MenuProps, 'children'>
/**
* @see https://material-ui.com/api/list-item/
*/
button?: true | undefined
}
const TRANSPARENT = 'rgba(0,0,0,0)'
const useMenuItemStyles = makeStyles((theme) => ({
root: (props: any) => ({
backgroundColor: props.open ? theme.palette.action.hover : TRANSPARENT
})
}))
/**
* Use as a drop-in replacement for `<MenuItem>` when you need to add cascading
* menu elements as children to this component.
*/
const NestedMenuItem = React.forwardRef<
HTMLLIElement | null,
NestedMenuItemProps
>(function NestedMenuItem(props, ref) {
const {
parentMenuOpen,
component = 'div',
label,
rightIcon = <ArrowRight />,
children,
className,
tabIndex: tabIndexProp,
MenuProps = {},
ContainerProps: ContainerPropsProp = {},
...MenuItemProps
} = props
const {ref: containerRefProp, ...ContainerProps} = ContainerPropsProp
const menuItemRef = useRef<HTMLLIElement>(null)
useImperativeHandle(ref, () => menuItemRef.current)
const containerRef = useRef<HTMLDivElement>(null)
useImperativeHandle(containerRefProp, () => containerRef.current)
const menuContainerRef = useRef<HTMLDivElement>(null)
const [isSubMenuOpen, setIsSubMenuOpen] = useState(false)
const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {
setIsSubMenuOpen(true)
if (ContainerProps?.onMouseEnter) {
ContainerProps.onMouseEnter(event)
}
}
const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {
setIsSubMenuOpen(false)
if (ContainerProps?.onMouseLeave) {
ContainerProps.onMouseLeave(event)
}
}
// Check if any immediate children are active
const isSubmenuFocused = () => {
const active = containerRef.current?.ownerDocument?.activeElement
for (const child of menuContainerRef.current?.children ?? []) {
if (child === active) {
return true
}
}
return false
}
const handleFocus = (event: React.FocusEvent<HTMLElement>) => {
if (event.target === containerRef.current) {
setIsSubMenuOpen(true)
}
if (ContainerProps?.onFocus) {
ContainerProps.onFocus(event)
}
}
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {
if (event.key === 'Escape') {
return
}
if (isSubmenuFocused()) {
event.stopPropagation()
}
const active = containerRef.current?.ownerDocument?.activeElement
if (event.key === 'ArrowLeft' && isSubmenuFocused()) {
containerRef.current?.focus()
}
if (
event.key === 'ArrowRight' &&
event.target === containerRef.current &&
event.target === active
) {
const firstChild = menuContainerRef.current?.children[0] as
| HTMLElement
| undefined
firstChild?.focus()
}
}
const open = isSubMenuOpen && parentMenuOpen
const menuItemClasses = useMenuItemStyles({open})
// Root element must have a `tabIndex` attribute for keyboard navigation
let tabIndex
if (!props.disabled) {
tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1
}
return (
<div
{...ContainerProps}
ref={containerRef}
onFocus={handleFocus}
tabIndex={tabIndex}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onKeyDown={handleKeyDown}
>
<MenuItem
{...MenuItemProps}
className={clsx(menuItemClasses.root, className)}
ref={menuItemRef}
>
{label}
{rightIcon}
</MenuItem>
<Menu
// Set pointer events to 'none' to prevent the invisible Popover div
// from capturing events for clicks and hovers
style={{pointerEvents: 'none'}}
anchorEl={menuItemRef.current}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left'
}}
open={open}
autoFocus={false}
disableAutoFocus
disableEnforceFocus
onClose={() => {
setIsSubMenuOpen(false)
}}
>
<div ref={menuContainerRef} style={{pointerEvents: 'auto'}}>
{children}
</div>
</Menu>
</div>
)
})
export default NestedMenuItem
+106 -101
View File
@@ -1,101 +1,106 @@
import React, {useState} from 'react';
import theme from '../theme.jsx';
import {isMobile} from "react-device-detect";
import ReactGA from 'react-ga4';
import {TextField, Typography, Button} from '@material-ui/core';
const Newsletter = (props) => {
const { globalUrl, } = props;
const [email, setEmail] = useState("");
const [msg, setMsg] = useState("");
const [buttonActive, setButtonActive] = useState(true);
const buttonStyle = {minWidth: 300, borderRadius: 30, height: 60, width: 140, margin: isMobile ? "15px auto 15px auto" : "20px 20px 20px 10px", fontSize: 18,}
const newsletterSignup = (inemail) => {
if (inemail.length < 4) {
setMsg("Invalid email")
setButtonActive(true)
return
}
setButtonActive(false)
const data = {"email": inemail}
const url = globalUrl+'/api/v1/functions/newsletter_signup'
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
})
.then(response =>
response.json().then(responseJson => {
setButtonActive(true)
setMsg(responseJson["reason"])
if (responseJson["success"] === false) {
} else {
setEmail("")
}
}),
)
.catch(error => {
setMsg("Something went wrong: ", error.toString())
setButtonActive(true)
});
}
return (
<div style={{margin: "auto", color: "white", textAlign: "center",}}>
<Typography variant="h4" style={{marginTop: 35,}}>
Security Automation Newsletter
</Typography>
<Typography variant="h6" style={{color: "#7d7f82", marginTop: 20, }}>
Defensive security is 99% noise. Join us to sift through it.
</Typography>
<div style={{}}>
<TextField
style={{minWidth: isMobile ? "90%" : 450, backgroundColor: theme.palette.inputColor, marginTop: 20, borderRadius: 10, }}
InputProps={{
style:{
borderRadius: 10,
height: 60,
color: "white",
},
}}
color="primary"
value={email}
onChange={(e) => {
setEmail(e.target.value)
}}
placeholder="Your email"
id="standard-required"
margin="normal"
variant="outlined"
/>
</div>
<Button
variant="contained"
color="primary"
style={buttonStyle}
disabled={!buttonActive}
onClick={() => {
newsletterSignup(email)
ReactGA.event({
category: "newsletter",
action: `signup_click`,
label: "",
})
}}
>
Sign up
</Button>
<div/>
{msg}
</div>
)
}
export default Newsletter;
import React, {useState} from 'react';
import { useTheme } from '@mui/styles';
import {isMobile} from "react-device-detect";
import ReactGA from 'react-ga4';
import {
TextField,
Typography,
Button
} from '@mui/material';
const Newsletter = (props) => {
const { globalUrl, } = props;
const theme = useTheme();
const [email, setEmail] = useState("");
const [msg, setMsg] = useState("");
const [buttonActive, setButtonActive] = useState(true);
const buttonStyle = {minWidth: 300, borderRadius: 30, height: 60, width: 140, margin: isMobile ? "15px auto 15px auto" : "20px 20px 20px 10px", fontSize: 18,}
const newsletterSignup = (inemail) => {
if (inemail.length < 4) {
setMsg("Invalid email")
setButtonActive(true)
return
}
setButtonActive(false)
const data = {"email": inemail}
const url = globalUrl+'/api/v1/functions/newsletter_signup'
fetch(url, {
method: 'POST',
body: JSON.stringify(data),
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
})
.then(response =>
response.json().then(responseJson => {
setButtonActive(true)
setMsg(responseJson["reason"])
if (responseJson["success"] === false) {
} else {
setEmail("")
}
}),
)
.catch(error => {
setMsg("Something went wrong: ", error.toString())
setButtonActive(true)
});
}
return (
<div style={{margin: "auto", color: "white", textAlign: "center",}}>
<Typography variant="h4" style={{marginTop: 35,}}>
Security Automation Newsletter
</Typography>
<Typography variant="h6" style={{color: "#7d7f82", marginTop: 20, }}>
Defensive security is 99% noise. Join us to sift through it.
</Typography>
<div style={{}}>
<TextField
style={{minWidth: isMobile ? "90%" : 450, backgroundColor: theme.palette.inputColor, marginTop: 20, borderRadius: 10, }}
InputProps={{
style:{
borderRadius: 10,
height: 60,
color: "white",
},
}}
color="primary"
value={email}
onChange={(e) => {
setEmail(e.target.value)
}}
placeholder="Your email"
id="standard-required"
margin="normal"
variant="outlined"
/>
</div>
<Button
variant="contained"
color="primary"
style={buttonStyle}
disabled={!buttonActive}
onClick={() => {
newsletterSignup(email)
ReactGA.event({
category: "newsletter",
action: `signup_click`,
label: "",
})
}}
>
Sign up
</Button>
<div/>
{msg}
</div>
)
}
export default Newsletter;
-1
View File
@@ -1,6 +1,5 @@
import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { useParams, useNavigate, Link } from "react-router-dom";
//import { useTheme } from "@material-ui/core/styles";
import theme from '../theme.jsx';
import { useAlert } from "react-alert";
-3
View File
@@ -6,7 +6,6 @@ import theme from '../theme.jsx';
import { validateJson, GetIconInfo } from "../views/Workflows.jsx";
import { GetParsedPaths } from "../views/Apps.jsx";
import { sortByKey } from "../views/AngularWorkflow.jsx";
//import NestedMenuItem from "material-ui-nested-menu-item-v5";
import { NestedMenuItem } from "mui-nested-menu";
import { useAlert } from "react-alert";
@@ -86,7 +85,6 @@ import {
Circle as CircleIcon,
SquareFoot as SquareFootIcon,
} from '@mui/icons-material';
//} from "@material-ui/icons";
//import CodeMirror from "@uiw/react-codemirror";
@@ -113,7 +111,6 @@ const useStyles = makeStyles({
},
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",
},
-177
View File
@@ -1,177 +0,0 @@
import React, { useState } from "react";
import DialogTitle from "@material-ui/core/DialogTitle";
import Dialog from "@material-ui/core/Dialog";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import Divider from "@material-ui/core/Divider";
const SettingsDialog = (props) => {
const {
classes,
onClose,
settingsOpen,
settingsData,
globalUrl,
isLoggedIn,
setIsLoggedIn,
...other
} = props;
const [password1, setPassword1] = useState("");
const [password2, setPassword2] = useState("");
const [password3, setPassword3] = useState("");
const handleValidateForm = () => {
var passlength = 10;
if (
password1 === password2 &&
password1.length >= passlength &&
password3.length >= passlength
) {
return true;
}
return false;
};
const onChangePass1 = (e) => {
setPassword1(e.target.value);
};
const onChangePass2 = (e) => {
setPassword2(e.target.value);
};
const onChangePass3 = (e) => {
setPassword3(e.target.value);
};
const onSubmitPassReset = () => {
console.log("Should change password");
// Rofl, this can't possibly be typesafe
var data =
'{"password1": "' +
password1 +
'", "password2": "' +
password2 +
'", "password3": "' +
password3 +
'"}';
fetch(globalUrl + "/passwordreset", {
body: data,
method: "POST",
headers: {
"Content-Type": "application/json",
},
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
if (responseJson.status === true) {
console.log("SUCCESS");
}
})
.catch((error) => {
console.log(error);
});
};
//PaperProps={{style: {minWidth: "500px"}}
return (
<Dialog open={settingsOpen} onClose={() => onClose()} {...other}>
<DialogTitle>Settings</DialogTitle>
<Divider />
<div style={{ marginLeft: "15px", marginRight: "15px" }}>
<h3>Username</h3>
{settingsData.username}
</div>
<div
style={{
marginLeft: "15px",
marginRight: "15px",
marginBottom: "15px",
}}
>
<h3>ApiKey</h3>
<TextField
id="outlined-read-only-input"
defaultValue={settingsData.apikey}
value={settingsData.apikey}
style={{ width: 320 }}
InputProps={{
readOnly: true,
}}
variant="outlined"
/>
</div>
<Divider />
<form style={{ margin: "15px 15px 15px 15px" }}>
<h3>Change password</h3>
<div>
<TextField
id="standard-password-input"
label="Current password"
type="password"
name="password"
style={{ width: 320 }}
placeholder="********************************"
autoComplete="current-password"
margin="normal"
variant="outlined"
onChange={onChangePass1}
/>
</div>
<div>
<TextField
label="Confirm current password"
type="password"
placeholder="********************************"
name="password"
style={{ width: 320 }}
autoComplete="current-password"
margin="normal"
variant="outlined"
onChange={onChangePass2}
/>
</div>
<div>
<TextField
label="New password"
type="password"
name="password"
placeholder="********************************"
style={{ width: 320 }}
margin="normal"
variant="outlined"
onChange={onChangePass3}
/>
</div>
<div style={{ display: "flex", marginTop: "10px" }}>
<Button
color="secondary"
variant="contained"
onClick={onSubmitPassReset}
type="button"
style={{ flex: "1", marginRight: "5px" }}
disabled={!handleValidateForm()}
>
SUBMIT
</Button>
<Button
color="primary"
variant="contained"
type="button"
style={{ flex: "1" }}
onClick={onClose}
>
Cancel
</Button>
</div>
</form>
</Dialog>
);
};
export default SettingsDialog;
-291
View File
@@ -1,291 +0,0 @@
import React, { useState, useEffect, useLayoutEffect } from "react";
import theme from '../theme';
import {
Chip,
Typography,
Paper,
Avatar,
Grid,
Tooltip,
} from "@material-ui/core";
import {
AvatarGroup,
} from "@mui/material"
import {
Restore as RestoreIcon,
Edit as EditIcon,
BubbleChart as BubbleChartIcon,
MoreVert as MoreVertIcon,
} from '@material-ui/icons';
import { useNavigate, Link, useParams } from "react-router-dom";
const workflowActionStyle = {
display: "flex",
width: 160,
height: 44,
justifyContent: "space-between",
}
const paperAppStyle = {
minHeight: 130,
maxHeight: 130,
overflow: "hidden",
width: "100%",
color: "white",
backgroundColor: theme.palette.surfaceColor,
padding: "12px 12px 0px 15px",
borderRadius: 5,
display: "flex",
boxSizing: "border-box",
position: "relative",
}
const chipStyle = {
backgroundColor: "#3d3f43",
marginRight: 5,
paddingLeft: 5,
paddingRight: 5,
height: 28,
cursor: "pointer",
borderColor: "#3d3f43",
color: "white",
}
const WorkflowPaper = (props) => {
const { data } = props;
let navigate = useNavigate();
const [open, setOpen] = React.useState(false);
const [anchorEl, setAnchorEl] = React.useState(null);
const appGroup = data.action_references === undefined || data.action_references === null ? [] : data.action_references
//console.log("Workflow: ", data)
var boxColor = "#86c142";
var parsedName = data.name;
if (
parsedName !== undefined &&
parsedName !== null &&
parsedName.length > 20
) {
parsedName = parsedName.slice(0, 21) + "..";
}
const imageStyle = {
width: 24,
height: 24,
marginRight: 10,
border: "1px solid rgba(255,255,255,0.3)",
}
var image = data.creator_info !== undefined && data.creator_info !== null && data.creator_info.image !== undefined && data.creator_info.image !== null && data.creator_info.image.length > 0 ? <Avatar alt={data.creator} src={data.creator_info.image} style={imageStyle}/> : <Avatar alt={"shuffle_image"} src={theme.palette.defaultImage} style={imageStyle}/>
const creatorname = data.creator_info !== undefined && data.creator_info !== null && data.creator_info.username !== undefined && data.creator_info.username !== null && data.creator_info.username.length > 0 ? data.creator_info.username : ""
var orgName = "";
var orgId = "";
if ((data.objectID === undefined || data.objectID === null) && data.id !== undefined && data.id !== null) {
data.objectID = data.id
}
//console.log("IMG: ", data)
var parsedUrl = `/workflows/${data.objectID}`
if (data.__queryID !== undefined && data.__queryID !== null) {
parsedUrl += `?queryID=${data.__queryID}`
}
return (
<div style={{width: "100%", position: "relative",}}>
<Paper square style={paperAppStyle}>
<div
style={{
position: "absolute",
bottom: 1,
left: 1,
height: 12,
width: 12,
backgroundColor: boxColor,
borderRadius: "0 100px 0 0",
}}
/>
<Grid
item
style={{ display: "flex", flexDirection: "column", width: "100%" }}
>
<Grid item style={{ display: "flex", maxHeight: 34 }}>
<Tooltip title={`${creatorname}`} placement="bottom">
<div
style={{ cursor: data.creator_info !== undefined ? "pointer" : "inherit" }}
onClick={() => {
if (data.creator_info !== undefined) {
navigate("/creators/"+data.creator_info.username)
}
}}
>
{image}
</div>
</Tooltip>
<Tooltip title={`Edit ${data.name}`} placement="bottom">
<Typography
variant="body1"
style={{
marginBottom: 0,
paddingBottom: 0,
maxHeight: 30,
flex: 10,
}}
>
<Link
to={parsedUrl}
style={{ textDecoration: "none", color: "inherit" }}
>
{parsedName}
</Link>
</Typography>
</Tooltip>
</Grid>
<Grid item style={workflowActionStyle}>
{appGroup.length > 0 ?
<div style={{display: "flex", marginTop: 8, }}>
<AvatarGroup max={4} style={{marginLeft: 5, maxHeight: 24,}}>
{appGroup.map((app, index) => {
return (
<div
key={index}
style={{
height: 24,
width: 24,
filter: "brightness(0.6)",
cursor: "pointer",
}}
onClick={() => {
navigate("/apps/"+app.id)
}}
>
<Tooltip color="primary" title={app.name} placement="bottom">
<Avatar alt={app.name} src={app.image_url} style={{width: 24, height: 24}}/>
</Tooltip>
</div>
)
})}
</AvatarGroup>
</div>
:
<Tooltip color="primary" title="Action amount" placement="bottom">
<span style={{ color: "#979797", display: "flex" }}>
<BubbleChartIcon
style={{ marginTop: "auto", marginBottom: "auto" }}
/>
<Typography
style={{
marginLeft: 5,
marginTop: "auto",
marginBottom: "auto",
}}
>
{data.actions === undefined || data.actions === null ? 1 : data.actions.length}
</Typography>
</span>
</Tooltip>
}
<Tooltip
color="primary"
title="Trigger amount"
placement="bottom"
>
<span
style={{ marginLeft: 15, color: "#979797", display: "flex" }}
>
<RestoreIcon
style={{
color: "#979797",
marginTop: "auto",
marginBottom: "auto",
}}
/>
<Typography
style={{
marginLeft: 5,
marginTop: "auto",
marginBottom: "auto",
}}
>
{data.triggers === undefined || data.triggers === null ? 1 : data.triggers.length}
</Typography>
</span>
</Tooltip>
<Tooltip color="primary" title="Subflows used" placement="bottom">
<span
style={{
marginLeft: 15,
display: "flex",
color: "#979797",
cursor: "pointer",
}}
onClick={() => {
}}
>
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
style={{
color: "#979797",
marginTop: "auto",
marginBottom: "auto",
}}
>
<path
d="M0 0H15V15H0V0ZM16 16H18V18H16V16ZM16 13H18V15H16V13ZM16 10H18V12H16V10ZM16 7H18V9H16V7ZM16 4H18V6H16V4ZM13 16H15V18H13V16ZM10 16H12V18H10V16ZM7 16H9V18H7V16ZM4 16H6V18H4V16Z"
fill="#979797"
/>
</svg>
<Typography
style={{
marginLeft: 5,
marginTop: "auto",
marginBottom: "auto",
}}
>
{0}
</Typography>
</span>
</Tooltip>
</Grid>
<Grid
item
style={{
justifyContent: "left",
overflow: "hidden",
marginTop: 5,
}}
>
{data.tags !== undefined && data.tags !== null
? data.tags.map((tag, index) => {
if (index >= 3) {
return null;
}
return (
<Chip
key={index}
style={chipStyle}
label={tag}
variant="outlined"
color="primary"
/>
);
})
: null}
</Grid>
</Grid>
</Paper>
</div>
)
}
export default WorkflowPaper
-1
View File
@@ -369,7 +369,6 @@ const useStyles = makeStyles({
},
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",
},
-468
View File
@@ -1,468 +0,0 @@
import { Grid, Divider, List, ListItem, ListItemText } from "@mui/material";
import { experimentalStyled as styled } from '@mui/material/styles';
import Typography from "@material-ui/core/Typography";
import Paper from "@material-ui/core/Paper";
import Button from '@mui/material/Button';
import Box from '@material-ui/core/Box';
import React, { useState, useEffect } from "react";
import algoliasearch from "algoliasearch";
//import algoliarecommend from "algoliarecommend";
const searchClient = algoliasearch(
"JNSS5CFDZZ",
"db08e40265e2941b9a7d8f644b6e5240"
);
// https://www.algolia.com/doc/api-client/getting-started/install/
/*const algoliarecommend = require('@algolia/recommend');
const client = algoliarecommend(
"NSS5CFDZZ",
"db08e40265e2941b9a7d8f644b6e5240"
);*/
const Item = styled(Paper)(({ theme }) => ({
padding: theme.spacing(2),
border: "0.0625rem solid #b2b2b2",
borderRadius: "1.5625rem",
boxSizing: "content-box",
backgroundColor: "transparent",
width: "200px",
textAlign: 'center',
color: theme.palette.text.secondary,
marginTop: "20px",
marginBottom: "20px",
color: "textPrimary"
}));
const AppExplorer = (props) => {
const [algoliaResult, setAlgoliaResult] = useState("");
const runAlgoliaAppSearch = (query) => {
const index = searchClient.initIndex("appsearch");
index
.search(`${query}`)
.then(({ hits }) => {
setAlgoliaResult(hits);
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
runAlgoliaAppSearch("wazuh")
}, [])
const brandApp = () => {
const index = searchClient.initIndex("appsearch");
const replicaIndex = searchClient.initIndex('appsearch');
replicaIndex.setSettings({
customRanking: [
"asc(time_edited)"
]
})
.then(({ hits }) => {
console.log(hits);
})
.catch((err) => {
console.log(err);
});
};
useEffect(() => {
brandApp()
}, [])
/*const trandingApp = () => {
const index = client.getTrendingGlobalItems([
{
indexName: "appsearch",
threshold: 60
},
])
.then(({ results }) => {
console.log(results);
})
.catch(err => {
console.log(err);
});
};
useEffect(() => {
trandingApp();
}, [])
*/
const SideBar = {
minWidth: 250,
borderRight: "1px solid rgba(255,255,255,0.3)",
left: 0,
position: "sticky",
minHeight: "90vh",
maxHeight: "90vh",
overflowX: "hidden",
overflowY: "auto",
zIndex: 1000,
color: "white"
};
const contentbar = {
padding: "40px",
};
const boxdata = {
paddingLeft: "30px"
}
const link = {
textDecoration: "none"
}
const catItems = (
<div style={SideBar}>
<List>
<ListItem >
<ListItemText>
<span><Typography variant="primary">Categories</Typography></span>
</ListItemText>
</ListItem>
<span></span>
<Divider />
<ListItem>
<ListItemText>
<Button variant="primary">
ASSETS
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
CASES
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
COMMS
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
EDR & AV
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
IAM
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
INTEL
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
NETWORK
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary">
SIEM
</Button>
</ListItemText>
</ListItem>
</List>
</div>
)
return (
<div>
<div style={{ display: "flex" }}>
{catItems}
<div style={contentbar}>
<Grid>
<Grid item xl={8} style={{ "border": "20px" }}>
<Typography type="title" variant="h6">
Getting Started
</Typography>
<div style={{
paddingLeft: "50px",
}}>
</div>
</Grid>
</Grid>
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={{ xs: 1, md: 4 }}
columns={{ xs: 4, sm: 8, md: 12 }}
>
{Array.from(Array(algoliaResult.length)).map((_, index) => (
<Grid item xs={2} sm={4} md={4} key={index}>
<a href={algoliaResult[0]["objectID"]} style={link}>
<Item>
<div class="row">
<div class="column" style={{ float: "left" }}>
<img src={algoliaResult[0]["image_url"]} alt="shuffle" width="50px" />
</div>
<div class="column " style={boxdata}>
<div style={boxdata}>
<Typography align="left" variant="body1">
{algoliaResult[0]["name"]}
</Typography>
</div>
<div style={boxdata}>
<Typography align="left" variant="body2">
{algoliaResult[0]["description"].substring(0, 20)}
</Typography>
</div>
</div>
</div>
</Item>
</a>
</Grid>
))}
</Grid>
</Box>
<Grid item xl={8} style={{ "border": "20px" }}>
<Typography type="title" variant="h6">
Most Popular
</Typography>
<div style={{
paddingLeft: "50px",
}}>
</div>
</Grid>
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={{ xs: 1, md: 3 }}
columns={{ xs: 4, sm: 8, md: 12 }}
>
{Array.from(Array(3)).map((_, index) => (
<Grid item xs={2} sm={4} md={4} key={index}>
<a href="#" style={link}>
<Item>
<div class="row">
<div class="column" style={{ float: "left" }}>
<img src="/images/testing.png" alt="shuffle" width="50px" />
</div>
<div class="column " style={boxdata}>
<div style={boxdata}>
<Typography align="left" variant="body1">
App Name
</Typography>
</div>
<div style={boxdata}>
<Typography align="left" variant="body2">
Description
</Typography>
</div>
</div>
</div>
</Item>
</a>
</Grid>
))}
</Grid>
</Box>
<Grid item xl={8} style={{ "border": "20px" }}>
<Typography type="title" variant="h6">
Brand New
</Typography>
<div style={{
paddingLeft: "50px",
}}>
</div>
</Grid>
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={{ xs: 1, md: 3 }}
columns={{ xs: 4, sm: 8, md: 12 }}
>
{Array.from(Array(3)).map((_, index) => (
<Grid item xs={2} sm={4} md={4} key={index}>
<a href="#" style={link}>
<Item>
<div class="row">
<div class="column" style={{ float: "left" }}>
<img src="/images/testing.png" alt="shuffle" width="50px" />
</div>
<div class="column " style={boxdata}>
<div style={boxdata}>
<Typography align="left" variant="body1">
App Name
</Typography>
</div>
<div style={boxdata}>
<Typography align="left" variant="body2">
Description
</Typography>
</div>
</div>
</div>
</Item>
</a>
</Grid>
))}
</Grid>
</Box>
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={{ xs: 1, md: 3 }}
columns={{ xs: 4, sm: 8, md: 12 }}
>
{Array.from(Array(3)).map((_, index) => (
<Grid item xs={2} sm={4} md={4} key={index}>
<div className="row" >
<div className="column" style={{ float: "left", width: "33.33%", marginTop: "20px", marginBottom: "20px", }}>
<img src="/images/shuffle_logo.png" alt="shuffle" width="200px" />
</div>
</div>
</Grid>
))}
</Grid>
</Box>
<Grid item xl={8} style={{ "border": "20px" }}>
<Typography type="title" variant="h6">
Hybrid work
</Typography>
<div style={{
paddingLeft: "50px",
}}>
</div>
</Grid>
<Box sx={{ flexGrow: 1 }}>
<Grid
container
spacing={{ xs: 1, md: 3 }}
columns={{ xs: 4, sm: 8, md: 12 }}
>
{Array.from(Array(3)).map((_, index) => (
<Grid item xs={2} sm={4} md={4} key={index}>
<a href="#" style={link}>
<Item>
<div class="row">
<div class="column" style={{ float: "left" }}>
<img src="/images/testing.png" alt="shuffle" width="50px" />
</div>
<div class="column " style={boxdata}>
<div style={boxdata}>
<Typography align="left" variant="body1">
App Name
</Typography>
</div>
<div style={boxdata}>
<Typography align="left" variant="body2">
Description
</Typography>
</div>
</div>
</div>
</Item>
</a>
</Grid>
))}
</Grid>
</Box>
<div className="row" style={{ display: "flex" }}>
<div className="col" style={{ width: "40%", marginTop: "50px" }}>
<Typography variant="h6">Don't see it? Build it!</Typography>
<Typography variant="body2">Use our APIs to create an app that makes your working life better.And maybe even share it with the world.</Typography>
<a href="#" target="_blank" rel="nonref"
style={{
background: "#FF4500",
borderRadius: "3.125rem",
color: "#fff",
display: "block",
fontSize: ".9375rem",
fontWeight: "500",
height: "1rem",
letterSpacing: "-.02em",
lineHeight: ".875rem",
marginTop: "1.5rem",
padding: "1.3125rem 1.375rem",
textAlign: "center",
textDecoration: "none",
width: "8.5rem"
}}><span>visit developer portal</span></a>
</div>
<div className="col" style={{ float: "right" }}>
<div className="row" style={{ float: "left", marginLeft: "90px" }}>
<div className="column" style={{ float: "left", margin: "60px 10px 20px 30px" }}>
<img src="/images/demo1.png" alt="shuffle" width="90px" />
</div>
<div className="column" style={{ float: "left", margin: "60px 10px 20px 30px" }}>
<img src="/images/demo1.png" alt="shuffle" width="90px" />
</div>
<div className="column" style={{ float: "left", margin: "60px 10px 20px 30px" }}>
<img src="/images/demo1.png" alt="shuffle" width="90px" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
export default AppExplorer;
-789
View File
@@ -1,789 +0,0 @@
import React from "react";
import { Grid, Container, Divider, CardMedia, List, ListItem, ListItemText } from "@mui/material";
import { makeStyles } from "@material-ui/core/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import { LineChart, LineSeries, BarChart } from "reaviz";
import { Gridline, GridStripe } from "reaviz";
import { GridlineSeries } from "reaviz";
import InputLabel from '@material-ui/core/InputLabel';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import { styled, alpha } from '@mui/material/styles';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import InputBase from '@mui/material/InputBase';
import Badge from '@mui/material/Badge';
import MenuItem from '@mui/material/MenuItem';
import Menu from '@mui/material/Menu';
import MenuIcon from '@mui/icons-material/Menu';
import SearchIcon from '@mui/icons-material/Search';
import AccountCircle from '@mui/icons-material/AccountCircle';
import MailIcon from '@mui/icons-material/Mail';
import NotificationsIcon from '@mui/icons-material/Notifications';
import MoreIcon from '@mui/icons-material/MoreVert';
import SearchField from "../components/Searchfield";
import { SpaRounded } from "@material-ui/icons";
import { isMobile } from "react-device-detect"
const data = [
{
key: new Date("11/29/2019"),
data: 10,
},
{
key: new Date("11/30/2019"),
data: 14,
},
{
key: new Date("12/01/2019"),
data: 5,
},
{
key: new Date("12/02/2019"),
data: 18,
},
];
const useStyles1 = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
const useStyles = makeStyles({
table: {
minWidth: 650,
},
root: {
minWidth: 275,
},
bullet: {
display: "inline-block",
margin: "0 2px",
transform: "scale(0.8)",
},
title: {
fontSize: 14,
},
pos: {
marginBottom: 12,
},
});
function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
createData("Eclair", 262, 16.0, 24, 6.0),
createData("Cupcake", 305, 3.7, 67, 4.3),
createData("Gingerbread", 356, 16.0, 49, 3.9),
];
const Search = styled('div')(({ theme }) => ({
position: 'relative',
borderRadius: theme.shape.borderRadius,
backgroundColor: alpha(theme.palette.common.white, 0.15),
'&:hover': {
backgroundColor: alpha(theme.palette.common.white, 0.25),
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: '100%',
[theme.breakpoints.up('sm')]: {
marginLeft: theme.spacing(3),
width: 'auto',
},
}));
const SearchIconWrapper = styled('div')(({ theme }) => ({
padding: theme.spacing(0, 2),
height: '100%',
position: 'absolute',
pointerEvents: 'none',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}));
const StyledInputBase = styled(InputBase)(({ theme }) => ({
color: 'inherit',
'& .MuiInputBase-input': {
padding: theme.spacing(1, 1, 1, 0),
// vertical padding + font size from searchIcon
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
transition: theme.transitions.create('width'),
width: '100%',
[theme.breakpoints.up('md')]: {
width: '20ch',
},
},
}));
function PrimarySearchAppBar() {
const [anchorEl, setAnchorEl] = React.useState(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleProfileMenuOpen = (event) => {
setAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};
const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};
const handleMobileMenuOpen = (event) => {
setMobileMoreAnchorEl(event.currentTarget);
};
const menuId = 'primary-search-account-menu';
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id={menuId}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Profile</MenuItem>
<MenuItem onClick={handleMenuClose}>My account</MenuItem>
</Menu>
);
const mobileMenuId = 'primary-search-account-menu-mobile';
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{
vertical: 'top',
horizontal: 'right',
}}
id={mobileMenuId}
keepMounted
transformOrigin={{
vertical: 'top',
horizontal: 'right',
}}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton size="large" aria-label="show 4 new mails" color="inherit">
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
</IconButton>
<p>Messages</p>
</MenuItem>
<MenuItem>
<IconButton
size="large"
aria-label="show 17 new notifications"
color="inherit"
>
<Badge badgeContent={17} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
color="inherit"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
</Menu>
);
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="fixed" style={{ backgroundColor: "black", boxShadow: "unset" }}>
<Toolbar>
<img src="/images/Shuffle_logo.png" style={{ height: "3rem", width: "3rem" }} alt="shuffle img" />
<SearchField />
{/* <Box sx={{ flexGrow: 1 }} /> */}
</Toolbar>
</AppBar>
{renderMobileMenu}
{renderMenu}
</Box>
);
}
const AppHub = () => {
const classes = useStyles();
const classes1 = useStyles1();
const [usecases, setUsecases] = React.useState([
{
"name": "1. Collect",
"color": "#c51152",
"list": [
{
"name": "Email management",
"priority": 100,
"type": "communication",
"items": {
"name": "Release a quarantined message",
"items": {}
},
"matches": []
},
{
"name": "EDR to ticket",
"priority": 100,
"type": "edr",
"items": {
"name": "Get host information",
"items": {}
},
"matches": []
},
{
"name": "SIEM to ticket",
"priority": 100,
"type": "siem",
"description": "Ensure tickets are forwarded to the correct destination. Alternatively add enrichment on it's way there.",
"video": "https://www.youtube.com/watch?v=FBISHA7V15c&t=197s&ab_channel=OpenSecure",
"blogpost": "https://medium.com/shuffle-automation/introducing-shuffle-an-open-source-soar-platform-part-1-58a529de7d12",
"reference_image": "/images/detectionframework.png",
"items": {},
"matches": []
},
{
"name": "2-way Ticket synchronization",
"priority": 90,
"items": {},
"matches": []
},
{
"name": "ChatOps",
"priority": 70,
"items": {},
"matches": []
},
{
"name": "Threat Intel received",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Assign tickets",
"priority": 30,
"items": {},
"matches": []
},
{
"name": "Firewall alerts",
"priority": 90,
"items": {
"name": "URL filtering",
"items": {}
},
"matches": []
},
{
"name": "IDS/IPS alerts",
"priority": 90,
"items": {
"name": "Manage policies",
"items": {}
},
"matches": []
},
{
"name": "Deduplicate information",
"priority": 70,
"items": {},
"matches": []
}
],
"matches": []
},
{
"name": "2. Enrich",
"color": "#f4c20d",
"list": [
{
"name": "Internal Enrichment",
"priority": 100,
"items": {
"name": "...",
"items": {}
},
"matches": []
},
{
"name": "External historical Enrichment",
"priority": 90,
"items": {
"name": "...",
"items": {}
},
"matches": []
},
{
"name": "Realtime",
"priority": 50,
"items": {
"name": "Analyze screenshots",
"items": {}
},
"matches": []
}
],
"matches": []
},
{
"name": "3. Detect",
"color": "#3cba54",
"list": [
{
"name": "Search SIEM (Sigma)",
"priority": 90,
"items": {
"name": "Endpoint",
"items": {}
},
"matches": []
},
{
"name": "Search EDR (OSQuery)",
"priority": 90,
"items": {},
"matches": []
},
{
"name": "Search emails (Sublime)",
"priority": 90,
"items": {
"name": "Check headers and IOCs",
"items": {}
},
"matches": []
},
{
"name": "Search IOCs (ioc-finder)",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Search files (Yara)",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Memory Analysis (Volatility)",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "IDS & IPS (Snort/Surricata)",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Validate old tickets",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Honeypot access",
"priority": 50,
"items": {
"name": "...",
"items": {}
},
"matches": []
}
],
"matches": []
},
{
"name": "4. Respond",
"color": "#4885ed",
"list": [
{
"name": "Eradicate malware",
"priority": 90,
"items": {},
"matches": []
},
{
"name": "Quarantine host(s)",
"priority": 90,
"items": {},
"matches": []
},
{
"name": "Block IPs, URLs, Domains and Hashes",
"priority": 90,
"items": {},
"matches": []
},
{
"name": "Trigger scans",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Update indicators (FW, EDR, SIEM...)",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Autoblock activity when threat intel is received",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Lock/Delete/Reset account",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Lock vault",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Increase authentication",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Get policies from assets",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Run ansible scripts",
"priority": 50,
"items": {},
"matches": []
}
],
"matches": []
},
{
"name": "5. Verify",
"color": "#7f00ff",
"list": [
{
"name": "Discover vulnerabilities",
"priority": 80,
"items": {},
"matches": []
},
{
"name": "Discover assets",
"priority": 80,
"items": {},
"matches": []
},
{
"name": "Ensure policies are followed",
"priority": 80,
"items": {},
"matches": []
},
{
"name": "Find Inactive users",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Botnet tracker",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Ensure access rights match HR systems",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Ensure onboarding is followed",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Third party apps in SaaS",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Devices used for your cloud account",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Too much access in GCP/Azure/AWS/ other clouds",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Certificate validation",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Domain investigation with LetsEncrypt",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Monitor new DNS entries for domain with passive DNS",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Monitor and track password dumps",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Monitor for mentions of domain on darknet sites",
"priority": 50,
"items": {},
"matches": []
},
{
"name": "Reporting",
"priority": 50,
"items": {
"name": "Monthly reports",
"items": {
"name": "...",
"items": {}
}
},
"matches": []
}
],
"matches": []
}
]);
const SideBar = {
minWidth: 250,
maxWidth: 300,
borderRight: "1px solid rgba(255,255,255,0.3)",
left: 0,
position: "sticky",
minHeight: "90vh",
maxHeight: "90vh",
overflowX: "hidden",
overflowY: "auto",
zIndex: 1000,
color: "black"
};
const [age, setAge] = React.useState(0);
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<div>
<Card>
<CardContent style={{ padding: 0 }}>
<div style={{
background: "url('/images/home-header-bg.png')", height: "450px", backgroundSize: "cover",
backgroundRepeat: "no-repeat",
backgroundPosition: "center",
position: "relative"
}}>
<div style={{ width: "95%", margin: "auto", position: "relative", height: "450px" }}>
<div>
<PrimarySearchAppBar />
</div>
<div style={{
position: "absolute",
bottom: "10%",
display: "flex",
alignItems: "flex-end",
justifyContent: "space-between",
width: "100%"
}}>
<div>
<img src="/images/Shuffle_logo.png" style={{ height: "4rem", width: "4rem" }} alt="shuffle img" />
<Typography type="title" variant="h1" color="#ef5d29">
SHUFFLE
</Typography>
</div>
<div>
<SearchField />
</div>
</div>
</div>
</div>
</CardContent>
</Card>
<div style={{ display: "flex" }}>
<div style={SideBar}>
<List>
<ListItem >
<ListItemText>
<span style={{ fontSize: "25px", fontFamily: "revert", fontWeight: "bold" }}>Categories</span>
</ListItemText>
</ListItem>
<span></span>
<Divider />
<ListItem>
<ListItemText>
<span style={{ fontSize: "25px", fontFamily: "revert" }}>Workflows</span>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<span style={{ fontSize: "25px", fontFamily: "revert" }}>Apps</span>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<span style={{ fontSize: "25px", fontFamily: "revert" }}>Docs</span>
</ListItemText>
</ListItem>
</List>
</div>
<div style={{ padding: "20px", width: "100%" }}>
<Typography type="title" variant="h2" color="black">
Workflow
</Typography>
<div style={{ width: "100%", minHeight: isMobile ? 0 : 71, maxHeight: isMobile ? 0 : 71, }}>
{!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ?
<div style={{ display: "flex", }}>
<Grid container spacing={2}>
{usecases.map((usecase, index) => {
//console.log(usecase)
return (
<Grid item xs={4}>
<Paper
key={usecase.name}
style={{
flex: 1,
backgroundColor: "transparent",
marginRight: index === usecases.length - 1 ? 0 : 10,
cursor: "pointer",
overflow: "hidden",
padding: 10,
border: "0.0625rem solid #b2b2b2",
borderRadius: "1.5625rem",
boxSizing: "content-box",
cursor: "pointer",
height: "70px",
}}
onClick={() => {
console.log("clicked...")
}}
>
<a href={`/usecases?selected=${usecase.name}`} rel="noopener noreferrer" target="_blank" style={{ textDecoration: "none", }}>
<Typography variant="body1" color="textPrimary">
{usecase.name}
</Typography>
<Typography variant="body2" color="textSecondary">
In use: {usecase.matches.length}/{usecase.list.length}
</Typography>
</a>
</Paper>
</Grid>
)
})}
</Grid>
</div>
: null}
</div>
</div>
</div>
<Card>
<CardContent style={{ padding: 0 }}>
<Typography type="title" variant="h3" color="#ffffff" style={{
backgroundColor: "black", padding: "10px", height: "200px",
display: "flex",
justifyContent: "center",
alignItems: "center"
}}>
footer
</Typography>
</CardContent>
</Card>
</div>
);
};
export default AppHub;
-268
View File
@@ -1,268 +0,0 @@
import React, { useState, useEffect } from "react";
import { Grid, Container, Divider, CardMedia, List, ListItem, ListItemText } from "@mui/material";
import Typography from "@material-ui/core/Typography";
import theme from '../theme';
import {isMobile} from "react-device-detect";
import AppGrid1 from "../components/AppGrid1.jsx"
import WorkflowGrid from "../components/WorkflowGrid.jsx"
import CreatorGrid from "../components/CreatorGrid.jsx"
import DocsGrid from "../components/DocsGrid.jsx"
import Button from '@mui/material/Button';
import { useNavigate, Link } from "react-router-dom";
import {
Tabs,
Paper,
Tab,
} from "@material-ui/core";
import {
Business as BusinessIcon,
Apps as AppsIcon,
Polymer as PolymerIcon,
EmojiObjects as EmojiObjectsIcon,
Description as DescriptionIcon,
} from "@material-ui/icons";
const bodyDivStyle = {
margin: "auto",
maxWidth: 1024,
scrollX: "hidden",
overflowX: "hidden",
}
// Should be different if logged in :|
const Appdemo = (props) => {
const { globalUrl, isLoaded, serverside, userdata, hidemargins, } = props;
const [appCategory,setAppCategory] = useState();
let navigate = useNavigate();
const [curTab, setCurTab] = useState(0);
const iconStyle = { marginRight: 10 };
useEffect(() => {
if (serverside !== true && window.location.search !== undefined && window.location.search !== null) {
const urlSearchParams = new URLSearchParams(window.location.search)
const params = Object.fromEntries(urlSearchParams.entries())
const foundTab = params["tab"]
if (foundTab !== null && foundTab !== undefined) {
for (var key in Object.keys(views)) {
const value = views[key]
console.log(key, value)
if (value === foundTab) {
setConfig("", key)
break
}
}
}
}
}, [])
if (serverside === true) {
return null
}
const boxStyle = {
color: "white",
flex: "1",
marginLeft: 10,
marginRight: 10,
paddingLeft: 30,
paddingRight: 30,
paddingBottom: 30,
paddingTop: hidemargins === true ? 0 : 30,
display: "flex",
flexDirection: "column",
overflowX: "hidden",
minHeight: 400,
}
const NoArguments_NoReturn = () => {
alert('Function Called...');
}
const SideBar = {
minWidth: 250,
maxWidth: 300,
borderRight: "1px solid rgba(255,255,255,0.3)",
left: 0,
position: "sticky",
minHeight: "90vh",
maxHeight: "90vh",
overflowX: "hidden",
overflowY: "auto",
zIndex: 1000,
color: "white"
};
const catItems = (
<div style={SideBar}>
<List>
<ListItem >
<ListItemText>
<span><Typography variant="primary">Categories</Typography></span>
</ListItemText>
</ListItem>
<span></span>
<Divider />
<ListItem>
<ListItemText>
<Button id="ASSETS" variant="primary" onClick={()=>{setAppCategory("assets")}}>
ASSETS
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("cases")}}>
CASES
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("comms")}}>
COMMS
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("edr av")}}>
EDR & AV
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("iam")}}>
IAM
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("intel")}}>
INTEL
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("network")}}>
NETWORK
</Button>
</ListItemText>
</ListItem>
<ListItem>
<ListItemText>
<Button variant="primary" onClick={()=>{setAppCategory("siem")}}>
SIEM
</Button>
</ListItemText>
</ListItem>
</List>
</div>
)
const views = {
0: "apps",
1: "workflows",
2: "docs",
3: "creators",
}
const setConfig = (event, inputValue) => {
const newValue = parseInt(inputValue)
setCurTab(newValue)
if (newValue === 0) {
document.title = "Shuffle - search - apps";
} else if (newValue === 1) {
document.title = "Shuffle - search - workflows";
} else if (newValue === 2) {
document.title = "Shuffle - search - documentation";
} else if (newValue === 3) {
document.title = "Shuffle - search - creators";
} else {
document.title = "Shuffle - search";
}
const urlSearchParams = new URLSearchParams(window.location.search)
const params = Object.fromEntries(urlSearchParams.entries())
const foundQuery = params["q"]
var extraQ = ""
if (foundQuery !== null && foundQuery !== undefined) {
extraQ = "&q="+foundQuery
}
if ((serverside === false || serverside === undefined) && window.location.pathname.includes("/search")) {
navigate(`/search?tab=${views[newValue]}`+extraQ)
}
}
if (isLoaded === false) {
return null
}
// Random names for type & autoComplete. Didn't research :^)
const landingpageDataBrowser =
<div style={{paddingBottom: hidemargins === true ? 0 : 100, color: "white", backgroundColor: theme.palette.surfacColor}}>
<div style={boxStyle}>
<Tabs
style={{width: 610, margin: "auto", marginTop: hidemargins === true ? 0 : 25, }}
value={curTab}
indicatorColor="primary"
textColor="secondary"
onChange={setConfig}
aria-label="disabled tabs example"
>
<Tab
label=<span>
<AppsIcon style={iconStyle} /> Apps
</span>
/>
</Tabs>
{curTab === 0 ?
<AppGrid1 maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} searchValue={appCategory} key={appCategory} />
:
curTab === 1 ?
window.location.pathname === "/search" ?
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
<WorkflowGrid maxRows={3} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 2 ?
<DocsGrid maxRows={6} parsedXs={12} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
curTab === 3 ?
<CreatorGrid parsedXs={4} showSuggestion={true} globalUrl={globalUrl} isMobile={isMobile} userdata={userdata} />
:
null}
</div>
</div>
//{/*alternativeView={true} />*/}
const loadedCheck = isLoaded ?
<div>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
</div>
:
<div>
</div>
// #1f2023?
return(
<div style={{backgroundColor: "#1f2023", display: "flex"}}>
{catItems}
{loadedCheck}
</div>
)
}
export default Appdemo;
-343
View File
@@ -1,343 +0,0 @@
import React, { useState } from 'react';
import { BrowserView, MobileView } from "react-device-detect";
import theme from '../theme.jsx';
import Paper from '@material-ui/core/Paper';
import Button from '@material-ui/core/Button';
import TextField from '@material-ui/core/TextField';
const bodyDivStyle = {
margin: "auto",
textAlign: "center",
width: "900px",
}
// Should be different if logged in :|
const Contact = (props) => {
const { globalUrl, isLoaded } = props;
const boxStyle = {
flex: "1",
marginLeft: "10px",
marginRight: "10px",
paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: theme.palette.surfaceColor,
display: "flex",
flexDirection: "column"
}
const bodyTextStyle = {
color: "#ffffff",
}
const [firstname, setFirstname] = useState("");
const [lastname, setLastname] = useState("");
const [title, setTitle] = useState("");
const [companyname, setCompanyname] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [message, setMessage] = useState("");
const [formMessage, setFormMessage] = useState("");
const submitContact = () => {
const data = {
"firstname": firstname,
"lastname": lastname,
"title": title,
"companyname": companyname,
"email": email,
"phone": phone,
"message": message,
}
console.log(data)
fetch(globalUrl + "/api/v1/contact", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
})
.then(response => response.json())
.then(response => {
if (response.success === true) {
setFormMessage(response.message)
} else {
setFormMessage("Something went wrong. Please contact frikky@shuffler.io.")
}
console.log(response)
})
.catch(error => {
console.log(error)
});
}
// Random names for type & autoComplete. Didn't research :^)
const landingpageDataBrowser =
<div>
<div style={bodyTextStyle}>
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
<h2>Lets talk!</h2>
</div>
<div style={{ display: "flex" }}>
<Paper style={boxStyle}>
<h2>Contact Details</h2>
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField
required
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="First Name"
type="firstname"
id="standard-required"
autoComplete="firstname"
margin="normal"
variant="outlined"
onChange={e => setFirstname(e.target.value)}
/>
<TextField
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="Last Name"
type="lastname"
id="standard"
autoComplete="lastname"
margin="normal"
variant="outlined"
onChange={e => setLastname(e.target.value)}
/>
</div>
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="Job Title"
type="jobtitle"
id="standard-required"
autoComplete="jobtitle"
margin="normal"
variant="outlined"
onChange={e => setTitle(e.target.value)}
/>
<TextField
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
type="companyname"
placeholder="Company Name"
id="standard-required"
autoComplete="companyname"
margin="normal"
variant="outlined"
onChange={e => setCompanyname(e.target.value)}
/>
</div>
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField
required
style={{ flex: "1", marginRight: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="Email"
type="email"
id="standard-required"
autoComplete="email"
margin="normal"
variant="outlined"
onChange={e => setEmail(e.target.value)}
/>
<TextField
style={{ flex: "1", marginLeft: "15px", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
type="phone"
placeholder="Phone number"
id="standard-required"
autoComplete="phone"
margin="normal"
variant="outlined"
onChange={e => setPhone(e.target.value)}
/>
</div>
<div style={{ flex: 1 }}>
<h2>Message</h2>
</div>
<div style={{ flex: 4 }}>
<TextField
multiline
InputProps={{
style: {
color: "white",
},
}}
color="primary"
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
rows="6"
fullWidth={true}
placeholder="What can we help you with?"
id="filled-multiline-static"
margin="normal"
variant="outlined"
onChange={e => setMessage(e.target.value)}
/>
</div>
<Button
disabled={email.length <= 0 || message.length <= 0}
style={{ width: "100%", height: "60px", marginTop: "10px" }}
variant="contained"
color="primary"
onClick={submitContact}
>
Submit
</Button>
<h3>{formMessage}</h3>
</Paper>
</div>
</div>
const landingpageDataMobile =
<div style={{ paddingBottom: "50px" }}>
<div style={{ color: "white", textAlign: "center" }}>
<h3 style={{ color: "#f85a3e" }}>Contact us</h3>
<h2>Lets talk!</h2>
</div>
<div style={{ display: "flex" }}>
<Paper style={boxStyle}>
<h2>Contact Details</h2>
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField
required
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="Name"
type="firstname"
id="standard-required"
autoComplete="firstname"
margin="normal"
variant="outlined"
onChange={e => setFirstname(e.target.value)}
/>
</div>
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<TextField
required
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
fullWidth={true}
placeholder="Email"
type="email"
id="standard-required"
autoComplete="email"
margin="normal"
variant="outlined"
onChange={e => setEmail(e.target.value)}
/>
</div>
<div style={{ flex: 1 }}>
<h2>Message</h2>
</div>
<div style={{ flex: 4 }}>
<TextField
multiline
style={{ flex: "1", backgroundColor: theme.palette.inputColor }}
InputProps={{
style: {
color: "white",
},
}}
color="primary"
rows="6"
fullWidth={true}
placeholder="What can we help you with?"
id="filled-multiline-static"
margin="normal"
variant="outlined"
onChange={e => setMessage(e.target.value)}
/>
</div>
<Button
disabled={email.length <= 0 || message.length <= 0}
style={{ width: "100%", height: "60px", marginTop: "10px" }}
variant="contained"
color="primary"
onClick={submitContact}
>
Submit
</Button>
<h3>{formMessage}</h3>
</Paper>
</div>
</div>
const loadedCheck = isLoaded ?
<div>
<BrowserView>
<div style={bodyDivStyle}>{landingpageDataBrowser}</div>
</BrowserView>
<MobileView>
{landingpageDataMobile}
</MobileView>
</div>
:
<div>
</div>
return (
<div>
{loadedCheck}
</div>
)
}
export default Contact;
-1
View File
@@ -83,7 +83,6 @@ const useStyles = makeStyles({
},
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",
},
-1
View File
@@ -93,7 +93,6 @@ const useStyles = makeStyles({
},
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",
},
File diff suppressed because it is too large Load Diff
-393
View File
@@ -1,393 +0,0 @@
import React, { useState, useEffect } from "react";
import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";
import Divider from "@material-ui/core/Divider";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import WebhookImage from "../assets/img/webhook.png";
import KafkaImage from "../assets/img/kafka.png";
import EditWorkflow from "./EditWorkflow";
const EditWebhook = (props) => {
const { globalUrl, isLoaded } = props;
// FIXME
//const [webhookData, setWebhookData] = useState(webhooktest)
const [webhookData, setWebhookData] = useState({});
const [workflows, setWorkflows] = useState([]);
const [firstrequest, setFirstrequest] = React.useState(true);
const [selectedWorkflows, setSelectedWorkflows] = useState([]);
const getWorkflows = () => {
fetch(globalUrl + "/api/v1/workflows", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for workflows :O!");
}
return response.json();
})
.then((responseJson) => {
setWorkflows(responseJson);
})
.catch((error) => {
console.log(error);
});
};
const setWebhook = (inputdata) => {
console.log(inputdata);
fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
body: JSON.stringify(inputdata),
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
})
.catch((error) => {
console.log(error);
});
};
const getCurrentWebhook = () => {
fetch(globalUrl + "/api/v1/hooks/" + props.match.params.key, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200!");
window.location.pathname = "webhooks";
}
return response.json();
})
.then((responseJson) => {
if (responseJson.actions === null) {
responseJson.actions = [];
}
if (responseJson.transforms === null) {
responseJson.transforms = [];
}
setWebhookData(responseJson);
})
.catch((error) => {
console.log(error);
//window.location.pathname = "webhooks"
});
};
useEffect(() => {
if (firstrequest) {
setFirstrequest(false);
getCurrentWebhook();
if (workflows.length <= 0) {
getWorkflows();
}
}
// After everything is loaded
if (
Object.getOwnPropertyNames(webhookData).length > 0 &&
webhookData.actions.length > 0 &&
workflows.length > 0 &&
selectedWorkflows.length === 0
) {
// Setting startup actions. making like this in case we want other actions
var tmpActionWorkflows = [];
for (var key in webhookData.actions) {
if (webhookData.actions[key].type === "workflow") {
tmpActionWorkflows.push(webhookData.actions[key]);
}
}
// Fix duplicates... Meh
var foundWorkflowIds = [];
var tmpWorkflows = [];
for (key in tmpActionWorkflows) {
if (foundWorkflowIds.includes(tmpActionWorkflows[key].id)) {
continue;
}
for (var subkey in workflows) {
if (tmpActionWorkflows[key].id === workflows[subkey]["id_"]) {
console.log(tmpActionWorkflows[key].id, workflows[subkey]["id_"]);
foundWorkflowIds.push(tmpActionWorkflows[key].id);
tmpWorkflows.push(workflows[subkey]);
break;
}
}
}
if (tmpWorkflows.length > 0) {
setSelectedWorkflows(tmpWorkflows);
}
}
});
const hookPicture =
Object.getOwnPropertyNames(webhookData).length > 0 &&
webhookData.type === "webhook" ? (
<img src={WebhookImage} alt="webhook" width="100px" height="100px" />
) : (
<img src={KafkaImage} alt="MQ" width="100px" height="100px" />
);
const executeHook = (action) => {
fetch(
globalUrl + "/api/v1/hooks/" + props.match.params.key + "/" + action,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
}
)
.then((response) => response.json())
.then((responseJson) => {
setWebhookData({});
})
.catch((error) => {
console.log(error);
});
};
const headerPaperStyle = {
display: "flex",
maxHeight: "800px",
minHeight: "800px",
margin: "10px 30px 10px 10px",
padding: "10px 5px 5px 5px",
flexDirection: "column",
};
// FIXME - add with counter to change the correct one (not just edit)
const addNewWorkflow = (event) => {
// Verify if it already exists in the array. Returns if it exists
for (var key in selectedWorkflows) {
var item = selectedWorkflows[key];
if (item["id_"] === event.target.value["id_"]) {
return;
}
}
// FIXME - make this possible for all accounts
if (selectedWorkflows.length === 0) {
console.log("ADD FIRST ITEM FOR SELECTEDWORKFLOWS");
console.log(event.target.value);
// Cleanup previous actions
var newActions = [];
if (webhookData.actions.length > 0) {
for (key in webhookData.actions) {
if (
webhookData.actions[key].type === "" ||
webhookData.actions[key].type === undefined
) {
continue;
}
newActions.push(webhookData.actions[key]);
}
}
// FIXME - how to stringify this better hurr
var formattedWorkflow = {
type: "workflow",
name: event.target.value.name,
id: event.target.value.id_,
field: "",
};
// FIXME: patch this n
newActions.push(formattedWorkflow);
console.log(newActions);
webhookData.actions = newActions;
setWebhook(webhookData);
}
var tmpSelectedWorkflows = [].concat(selectedWorkflows, [
event.target.value,
]);
setSelectedWorkflows(tmpSelectedWorkflows);
};
// FIXME
// Create a list with + button
// For each, choose the new workflow I wanna add
// Current: JUST ONE
const selectedWorkflowIds = selectedWorkflows.map((data) => {
return data["id_"];
});
const availableWorkflows = workflows.filter(
(data) => !selectedWorkflowIds.includes(data["id_"])
);
const WorkflowSelect = (counter) => {
if (selectedWorkflows[counter.counter] === undefined) {
return null;
}
console.log(selectedWorkflows[0]);
console.log(selectedWorkflows[0]);
console.log(selectedWorkflows[0]);
console.log(selectedWorkflows[counter.counter]);
console.log(selectedWorkflows[counter.counter].name);
return (
<div>
Workflow select:
<Select
value={selectedWorkflows[counter.counter].name}
onChange={(event) => {
addNewWorkflow(event, counter.counter);
}}
displayEmpty
name="workflow"
>
{availableWorkflows.map((data) => (
<MenuItem key={data.name} value={data} name={data.name}>
{data.name}
</MenuItem>
))}
</Select>
</div>
);
};
const extraWorkflow =
workflows.length > 0 && availableWorkflows.length > 0 ? (
<WorkflowSelect counter={selectedWorkflows.length} />
) : null;
const multiWorkflowSelect =
workflows.length > 0 && selectedWorkflows.length > 0 ? (
<div>
{selectedWorkflows.map((data, count) => (
<WorkflowSelect key={count} counter={count} />
))}
{extraWorkflow}
</div>
) : (
<WorkflowSelect counter={0} />
);
const headerInfo =
Object.getOwnPropertyNames(webhookData).length > 0 ? (
<div>
<Paper style={headerPaperStyle}>
<div style={{ display: "flex", flex: "1" }}>
<div style={{ flex: "1" }}>{hookPicture}</div>
<div
style={{ display: "flex", flexDirection: "column", flex: "5" }}
>
<div style={{ flex: "1" }}>
<h1>Name: {webhookData.info.name}</h1>
</div>
</div>
</div>
<div style={{ flex: "4" }}>
Description: {webhookData.info.description}
<div>Id: {webhookData.id}</div>
<div>Url: {webhookData.info.url}</div>
<div>Type: {webhookData.type}</div>
<div>Status: {webhookData.status}</div>
<div>
CHOOSE ACTIONS:
{multiWorkflowSelect}
</div>
</div>
<Divider />
<div style={{ flex: "1", display: "flex", flexDirection: "row" }}>
<div style={{ flex: "1" }}>
<Button
disabled={
webhookData.running === true && webhookData.name !== ""
}
onClick={() => {
executeHook("start");
}}
style={{
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
}}
variant="outlined"
color="primary"
>
Start {webhookData.type}
</Button>
</div>
<div style={{ flex: "1" }}>
<Button
disabled={webhookData.running === false}
onClick={() => {
executeHook("stop");
}}
style={{
left: "50%",
top: "50%",
transform: "translate(-50%, -50%)",
}}
variant="outlined"
color="primary"
>
Stop {webhookData.type}
</Button>
</div>
</div>
</Paper>
</div>
) : null;
// FIXME - needs refresh every time you add a new workflow
const workflowdata =
Object.getOwnPropertyNames(webhookData).length > 0 &&
selectedWorkflows.length > 0 ? (
<EditWorkflow
globalUrl={globalUrl}
inputworkflows={selectedWorkflows}
inputname={webhookData.info.name}
inputtype={webhookData.type}
/>
) : null;
const loadedCheck = isLoaded ? (
<div style={{ display: "flex", backgroundColor: "#f7f7f7" }}>
<div style={{ flex: 1 }}>{workflowdata}</div>
<div style={{ flex: 1 }}>{headerInfo}</div>
</div>
) : (
<div></div>
);
// FIXME: Use this for testing
// <EditWorkflow globalUrl={globalUrl} inputname={"Helo?"} inputtype={"webhook"} /> : null
return <div>{loadedCheck}</div>;
};
export default EditWebhook;
-118
View File
@@ -1,118 +0,0 @@
/* eslint-disable react/no-multi-comp */
import React, { useState } from "react";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
import Paper from "@material-ui/core/Paper";
const bodyDivStyle = {
margin: "auto",
marginTop: "100px",
width: "500px",
};
const ForgotPassword = (props) => {
const { globalUrl, isLoaded, isLoggedIn, surfaceColor, inputColor } = props;
const boxStyle = {
paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: surfaceColor,
};
const [username, setUsername] = useState("");
const [resetInfo, setResetInfo] = useState(
"You will receive an email with instructions shortly."
);
const handleValidateForm = () => {
return username.length > 3;
};
if (isLoggedIn === true) {
window.location.pathname = "/";
}
const onSubmit = (e) => {
e.preventDefault();
// FIXME - add some check here ROFL
// Just use this one?
var data = { username: username };
var baseurl = globalUrl;
var url = baseurl + "/api/v1/passwordresetmail";
fetch(url, {
method: "POST",
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
setResetInfo(responseJson["reason"]);
}
})
)
.catch((error) => {
setResetInfo("Error in userdata: " + error);
});
};
const onChangeUser = (e) => {
setUsername(e.target.value);
};
const data = (
<div style={bodyDivStyle}>
<Paper style={boxStyle}>
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
<h2>Password reset</h2>
<div>
<TextField
required
fullWidth={true}
color="primary"
style={{ backgroundColor: inputColor }}
InputProps={{
style: {
height: "50px",
color: "white",
fontSize: "1em",
},
}}
type="username"
placeholder="Username / Email"
id="standard-required"
autoComplete="username"
margin="normal"
variant="outlined"
onChange={onChangeUser}
/>
</div>
<div style={{ display: "flex", marginTop: "15px" }}>
<Button
color="primary"
variant="contained"
type="submit"
style={{ flex: "1", marginRight: "5px" }}
disabled={!handleValidateForm()}
>
SUBMIT
</Button>
</div>
<div style={{ marginTop: "20px" }}>{resetInfo}</div>
</form>
</Paper>
</div>
);
const loadedCheck = isLoaded ? <div>{data}</div> : <div></div>;
return <div>{loadedCheck}</div>;
};
export default ForgotPassword;
-136
View File
@@ -1,136 +0,0 @@
import React, { useState, useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
const bodyDivStyle = {
margin: "auto",
textAlign: "center",
width: "768px",
};
const boxStyle = {
flex: "1",
marginLeft: "10px",
marginRight: "10px",
paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: "#e8eaf6",
display: "flex",
flexDirection: "column",
};
//const tmpdata = {
// "username": "frikky",
// "firstname": "fred",
// "lastname": "ode",
// "title": "topkek",
// "companyname": "company here",
// "email": "your email pls",
// "phone": "PHONE!!",
//}
// FIXME - add fetch for data fields
// FIXME - remove tmpdata
// FIXME: Use isLoggedIn :)
const Settings = (props) => {
const { globalUrl, isLoaded } = props;
const [newPassword, setNewPassword] = useState("");
const [newPassword2, setNewPassword2] = useState("");
const [passwordFormMessage, setPasswordFormMessage] = useState("");
const onPasswordChange = () => {
const data = {
newpassword: newPassword,
newpassword2: newPassword2,
reference: props.match.params.key,
};
const url = globalUrl + "/api/v1/passwordreset";
fetch(url, {
mode: "cors",
method: "POST",
body: JSON.stringify(data),
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
setPasswordFormMessage(responseJson["reason"]);
}
})
)
.catch((error) => {
setPasswordFormMessage("Something went wrong.");
});
};
// This should "always" have data
useEffect(() => {});
// Random names for type & autoComplete. Didn't research :^)
const landingpageData = (
<div style={{ display: "flex", marginTop: "80px" }}>
<Paper style={boxStyle}>
<h2>Password Reset</h2>
<div style={{ flex: "1", display: "flex", flexDirection: "column" }}>
<TextField
required
style={{ flex: "1" }}
fullWidth={true}
placeholder="New password"
type="password"
id="standard-required"
autoComplete="password"
margin="normal"
variant="outlined"
onChange={(e) => setNewPassword(e.target.value)}
/>
<TextField
required
style={{ flex: "1" }}
fullWidth={true}
type="password"
placeholder="Repeat new password"
id="standard-required"
margin="normal"
variant="outlined"
onChange={(e) => setNewPassword2(e.target.value)}
/>
</div>
<Button
disabled={
newPassword.length < 10 ||
newPassword2.length < 10 ||
newPassword !== newPassword2
}
style={{ width: "100%", height: "60px", marginTop: "10px" }}
variant="contained"
color="primary"
onClick={() => onPasswordChange()}
>
Submit password change
</Button>
<h3>{passwordFormMessage}</h3>
</Paper>
</div>
);
const loadedCheck = isLoaded ? (
<div style={bodyDivStyle}>{landingpageData}</div>
) : (
<div></div>
);
return <div>{loadedCheck}</div>;
};
export default Settings;
-2
View File
@@ -58,9 +58,7 @@ import {
CloudDownload as CloudDownloadIcon,
} from "@mui/icons-material";
//import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Done as DoneIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons';
//https://next.material-ui.com/components/material-icons/
import { DataGrid, GridToolbar } from "@mui/x-data-grid";
//import JSONPretty from 'react-json-pretty';
-221
View File
@@ -1,221 +0,0 @@
import React, { useEffect, useState } from "react";
import { Link, useParams } from "react-router-dom";
import theme from '../theme.jsx';
import Grid from "@material-ui/core/Grid";
import Card from "@material-ui/core/Card";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardContent from "@material-ui/core/CardContent";
import CardHeader from "@material-ui/core/CardHeader";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
const Workflows = (defaultprops) => {
const { globalUrl, isLoggedIn, isLoaded } = defaultprops;
const params = useParams();
var props = JSON.parse(JSON.stringify(defaultprops))
props.match = {}
props.match.params = params
const [curView, setCurView] = useState(0);
const [firstrequest, setFirstrequest] = useState(true);
const [selectedItems, setSelectedItems] = useState([]);
const viewdata1 = [
{
title: "General",
content: "Learn about our ticketing solutions",
subitems: [
{
name: "Search",
subtitle: "Search for anything, anywhere",
},
{
name: "Message",
subtitle: "Read and send messages",
},
{
name: "Parse emails",
subtitle: "what",
},
],
},
{
title: "Ticketing",
subitems: [
{
name: "Search",
subtitle: "Search for anything, anywhere",
},
{
name: "Message",
subtitle: "Read and send messages",
},
{
name: "Parse emails",
subtitle: "what",
},
],
},
{
title: "Threat intel",
subitems: [
{
name: "Search",
subtitle: "Search for anything, anywhere",
},
{
name: "Message",
subtitle: "Read and send messages",
},
{
name: "Parse emails",
subtitle: "what",
},
],
},
];
if (firstrequest) {
setFirstrequest(false);
if (props.match.params.key) {
console.log("PROPS: ", props.match.params.key);
const viewitem = viewdata1.find(
(item) =>
item.title.toLowerCase() === props.match.params.key.toLowerCase()
);
if (viewitem !== undefined && viewitem !== null) {
setCurView(1);
//setSelectedItem(viewitem)
}
}
}
const cardContentStyle = {
height: "100%",
width: "100%",
padding: 40,
};
const outerGridView = {
width: "100%",
marginTop: 15,
};
const paperStyle = {
height: 300,
color: "white",
backgroundColor: theme.palette.surfaceColor,
color: "white",
cursor: "pointer",
display: "flex",
textAlign: "center",
};
const HandleSelection = (data) => {
const [selected, setSelected] = useState(false);
var baseStyle = JSON.parse(JSON.stringify(paperStyle));
if (selected) {
baseStyle.backgroundColor = "white";
baseStyle.color = "black";
}
return (
<Grid
item
xs={4}
onClick={() => {
console.log(selectedItems);
if (selected) {
const index = selectedItems.findIndex(
(item) => item.title === data.title
);
if (index >= 0) {
selectedItems.splice(index, 1);
setSelectedItems(selectedItems);
}
} else {
selectedItems.push(data);
setSelectedItems(selectedItems);
}
setSelected(!selected);
//setCurView(1)
//setSelectedItem(data)
//window.location.pathname += "/"+data.title.toLowerCase()
}}
>
<Card style={baseStyle}>
<CardActionArea style={cardContentStyle}>
<CardContent>
<Typography variant="h4">{data.title}</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
);
};
const view1 =
curView === 0 ? (
<div>
<Typography variant="h4">What are you interested in?</Typography>
<Grid container style={outerGridView} spacing={3}>
{viewdata1.map((data) => {
return HandleSelection(data);
})}
</Grid>
{/*
<Button variant="contained" color="primary" style={{height: 50, width: 300, margin: "auto",}} onClick={() => {
setCurView(1)
}}>
Continue
</Button>
*/}
</div>
) : null;
const view2 =
curView === 1 ? (
<div>
<Typography variant="h4">Step 2.</Typography>
{/*
<Grid container style={outerGridView} spacing={3}>
{selectedItem.subitems === undefined ? null :
selectedItem.subitems.map(data => {
return (
<Grid item xs={4}>
<Card style={paperStyle}>
<CardActionArea style={cardContentStyle}>
<CardContent>
<Typography variant="h4">
{data.name}
</Typography>
<Typography variant="body1" style={{marginTop: 10}}>
{data.subtitle}
</Typography>
</CardContent>
</CardActionArea>
</Card>
</Grid>
)
})}
</Grid>
*/}
</div>
) : null;
const baseView = (
<div style={{ maxWidth: 1024, margin: "auto", paddingTop: 50 }}>
{view1}
{view2}
</div>
);
return <div>{baseView}</div>;
};
export default Workflows;
-207
View File
@@ -1,207 +0,0 @@
import React from "react";
import Paper from "@material-ui/core/Paper";
import Button from "@material-ui/core/Button";
import Divider from "@material-ui/core/Divider";
import { BrowserView, MobileView } from "react-device-detect";
import {
Schedule as ScheduleIcon,
Web as WebIcon,
AccountTree as AccountTreeIcon,
} from "@mui/icons-material";
const bodyDivStyle = {
margin: "auto",
marginTop: "75px",
textAlign: "center",
width: "1100px",
};
const surfaceColor = "#27292D";
const boxStyle = {
flex: "1",
marginLeft: "10px",
marginRight: "10px",
height: "400px",
//backgroundColor: "#e8eaf6",
backgroundColor: surfaceColor,
textAlign: "center",
display: "flex",
flexDirection: "column",
};
const bodyTextStyle = {
color: "#ffffff",
};
const hrefStyle = {
color: "black",
textDecoration: "none",
};
// Should be different if logged in :|
const LandingPage = (props) => {
const { isLoaded } = props;
const textColor = "#8899A6";
const iconColor = "#1DA1F2";
const iconSize = "8em";
const GridLayout = (header, description, link, icon) => {
return (
<Paper style={boxStyle}>
<a href={link} style={hrefStyle}>
<div style={{ flex: "1", color: "#FFFFFF" }}>
<h2>{header}</h2>
</div>
<Divider />
<div
style={{
flex: "3",
marginLeft: "10px",
marginRight: "10px",
marginTop: "10px",
color: textColor,
}}
>
{description}
</div>
<div style={{ margin: "auto" }}>{icon}</div>
<Divider style={{ marginTop: "20px", marginBottom: "20px" }} />
<div style={{ flex: "1", color: "#f85a3e" }}>
<div style={{}}>Learn more</div>
</div>
</a>
</Paper>
);
};
const listitems = [
GridLayout(
"Simple integrations",
"Easily use others' or create your own integration",
"/docs/apps",
<Web
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
GridLayout(
"Workflows",
"Access the power of automation within minutes, whether its on premise or in the cloud",
"/docs/workflows",
<AccountTree
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
GridLayout(
"Realtime actions",
"Beat the clock by leveraging our realtime triggers",
"/docs/triggers",
<ScheduleIcon
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
];
// The actual landing page
// <img style={{width: "400px"}} alt={"logo"} src={Default}/>
const landingpageDataBrowser = (
<div>
<div style={bodyTextStyle}>
<h1>Shuffle</h1>
<h3 style={{ color: "#8899A6" }}>
A general automation solution for Infosec and IT Professionals
</h3>
</div>
<a href="/register" style={hrefStyle}>
<Button
style={{ width: "180px", height: "50px", borderRadius: "0px" }}
variant="outlined"
color="primary"
>
Try it out
</Button>
</a>
<a href="/contact" style={hrefStyle}>
<Button
style={{ width: "180px", height: "50px", borderRadius: "0px" }}
variant="contained"
color="primary"
>
Contact
</Button>
</a>
<div style={{ display: "flex", marginTop: "100px" }}>
{listitems.map((item) => {
return <div>{item}</div>;
})}
</div>
</div>
);
const landingpageDataMobile = (
<div>
<div
style={{
color: "white",
textAlign: "center",
marginLeft: "10px",
marginRight: "10px",
}}
>
<h1>Shuffle</h1>
<h3>A general automation solution for Infosec and IT Professionals</h3>
<a href="/contact" style={hrefStyle}>
<Button
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
variant="contained"
color="primary"
>
Contact
</Button>
</a>
</div>
<div
style={{ display: "flex", flexDirection: "column", marginTop: "100px" }}
>
<div>{listitems[0]}</div>
<div style={{ marginTop: "20px" }}>{listitems[1]}</div>
<div style={{ marginTop: "20px", marginBottom: "30px" }}>
{listitems[2]}
</div>
<div
style={{
marginTop: "20px",
marginBottom: "30px",
textAlign: "center",
}}
>
<a href="/contact" style={hrefStyle}>
<Button
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
variant="contained"
color="primary"
>
Contact
</Button>
</a>
</div>
</div>
</div>
);
// Reroute if the user is logged in
// const landingSite = isLoggedIn ? <Workflows globalUrl={globalUrl}{...props} /> : <div style={bodyDivStyle}>{landingpageData}</div>
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>;
const loadedCheck = isLoaded ? (
<div>
<BrowserView>{landingSite}</BrowserView>
<MobileView>{landingpageDataMobile}</MobileView>
</div>
) : (
<div></div>
);
return <div>{loadedCheck}</div>;
};
export default LandingPage;
-531
View File
@@ -1,531 +0,0 @@
import React, { useState } from "react";
import Paper from "@material-ui/core/Paper";
import Card from "@material-ui/core/Card";
import CardActionArea from "@material-ui/core/CardActionArea";
import CardMedia from "@material-ui/core/CardMedia";
import CardContent from "@material-ui/core/CardContent";
import CardActions from "@material-ui/core/CardActions";
import Button from "@material-ui/core/Button";
import Divider from "@material-ui/core/Divider";
import Grid from "@material-ui/core/Grid";
import { BrowserView, MobileView } from "react-device-detect";
import {
Schedule as ScheduleIcon,
Web as WebIcon,
AccountTree as AccountTreeIcon,
Info as InfoIcon,
ArrowForward as ArrowForwardIcon,
Create as CreateIcon,
} from "@mui/icons-material";
const bodyDivStyle = {
margin: "auto",
};
const surfaceColor = "#27292D";
const boxStyle = {
flex: "1",
marginLeft: "10px",
marginRight: "10px",
height: "400px",
//backgroundColor: "#e8eaf6",
backgroundColor: surfaceColor,
textAlign: "center",
display: "flex",
flexDirection: "column",
};
const bodyTextStyle = {
color: "#ffffff",
};
const hrefStyle = {
color: "inherit",
textDecoration: "none",
};
// Should be different if logged in :|
const LandingPage = (props) => {
const { isLoaded } = props;
const textColor = "#8899A6";
const iconColor = "#1DA1F2";
const iconSize = "8em";
const GridLayout = (header, description, link, icon) => {
return (
<Paper style={boxStyle}>
<a href={link} style={hrefStyle}>
<div style={{ flex: "1", color: "#FFFFFF" }}>
<h2>{header}</h2>
</div>
<Divider />
<div
style={{
flex: "3",
marginLeft: "10px",
marginRight: "10px",
marginTop: "10px",
color: textColor,
}}
>
{description}
</div>
<div style={{ margin: "auto" }}>{icon}</div>
<Divider style={{ marginTop: "20px", marginBottom: "20px" }} />
<div style={{ flex: "1", color: "#f85a3e" }}>
<div style={{}}>Learn more</div>
</div>
</a>
</Paper>
);
};
const listitems = [
GridLayout(
"Simple integrations",
"Easily use others' or create your own integration",
"/docs/features",
<WebIcon
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
GridLayout(
"Workflows",
"Access the power of automation within minutes, whether its on premise or in the cloud",
"/docs/features",
<AccountTreeIcon
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
GridLayout(
"Realtime actions",
"Beat the clock by leveraging our realtime triggers",
"/docs/features",
<ScheduleIcon
style={{ fontSize: iconSize, marginTop: "20px", color: iconColor }}
/>
),
];
// The actual landing page
// <img style={{width: "400px"}} alt={"logo"} src={Default}/>
//We start by understanding your unique environment to help identify the right thing to automate.
const secondaryColor = "rgba(167,46,87,1)";
const primaryColor = "rgba(25, 35, 94, 1)";
const paperStyle = {
flex: 1,
backgroundColor: "inherit",
cursor: "pointer",
};
const secondaryItemList = [
{
primaryText: "No time to waste",
secondaryText:
"Bring all your applications into a single view, and make them all work together flawlessly!",
image: "/images/time.jpg",
},
{
primaryText: "Get a better overview",
secondaryText:
"Don't know what's happening? We'll help you track and act on your most valuable KPI's!",
image: "/images/overview.jpg",
},
{
primaryText: "Conquer your tasks",
secondaryText:
"Get access to powerful tools and pre-made workflows to help you crush your teams daily tasks!",
image: "/images/burnout.jpg",
},
];
const [image, setImage] = useState(secondaryItemList[0].image);
const landingpageDataBrowser = (
<div>
<div
style={{
backgroundImage: "url('/images/test.jpg')",
backgroundSize: "80% 100%",
backgroundRepeat: "no-repeat",
minHeight: "100vh",
maxHeight: 1024,
}}
>
<div
style={{
textAlign: "left",
paddingTop: 135,
maxWidth: 700,
paddingLeft: "50%",
color: secondaryColor,
display: "flex",
fontSize: 25,
}}
>
<div style={{ flex: 1 }}>
<a href="/docs/about" style={hrefStyle}>
<Grid container direction="row" alignItems="center">
<Grid item>
<InfoIcon />
</Grid>
<Grid item style={{ marginLeft: 5 }}>
About
</Grid>
</Grid>
</a>
</div>
<div style={{ flex: 1 }}>
<a href="/contact" style={hrefStyle}>
<Grid container direction="row" alignItems="center">
<Grid item>
<CreateIcon />
</Grid>
<Grid item style={{ marginLeft: 5 }}>
Get in touch
</Grid>
</Grid>
</a>
</div>
<div style={{ flex: 1 }}>
<a href="/login" style={hrefStyle}>
<Button
style={{
borderRadius: 25,
height: 50,
minWidth: 200,
backgroundColor: secondaryColor,
color: "white",
}}
variant="contained"
>
Try it out <ArrowForwardIcon />
</Button>
</a>
</div>
</div>
<div
style={
(bodyTextStyle,
{
textAlign: "left",
paddingTop: "8%",
paddingLeft: "28%",
maxWidth: 430,
})
}
>
<div style={{ fontSize: 25, color: "rgba(0,0,0,0.45)" }}>Shuffle</div>
<div style={{ fontSize: 50, color: "rgba(0,0,0,0.7)" }}>
INFORMATION <div style={{ color: secondaryColor }}>OVERLOAD</div>
</div>
<div
style={{
fontSize: 20,
color: "rgba(0, 0, 0, 0.45)",
marginTop: 20,
}}
>
Everyone run into the same fundamental operational problems. Mailbox
chaos, tickets getting out of hand and a constant feeling of being
overwhelmed. The good news?{" "}
<div style={{ color: secondaryColor, marginTop: 10 }}>
Shuffle solves them.
</div>
</div>
<a href="/docs/features" style={hrefStyle}>
<Button
style={{
borderRadius: 25,
height: 50,
marginTop: 50,
width: 200,
backgroundColor: secondaryColor,
color: "white",
}}
variant="contained"
>
Learn how
</Button>
</a>
</div>
</div>
<div
style={{
minHeight: 1024,
width: "100%",
backgroundImage: "linear-gradient(to bottom right, #19235e, #19235e)",
}}
>
<div
style={{
minHeight: 1000,
paddingTop: 150,
maxWidth: 1250,
margin: "auto",
}}
>
<div
style={{
color: "rgba(255,255,255,0.8",
fontSize: 60,
marginLeft: 25,
}}
>
<b>Automation is just the beginning </b>
</div>
<div style={{ marginTop: 40, display: "flex", flexDirection: "row" }}>
<div
style={{
flex: 8,
display: "flex",
flexDirection: "column",
fontSize: 40,
}}
>
{secondaryItemList.map((data, index) => {
const color =
image === data.image
? "rgba(255,255,255,1)"
: "rgba(255,255,255,0.4)";
return (
<div
style={{
borderRadius: 15,
padding: 25,
maxWidth: 600,
height: 150,
fontSize: 40,
color: color,
cursor: "pointer",
}}
onClick={() => setImage(data.image)}
>
{data.primaryText}
<div style={{ fontSize: 22, marginTop: 10 }}>
{data.secondaryText}
</div>
</div>
);
})}
</div>
<div style={{ flex: 1 }} />
<div style={{ flex: 10, height: "100%", width: "100%" }}>
<img
src={image}
style={{
borderRadius: 15,
minHeight: "100%",
minWidth: "100%",
maxWidth: "100%",
maxHeight: "100%",
}}
/>
</div>
</div>
</div>
<div
style={{
maxWidth: 1250,
paddingTop: 100,
paddingBottom: 100,
margin: "auto",
color: "rgba(255,255,255,0.8)",
}}
>
<Divider style={{ backgroundColor: "rgba(255,255,255,0.6)" }} />
<div
style={{
marginTop: 100,
fontSize: 40,
display: "flex",
marginLeft: 100,
marginRight: 100,
}}
>
<div style={{ flex: 3 }}>
Learn more about the benefits of Shuffle
</div>
<div style={{ flex: 1 }}>
<a href="/docs/features" style={hrefStyle}>
<Button
fullWidth
style={{
borderRadius: 25,
minHeight: 50,
minWidth: 200,
backgroundColor: secondaryColor,
color: "white",
}}
variant="contained"
>
See features
</Button>
</a>
</div>
</div>
</div>
</div>
<div
style={{
textAlign: "center",
maxWidth: 1100,
minHeight: 600,
paddingTop: 100,
margin: "auto",
color: "rgba(0,0,0,1)",
}}
>
<div style={{ fontSize: 50 }}>
<b>Focus on the work that matters to you</b>
</div>
<div
style={{ fontSize: 20, color: "rgba(0,0,0,0.7)", maxWidth: "100%" }}
>
Menial tasks, scattered content, constant copy pasting, waste of
talent - <b>there's a smarter way to work.</b>
</div>
<div style={{ display: "flex", marginTop: 50 }}>
<Card
onClick={() => {
window.location.pathname = "/docs/features";
}}
style={{ flex: 1, margin: 10, textAlign: "center" }}
>
<CardActionArea>
<CardMedia title="TEST" image="/images/time.jpg" />
<CardContent>
<h3>Premade playbooks</h3>
<p>Get your automation done with minimal effort</p>
</CardContent>
</CardActionArea>
<Button size="medium" color="green">
Learn more
</Button>
</Card>
<Card
onClick={() => {
window.location.pathname = "/docs/features";
}}
style={{ flex: 1, margin: 10, textAlign: "center" }}
>
<CardActionArea>
<CardMedia title="TEST" image="/images/time.jpg" />
<CardContent>
<h3>Open frameworks</h3>
<p>Mitre Att&ck, OpenAPI and more!</p>
</CardContent>
</CardActionArea>
<Button size="medium" color="green">
Learn more
</Button>
</Card>
<Card
onClick={() => {
window.location.pathname = "/docs/features";
}}
style={{ flex: 1, margin: 10, textAlign: "center" }}
>
<CardActionArea>
<CardMedia title="TEST" image="/images/time.jpg" />
<CardContent>
<h3>Hundreds of integrations</h3>
<p>Quickly integrate your software applications</p>
</CardContent>
</CardActionArea>
<Button size="medium" color="green">
Learn more
</Button>
</Card>
<Card
style={{ flex: 1, margin: 10, textAlign: "center" }}
onClick={() => {
window.location.pathname = "/docs/features";
}}
>
<CardActionArea>
<CardMedia title="TEST" image="images/time.jpg" />
<CardContent>
<h3>Automated compliance</h3>
<p>Stuck with compliance needs you can't meet?</p>
</CardContent>
</CardActionArea>
<Button size="medium" color="green">
Learn more
</Button>
</Card>
</div>
</div>
</div>
);
const landingpageDataMobile = (
<div style={{ backgroundColor: "#1F2023", paddingTop: 30 }}>
<div
style={{
color: "white",
textAlign: "center",
marginLeft: "10px",
marginRight: "10px",
}}
>
<h1>Shuffle</h1>
<h3>A general automation solution for Infosec and IT Professionals</h3>
<a href="/contact" style={hrefStyle}>
<Button
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
variant="contained"
color="primary"
>
Contact
</Button>
</a>
</div>
<div
style={{ display: "flex", flexDirection: "column", marginTop: "100px" }}
>
<div>{listitems[0]}</div>
<div style={{ marginTop: "20px" }}>{listitems[1]}</div>
<div style={{ marginTop: "20px", marginBottom: "30px" }}>
{listitems[2]}
</div>
<div
style={{
marginTop: "20px",
marginBottom: "30px",
textAlign: "center",
}}
>
<a href="/contact" style={hrefStyle}>
<Button
style={{ width: "220px", height: "60px", borderRadius: "0px" }}
variant="contained"
color="primary"
>
Contact
</Button>
</a>
</div>
</div>
</div>
);
// Reroute if the user is logged in
// const landingSite = isLoggedIn ? <Workflows globalUrl={globalUrl}{...props} /> : <div style={bodyDivStyle}>{landingpageData}</div>
const landingSite = <div style={bodyDivStyle}>{landingpageDataBrowser}</div>;
const loadedCheck = isLoaded ? (
<div>
<BrowserView>{landingSite}</BrowserView>
<MobileView>{landingpageDataMobile}</MobileView>
</div>
) : (
<div></div>
);
return <div>{loadedCheck}</div>;
};
export default LandingPage;
File diff suppressed because it is too large Load Diff
-93
View File
@@ -1,93 +0,0 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import Paper from "@material-ui/core/Paper";
const bodyDivStyle = {
margin: "auto",
textAlign: "center",
width: "768px",
};
//const tmpdata = {
// "username": "frikky",
// "firstname": "fred",
// "lastname": "ode",
// "title": "topkek",
// "companyname": "company here",
// "email": "your email pls",
// "phone": "PHONE!!",
//}
// FIXME - add fetch for data fields
// FIXME - remove tmpdata
// FIXME: Use isLoggedIn :)
const Settings = (defaultprops) => {
const { globalUrl, isLoaded, surfaceColor } = defaultprops;
const params = useParams();
var props = JSON.parse(JSON.stringify(defaultprops))
props.match = {}
props.match.params = params
const [firstRequest, setFirstRequest] = useState(true);
const boxStyle = {
flex: "1",
marginLeft: "10px",
marginRight: "10px",
paddingLeft: "30px",
paddingRight: "30px",
paddingBottom: "30px",
paddingTop: "30px",
backgroundColor: surfaceColor,
color: "white",
display: "flex",
flexDirection: "column",
};
const registerCall = () => {
const url = globalUrl + "/api/v1/register/" + props.match.params.key;
fetch(url, {
method: "GET",
credentials: "include",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
})
.then((response) =>
response.json().then((responseJson) => {
console.log(responseJson);
})
)
.catch((error) => {
console.log("SOMETHING WRONG");
});
};
// This should "always" have data
useEffect(() => {
if (firstRequest) {
setFirstRequest(false);
registerCall();
}
});
// Random names for type & autoComplete. Didn't research :^)
const landingpageData = (
<div style={{ display: "flex", marginTop: "80px" }}>
<Paper style={boxStyle}>
<h2>Registration verification</h2>
<p>Thanks for verifying, redirecting you to our login!</p>
</Paper>
</div>
);
const loadedCheck = isLoaded ? (
<div style={bodyDivStyle}>{landingpageData}</div>
) : (
<div></div>
);
return <div>{loadedCheck}</div>;
};
export default Settings;
-176
View File
@@ -1,176 +0,0 @@
/* eslint-disable react/no-multi-comp */
import React, { useState } from "react";
import DialogTitle from "@material-ui/core/DialogTitle";
import Dialog from "@material-ui/core/Dialog";
import TextField from "@material-ui/core/TextField";
import Button from "@material-ui/core/Button";
const LoginDialog = (props) => {
const {
classes,
onClose,
open,
globalUrl,
isLoggedIn,
setIsLoggedIn,
...other
} = props;
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
//const [selectedValue, setSelectedValue] = useState(false);
// Used to swap from login to register. True = login, false = register
const [loginCheck, setLoginCheck] = useState(true);
// Error messages etc
const [loginInfo, setLoginInfo] = useState("");
const handleValidateForm = () => {
return username.length > 1 && password.length > 8;
};
const onSubmit = (e) => {
e.preventDefault();
// Just use this one?
var data =
'{"username": "' + username + '", "password": "' + password + '"}';
var baseurl = globalUrl;
if (loginCheck) {
var url = baseurl + "/login";
fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
console.log(responseJson);
//console.log(e)
if (responseJson["success"] === false) {
setLoginInfo(responseJson["reason"]);
} else {
setLoginInfo("Successful login :)");
onClose();
setIsLoggedIn(true);
}
})
)
.catch((error) => {
setLoginInfo("Error in userdata");
});
} else {
url = baseurl + "/register";
fetch(url, {
method: "POST",
body: data,
headers: {
"Content-Type": "application/json",
},
})
.then((response) =>
response.json().then((responseJson) => {
if (responseJson["success"] === false) {
setLoginInfo(responseJson["reason"]);
} else {
setLoginInfo("Successful register. Please check your mail :)");
onClose();
setIsLoggedIn(true);
}
})
)
.catch((error) => {
setLoginInfo("Error in userdata");
});
}
};
const onChangeUser = (e) => {
setUsername(e.target.value);
};
const onChangePass = (e) => {
setPassword(e.target.value);
};
const onClickRegister = () => {
setLoginCheck(!loginCheck);
};
//var loginChange = loginCheck ? (<div><p onClick={setLoginCheck(false)}>Want to register? Click here.</p></div>) : (<div><p onClick={setLoginCheck(true)}>Go back to login? Click here.</p></div>);
var formtitle = loginCheck ? <div>Login</div> : <div>Register</div>;
var formButton = loginCheck ? (
<div>Click to Register</div>
) : (
<div>Click to Login</div>
);
return (
<Dialog modal open={open} onClose={onClose} {...other}>
<DialogTitle>{formtitle}</DialogTitle>
<form onSubmit={onSubmit} style={{ margin: "15px 15px 15px 15px" }}>
Username
<div>
<TextField
required
id="standard-required"
autoComplete="username"
margin="normal"
variant="outlined"
onChange={onChangeUser}
/>
</div>
Password
<div>
<TextField
id="outlined-password-input"
type="password"
autoComplete="current-password"
margin="normal"
variant="outlined"
onChange={onChangePass}
/>
</div>
<div style={{ display: "flex", marginTop: "15px" }}>
<Button
color="secondary"
variant="contained"
type="submit"
style={{ flex: "1", marginRight: "5px" }}
disabled={!handleValidateForm()}
>
SUBMIT
</Button>
<Button
color="primary"
variant="contained"
type="button"
style={{ flex: "1" }}
onClick={onClose}
>
Cancel
</Button>
</div>
{loginInfo}
</form>
<div style={{ display: "flex" }}>
<Button
color="secondary"
variant="contained"
onClick={onClickRegister}
type="button"
style={{ flex: "1" }}
>
{formButton}
</Button>
</div>
</Dialog>
);
};
export default LoginDialog;
-232
View File
@@ -1,232 +0,0 @@
import React, { useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import ButtonBase from "@material-ui/core/ButtonBase";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import Button from "@material-ui/core/Button";
//import Breadcrumbs from '@material-ui/core/Breadcrumbs';
const Schedules = (props) => {
const { globalUrl } = props;
//const [schedules, setSchedules] = React.useState(scheduledata);
const [schedules, setSchedules] = React.useState({});
const getAvailableSchedules = () => {
fetch(globalUrl + "/api/v1/schedules", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((response) => response.json())
.then((responseJson) => {
setSchedules(responseJson);
})
.catch((error) => {
console.log(error);
});
};
// FIXME - add automated redirection, as empty apps look horrible currently
const newSchedule = () => {
fetch(globalUrl + "/api/v1/schedules/new", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(),
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
setSchedules({});
})
.catch((error) => {
console.log(error);
});
};
const deleteSchedule = (id) => {
if (id === undefined) {
return;
}
fetch(globalUrl + "/api/v1/schedules/" + id + "/delete", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((response) => response.json())
.then((responseJson) => {
setSchedules({});
})
.catch((error) => {
console.log(error);
});
};
// FIXME - use this?
//const getNewScheduleInfo = () => {
// fetch(globalUrl+"/api/v1/schedules", {
// method: 'GET',
// headers: {
// 'Content-Type': 'application/json',
// 'Accept': 'application/json',
// },
// })
// .then((response) => response.json())
// .then((responseJson) => {
// setSchedules(responseJson)
// })
// .catch(error => {
// console.log(error)
// });
//}
useEffect(() => {
if (Object.getOwnPropertyNames(schedules).length <= 0) {
getAvailableSchedules();
}
});
const bodyDivStyle = {
marginLeft: "20px",
marginRight: "20px",
width: "1350px",
minWidth: "1350px",
maxWidth: "1350px",
};
const scheduleApp = (app) => {
console.log(app);
return (
<Grid container spacing={2} style={{ margin: "10px 10px 10px 10px" }}>
<Grid item>
<ButtonBase>
<img alt="" style={{ width: "100px", height: "100px" }} />
</ButtonBase>
</Grid>
<Grid item xs={12} sm container>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<div>
<h2>{app.name}</h2>
</div>
<div>{app.description}</div>
</Grid>
<Grid item>{app.action}</Grid>
</Grid>
</Grid>
</Grid>
);
};
const splitter = (
<div
style={{
width: "1px",
backgroundColor: "grey",
margin: "5px 5px 5px 5px",
}}
/>
);
const hrefStyle = {
color: "#385f71",
textDecoration: "none",
};
// FIXME - add Schedule modal
const schedulePaper = (schedule) => {
return (
<div>
<Paper
style={{
maxWidth: "1000px",
display: "flex",
padding: "10px 10px 10px 10px",
}}
>
<div style={{ flex: "5" }}>
{scheduleApp(schedule.appinfo.sourceapp)}
</div>
<div style={{ flex: "1", alignItems: "center" }}>ARROW</div>
<div style={{ flex: "5" }}>
{scheduleApp(schedule.appinfo.destinationapp)}
</div>
{splitter}
<div style={{ flex: "1" }}>
<List style={{ backgroundColor: "#ffffff" }}>
<ListItem style={{ flex: "1", textAlign: "center" }}>
<a href={"/schedules/" + schedule.id} style={hrefStyle}>
<Button disabled={false} color="primary">
Edit
</Button>
</a>
</ListItem>
<ListItem style={{ flex: "1", textAlign: "center" }}>
<Button
disabled={false}
onClick={() => {
deleteSchedule(schedule.id);
}}
color="primary"
>
Delete
</Button>
</ListItem>
</List>
</div>
</Paper>
</div>
);
};
console.log(schedules);
console.log(schedules);
console.log(schedules.schedules);
const schedulemap =
Object.getOwnPropertyNames(schedules).length > 0 &&
schedules.schedules &&
schedules.schedules.length > 0 ? (
<div>{schedules.schedules.map((data) => schedulePaper(data))}</div>
) : (
<div style={{ marginTop: "10%", marginLeft: "50%" }}>
<Button
disabled={false}
onClick={() => {
newSchedule();
}}
variant="outlined"
color="primary"
>
CREATE NEW SCHEDULE
</Button>
</div>
);
const scheduleView =
Object.getOwnPropertyNames(schedules).length > 0 ? (
<div style={bodyDivStyle}>
<Button
disabled={false}
onClick={() => {
newSchedule();
}}
color="primary"
>
New
</Button>
{schedulemap}
</div>
) : null;
// Maybe use gridview or something, idk
return <div>{scheduleView}</div>;
};
export default Schedules;
-298
View File
@@ -1,298 +0,0 @@
import React from "react";
import { Grid, Container, Divider } from "@mui/material";
import { makeStyles } from "@mui/material/styles";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import Typography from "@material-ui/core/Typography";
import Table from "@material-ui/core/Table";
import TableBody from "@material-ui/core/TableBody";
import TableCell from "@material-ui/core/TableCell";
import TableContainer from "@material-ui/core/TableContainer";
import TableHead from "@material-ui/core/TableHead";
import TableRow from "@material-ui/core/TableRow";
import Paper from "@material-ui/core/Paper";
import { LineChart, LineSeries, BarChart } from "reaviz";
import { GridStripe } from "reaviz";
//import { GridlineSeries } from "reaviz";
import InputLabel from '@material-ui/core/InputLabel';
import FormControl from '@material-ui/core/FormControl';
import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem';
const data = [
{
key: new Date("11/29/2019"),
data: 10,
},
{
key: new Date("11/30/2019"),
data: 14,
},
{
key: new Date("12/01/2019"),
data: 5,
},
{
key: new Date("12/02/2019"),
data: 18,
},
];
const useStyles1 = makeStyles((theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
selectEmpty: {
marginTop: theme.spacing(2),
},
}));
const useStyles = makeStyles({
table: {
minWidth: 650,
},
root: {
minWidth: 275,
},
bullet: {
display: "inline-block",
margin: "0 2px",
transform: "scale(0.8)",
},
title: {
fontSize: 14,
},
pos: {
marginBottom: 12,
},
});
function createData(name, calories, fat, carbs, protein) {
return { name, calories, fat, carbs, protein };
}
const rows = [
createData("Frozen yoghurt", 159, 6.0, 24, 4.0),
createData("Ice cream sandwich", 237, 9.0, 37, 4.3),
createData("Eclair", 262, 16.0, 24, 6.0),
createData("Cupcake", 305, 3.7, 67, 4.3),
createData("Gingerbread", 356, 16.0, 49, 3.9),
];
const DashboardPage = () => {
const classes = useStyles();
const classes1 = useStyles1();
const [age, setAge] = React.useState(0);
const handleChange = (event) => {
setAge(event.target.value);
};
return (
<Container maxWidth="xl">
<Grid>
<Grid item xl={8} style={{"border":"20px"}}>
<center>
<Typography type="title" variant="h1" color="inherit">
Dashboard
</Typography>
<div style={{
"paddingLeft": "50px"
}}>
<FormControl className={classes1.formControl}>
<InputLabel id="demo-simple-select-label">Organization</InputLabel>
<Select
labelId="demo-simple-select-label"
onChange={handleChange}
>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
</FormControl>
</div>
</center>
</Grid>
<Divider />
</Grid>
<Grid
container
spacing={2}
style={{
maxWidth: "1250px",
margin: "auto auto 10px",
padding: "10px",
}}
>
<Grid item xs={4}>
<Card
className={classes.root}
style={{
color: "white",
backgroundColor: "RGB(31, 32, 36)",
height: "100px",
border: "2px solid rgb(197, 17, 82)",
}}
>
<CardContent>
<Typography
className={classes.title}
color="textSecondary"
gutterBottom
>
Total workflows executions
</Typography>
<Typography
variant="h1"
className={classes.pos}
color="textSecondary"
>
456
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={4}>
<Card
className={classes.root}
style={{
color: "white",
backgroundColor: "RGB(31, 32, 36)",
height: "100px",
border: "2px solid rgb(244, 194, 13)",
}}
>
<CardContent>
<Typography
className={classes.title}
color="textSecondary"
gutterBottom
>
Total Apps executions
</Typography>
<Typography
variant="h1"
className={classes.pos}
color="textSecondary"
>
587
</Typography>
</CardContent>
</Card>
</Grid>
<Grid item xs={4}>
<Card
className={classes.root}
style={{
color: "white",
backgroundColor: "RGB(31, 32, 36)",
height: "100px",
border: "2px solid rgb(72, 133, 237)",
}}
>
<CardContent>
<Typography
className={classes.title}
color="textSecondary"
gutterBottom
>
Total failed executions
</Typography>
<Typography
variant="h1"
className={classes.pos}
color="textSecondary"
>
999
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
<Grid
container
spacing={3}
style={{
maxWidth: "1250px",
margin: "auto auto 10px",
color: "white",
backgroundColor: "rgb(39, 41, 45)",
padding: "20px",
}}
>
<Grid item md={6}>
<BarChart width={600} height={400} data={data} />
</Grid>
<Grid item md={6}>
<LineChart
width={600}
height={400}
data={data}
line={<GridStripe fill={"a#393c3e"} />}
series={<LineSeries symbols={null} />}
/>
</Grid>
</Grid>
<Grid
container
spacing={1}
style={{
maxWidth: "1250px",
margin: "auto auto 10px",
color: "white",
backgroundColor: "rgb(39, 41, 45)",
padding: "20px",
}}
>
<Grid item md={12}>
<TableContainer
component={Paper}
style={{
color: "white",
backgroundColor: "rgb(39, 41, 45) ",
}}
>
<Table
className={classes.table}
size="small"
aria-label="a dense table"
>
<TableHead>
<TableRow>
<TableCell>Dessert (100g serving)</TableCell>
<TableCell align="right">Calories</TableCell>
<TableCell align="right">Fat&nbsp;(g)</TableCell>
<TableCell align="right">Carbs&nbsp;(g)</TableCell>
<TableCell align="right">Protein&nbsp;(g)</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map((row) => (
<TableRow key={row.name}>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="right">{row.calories}</TableCell>
<TableCell align="right">{row.fat}</TableCell>
<TableCell align="right">{row.carbs}</TableCell>
<TableCell align="right">{row.protein}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Grid>
</Grid>
</Container>
);
};
export default DashboardPage;
-316
View File
@@ -1,316 +0,0 @@
import React, { useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import Grid from "@material-ui/core/Grid";
import ButtonBase from "@material-ui/core/ButtonBase";
import Button from "@material-ui/core/Button";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import TextField from "@material-ui/core/TextField";
import Select from "@material-ui/core/Select";
import MenuItem from "@material-ui/core/MenuItem";
import Dialog from "@material-ui/core/Dialog";
import DialogTitle from "@material-ui/core/DialogTitle";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import WebhookImage from "../assets/img/webhook.png";
import KafkaImage from "../assets/img/kafka.png";
const Webhooks = (props) => {
const { globalUrl, isLoaded } = props;
const validtypes = ["webhook"];
//const [hooks, setSchedules] = React.useState(hookdata);
const [hooks, setHooks] = React.useState([]);
const [modalOpen, setModalOpen] = React.useState(false);
const [newHookName, setNewHookName] = React.useState("");
const [newHookDescription, setNewHookDescription] = React.useState("");
const [newHookType, setNewHookType] = React.useState("");
const [firstrequest, setFirstrequest] = React.useState(true);
const [, setModalError] = React.useState("");
useEffect(() => {
if (firstrequest) {
setFirstrequest(false);
getAvailableHooks();
}
});
const newHook = () => {
if (newHookName.length === 0) {
setModalError("Missing name in modal");
return;
}
if (!validtypes.includes(newHookType)) {
setModalError(
newHookType + " is not a valid type. Try this: " + validtypes
);
}
fetch(globalUrl + "/api/v1/hooks/new", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
name: newHookName,
description: newHookDescription,
type: newHookType,
}),
credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
setHooks([]);
})
.catch((error) => {
console.log(error);
});
};
const getAvailableHooks = () => {
fetch(globalUrl + "/api/v1/hooks", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
setHooks(responseJson);
})
.catch((error) => {
console.log(error);
// window.location.pathname = "/"
});
};
const deleteHook = (id) => {
if (id === undefined) {
return;
}
fetch(globalUrl + "/api/v1/hooks/" + id + "/delete", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => response.json())
.then((responseJson) => {
setHooks([]);
})
.catch((error) => {
console.log(error);
});
};
const bodyDivStyle = {
marginLeft: "20px",
marginRight: "20px",
width: "1350px",
minWidth: "1350px",
maxWidth: "1350px",
};
const hookApp = (app) => {
// Might be more options, but should be webhook or MQ
const appPicture =
app.type === "webhook" ? (
<img src={WebhookImage} alt="webhook" width="100px" height="100px" />
) : (
<img src={KafkaImage} alt="MQ" width="100px" height="100px" />
);
return (
<Grid container spacing={2} style={{ margin: "10px 10px 10px 10px" }}>
<Grid item style={{ marginRight: "10px" }}>
<ButtonBase>{appPicture}</ButtonBase>
</Grid>
{splitter}
<Grid item xs={12} sm container style={{ marginLeft: "10px" }}>
<Grid item xs container direction="column" spacing={2}>
<Grid item xs>
<div>
<h2>{app.info.name}</h2>
</div>
<div>Desc: {app.info.description}</div>
<div>Status: {app.status}</div>
</Grid>
<Grid item>{app.action}</Grid>
</Grid>
</Grid>
</Grid>
);
};
const splitter = (
<div
style={{
width: "1px",
backgroundColor: "grey",
margin: "5px 5px 5px 5px",
}}
/>
);
const hrefStyle = {
color: "#385f71",
textDecoration: "none",
};
// FIXME - add Schedule modal
const hookPaper = (hook) => {
return (
<div>
<Paper
style={{
maxWidth: "500px",
display: "flex",
padding: "10px 10px 10px 10px",
marginTop: "10px",
}}
>
<div style={{ flex: "5" }}>{hookApp(hook)}</div>
{splitter}
<div style={{ flex: "1" }}>
<List style={{ backgroundColor: "#ffffff" }}>
<ListItem style={{ flex: "1", textAlign: "center" }}>
<a href={"/webhooks/" + hook.id} style={hrefStyle}>
<Button disabled={false} color="primary">
Edit
</Button>
</a>
</ListItem>
<ListItem style={{ flex: "1", textAlign: "center" }}>
<Button
disabled={false}
onClick={() => {
deleteHook(hook.id);
}}
color="primary"
>
Delete
</Button>
</ListItem>
</List>
</div>
</Paper>
</div>
);
};
const modalView = modalOpen ? (
<Dialog
modal
open={modalOpen}
onClose={() => {
setModalOpen(false);
}}
>
<DialogTitle>Hook configuration</DialogTitle>
<DialogContent>
<TextField
onChange={(event) => {
setNewHookName(event.target.value);
}}
color="primary"
placeholder="Name"
margin="dense"
fullWidth
/>
<TextField
onChange={(event) => {
setNewHookDescription(event.target.value);
}}
color="primary"
placeholder="Description"
margin="dense"
fullWidth
/>
<Select
value={newHookType}
onChange={(event) => {
setNewHookType(event.target.value);
}}
fullWidth="true"
>
{validtypes.map((data) => (
<MenuItem value={data}>{data}</MenuItem>
))}
</Select>
</DialogContent>
<DialogActions>
<Button onClick={() => setModalOpen(false)} color="primary">
Cancel
</Button>
<Button
disabled={
newHookName.length === 0 || !validtypes.includes(newHookType)
}
onClick={() => {
newHook();
setModalOpen(false);
}}
color="primary"
>
Submit
</Button>
</DialogActions>
</Dialog>
) : null;
const hookmap =
hooks.length > 0 ? (
<div>{hooks.map((data) => hookPaper(data))}</div>
) : (
<div style={{ marginTop: "10%", marginLeft: "50%" }}>
<Button
disabled={false}
onClick={() => {
setModalOpen(true);
}}
variant="outlined"
color="primary"
>
CREATE NEW HOOK
</Button>
</div>
);
const hookView = (
<div style={bodyDivStyle}>
<Button
disabled={false}
onClick={() => {
setModalOpen(true);
}}
color="primary"
>
New
</Button>
{hookmap}
</div>
);
const loadedCheck = isLoaded ? (
<div>
{modalView}
{hookView}
</div>
) : (
<div></div>
);
// Maybe use gridview or something, idk
return <div>{loadedCheck}</div>;
};
export default Webhooks;
-13
View File
@@ -75,14 +75,8 @@ import {
ArrowRight as ArrowRightIcon,
} from "@mui/icons-material";
//import NestedMenuItem from "material-ui-nested-menu-item";
//import {Search as SearchIcon, ArrowUpward as ArrowUpwardIcon, Visibility as VisibilityIcon, Close as CloseIcon, Error as ErrorIcon, FindReplace as FindreplaceIcon, ArrowLeft as ArrowLeftIcon, Cached as CachedIcon, DirectionsRun as DirectionsRunIcon, Add as AddIcon, Polymer as PolymerIcon, FormatListNumbered as FormatListNumberedIcon, Create as CreateIcon, PlayArrow as PlayArrowIcon, AspectRatio as AspectRatioIcon, MoreVert as MoreVertIcon, Apps as AppsIcon, Schedule as ScheduleIcon, FavoriteBorder as FavoriteBorderIcon, Pause as PauseIcon, Delete as DeleteIcon, AddCircleOutline as AddCircleOutlineIcon, Save as SaveIcon, KeyboardArrowLeft as KeyboardArrowLeftIcon, KeyboardArrowRight as KeyboardArrowRightIcon, ArrowBack as ArrowBackIcon, Settings as SettingsIcon, LockOpen as LockOpenIcon, ExpandMore as ExpandMoreIcon, VpnKey as VpnKeyIcon} from '@material-ui/icons';
//https://next.material-ui.com/components/material-icons/
import { DataGrid, GridToolbar } from "@mui/x-data-grid";
//import JSONPretty from 'react-json-pretty';
//import JSONPrettyMon from 'react-json-pretty/dist/monikai'
import Dropzone from "../components/Dropzone.jsx";
import { useNavigate, Link } from "react-router-dom";
@@ -1747,13 +1741,6 @@ const Workflows = (props) => {
<FileCopyIcon style={{ marginLeft: 0, marginRight: 8 }} />
{"Duplicate Workflow"}
</MenuItem>
{/*<NestedMenuItem disabled={userdata.orgs === undefined || userdata.orgs === null || userdata.orgs.length === 1 || userdata.orgs.length >= 0} style={{backgroundColor: theme.palette.inputColor, color: "white"}} onClick={() => {
//copyWorkflow(data)
//setOpen(false)
}} key={"duplicate"}>
<FileCopyIcon style={{marginLeft: 0, marginRight: 8}}/>
{"Copy to Child Org"}
</NestedMenuItem>*/}
<MenuItem
style={{ backgroundColor: theme.palette.inputColor, color: "white" }}
onClick={() => {