From ddbbecc3cc0a2f2996f67e97dd1b354a2aeb6b4d Mon Sep 17 00:00:00 2001 From: jaydeepkotak Date: Mon, 10 Oct 2022 15:23:11 +0530 Subject: [PATCH] front file added --- frontend/public/images/demo1.png | Bin 0 -> 6411 bytes frontend/public/images/demo2.png | Bin 0 -> 6008 bytes frontend/public/images/demo3.png | Bin 0 -> 6671 bytes frontend/public/images/testing.png | Bin 0 -> 4522 bytes frontend/src/components/AppGrid1.jsx | 377 +++++++++++++ frontend/src/views/AppExplorer.jsx | 468 ++++++++++++++++ frontend/src/views/AppHub.jsx | 789 +++++++++++++++++++++++++++ frontend/src/views/Appdemo.jsx | 268 +++++++++ 8 files changed, 1902 insertions(+) create mode 100644 frontend/public/images/demo1.png create mode 100644 frontend/public/images/demo2.png create mode 100644 frontend/public/images/demo3.png create mode 100644 frontend/public/images/testing.png create mode 100644 frontend/src/components/AppGrid1.jsx create mode 100644 frontend/src/views/AppExplorer.jsx create mode 100644 frontend/src/views/AppHub.jsx create mode 100644 frontend/src/views/Appdemo.jsx diff --git a/frontend/public/images/demo1.png b/frontend/public/images/demo1.png new file mode 100644 index 0000000000000000000000000000000000000000..4cd8faf19995e56c1db825eccd223862eed419dd GIT binary patch literal 6411 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 ZKLhN&w3Os>wG;pV002ovPDHLkV1h>xgysMM literal 0 HcmV?d00001 diff --git a/frontend/public/images/testing.png b/frontend/public/images/testing.png new file mode 100644 index 0000000000000000000000000000000000000000..032c94a83676ec056ceb34205890d5a979a325fe GIT binary patch literal 4522 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 literal 0 HcmV?d00001 diff --git a/frontend/src/components/AppGrid1.jsx b/frontend/src/components/AppGrid1.jsx new file mode 100644 index 00000000..8706ef17 --- /dev/null +++ b/frontend/src/components/AppGrid1.jsx @@ -0,0 +1,377 @@ +import React, {useEffect, useState} from 'react'; + +import ReactGA from 'react-ga'; +import { useTheme } from '@material-ui/core/styles'; +import {Link} from 'react-router-dom'; + +import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon } from '@material-ui/icons'; + +import algoliasearch from 'algoliasearch/lite'; +import { InstantSearch, Configure, connectSearchBox, connectHits, connectHitInsights } from 'react-instantsearch-dom'; + +import aa from 'search-insights' + +import { + Zoom, + Grid, + Paper, + TextField, + ButtonBase, + InputAdornment, + Typography, + Button, + Tooltip +} from '@material-ui/core'; + +const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") +//const searchClient = algoliasearch("L55H18ZINA", "a19be455e7e75ee8f20a93d26b9fc6d6") +const AppGrid1 = props => { + const { maxRows, showName, showSuggestion, isMobile, globalUrl, parsedXs, userdata, searchValue } = props + + const isCloud = + window.location.host === "localhost:3000" || + window.location.host === "shuffler.io"; + + const rowHandler = maxRows === undefined || maxRows === null ? 50 : maxRows + const xs = parsedXs === undefined || parsedXs === null ? isMobile ? 6 : 2 : parsedXs + const theme = useTheme(); + //const [apps, setApps] = React.useState([]); + //const [filteredApps, setFilteredApps] = React.useState([]); + const [formMail, setFormMail] = React.useState(""); + const [message, setMessage] = React.useState(""); + const [formMessage, setFormMessage] = React.useState(""); + + const buttonStyle = {borderRadius: 30, height: 50, width: 220, margin: isMobile ? "15px auto 15px auto" : 20, fontSize: 18,} + + const innerColor = "rgba(255,255,255,0.65)" + const borderRadius = 3 + window.title = "Shuffle | Apps | Find and integrate any app" + + const submitContact = (email, message) => { + const data = { + "firstname": "", + "lastname": "", + "title": "", + "companyname": "", + "email": email, + "phone": "", + "message": message, + } + + const errorMessage = "Something went wrong. Please contact frikky@shuffler.io directly." + + 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.reason) + //alert.info("Thanks for submitting!") + } else { + setFormMessage(errorMessage) + } + + setFormMail("") + setMessage("") + }) + .catch(error => { + setFormMessage(errorMessage) + console.log(error) + }); + } + + const SearchBox = ({currentRefinement, refine, isSearchStalled} ) => { + + useEffect(() => { + if (window !== undefined && window.location !== undefined && window.location.search !== undefined && window.location.search !== null) { + const urlSearchParams = new URLSearchParams(window.location.search) + const params = Object.fromEntries(urlSearchParams.entries()) + const foundQuery = {searchValue} + if (foundQuery !== null && foundQuery !== undefined) { + console.log("Got query: ", foundQuery) + refine(foundQuery) + } + } + }, []) + + return ( +
+ + + + ), + }} + autoComplete='off' + type="hidden" + color="primary" + defaultValue={currentRefinement} + placeholder="Find Apps..." + id="shuffle_search_field" + onChange={(event) => { + refine(event.currentTarget.value) + }} + limit={5} + /> + {/*isSearchStalled ? 'My search is stalled' : ''*/} + + ) + } + + var workflowDelay = -50 + const Hits = ({ hits, insights }) => { + const [mouseHoverIndex, setMouseHoverIndex] = useState(-1) + var counted = 0 + + //console.log(hits) + //var curhits = hits + //if (hits.length > 0 && defaultApps.length === 0) { + // setDefaultApps(hits) + //} + + //const [defaultApps, setDefaultApps] = React.useState([]) + //console.log(hits) + //if (hits.length > 0 && hits.length !== innerHits.length) { + // setInnerHits(hits) + //} + + return ( + + {hits.map((data, index) => { + + workflowDelay += 50 + + const paperStyle = { + backgroundColor: index === mouseHoverIndex ? "rgba(255,255,255,0.8)" : theme.palette.inputColor, + color: index === mouseHoverIndex ? theme.palette.inputColor : "rgba(255,255,255,0.8)", + border: `1px solid ${innerColor}`, + padding: 15, + cursor: "pointer", + position: "relative", + minHeight: 116, + } + + if (counted === 12/xs*rowHandler) { + return null + } + + counted += 1 + var parsedname = "" + for (var key = 0; key < data.name.length; key++) { + var character = data.name.charAt(key) + if (character === character.toUpperCase()) { + //console.log(data.name[key], data.name[key+1]) + if (data.name.charAt(key+1) !== undefined && data.name.charAt(key+1) === data.name.charAt(key+1).toUpperCase()) { + } else { + parsedname += " " + } + } + + parsedname += character + } + + parsedname = (parsedname.charAt(0).toUpperCase()+parsedname.substring(1)).replaceAll("_", " ") + + return ( + + + + { + setMouseHoverIndex(index) + /* + ReactGA.event({ + category: "app_grid_view", + action: `search_bar_click`, + label: "", + }) + */ + }} onMouseOut={() => { + setMouseHoverIndex(-1) + }} onClick={() => { + if (isCloud) { + ReactGA.event({ + category: "app_grid_view", + action: `app_${parsedname}_${data.id}_click`, + label: "", + }) + } + + //const searchClient = algoliasearch("L55H18ZINA", "a19be455e7e75ee8f20a93d26b9fc6d6") + console.log(searchClient) + aa('init', { + appId: searchClient.appId, + apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"] + }) + + const timestamp = new Date().getTime() + aa('sendEvents', [ + { + eventType: 'click', + eventName: 'Product Clicked', + index: 'appsearch', + objectIDs: [data.objectID], + timestamp: timestamp, + queryID: data.__queryID, + positions: [data.__position], + userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id, + } + ]) + + }}> + + {data.name} + +
+ {index === mouseHoverIndex || showName === true ? + parsedname + : + null + } + {data.generated ? + + {data.invalid ? + + : + + } + + : + + + + } + + + + + ) + })} + + ) + } + + const CustomSearchBox = connectSearchBox(SearchBox) + const CustomHits = connectHits(Hits) + //const CustomHits = connectHitInsights(aa)(Hits) + const selectButtonStyle = { + minWidth: 150, + maxWidth: 150, + minHeight: 50, + } + + return ( + + ) +} + +export default AppGrid1; diff --git a/frontend/src/views/AppExplorer.jsx b/frontend/src/views/AppExplorer.jsx new file mode 100644 index 00000000..01fc4546 --- /dev/null +++ b/frontend/src/views/AppExplorer.jsx @@ -0,0 +1,468 @@ + +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 = ( +
+ + + + Categories + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ) + return ( +
+
+ + {catItems} +
+ + + + + Getting Started + +
+
+ +
+
+ + + {Array.from(Array(algoliaResult.length)).map((_, index) => ( + + + + + + +
+ +
+ shuffle +
+
+
+ + {algoliaResult[0]["name"]} + +
+
+ + {algoliaResult[0]["description"].substring(0, 20)} + +
+
+ +
+
+
+
+ ))} +
+
+ + + + Most Popular + +
+
+ +
+ + + {Array.from(Array(3)).map((_, index) => ( + + + +
+
+ shuffle +
+
+
+ + App Name + +
+
+ + Description + +
+
+ +
+
+
+
+ ))} +
+
+ + + + + Brand New + +
+
+ +
+ + + {Array.from(Array(3)).map((_, index) => ( + + + +
+
+ shuffle +
+
+
+ + App Name + +
+
+ + Description + +
+
+ +
+
+
+
+ ))} +
+
+ + + + + {Array.from(Array(3)).map((_, index) => ( + + +
+
+ shuffle +
+
+ +
+ ))} +
+
+ + + + + Hybrid work + +
+
+ +
+ + + + {Array.from(Array(3)).map((_, index) => ( + + + +
+
+ shuffle +
+
+
+ + App Name + +
+
+ + Description + +
+
+ +
+
+
+
+ ))} +
+
+ +
+
+ Don't see it? Build it! + Use our APIs to create an app that makes your working life better.And maybe even share it with the world. + visit developer portal +
+
+
+
+ shuffle +
+
+ shuffle +
+
+ shuffle +
+
+
+
+ +
+ +
+
+ + ); +} +export default AppExplorer; diff --git a/frontend/src/views/AppHub.jsx b/frontend/src/views/AppHub.jsx new file mode 100644 index 00000000..5a4db83a --- /dev/null +++ b/frontend/src/views/AppHub.jsx @@ -0,0 +1,789 @@ +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 = ( + + Profile + My account + + ); + + const mobileMenuId = 'primary-search-account-menu-mobile'; + const renderMobileMenu = ( + + + + + + + +

Messages

+
+ + + + + + +

Notifications

+
+ + + + +

Profile

+
+
+ ); + + return ( + + + + shuffle img + + {/* */} + + + + {renderMobileMenu} + {renderMenu} + + ); +} + +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 ( +
+ + +
+
+
+ +
+
+
+ shuffle img + + SHUFFLE + +
+
+ +
+
+
+
+
+
+
+
+ + + + Categories + + + + + + + Workflows + + + + + Apps + + + + + Docs + + + +
+
+ + Workflow + +
+ {!isMobile && usecases !== null && usecases !== undefined && usecases.length > 0 ? +
+ + {usecases.map((usecase, index) => { + //console.log(usecase) + return ( + + { + console.log("clicked...") + }} + > + + + {usecase.name} + + + In use: {usecase.matches.length}/{usecase.list.length} + + + + + ) + })} + +
+ : null} + +
+
+
+ + + + footer + + + +
+ ); +}; + +export default AppHub; \ No newline at end of file diff --git a/frontend/src/views/Appdemo.jsx b/frontend/src/views/Appdemo.jsx new file mode 100644 index 00000000..3fe5aae1 --- /dev/null +++ b/frontend/src/views/Appdemo.jsx @@ -0,0 +1,268 @@ +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 = ( +
+ + + + Categories + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+) + + 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 = +
+
+ + + Apps + + /> + + + {curTab === 0 ? + + : + curTab === 1 ? + window.location.pathname === "/search" ? + + : + + : + curTab === 2 ? + + : + curTab === 3 ? + + : + null} +
+
+ //{/*alternativeView={true} />*/} + + const loadedCheck = isLoaded ? +
+
{landingpageDataBrowser}
+
+ : +
+
+ + // #1f2023? + return( +
+ {catItems} + {loadedCheck} +
+ ) +} + +export default Appdemo;