1.4.0 changes too

This commit is contained in:
Frikky
2023-11-14 15:20:31 +01:00
parent a3af4c09ae
commit f6c7939dda
16 changed files with 614 additions and 990 deletions
+2
View File
@@ -38,6 +38,7 @@ import ScrollToTop from "./components/ScrollToTop";
import AlertTemplate from "./components/AlertTemplate"; import AlertTemplate from "./components/AlertTemplate";
import { useAlert, positions, Provider } from "react-alert"; import { useAlert, positions, Provider } from "react-alert";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import RuntimeDebugger from "./components/RuntimeDebugger.jsx"
import { ToastContainer, toast } from 'react-toastify'; import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
@@ -346,6 +347,7 @@ const App = (message, props) => {
/> />
} }
/> />
<Route exact path="/debug" element={<RuntimeDebugger userdata={userdata} globalUrl={globalUrl} /> } />
<Route exact path="/apps/authentication" element={<UpdateAuthentication serverside={false} userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} /> <Route exact path="/apps/authentication" element={<UpdateAuthentication serverside={false} userdata={userdata} isLoggedIn={isLoggedIn} setIsLoggedIn={setIsLoggedIn} register={true} isLoaded={isLoaded} globalUrl={globalUrl} setCookie={setCookie} cookies={cookies} {...props} />} />
<Route <Route
exact exact
+29 -9
View File
@@ -37,7 +37,7 @@ import {
} from '@mui/material'; } from '@mui/material';
const AppSearchButtons = (props) => { const AppSearchButtons = (props) => {
const { userdata, globalUrl, appFramework, finishedApps, appType, totalApps, index, onNodeSelect, setDiscoveryData, appName, AppImage, setDefaultSearch, discoveryData, checkLogin, setMissing, } = props const { userdata, globalUrl, appFramework, moreButton, finishedApps, appType, totalApps, index, onNodeSelect, setDiscoveryData, appName, AppImage, setDefaultSearch, discoveryData, checkLogin, setMissing, } = props
const ref = useRef() const ref = useRef()
let navigate = useNavigate(); let navigate = useNavigate();
@@ -131,20 +131,38 @@ const AppSearchButtons = (props) => {
//setFrameworkLoaded(true) //setFrameworkLoaded(true)
}) })
} }
const icon = foundApp.large_image const icon = foundApp.large_image
console.log("index:", moreButton)
console.log("totalApps:", totalApps)
let xsValue = 12; let xsValue = 12;
if (index !== undefined && index !== 0) { if (index === totalApps - 1 || index === totalApps - 2 || index === totalApps - 3 || index === totalApps - 4) {
xsValue = 6; xsValue = 6;
} }
if (index === totalApps - 5) {
if (index === totalApps - 4 && totalApps % 2 === 1) {
xsValue = 12; xsValue = 12;
} }
if (moreButton) {
if (index === totalApps - 1 || index === totalApps - 2 || index === totalApps - 3) { switch (index) {
case totalApps - 1:
case totalApps - 2:
case totalApps - 3:
xsValue = 4; xsValue = 4;
break;
case totalApps - 4:
case totalApps - 5:
case totalApps - 6:
case totalApps - 7:
xsValue = 6;
break;
case totalApps - 8:
xsValue = 12;
break;
default:
// Handle other cases if needed
} }
}
return ( return (
<Grid item xs={xsValue} style={{ alignItems: "center", marginTop: 5, }} <Grid item xs={xsValue} style={{ alignItems: "center", marginTop: 5, }}
@@ -239,8 +257,10 @@ const AppSearchButtons = (props) => {
/> />
</div> </div>
) : null} ) : null}
<div style={{ display: "flex", height: 70, border: isHover ? "1px solid #f85a3e" : "var(--Container, #212121)", borderRadius: 8, background: isHover ? "var(--Container, #212121)":"var(--Container, #212121)", <div style={{
alignItems: "center", justifyContent: "center",}} display: "flex", height: 70, border: isHover ? "1px solid #f85a3e" : "var(--Container, #212121)", borderRadius: 8, background: isHover ? "var(--Container, #212121)" : "var(--Container, #212121)",
alignItems: "center", justifyContent: "center",
}}
> >
<Button <Button
fullWidth fullWidth
+22 -4
View File
@@ -1,7 +1,7 @@
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react";
import theme from '../theme.jsx'; import theme from '../theme.jsx';
import ReactGA from 'react-ga4'; import ReactGA from 'react-ga4';
import { useNavigate, Link } from 'react-router-dom'; import { useNavigate, Link, } from 'react-router-dom';
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon, Close as CloseIcon, Folder as FolderIcon, LibraryBooks as LibraryBooksIcon } from '@mui/icons-material'; import { Search as SearchIcon, CloudQueue as CloudQueueIcon, Code as CodeIcon, Close as CloseIcon, Folder as FolderIcon, LibraryBooks as LibraryBooksIcon } from '@mui/icons-material';
import aa from 'search-insights' import aa from 'search-insights'
@@ -13,6 +13,7 @@ import NewReleasesIcon from "@mui/icons-material/NewReleases";
import ExtensionIcon from "@mui/icons-material/Extension"; import ExtensionIcon from "@mui/icons-material/Extension";
import EmailIcon from "@mui/icons-material/Email"; import EmailIcon from "@mui/icons-material/Email";
import FingerprintIcon from '@mui/icons-material/Fingerprint'; import FingerprintIcon from '@mui/icons-material/Fingerprint';
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import AppSearch from "../components/Appsearch.jsx"; import AppSearch from "../components/Appsearch.jsx";
import AppSearchButtons from "../components/AppSearchButtons.jsx"; import AppSearchButtons from "../components/AppSearchButtons.jsx";
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
@@ -304,12 +305,29 @@ const AppSelection = props => {
return ( return (
<Collapse in={true}> <Collapse in={true}>
<Tooltip
title="Back"
placement="top"
style={{ zIndex: 10011 }}
>
<IconButton
style={{
}}
onClick={() => {
navigate('/welcome');
window.location.reload();
}}
>
<ArrowBackIcon style={{ width: 20 }} />
<Typography style={{fontSize : 16, marginLeft : 2}}>Back</Typography>
</IconButton>
</Tooltip>
<div <div
style={{ style={{
// minHeight: sizing, // minHeight: sizing,
// maxHeight: sizing, // maxHeight: sizing,
marginTop: 10, marginTop: 10,
width: isMobile ? 380 : 500, width: isMobile ? 350 : 500,
marginBottom: 25, marginBottom: 25,
textAlign: isMobile ? "center" : null, textAlign: isMobile ? "center" : null,
}} }}
@@ -470,7 +488,7 @@ const AppSelection = props => {
</Grid> </Grid>
</div> </div>
{!moreButton ? ( {!moreButton ? (
<div style={{width: "100%", marginLeft: isMobile ? 100 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null}}> <div style={{ width: "100%", marginLeft: isMobile ? 80 : 200, marginBottom: 20, textAlign: isMobile ? "center" : null }}>
<Link style={{ color: "#FF8444" }} onClick={() => { <Link style={{ color: "#FF8444" }} onClick={() => {
setMoreButton(true) setMoreButton(true)
@@ -480,7 +498,7 @@ const AppSelection = props => {
}} }}
>See More Apps</Link> >See More Apps</Link>
</div>) : ""} </div>) : ""}
<div style={{ flexDirection: "row", width: isMobile ? 380 : null, textAlign: isMobile ? "center" : null}}> <div style={{ flexDirection: "row", width: isMobile ? 340 : null, textAlign: isMobile ? "center" : null }}>
<Button variant="contained" type="submit" fullWidth style={bottomButtonStyle} onClick={() => { <Button variant="contained" type="submit" fullWidth style={bottomButtonStyle} onClick={() => {
navigate("/welcome?tab=3") navigate("/welcome?tab=3")
setActiveStep(2) setActiveStep(2)
+27
View File
@@ -887,6 +887,31 @@ const Billing = (props) => {
"Shuffle is an Open Source automation platform, and no license is required to use it. You may however activate Cloud Sync, get our Scale license, get help with Kubernetes, or talk to Shuffle's Support team to get automation help." "Shuffle is an Open Source automation platform, and no license is required to use it. You may however activate Cloud Sync, get our Scale license, get help with Kubernetes, or talk to Shuffle's Support team to get automation help."
} }
</Typography> </Typography>
{userdata.support === true ?
<div style={{marginBottom: 10, }}>
For sales: Create&nbsp;
<a href={"https://docs.google.com/document/d/1OeJSi42812EMg7fUAw1HAj1ymOG8rfp8Ma_DGJKvwgI/copy?usp=sharing&organization=" + selectedOrganization.id} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
New Cloud Contract
</a>
&nbsp;or&nbsp;
<a href={"https://docs.google.com/document/d/1IguxpeV4Wwwr9C0MPyUNhhajEu_PxjRfP7f0hYyRYOI/copy?usp=sharing&organization=" + selectedOrganization.id} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
New Onprem Contract
</a>
&nbsp; - &nbsp;
<a href={"https://drive.google.com/drive/folders/1zVvwwkbQXW3p-DJYa0GBDzFo_ZnV_I_5"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
Google Drive Link
</a>
&nbsp; - &nbsp;
<a href={"https://github.com/Shuffle/Shuffle-docs/tree/master/handbook/Sales"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
Sales Process
</a>
</div>
:
null
}
<div style={{display: "flex", maxWidth: 768, minWidth: 768, }}> <div style={{display: "flex", maxWidth: 768, minWidth: 768, }}>
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? {isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ?
<SubscriptionObject <SubscriptionObject
@@ -1009,6 +1034,8 @@ const Billing = (props) => {
</Grid> </Grid>
*/} */}
</div> </div>
{isCloud && {isCloud &&
selectedOrganization.partner_info !== undefined && selectedOrganization.partner_info !== undefined &&
selectedOrganization.partner_info.reseller === true ? ( selectedOrganization.partner_info.reseller === true ? (
+1 -1
View File
@@ -339,7 +339,7 @@ const CacheView = (props) => {
<div style={{ marginTop: 20, marginBottom: 20 }}> <div style={{ marginTop: 20, marginBottom: 20 }}>
<h2 style={{ display: "inline" }}>Shuffle Datastore</h2> <h2 style={{ display: "inline" }}>Shuffle Datastore</h2>
<span style={{ marginLeft: 25 }}> <span style={{ marginLeft: 25 }}>
Datastore is a key-value store for storing data that can be used cross-workflow.&nbsp; Datastore is a permanent key-value database for storing data that can be used cross-workflow. You can store anything from lists of IPs to complex configurations.&nbsp;
<a <a
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
@@ -1256,7 +1256,7 @@ const ConfigureWorkflow = (props) => {
</Typography> </Typography>
: null} : null}
<List style={{paddingBottom: 250, }}> <List style={{paddingBottom: window.location.pathname.includes("/workflows/") ? 0 : 250, }}>
{requiredActions.map((data, index) => { {requiredActions.map((data, index) => {
return ( return (
<div key={index} style={{marginBottom: 10, }}> <div key={index} style={{marginBottom: 10, }}>
+20 -1
View File
@@ -5,6 +5,7 @@ import 'react-alice-carousel/lib/alice-carousel.css';
import TrendingFlatIcon from '@mui/icons-material/TrendingFlat'; import TrendingFlatIcon from '@mui/icons-material/TrendingFlat';
import theme from '../theme.jsx'; import theme from '../theme.jsx';
import {isMobile} from "react-device-detect"; import {isMobile} from "react-device-detect";
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import CheckBoxSharpIcon from '@mui/icons-material/CheckBoxSharp'; import CheckBoxSharpIcon from '@mui/icons-material/CheckBoxSharp';
import { findSpecificApp } from "../components/AppFramework.jsx" import { findSpecificApp } from "../components/AppFramework.jsx"
import { import {
@@ -291,11 +292,29 @@ const ExploreWorkflow = (props) => {
return ( return (
<div style={{ marginTop: 0, margin: "auto", minHeight: sizing, maxHeight: sizing, }}> <div style={{ marginTop: 0, margin: "auto", minHeight: sizing, maxHeight: sizing, }}>
<Tooltip
title="Back"
placement="top"
style={{ zIndex: 10011 }}
>
<IconButton
style={{
marginRight: isMobile ? 230 : null
}}
onClick={() => {
navigate('/welcome?tab=2');
window.location.reload();
}}
>
<ArrowBackIcon style={{ width: 20 }} />
<Typography style={{fontSize : 16, marginLeft : 2}}>Back</Typography>
</IconButton>
</Tooltip>
{modalView} {modalView}
<Typography variant="h4" style={{ marginLeft: 8, marginTop: isMobile ? null : 40, marginRight: 30, marginBottom: 0, }} color="rgba(241, 241, 241, 1)"> <Typography variant="h4" style={{ marginLeft: 8, marginTop: isMobile ? null : 40, marginRight: 30, marginBottom: 0, }} color="rgba(241, 241, 241, 1)">
Start using workflows Start using workflows
</Typography> </Typography>
<Typography variant="body2" style={{ marginLeft: 8, marginTop: 10, marginRight: 30, marginBottom: 40, }} color="rgba(158, 158, 158, 1)"> <Typography variant="body2" style={{ marginLeft: isMobile ? null : 8, marginTop: isMobile ? 5 : 10, marginRight: isMobile ? null : 100, marginBottom: isMobile ? 20 : 40, }} color="rgba(158, 158, 158, 1)">
Based on what you selected workflows, here are our recommendations! You will see more of these later. Based on what you selected workflows, here are our recommendations! You will see more of these later.
</Typography> </Typography>
+1 -1
View File
@@ -382,7 +382,7 @@ const Files = (props) => {
<div style={{ marginTop: 20, marginBottom: 20 }}> <div style={{ marginTop: 20, marginBottom: 20 }}>
<h2 style={{ display: "inline" }}>Files</h2> <h2 style={{ display: "inline" }}>Files</h2>
<span style={{ marginLeft: 25 }}> <span style={{ marginLeft: 25 }}>
Files from Workflows.{" "} Files from Workflows are a way to store as well as edit files.{" "}
<a <a
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
+6 -50
View File
@@ -51,10 +51,6 @@ const hoverOutColor = "#e8eaf6"
const Header = props => { const Header = props => {
const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, homePage, userdata, serverside, } = props; const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, homePage, userdata, serverside, } = props;
//const theme = useTheme();
//const alert = useAlert()
const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor); const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor);
const [SoarHoverColor, setSoarHoverColor] = useState(hoverOutColor); const [SoarHoverColor, setSoarHoverColor] = useState(hoverOutColor);
const [LoginHoverColor, setLoginHoverColor] = useState(hoverOutColor); const [LoginHoverColor, setLoginHoverColor] = useState(hoverOutColor);
@@ -543,6 +539,8 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
</Button> </Button>
</Link> </Link>
</ListItem> </ListItem>
</div>
<div style={{display: "flex", flex: 1, }}>
<ListItem style={{textAlign: "center", marginLeft: "0px",}}> <ListItem style={{textAlign: "center", marginLeft: "0px",}}>
<Link to ="/usecases" style={hrefStyle}> <Link to ="/usecases" style={hrefStyle}>
@@ -559,21 +557,6 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
</Button> </Button>
</Link> </Link>
</ListItem> </ListItem>
{/*
<ListItem style={{textAlign: "center", marginLeft: "0px", paddingRight: 0, }}>
<Link to ="/contact" style={hrefStyle}>
<Button variant="text" color="secondary" style={{textTransform: "none"}} onClick={() => {
ReactGA.event({
category: "header",
action: "contact_click",
label: "",
})
}}>
Contact
</Button>
</Link>
</ListItem>
*/}
{isCloud ? {isCloud ?
<ListItem style={{textAlign: "center", marginLeft: "0px", paddingRight: 0,}}> <ListItem style={{textAlign: "center", marginLeft: "0px", paddingRight: 0,}}>
<Link to ="/pricing" style={hrefStyle}> <Link to ="/pricing" style={hrefStyle}>
@@ -615,13 +598,11 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
</List> </List>
</div> </div>
<div style={{flex: 1, marginTop: 0,}}>
<SearchField serverside={serverside} userdata={userdata} />
</div>
<div style={{flex: 1, display: "flex", flexDirection: "row-reverse"}}> <div style={{flex: 1, display: "flex", flexDirection: "row-reverse"}}>
<SearchField serverside={serverside} userdata={userdata} />
<List style={{display: 'flex', flexDirection: 'row-reverse'}} component="nav"> <List style={{display: 'flex', flexDirection: 'row-reverse'}} component="nav">
<ListItem style={{textAlign: "center"}}> <ButtonGroup>
<Link to="/login" style={hrefStyle}>
<Button variant="outlined" style={{textTransform: "none", borderRadius: 25, padding: "7px 14px 7px 14px", maxWidth: 100, minWidth: 100, }} onClick={() => { <Button variant="outlined" style={{textTransform: "none", borderRadius: 25, padding: "7px 14px 7px 14px", maxWidth: 100, minWidth: 100, }} onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
@@ -631,11 +612,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
}) })
} }
}}>Login</Button> }}>Login</Button>
</Link>
</ListItem>
{isCloud ? {isCloud ?
<ListItem style={{flextextAlign: "center", marginRight: 10, }}>
<Link to="/register" style={hrefStyle}> <Link to="/register" style={hrefStyle}>
<Button variant="contained" color="primary" style={{minWidth: 100, maxWidth: 100, padding: "7px 14px 7px 14px", borderRadius: 25, textTransform: "none", backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", color: "white",}} onClick={() => { <Button variant="contained" color="primary" style={{minWidth: 100, maxWidth: 100, padding: "7px 14px 7px 14px", borderRadius: 25, textTransform: "none", backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", color: "white",}} onClick={() => {
ReactGA.event({ ReactGA.event({
@@ -647,28 +624,7 @@ const { globalUrl, setNotifications, notifications, isLoggedIn, removeCookie, ho
</Link> </Link>
</ListItem> </ListItem>
: null} : null}
</ButtonGroup>
{/*
<span style={{marginTop: 8}}>
{supportMenu}
</span>
*/}
{/*
<ListItem style={{textAlign: "center", marginLeft: "0px", paddingRight: 0, }}>
<Link rel="noopener noreferrer" to="/docs" style={hrefStyle}>
<Button variant="text" color="secondary" style={{textTransform: "none"}} onClick={() => {
ReactGA.event({
category: "header",
action: "docs_click_not_signedin",
label: "",
})
}}>
Docs
</Button>
</Link>
</ListItem>
*/}
</List> </List>
</div> </div>
</div> </div>
+98 -593
View File
@@ -2,6 +2,7 @@ import React, {useState, useEffect, useRef} from 'react';
import theme from '../theme.jsx'; import theme from '../theme.jsx';
import { useNavigate, Link, useParams } from "react-router-dom"; import { useNavigate, Link, useParams } from "react-router-dom";
import SearchBox from "./SearchData.jsx";
import { import {
Chip, Chip,
@@ -11,24 +12,31 @@ import {
List, List,
Card, Card,
ListItem, ListItem,
Button,
Dialog,
ListItemAvatar, ListItemAvatar,
ListItemText, ListItemText,
Avatar, Avatar,
Typography, Typography,
Tooltip, Tooltip,
Divider,
DialogTitle,
DialogContent,
} from '@mui/material'; } from '@mui/material';
import Mousetrap from 'mousetrap';
import { import {
AvatarGroup, AvatarGroup,
} from "@mui/material" } from "@mui/material"
import { Search as SearchIcon, Close as CloseIcon, Folder as FolderIcon, Code as CodeIcon, LibraryBooks as LibraryBooksIcon } from '@mui/icons-material' import { Search as SearchIcon, Close as CloseIcon, Folder as FolderIcon, Code as CodeIcon, LibraryBooks as LibraryBooksIcon } from '@mui/icons-material'
import KeyboardCommandKeyIcon from '@mui/icons-material/KeyboardCommandKey';
import algoliasearch from 'algoliasearch/lite'; import algoliasearch from 'algoliasearch/lite';
import aa from 'search-insights' import aa from 'search-insights'
import { InstantSearch, Configure, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom'; import { InstantSearch, Configure, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom';
//import { InstantSearch, SearchBox, Hits, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom'; //import { InstantSearch, SearchBox, Hits, connectSearchBox, connectHits, Index } from 'react-instantsearch-dom';
import { HotKeys } from 'react-hotkeys';
// https://www.algolia.com/doc/api-reference/widgets/search-box/react/ // https://www.algolia.com/doc/api-reference/widgets/search-box/react/
const chipStyle = { const chipStyle = {
backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white", backgroundColor: "#3d3f43", height: 30, marginRight: 5, paddingLeft: 5, paddingRight: 5, height: 28, cursor: "pointer", borderColor: "#3d3f43", color: "white",
@@ -36,623 +44,120 @@ const chipStyle = {
const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240") const searchClient = algoliasearch("JNSS5CFDZZ", "db08e40265e2941b9a7d8f644b6e5240")
const SearchField = props => { const SearchField = props => {
const { serverside, userdata } = props const { serverside, userdata, isMobile, isLoaded, globalUrl, isHeader, isLoggedIn, small, rounded } = props
let navigate = useNavigate(); let navigate = useNavigate();
const borderRadius = 3 const borderRadius = 3
const node = useRef() const node = useRef()
const [searchOpen, setSearchOpen] = useState(false) const [searchOpen, setSearchOpen] = useState(false)
const [modalOpen, setModalOpen] = React.useState(false);
const [oldPath, setOldPath] = useState("") const [oldPath, setOldPath] = useState("")
const [value, setValue] = useState(""); const [value, setValue] = useState("");
useEffect(() => {
Mousetrap.bind(['command+k', 'ctrl+k'], () => {
setModalOpen(true);
return false; // Prevent the default action
});
Mousetrap.bind(['esc'], () => {
setModalOpen(false);
return false; // Prevent the default action
});
if (serverside === true) { return () => {
return null Mousetrap.unbind(['command+k', 'ctrl+k']);
}
if (window !== undefined && window.location !== undefined && window.location.pathname === "/search") {
return null
}
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
if (window.location.pathname !== oldPath) {
setSearchOpen(false)
setOldPath(window.location.pathname)
}
//useEffect(() => {
// if (searchOpen) {
// var tarfield = document.getElementById("shuffle_search_field")
// tarfield.focus()
// }
//}, searchOpen)
const SearchBox = ({currentRefinement, refine, isSearchStalled, } ) => {
const keyPressHandler = (e) => {
// e.preventDefault();
if (e.which === 13) {
// alert("You pressed enter!");
navigate("/search?q=" + currentRefinement, { state: value, replace: true });
}
}; };
/* }, []);
endAdornment: (
<InputAdornment position="end" style={{textAlign: "right", zIndex: 5001, cursor: "pointer", width: 100, }} onMouseOver={(event) => {
event.preventDefault()
}}>
<CloseIcon style={{marginRight: 5,}} onClick={() => {
setSearchOpen(false)
}} />
</InputAdornment>
),
*/
return ( const fieldWidth = small === true ? 120 : 310
<form id="search_form" noValidate type="searchbox" action="" role="search" style={{margin: "10px 0px 0px 0px", }} onClick={() => { const modalView = (
}}> // console.log("key:", dataValue.key),
<TextField //console.log("value:",dataValue.value),
fullWidth <Dialog
style={{backgroundColor: theme.palette.surfaceColor, borderRadius: borderRadius, minWidth: 403, maxWidth: 403, }} open={modalOpen}
InputProps={{ onClose={() => {
setModalOpen(false);
}}
PaperProps={{
style: { style: {
color: "white", color: "white",
fontSize: "1em", minWidth: 750,
height: 50, height: 685,
margin: 0, borderRadius: 16,
fontSize: "0.9em", border: "1px solid var(--Container-Stroke, #494949)",
paddingLeft: 10, background: "var(--Container, #000000)",
boxShadow: "0px 16px 24px 8px rgba(0, 0, 0, 0.25)",
zIndex: 13000,
}, },
disableUnderline: true,
endAdornment: (
<InputAdornment position="start">
<SearchIcon style={{marginLeft: 5, color: "#f86a3e",}}/>
</InputAdornment>
),
}}
autoComplete='off'
type="search"
color="primary"
placeholder="Find Public Apps, Workflows, Documentation..."
value={currentRefinement}
onKeyDown={keyPressHandler}
id="shuffle_search_field"
onClick={(event) => {
if (!searchOpen) {
setSearchOpen(true)
setTimeout(() => {
var tarfield = document.getElementById("shuffle_search_field")
//console.log("TARFIELD: ", tarfield)
tarfield.focus()
}, 100)
}
}}
onBlur={(event) => {
setTimeout(() => {
setSearchOpen(false)
}, 500)
}}
onChange={(event) => {
//if (event.currentTarget.value.length > 0 && !searchOpen) {
// setSearchOpen(true)
//}
refine(event.currentTarget.value)
}}
limit={5}
/>
{/*isSearchStalled ? 'My search is stalled' : ''*/}
</form>
)
}
const WorkflowHits = ({ hits }) => {
const [mouseHoverIndex, setMouseHoverIndex] = useState(0)
var tmp = searchOpen
if (!searchOpen) {
return null
}
const positionInfo = document.activeElement.getBoundingClientRect()
const outerlistitemStyle = {
width: "100%",
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
}
if (hits.length > 4) {
hits = hits.slice(0, 4)
}
var type = "workflows"
const baseImage = <CodeIcon />
return (
<Card elevation={0} style={{position: "relative", marginLeft: 10, marginRight: 10, position: "absolute", color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: 405, height: 408, left: 75, boxShadows: "none",}}>
<Typography variant="h6" style={{margin: "10px 10px 0px 20px", }}>
Workflows
</Typography>
<List style={{backgroundColor: theme.palette.inputColor, }}>
{hits.length === 0 ?
<ListItem style={outerlistitemStyle}>
<ListItemAvatar onClick={() => console.log(hits)}>
<Avatar>
<FolderIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={"No workflows found."}
secondary={"Try a broader search term"}
/>
</ListItem>
:
hits.map((hit, index) => {
const innerlistitemStyle = {
width: positionInfo.width+35,
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
cursor: "pointer",
marginLeft: 5,
marginRight: 5,
maxHeight: 75,
minHeight: 75,
maxWidth: 420,
minWidth: "100%",
}
const name = hit.name === undefined ?
hit.filename.charAt(0).toUpperCase() + hit.filename.slice(1).replaceAll("_", " ") + " - " + hit.title :
(hit.name.charAt(0).toUpperCase()+hit.name.slice(1)).replaceAll("_", " ")
const secondaryText = hit.description !== undefined && hit.description !== null && hit.description.length > 3 ? hit.description.slice(0, 40)+"..." : ""
const appGroup = hit.action_references === undefined || hit.action_references === null ? [] : hit.action_references
const avatar = baseImage
var parsedUrl = isCloud ? `/workflows/${hit.objectID}` : `https://shuffler.io/workflows/${hit.objectID}`
parsedUrl += `?queryID=${hit.__queryID}`
// <a rel="noopener noreferrer" href="https://www.algolia.com/" target="_blank" style={{textDecoration: "none", color: "white"}}>
return (
<Link key={hit.objectID} to={parsedUrl} rel="noopener noreferrer" style={{textDecoration: "none", color: "white",}} onClick={(event) => {
//console.log("CLICK")
setSearchOpen(true)
aa('init', {
appId: searchClient.appId,
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'click',
eventName: 'Workflow Clicked',
index: 'workflows',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: hit.__queryID,
positions: [hit.__position],
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
if (!isCloud) {
event.preventDefault()
window.open(parsedUrl, '_blank');
}
}}>
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
setMouseHoverIndex(index)
}}>
<ListItemAvatar>
{avatar}
</ListItemAvatar>
<div style={{}}>
<ListItemText
primary={name}
/>
<AvatarGroup max={10} style={{flexDirection: "row", padding: 0, margin: 0, itemAlign: "left", textAlign: "left",}}>
{appGroup.map((app, index) => {
// Putting all this in secondary of ListItemText looked weird.
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"> {isHeader ? <div style={{ display: "flex" }}>
<Avatar alt={app.name} src={app.image_url} style={{width: 24, height: 24}}/> <DialogTitle style={{ marginTop: 15, marginLeft: 5, color: "var(--Paragraph-text, #C8C8C8)" }} >Search Shuffle</DialogTitle>
</Tooltip> <Button fullWidth style={{ marginLeft: 470 }} onClick={() => {
setModalOpen(false);
}}><CloseIcon /></Button>
</div> </div>
) : null}
})} <DialogContent style={{}}>
</AvatarGroup> <SearchBox setModalOpen={setModalOpen} modalOpen={modalOpen} serverside={serverside} userdata={userdata} />
</DialogContent>
<Divider style={{overflow: "hidden"}}/>
<span style={{display:"flex", width:"100%"}}>
<div style={{display: "flex", marginTop: 6, marginBottom: 6, marginRight: 100, marginLeft: 20, alignItems: "center"}}>
{/* <Typography variant="body2" style={{ fontSize: 16, fontWidth: 550, color: "var(--Paragraph-text, #C8C8C8)"}}>
Discord
</Typography> */}
<a rel="noopener noreferrer" href="https://discord.com/invite/B2CBzUm" target="_blank" style={{ textDecoration: "none", color: "white" }}>
<img src={"/images/social/discode.svg"} alt="Algolia logo" style={{ height: 22, marginLeft: 5, marginTop: 3, }} />
</a>
</div> </div>
{/* <div style={{ display: "flex", marginTop: 6, marginBottom: 6, marginLeft: 440 }}>
<ListItemSecondaryAction> <Typography variant="body2" style={{color: "var(--Paragraph-text, #C8C8C8)"}}>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
*/}
</ListItem>
</Link>
)})
}
</List>
{/*
<span style={{display: "flex", textAlign: "left", float: "left", position: "absolute", left: 15, bottom: 10, }}>
<Link to="/search" style={{textDecoration: "none", color: "#f85a3e"}}>
<Typography variant="body2" style={{}}>
See all workflows
</Typography>
</Link>
</span>
*/}
</Card>
)
}
const AppHits = ({ hits }) => {
const [mouseHoverIndex, setMouseHoverIndex] = useState(0)
var tmp = searchOpen
if (!searchOpen) {
return null
}
const positionInfo = document.activeElement.getBoundingClientRect()
const outerlistitemStyle = {
width: "100%",
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
}
if (hits.length > 4) {
hits = hits.slice(0, 4)
}
var type = "app"
const baseImage = <LibraryBooksIcon />
return (
<Card elevation={0} style={{position: "relative", marginLeft: 10, marginRight: 10, position: "absolute", color: "white", zIndex: 1001, backgroundColor: theme.palette.inputColor, width: 1155, height: 408, left: -305, boxShadows: "none",}}>
<IconButton style={{zIndex: 5000, position: "absolute", right: 14, color: "grey"}} onClick={() => {
setSearchOpen(false)
}}>
<CloseIcon />
</IconButton>
<Typography variant="h6" style={{margin: "10px 10px 0px 20px", }}>
Apps
</Typography>
<List style={{backgroundColor: theme.palette.inputColor, }}>
{hits.length === 0 ?
<ListItem style={outerlistitemStyle}>
<ListItemAvatar onClick={() => console.log(hits)}>
<Avatar>
<FolderIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={"No apps found."}
secondary={"Try a broader search term"}
/>
</ListItem>
:
hits.map((hit, index) => {
const innerlistitemStyle = {
width: positionInfo.width+35,
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
cursor: "pointer",
marginLeft: 5,
marginRight: 5,
maxHeight: 75,
minHeight: 75,
maxWidth: 420,
minWidth: "100%",
}
const name = hit.name === undefined ?
hit.filename.charAt(0).toUpperCase() + hit.filename.slice(1).replaceAll("_", " ") + " - " + hit.title :
(hit.name.charAt(0).toUpperCase()+hit.name.slice(1)).replaceAll("_", " ")
var secondaryText = hit.data !== undefined ? hit.data.slice(0, 40)+"..." : ""
const avatar = hit.image_url === undefined ?
baseImage
:
<Avatar
src={hit.image_url}
variant="rounded"
/>
//console.log(hit)
if (hit.categories !== undefined && hit.categories !== null && hit.categories.length > 0) {
secondaryText = hit.categories.slice(0,3).map((data, index) => {
if (index === 0) {
return data
}
return ", "+data
/*
<Chip
key={index}
style={chipStyle}
label={data}
onClick={() => {
//handleChipClick
}}
variant="outlined"
color="primary"
/>
*/
})
}
var parsedUrl = isCloud ? `/apps/${hit.objectID}` : `https://shuffler.io/apps/${hit.objectID}`
parsedUrl += `?queryID=${hit.__queryID}`
return (
<Link key={hit.objectID} to={parsedUrl} style={{textDecoration: "none", color: "white",}} onClick={(event) => {
console.log("CLICK")
setSearchOpen(true)
aa('init', {
appId: searchClient.appId,
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'click',
eventName: 'App Clicked',
index: 'appsearch',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: hit.__queryID,
positions: [hit.__position],
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
if (!isCloud) {
event.preventDefault()
window.open(parsedUrl, '_blank');
}
}}>
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
setMouseHoverIndex(index)
}}>
<ListItemAvatar>
{avatar}
</ListItemAvatar>
<ListItemText
primary={name}
secondary={secondaryText}
/>
{/*
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
*/}
</ListItem>
</Link>
)})
}
</List>
<span style={{display: "flex", textAlign: "left", float: "left", position: "absolute", left: 15, bottom: 10, }}>
<Link to="/search" style={{textDecoration: "none", color: "#f85a3e"}}>
<Typography variant="body1" style={{}}>
See more
</Typography>
</Link>
</span>
</Card>
)
}
const DocHits = ({ hits }) => {
const [mouseHoverIndex, setMouseHoverIndex] = useState(0)
var tmp = searchOpen
if (!searchOpen) {
return null
}
const positionInfo = document.activeElement.getBoundingClientRect()
const outerlistitemStyle = {
width: "100%",
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
}
if (hits.length > 4) {
hits = hits.slice(0, 4)
}
const type = "documentation"
const baseImage = <LibraryBooksIcon />
//console.log(type, hits.length, hits)
return (
<Card elevation={0} style={{position: "relative", marginLeft: 10, marginRight: 10, position: "absolute", color: "white", zIndex: 1002, backgroundColor: theme.palette.inputColor, width: 405, height: 408, left: 470, boxShadows: "none",}}>
<IconButton style={{zIndex: 5000, position: "absolute", right: 14, color: "grey"}} onClick={() => {
setSearchOpen(false)
}}>
<CloseIcon />
</IconButton>
<Typography variant="h6" style={{margin: "10px 10px 0px 20px", }}>
Documentation
</Typography>
{/*
<IconButton edge="end" aria-label="delete" style={{position: "absolute", top: 5, right: 15,}} onClick={() => {
setSearchOpen(false)
}}>
<DeleteIcon />
</IconButton>
*/}
<List style={{backgroundColor: theme.palette.inputColor, }}>
{hits.length === 0 ?
<ListItem style={outerlistitemStyle}>
<ListItemAvatar onClick={() => console.log(hits)}>
<Avatar>
<FolderIcon />
</Avatar>
</ListItemAvatar>
<ListItemText
primary={"No documentation."}
secondary={"Try a broader search term"}
/>
</ListItem>
:
hits.map((hit, index) => {
const innerlistitemStyle = {
width: positionInfo.width+35,
overflowX: "hidden",
overflowY: "hidden",
borderBottom: "1px solid rgba(255,255,255,0.4)",
backgroundColor: mouseHoverIndex === index ? "#1f2023" : "inherit",
cursor: "pointer",
marginLeft: 5,
marginRight: 5,
maxHeight: 75,
minHeight: 75,
maxWidth: 420,
minWidth: "100%",
}
var name = hit.name === undefined ?
hit.filename.charAt(0).toUpperCase() + hit.filename.slice(1).replaceAll("_", " ") + " - " + hit.title
:
(hit.name.charAt(0).toUpperCase()+hit.name.slice(1)).replaceAll("_", " ")
if (name.length > 30) {
name = name.slice(0, 30)+"..."
}
const secondaryText = hit.data !== undefined ? hit.data.slice(0, 40)+"..." : ""
const avatar = hit.image_url === undefined ?
baseImage
:
<Avatar
src={hit.image_url}
variant="rounded"
/>
var parsedUrl = hit.urlpath !== undefined ? hit.urlpath : ""
parsedUrl += `?queryID=${hit.__queryID}`
if (parsedUrl.includes("/apps/")) {
const extraHash = hit.url_hash === undefined ? "" : `#${hit.url_hash}`
parsedUrl = `/apps/${hit.filename}`
parsedUrl += `?tab=docs&queryID=${hit.__queryID}${extraHash}`
}
return (
<Link key={hit.objectID} to={parsedUrl} style={{textDecoration: "none", color: "white",}} onClick={(event) => {
aa('init', {
appId: searchClient.appId,
apiKey: searchClient.transporter.queryParameters["x-algolia-api-key"]
})
const timestamp = new Date().getTime()
aa('sendEvents', [
{
eventType: 'click',
eventName: 'Document Clicked',
index: 'documentation',
objectIDs: [hit.objectID],
timestamp: timestamp,
queryID: hit.__queryID,
positions: [hit.__position],
userToken: userdata === undefined || userdata === null || userdata.id === undefined ? "unauthenticated" : userdata.id,
}
])
console.log("CLICK")
setSearchOpen(true)
}}>
<ListItem key={hit.objectID} style={innerlistitemStyle} onMouseOver={() => {
setMouseHoverIndex(index)
}}>
<ListItemAvatar>
{avatar}
</ListItemAvatar>
<ListItemText
primary={name}
secondary={secondaryText}
/>
{/*
<ListItemSecondaryAction>
<IconButton edge="end" aria-label="delete">
<DeleteIcon />
</IconButton>
</ListItemSecondaryAction>
*/}
</ListItem>
</Link>
)})
}
</List>
{type === "documentation" ?
<span style={{display: "flex", textAlign: "right", position: "absolute", right: 15, bottom: 10,}}>
<Typography variant="body2" style={{}}>
Search by Search by
</Typography> </Typography>
<a rel="noopener noreferrer" href="https://www.algolia.com/" target="_blank" style={{ textDecoration: "none", color: "white" }}> <a rel="noopener noreferrer" href="https://www.algolia.com/" target="_blank" style={{ textDecoration: "none", color: "white" }}>
<img src={"/images/logo-algolia-nebula-blue-full.svg"} alt="Algolia logo" style={{ height: 17, marginLeft: 5, marginTop: 3, }} /> <img src={"/images/logo-algolia-nebula-blue-full.svg"} alt="Algolia logo" style={{ height: 17, marginLeft: 5, marginTop: 3, }} />
</a> </a>
</div>
</span> </span>
: null} </Dialog>
</Card> );
)
}
const CustomSearchBox = connectSearchBox(SearchBox)
const CustomAppHits = connectHits(AppHits)
const CustomWorkflowHits = connectHits(WorkflowHits)
const CustomDocHits = connectHits(DocHits)
return ( return (
<div ref={node} style={{width: "100%", maxWidth: 425, margin: "auto", position: "relative", }}> <div style={{ marginTop: "auto", marginLeft: !isLoggedIn ? 0 : 130 }}>
<InstantSearch searchClient={searchClient} indexName="appsearch" onClick={() => { {modalView}
console.log("CLICKED") <TextField
}}> style={{ backgroundColor: "#212121", height: 48, borderRadius: rounded === true ? 25 : theme.palette.borderRadius, minWidth: fieldWidth, maxWidth: fieldWidth, }}
<Configure clickAnalytics /> InputProps={{
<CustomSearchBox /> style: {
<Index indexName="appsearch"> color: "white",
<CustomAppHits /> fontSize: "1em",
</Index> height: 50,
<Index indexName="documentation"> margin: 7,
<CustomDocHits /> fontSize: "0.9em",
</Index> },
<Index indexName="workflows"> readOnly: true,
<CustomWorkflowHits /> disableUnderline: true,
</Index> startAdornment: (
</InstantSearch> <InputAdornment position="start">
<SearchIcon style={{ color: "#f86a3e", }} />
</InputAdornment>
),
endAdornment: (
<Button position="end" style={{ marginLeft: 10, width: 15 }}>
<KeyboardCommandKeyIcon style={{ width: 15 }} />
+ K
</Button>
)
}}
variant="standard"
autoComplete='off'
color="primary"
placeholder="Search Apps, Workflows, Docs..."
onClick={(event) => {
setModalOpen(true)
}}
limit={5}
/>
</div> </div>
) )
} }
@@ -22,6 +22,7 @@ import {
Check as CheckIcon, Check as CheckIcon,
TrendingFlat as TrendingFlatIcon, TrendingFlat as TrendingFlatIcon,
Close as CloseIcon, Close as CloseIcon,
East as EastIcon,
} from '@mui/icons-material'; } from '@mui/icons-material';
import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup.jsx"; import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup.jsx";
@@ -36,6 +37,7 @@ const WorkflowTemplatePopup = (props) => {
const [errorMessage, setErrorMessage] = useState(""); const [errorMessage, setErrorMessage] = useState("");
const [workflowLoading, setWorkflowLoading] = useState(false); const [workflowLoading, setWorkflowLoading] = useState(false);
const [workflow, setWorkflow] = useState({}); const [workflow, setWorkflow] = useState({});
const [showLoginButton, setShowLoginButton] = useState(false);
const [appAuthentication, setAppAuthentication] = React.useState(undefined); const [appAuthentication, setAppAuthentication] = React.useState(undefined);
const [missingSource, setMissingSource] = React.useState(undefined) const [missingSource, setMissingSource] = React.useState(undefined)
@@ -119,7 +121,8 @@ const WorkflowTemplatePopup = (props) => {
const loadAppAuth = () => { const loadAppAuth = () => {
// Check if it exists, and has keys // Check if it exists, and has keys
if (userdata === undefined || userdata === null || Object.keys(userdata).length === 0) { if (userdata === undefined || userdata === null || Object.keys(userdata).length === 0) {
setErrorMessage("You need to be logged in to try usecases. Redirecting in 5 seconds...") setErrorMessage("You need to be logged in to try the pre-built Workflow Templates.")
setShowLoginButton(true)
// Send the user to the login screen after 3 seconds // Send the user to the login screen after 3 seconds
setTimeout(() => { setTimeout(() => {
@@ -350,12 +353,35 @@ const WorkflowTemplatePopup = (props) => {
<Typography variant="h6" style={{marginTop: 75, }}> <Typography variant="h6" style={{marginTop: 75, }}>
{errorMessage !== "" ? errorMessage : ""} {errorMessage !== "" ? errorMessage : ""}
</Typography> </Typography>
{showLoginButton ?
<Link to="/register?message=Please login to create workflows&view=usecases"
style={{
textDecoration: 'none',
marginBottom: 50,
}}
>
<Typography
style={{
display: "flex",
fontSize: 18,
color: "rgba(255, 132, 68, 1)",
marginTop: 32,
justifyContent: isMobile ? "center" : null,
fontFamily: "var(--zds-typography-base,Inter,Helvetica,arial,sans-serif)",
fontWeight: 550,
}}
>
Sign up
<EastIcon style={{ marginTop: 3, marginLeft: 7 }} />
</Typography>
</Link>
: null}
</div> </div>
} }
{isLoggedIn && (missingSource !== undefined || missingDestination !== undefined) ? {(missingSource !== undefined || missingDestination !== undefined) ?
<Typography variant="body1" style={{marginTop: 75, }}> <Typography variant="body1" style={{marginTop: 75, marginBottom: 10, }}>
{"The following app category is required generate this workflow: "} {"Find relevevant Apps for this Usecase"}
</Typography> </Typography>
: null} : null}
@@ -502,7 +528,7 @@ const WorkflowTemplatePopup = (props) => {
<Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16,fontWeight: isHomePage? 600 : null,textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" :"rgba(241, 241, 241, 1)"}} > <Typography variant="body1" style={{ marginTop: parsedDescription.length === 0 ? 10 : 0, fontSize: isMobile ? 13 : 16,fontWeight: isHomePage? 600 : null,textTransform: 'capitalize', color: isHomePage ? "var(--White-text, #F1F1F1)" :"rgba(241, 241, 241, 1)"}} >
{parsedTitle} {parsedTitle}
</Typography> </Typography>
<Typography variant="body2" color="textSecondary" style={{ fontSize: isMobile ? 10: 16, fontWeight: isHomePage ? 400 : null, textTransform: 'capitalize', marginTop: 0, overflow: "hidden",}} color="rgba(158, 158, 158, 1)"> <Typography variant="body2" color="textSecondary" style={{ fontSize: isMobile ? 10: 16, fontWeight: isHomePage ? 400 : null, textTransform: 'capitalize', marginTop: 0, overflow: "hidden", maxHeight: 21, overflow: "hidden",}} color="rgba(158, 158, 158, 1)">
{parsedDescription} {parsedDescription}
</Typography> </Typography>
</div> </div>
+33 -10
View File
@@ -291,8 +291,6 @@ const Admin = (props) => {
//const alert = useAlert(); //const alert = useAlert();
const handleStatusChange = (event) => { const handleStatusChange = (event) => {
const { value } = event.target; const { value } = event.target;
console.log("value: ", value)
setSelectedStatus(value); setSelectedStatus(value);
@@ -331,7 +329,7 @@ const Admin = (props) => {
var your_apps = "- Connecting " var your_apps = "- Connecting "
var subject_add = 0 var subject_add = 0
var subject = "Want to automate " var subject = "POC to automate "
if (org.security_framework !== undefined && org.security_framework !== null) { if (org.security_framework !== undefined && org.security_framework !== null) {
if (org.security_framework.cases.name !== undefined && org.security_framework.cases.name !== null && org.security_framework.cases.name !== "") { if (org.security_framework.cases.name !== undefined && org.security_framework.cases.name !== null && org.security_framework.cases.name !== "") {
@@ -400,7 +398,7 @@ const Admin = (props) => {
// Remove comma // Remove comma
subject += "?" //subject += "?"
your_apps = your_apps.substring(0, your_apps.length - 2) your_apps = your_apps.substring(0, your_apps.length - 2)
} }
@@ -432,11 +430,24 @@ const Admin = (props) => {
var admins = "" var admins = ""
// Loop users // Loop users
var lastLogin = 0
for (var i = 0; i < users.length; i++) { for (var i = 0; i < users.length; i++) {
if (users[i].username.includes("shuffler")) {
continue
}
if (users[i].role === "admin") { if (users[i].role === "admin") {
admins += users[i].username + "," admins += users[i].username + ","
} }
const data = users[i]
for (var i = 0; i < data.login_info.length; i++) {
if (data.login_info[i].timestamp > lastLogin) {
lastLogin = data.login_info[i].timestamp
} }
}
}
// Remove last comma // Remove last comma
admins = admins.substring(0, admins.length - 1) admins = admins.substring(0, admins.length - 1)
@@ -452,15 +463,24 @@ const Admin = (props) => {
// Get drift username from userdata.username before @ in email // Get drift username from userdata.username before @ in email
const username = userdata.username.substring(0, userdata.username.indexOf("@")) const username = userdata.username.substring(0, userdata.username.indexOf("@"))
var body = `Hey,%0D%0A%0D%0AI saw you trying to use Shuffle, and thought we may be able to help. Right now, it looks like you have ${workflow_amount} workflows made, but it still doesn't look like you are getting the most out of Shuffle. If you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A // Check if timestamp is more than 2 weeks ago and add "a while back" to the message
const timeComparison = 1209600
const extra_timestamp_text = lastLogin === 0 ? 0 : (Date.now()/1000 - lastLogin) > timeComparison ? " a while back" : ""
console.log("LAST LOGIN: " + lastLogin, extra_timestamp_text)
// Check if cloud sync is active, and if so, add a message about it
const cloudSyncInfo = selectedOrganization.cloud_sync === true ? "- Scale your onprem installation" : ""
var body = `Hey,%0D%0A%0D%0AI noticed you tried to use Shuffle${extra_timestamp_text}, and thought you may be interested in a POC. It looks like you have ${workflow_amount} workflows made, but it still doesn't look like you are getting what you wanted out of Shuffle. If you're interested, I'd love to set up a quick call to see if we can help you get more out of Shuffle. %0D%0A%0D%0A
Some of the things we can help with:%0D%0A Some of the things we can help with:%0D%0A
${your_apps} ${your_apps}
- Configuring and authenticating your apps%0D%0A - Configuring and authenticating your apps%0D%0A
${usecases} ${usecases}
- Creating special usecases and apps%0D%0A%0D%0A - Multi-Tenancy and creating special usecases%0D%0A
${cloudSyncInfo}%0D%0A
Let me know if you're interested, or set up a call here: https://drift.me/${username}` If you're interested, please let me know a time that works for you, or set up a call here: https://drift.me/${username}`
return `mailto:${admins}?bcc=frikky@shuffler.io,binu@shuffler.io&subject=${subject}&body=${body}` return `mailto:${admins}?bcc=frikky@shuffler.io,binu@shuffler.io&subject=${subject}&body=${body}`
} }
@@ -984,6 +1004,10 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
leads.push("old customer") leads.push("old customer")
} }
if (responseJson.lead_info.old_lead) {
leads.push("old lead")
}
if (responseJson.lead_info.tech_partner) { if (responseJson.lead_info.tech_partner) {
leads.push("tech partner") leads.push("tech partner")
} }
@@ -2428,7 +2452,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
renderValue={(selected) => selected.join(', ')} renderValue={(selected) => selected.join(', ')}
MenuProps={MenuProps} MenuProps={MenuProps}
> >
{["contacted", "lead", "demo done", "pov", "customer", "open source", "student", "internal", "old customer", "creator", "tech partner"].map((name) => ( {["contacted", "lead", "demo done", "pov", "customer", "open source", "student", "internal", "creator", "tech partner", "old customer", "old lead", ].map((name) => (
<MenuItem key={name} value={name}> <MenuItem key={name} value={name}>
<Checkbox checked={selectedStatus.indexOf(name) > -1} /> <Checkbox checked={selectedStatus.indexOf(name) > -1} />
<ListItemText primary={name} /> <ListItemText primary={name} />
@@ -3124,7 +3148,6 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
} }
if (loginInfo > 0) { if (loginInfo > 0) {
console.log("SETTING LAST LOGIN: " + loginInfo)
lastLogin = new Date(loginInfo * 1000).toISOString().slice(0, 10) + " (" + data.login_info.length + ")" lastLogin = new Date(loginInfo * 1000).toISOString().slice(0, 10) + " (" + data.login_info.length + ")"
} }
} }
@@ -4382,7 +4405,7 @@ Let me know if you're interested, or set up a call here: https://drift.me/${user
<Tab <Tab
label=<span> label=<span>
<LockIcon style={iconStyle} /> <LockIcon style={iconStyle} />
App Authentication App Auth
</span> </span>
/> />
<Tab <Tab
+18 -3
View File
@@ -110,8 +110,8 @@ import {
Circle as CircleIcon, Circle as CircleIcon,
SquareFoot as SquareFootIcon, SquareFoot as SquareFootIcon,
AutoFixHigh as AutoFixHighIcon, AutoFixHigh as AutoFixHighIcon,
Polyline as PolylineIcon, Polyline as PolylineIcon,
QueryStats as QueryStatsIcon,
} from "@mui/icons-material"; } from "@mui/icons-material";
@@ -14591,7 +14591,7 @@ const AngularWorkflow = (defaultprops) => {
onClose={() => { onClose={() => {
setExecutionModalOpen(false) setExecutionModalOpen(false)
}} }}
style={{ resize: "both", overflow: "auto", zIndex: 10005 }} style={{ resize: "both", overflow: "auto", }}
hideBackdrop={false} hideBackdrop={false}
variant="temporary" variant="temporary"
BackdropProps={{ BackdropProps={{
@@ -14607,7 +14607,6 @@ const AngularWorkflow = (defaultprops) => {
maxWidth: isMobile ? "100%" : 420, maxWidth: isMobile ? "100%" : 420,
color: "white", color: "white",
fontSize: 18, fontSize: 18,
zIndex: 10005,
borderLeft: theme.palette.defaultBorder, borderLeft: theme.palette.defaultBorder,
}, },
}} }}
@@ -14631,6 +14630,7 @@ const AngularWorkflow = (defaultprops) => {
: null} : null}
{executionModalView === 0 ? ( {executionModalView === 0 ? (
<div style={{ padding: isMobile ? "0px 0px 0px 10px" : 25, zIndex: 12502, }}> <div style={{ padding: isMobile ? "0px 0px 0px 10px" : 25, zIndex: 12502, }}>
<div style={{display: "flex", }}>
<Breadcrumbs <Breadcrumbs
aria-label="breadcrumb" aria-label="breadcrumb"
separator="›" separator="›"
@@ -14641,6 +14641,21 @@ const AngularWorkflow = (defaultprops) => {
All Workflow Runs All Workflow Runs
</h2> </h2>
</Breadcrumbs> </Breadcrumbs>
<Tooltip
title={"Explore Executions further"}
placement="left-start"
style={{ zIndex: 10010 }}
>
<a href={`/workflows/debug?workflow_id=${workflow.id}`} style={{textDecoration: "none", }}>
<Button
color="secondary"
style={{marginLeft: 50, maxHeight: 30, marginTop: 20, }}
>
<QueryStatsIcon style={{color: "white", }}/>
</Button>
</a>
</Tooltip>
</div>
<Button <Button
style={{ borderRadius: "0px" }} style={{ borderRadius: "0px" }}
variant="outlined" variant="outlined"
+4 -4
View File
@@ -3125,7 +3125,7 @@ const AppCreator = (defaultprops) => {
</Select> </Select>
</div> </div>
<div style={{marginLeft: 5, flex: 1,}}> <div style={{marginLeft: 5, flex: 1,}}>
Value prefix Prefix
<TextField <TextField
style={{ marginTop: 0, flex: "1", backgroundColor: inputColor }} style={{ marginTop: 0, flex: "1", backgroundColor: inputColor }}
fullWidth={true} fullWidth={true}
@@ -3622,9 +3622,9 @@ const AppCreator = (defaultprops) => {
style: { style: {
backgroundColor: surfaceColor, backgroundColor: surfaceColor,
color: "white", color: "white",
minWidth: 500, minWidth: 550,
maxWidth: 500, maxWidth: 550,
maxHeight: 800, maxHeight: 750,
}, },
}} }}
onClose={() => { onClose={() => {
+1 -1
View File
@@ -419,7 +419,7 @@ const Welcome = (props) => {
</div> </div>
: :
<Fade in={true}> <Fade in={true}>
<div style={{maxWidth: isMobile ? null : 590, margin: "auto", marginTop: 50, }}> <div style={{maxWidth: isMobile ? null : 590, margin: "auto", marginTop: 50,textAlign : isMobile ? "center" : null }}>
<Typography variant="h4" style={{color: "#F1F1F1", marginTop: 50, fontSize: 32}}> <Typography variant="h4" style={{color: "#F1F1F1", marginTop: 50, fontSize: 32}}>
Help us get to know you Help us get to know you
</Typography> </Typography>
+16 -3
View File
@@ -73,6 +73,7 @@ import {
RadioButtonUnchecked as RadioButtonUncheckedIcon, RadioButtonUnchecked as RadioButtonUncheckedIcon,
ArrowLeft as ArrowLeftIcon, ArrowLeft as ArrowLeftIcon,
ArrowRight as ArrowRightIcon, ArrowRight as ArrowRightIcon,
QueryStats as QueryStatsIcon,
} from "@mui/icons-material"; } from "@mui/icons-material";
import { DataGrid, GridToolbar } from "@mui/x-data-grid"; import { DataGrid, GridToolbar } from "@mui/x-data-grid";
@@ -3061,6 +3062,18 @@ const Workflows = (props) => {
const workflowButtons = ( const workflowButtons = (
<span> <span>
<Tooltip color="primary" title={"Explore Workflow Runs"} placement="top">
<Button
disabled={workflows.length === 0}
color="secondary"
variant="text"
onClick={() => {
navigate("/workflows/debug")
}}
>
<QueryStatsIcon />
</Button>
</Tooltip>
{view === "list" && ( {view === "list" && (
<Tooltip color="primary" title={"Grid View"} placement="top"> <Tooltip color="primary" title={"Grid View"} placement="top">
<Button <Button
@@ -3423,8 +3436,8 @@ const Workflows = (props) => {
height: isCloud ? imgSize : imgSize+4, height: isCloud ? imgSize : imgSize+4,
width: isCloud ? imgSize : imgSize+4, width: isCloud ? imgSize : imgSize+4,
position: "absolute", position: "absolute",
top: isCloud ? -1 : -2, top: -2,
left: isCloud ? -1 : -2, left: -2,
cursor: "pointer", cursor: "pointer",
zIndex: 99, zIndex: 99,
border: "2px solid rgba(255,255,255,0.7)", border: "2px solid rgba(255,255,255,0.7)",
@@ -3786,7 +3799,7 @@ const Workflows = (props) => {
color: "white", color: "white",
fontSize: 18, fontSize: 18,
borderLeft: theme.palette.defaultBorder, borderLeft: theme.palette.defaultBorder,
marginTop: 64, marginTop: 100,
borderRadius: "5px 0px 0px 0px", borderRadius: "5px 0px 0px 0px",
}, },
}} }}