Merged in all UI fixes

This commit is contained in:
Frikky
2024-07-18 14:41:05 +02:00
parent 0dd5913072
commit 5875745056
12 changed files with 737 additions and 354 deletions
+3 -2
View File
@@ -36,6 +36,7 @@ import edgehandles from "cytoscape-edgehandles";
import cytoscape from "cytoscape"; import cytoscape from "cytoscape";
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { isMobile } from 'react-device-detect';
cytoscape.use(edgehandles) cytoscape.use(edgehandles)
@@ -2152,7 +2153,7 @@ const AppFramework = (props) => {
{ {
Object.getOwnPropertyNames(discoveryData).length > 0 ? Object.getOwnPropertyNames(discoveryData).length > 0 ?
<Paper style={{width: 300, maxHeight: 400, overflow: "hidden", zIndex: 12500, padding: 25, paddingRight: 25, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -50, left: 50, }}> <Paper style={{width: 300, maxHeight: 400, overflow: "hidden", zIndex: 12500, padding: 25, paddingRight: 25, backgroundColor: theme.palette.surfaceColor, border: "1px solid rgba(255,255,255,0.2)", position: "absolute", top: -50, left: isMobile?-50: 50, }}>
{paperTitle.length > 0 ? {paperTitle.length > 0 ?
<span> <span>
<Typography variant="h6" style={{textAlign: "center"}}> <Typography variant="h6" style={{textAlign: "center"}}>
@@ -2321,7 +2322,7 @@ const AppFramework = (props) => {
elements={elements} elements={elements}
minZoom={0.35} minZoom={0.35}
maxZoom={2.00} maxZoom={2.00}
style={{width: 560*scale, height: 560*scale, backgroundColor: theme.palette.backgroundColor, margin: "auto",}} style={{width: isMobile?null:560*scale, height: 560*scale, backgroundColor: theme.palette.backgroundColor, margin: isMobile?null:"auto",}}
stylesheet={frameworkStyle} stylesheet={frameworkStyle}
boxSelectionEnabled={false} boxSelectionEnabled={false}
panningEnabled={false} panningEnabled={false}
+2 -2
View File
@@ -2,7 +2,7 @@ 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 { Search as Searchicon, CloudQueue as CloudQueueicon, Code as Codeicon, Close as Closeicon, Folder as Foldericon, LibraryBooks as LibraryBooksicon, Delete as DeleteIcon, Close as CloseIcon, } from '@mui/icons-material'; import { Search as Searchicon, CloudQueue as CloudQueueicon, Code as Codeicon, Close as Closeicon, Folder as Foldericon, LibraryBooks as LibraryBooksicon, Delete as DeleteIcon, Close as CloseIcon, } from '@mui/icons-material';
import aa from 'search-insights' import aa from 'search-insights'
import Deleteicon from '@mui/icons-material/Delete'; import Deleteicon from '@mui/icons-material/Delete';
@@ -181,7 +181,7 @@ const AppSearchButtons = (props) => {
width: 319, width: 319,
height: 395, height: 395,
flexShrink: 0, flexShrink: 0,
marginLeft: 70, marginLeft: isMobile? null:70,
marginTop: 68, marginTop: 68,
position: "absolute", position: "absolute",
zIndex: 100, zIndex: 100,
+358 -62
View File
@@ -41,11 +41,12 @@ import {
Close as CloseIcon, Close as CloseIcon,
Delete, Delete,
RestaurantRounded, RestaurantRounded,
Cloud,
} from "@mui/icons-material"; } from "@mui/icons-material";
//import { useAlert //import { useAlert
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx"; import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
import BillingStats from "../components/BillingStats.jsx"; import BillingStats from "./BillingStats.jsx";
import { handlePayasyougo } from "../views/HandlePaymentNew.jsx" import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
import DeleteIcon from '@mui/icons-material/Delete'; import DeleteIcon from '@mui/icons-material/Delete';
@@ -173,10 +174,10 @@ const Billing = (props) => {
const paperStyle = { const paperStyle = {
padding: 20, padding: 20,
height: "100%", // maxWidth: 400,
minHeight: 280, width: 340,
maxWidth: 400, height: 480,
width: "100%", // width: "100%",
backgroundColor: theme.palette.platformColor, backgroundColor: theme.palette.platformColor,
borderRadius: theme.palette.borderRadius * 2, borderRadius: theme.palette.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)", border: "1px solid rgba(255,255,255,0.3)",
@@ -470,9 +471,11 @@ const Billing = (props) => {
style: { style: {
pointerEvents: "auto", pointerEvents: "auto",
color: "white", color: "white",
minWidth: 750, // minWidth: 750,
width: 340,
padding: 30, padding: 30,
maxHeight: 700, // maxHeight: 700,
height: 480,
overflowY: "auto", overflowY: "auto",
overflowX: "hidden", overflowX: "hidden",
zIndex: 10012, zIndex: 10012,
@@ -546,7 +549,7 @@ const Billing = (props) => {
</div> </div>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
<div style={{ display: "flex" }}> <div style={{ display: "flex", width: 340 }}>
{top_text === "Base Cloud Access" && userdata.has_card_available === true ? {top_text === "Base Cloud Access" && userdata.has_card_available === true ?
<Chip <Chip
style={{ style={{
@@ -715,14 +718,14 @@ const Billing = (props) => {
userdata.has_card_available === true ? userdata.has_card_available === true ?
"While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month." "While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month."
: :
isCloud ? isCloud ?
`You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.` `You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
: :
`You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.` `You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.`
} }
</Typography> </Typography>
<div style={{ display: 'flex', flexDirection: 'row' }}> <div style={{ display: 'flex', flexDirection: 'row' }}>
<Typography variant="body2" style={{}}> <Typography variant="body2" style={{ marginTop: !userdata.has_card_available ? 5 : 0 }}>
Billing email: {BillingEmail} Billing email: {BillingEmail}
</Typography> </Typography>
{userdata.has_card_available === true && ( {userdata.has_card_available === true && (
@@ -741,7 +744,7 @@ const Billing = (props) => {
boxShadow: 'none', boxShadow: 'none',
border: 'none', border: 'none',
cursor: 'pointer', cursor: 'pointer',
transition: 'background-color 0.3s, color 0.3s' transition: 'background-color 0.3s, color 0.3s',
}} }}
> >
Change Change
@@ -813,12 +816,13 @@ const Billing = (props) => {
variant="outlined" variant="outlined"
color="primary" color="primary"
style={{ style={{
marginTop: 10, marginTop: !userdata.has_card_available ? 20 : 10,
borderRadius: 25, borderRadius: 25,
height: 40, height: 40,
fontSize: 14, fontSize: 16,
color: "white", color: "white",
backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)", backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: "none",
}} }}
onClick={() => { onClick={() => {
@@ -847,9 +851,10 @@ const Billing = (props) => {
marginTop: 10, marginTop: 10,
borderRadius: 25, borderRadius: 25,
height: 40, height: 40,
fontSize: 14, fontSize: 16,
color: "white", color: "white",
backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: 'none'
}} }}
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
@@ -904,9 +909,11 @@ const Billing = (props) => {
const [editConsultation, setEditConsultation] = React.useState(false); const [editConsultation, setEditConsultation] = React.useState(false);
const [openUpgradePlan, setOpenUpgradePlan] = React.useState(false); const [openUpgradePlan, setOpenUpgradePlan] = React.useState(false);
const [consultationHours, setConsultationHours] = React.useState(5); const [consultationHours, setConsultationHours] = React.useState(1);
const [message, setMessage] = React.useState(""); const [message, setMessage] = React.useState("");
const [hovered, setHovered] = React.useState(false) const [hovered, setHovered] = React.useState(false)
const [getProfessionalServices, setGetProfessionalServices] = React.useState(false)
const [clickOnBuy, setClickOnBuy] = React.useState(false)
const formatedHours = String(inputHour).padStart(2, "0") const formatedHours = String(inputHour).padStart(2, "0")
const formatedMinutes = String(inputMinutes).padStart(2, "0") const formatedMinutes = String(inputMinutes).padStart(2, "0")
@@ -959,13 +966,17 @@ const Billing = (props) => {
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
console.log("Response from consultation save: ", responseJson);
if (responseJson.success === true) { if (responseJson.success === true) {
toast.success("Consultation hours saved successfully"); toast.success("Consultation hours saved successfully");
setEditConsultation(false); setEditConsultation(false);
} else { } else {
toast.error("Failed saving consultation hours."); toast.error("Failed saving consultation hours.");
} }
if (inputHour > 0 || inputMinutes > 0) {
setGetProfessionalServices(true)
} else {
setGetProfessionalServices(false)
}
}) })
.catch((error) => { .catch((error) => {
console.log("Error: ", error); console.log("Error: ", error);
@@ -1001,7 +1012,6 @@ const Billing = (props) => {
return response.json(); return response.json();
}) })
.then((responseJson) => { .then((responseJson) => {
console.log("Response from consultation save: ", responseJson);
if (responseJson.success === true) { if (responseJson.success === true) {
toast.success("Thank you for your request. We will get back to you soon."); toast.success("Thank you for your request. We will get back to you soon.");
setOpenUpgradePlan(false); setOpenUpgradePlan(false);
@@ -1015,18 +1025,23 @@ const Billing = (props) => {
}); });
} }
var newPaperstyle = JSON.parse(JSON.stringify(paperStyle)) useEffect(() => {
if (inputHour !== undefined && inputMinutes !== undefined && inputHour > 0 || inputMinutes > 0) {
setGetProfessionalServices(true)
} else {
setGetProfessionalServices(false)
}
})
return ( return (
<Paper style={{ <Paper style={{
padding: 20, padding: 20,
height: "100%", // maxWidth: 400,
minHeight: 280, minWidth: 340,
maxWidth: 400, height: 480,
width: "100%",
backgroundColor: hovered ? "#232427" : theme.palette.platformColor, backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
borderRadius: theme.palette.borderRadius * 2, borderRadius: theme.palette.borderRadius * 2,
border: "1px solid rgba(255,255,255,0.3)", border: "1px solid #f85a3e",
marginRight: 10, marginRight: 10,
marginTop: 15, marginTop: 15,
}} }}
@@ -1041,9 +1056,9 @@ const Billing = (props) => {
</Typography> </Typography>
<div> <div>
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}> <Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
Current Plan includes total {inputHour} hours and {inputMinutes} minutes of consultation and management by our experts. You currently have a total of {inputHour} hours and {inputMinutes} minutes of professional services available by our experts.
</Typography> </Typography>
<div style={{ display: "flex", width: 'auto', justifyContent: 'center', marginTop: 10 }}> <div style={{ display: "flex", minWidth: 340, justifyContent: 'center', marginTop: userdata.support ? 0 : 10 }}>
{editConsultation ? {editConsultation ?
<> <>
<TextField <TextField
@@ -1074,6 +1089,7 @@ const Billing = (props) => {
variant="contained" variant="contained"
color="primary" color="primary"
onClick={handleCancel} onClick={handleCancel}
style={{ textTransform: 'none' }}
> >
Cancel Cancel
</Button> </Button>
@@ -1082,48 +1098,113 @@ const Billing = (props) => {
variant="contained" variant="contained"
color="primary" color="primary"
onClick={toggleEditMode} onClick={toggleEditMode}
style={{ textTransform: 'none' }}
> >
Edit Edit
</Button> </Button>
)} )}
{editConsultation && <Button variant="contained" color="primary" style={{ marginLeft: 5 }} onClick={handleSave}>Save</Button>} {editConsultation && <Button variant="contained" color="primary" style={{ marginLeft: 5, textTransform: 'none' }} onClick={handleSave}>Save</Button>}
</div> </div>
: null} : null}
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}> <Typography variant="body2" color="textSecondary" style={{ marginTop: userdata.support ? 5 : 10, }}>
Features Features
</Typography> </Typography>
<ul> <ul>
<li> <li>
<Typography variant="body2" color="textPrimary" style={{}}> <Typography variant="body2" color="textPrimary" style={{}}>
Debug/Create workflows with our experts Build custom apps, integrations, and worklows for your specific use cases or applications
</Typography> </Typography>
</li> </li>
<li> <li>
<Typography variant="body2" color="textPrimary" style={{}}> <Typography variant="body2" color="textPrimary" style={{}}>
Ask questions and get help with your workflows and integrations by our experts Help solve / debug / update / add features and capabilities of the platform
</Typography> </Typography>
</li> </li>
</ul> </ul>
</div> </div>
<Button <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', marginTop: 20 }}>
fullWidth <Button
disabled={false} fullWidth
variant="outlined" disabled={false}
color="primary" variant="outlined"
style={{ color="primary"
marginTop: 10, style={{
borderRadius: 25, marginTop: userdata.support ? 0 : 10,
height: 40, borderRadius: 25,
fontSize: 14, height: 40,
color: "white", fontSize: 16,
backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", color: "white",
}} backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)",
onClick={() => { textTransform: 'none'
setOpenUpgradePlan(true) }}
}} onClick={() => {
> if (Cloud) {
Upgrade plan ReactGA.event({
</Button> category: "Billing",
action: "Buy_consultation_hours",
});
}
setClickOnBuy(true)
}}
>
Buy
</Button>
<Dialog open={clickOnBuy} onClose={() => { setClickOnBuy(false) }}>
<Typography variant="body1" style={{ marginTop: 10, textAlign: 'center', padding: 20, fontSize: 18 }}>
You will be taken to Stripe to book professional service hours. You can adjust the number of hours on the left side of the Stripe page.
</Typography>
<DialogContent>
<Button
variant="contained"
color="primary"
style={{ display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none', fontSize: 16 }}
onClick={() => {
if (Cloud) {
ReactGA.event({
category: "Billing",
action: "Buy_consultation_hours",
});
}
const url = userdata.licensed === true
? "https://book.stripe.com/6oEeY23fw2T84M06oq"
: "https://book.stripe.com/00g6rw3fw9hwguI289";
window.open(url, "_blank");
}}
>
Book Professional Service Hours
</Button>
</DialogContent>
</Dialog>
<Tooltip title={!getProfessionalServices ? "Please buy the consultation hours to get this professional service" : ""}>
<span>
<Button
fullWidth
disabled={!getProfessionalServices}
variant="outlined"
color="primary"
style={{
marginTop: userdata.support ? 5 : 10,
borderRadius: 25,
height: 40,
fontSize: 16,
color: "white",
backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: 'none',
cursor: getProfessionalServices ? 'pointer' : 'not-allowed',
opacity: getProfessionalServices ? 1 : 0.6,
}}
onClick={() => {
if (getProfessionalServices) {
setOpenUpgradePlan(true);
}
}}
>
Get Professional Service
</Button>
</span>
</Tooltip>
</div>
<Dialog open={openUpgradePlan} <Dialog open={openUpgradePlan}
onClose={() => setOpenUpgradePlan(false)} onClose={() => setOpenUpgradePlan(false)}
fullWidth fullWidth
@@ -1140,20 +1221,21 @@ const Billing = (props) => {
</DialogTitle> </DialogTitle>
<DialogContent style={{ padding: '24px', }}> <DialogContent style={{ padding: '24px', }}>
<Typography variant="body1" color="textSecondary" style={{ marginBottom: '16px', textAlign: 'left' }}> <Typography variant="body1" color="textSecondary" style={{ marginBottom: '16px', textAlign: 'left' }}>
Enter the total hours of consultation you want to include in your plan. Enter the total hours of consultation you want.
</Typography> </Typography>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: '16px' }}> <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: '16px' }}>
<Slider <Slider
value={consultationHours} value={consultationHours}
onChange={(e, val) => setConsultationHours(val)} onChange={(e, val) => setConsultationHours(val)}
aria-labelledby="continuous-slider" aria-labelledby="continuous-slider"
step={5} step={1}
min={5} min={1}
max={50} max={(inputHour === "0" && inputMinutes > 0) ? 1 : inputHour}
style={{ width: '80%', color: theme.palette.primary.main }} // Adding primary color for better visibility style={{ width: '80%', color: theme.palette.primary.main }}
marks marks
valueLabelDisplay="auto" valueLabelDisplay="auto"
/> />
</div> </div>
<Typography variant="body1" color="textSecondary" style={{ marginTop: '24px', textAlign: 'left' }}> <Typography variant="body1" color="textSecondary" style={{ marginTop: '24px', textAlign: 'left' }}>
If you have any additional requirements or questions, please leave a message below. If you have any additional requirements or questions, please leave a message below.
@@ -1163,17 +1245,17 @@ const Billing = (props) => {
fullWidth fullWidth
multiline multiline
rows={4} rows={4}
placeholder="Your message" placeholder="What kind of services are you looking for?"
style={{ marginTop: '16px', borderRadius: '8px' }} style={{ marginTop: '16px', borderRadius: '8px' }}
onChange={(e) => setMessage(e.target.value)} onChange={(e) => setMessage(e.target.value)}
/> />
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px' }} style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none' }}
onClick={handleUpgradeConsultation} onClick={handleUpgradeConsultation}
> >
Submit Request Submit Request for {consultationHours} hours
</Button> </Button>
</DialogContent> </DialogContent>
</Dialog> </Dialog>
@@ -1181,6 +1263,217 @@ const Billing = (props) => {
) )
} }
const TrainingService = () => {
const [hovered, setHovered] = React.useState(false)
const [openPrivateTraining, setOpenPrivateTraining] = React.useState(false)
const [PrivateTrainingMember, setPrivateTrainingMember] = React.useState(5)
const [message, setMessage] = React.useState("");
const handlePrivateTraining = () => {
toast("Submitting your request for private training. Please wait...")
const data = {
org_id: selectedOrganization.id,
trainingMembers: String(PrivateTrainingMember),
message: message
}
const url = `${globalUrl}/api/v1/orgs/${selectedOrganization.id}/privateTraining`
fetch(url, {
body: JSON.stringify(data),
mode: "cors",
method: "POST",
credentials: "include",
crossDomain: true,
withCredentials: true,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
}).then((response) => {
if (response.status !== 200) {
console.log("Error in response");
}
return response.json();
}).then((responseJson) => {
if (responseJson.success === true) {
toast.success("Your request for private training has been submitted successfully. We will get back to you soon.")
setOpenPrivateTraining(false)
} else {
toast.error("Failed sending request for private training. Please try again later or contact support@shuffler.io for help.")
}
})
}
return (
<Paper
style={{
padding: 20,
height: 480,
// maxWidth: 400,
width: 340,
backgroundColor: hovered ? "#232427" : theme.palette.platformColor,
borderRadius: theme.palette.borderRadius * 2,
border: "1px solid #f85a3e",
marginRight: 10,
marginTop: 15,
}}
onMouseEnter={() => setHovered(true)}
onMouseLeave={() => setHovered(false)}
>
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, }}>
Training
</Typography>
<Divider />
<Typography variant="body1" style={{ marginTop: 10, }}>
Become a Shuffle Expert
</Typography>
<div>
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
Public Training
</Typography>
<ul>
<li>
<Typography variant="body2" color="textPrimary">
Public course on Automation for Security Professionals
</Typography>
</li>
<li>
<Typography variant="body2" color="textPrimary">
Covers Shuffle Platform, Apps, Workflows, Usecases, JSON, Liquid Formatting, and more.
</Typography>
</li>
</ul>
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
Private Training
</Typography>
<ul>
<li>
<Typography variant="body2" color="textPrimary">
Everything from Public Training
</Typography>
</li>
<li>
<Typography variant="body2" color="textPrimary" >
Customized for your teams usecases, date and time, location, and more.
</Typography>
</li>
</ul>
</div>
<div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'space-between', marginTop: 30, width: 340 }}>
<Button
fullWidth
disabled={false}
variant="outlined"
color="primary"
style={{
marginTop: 10,
borderRadius: 25,
height: 40,
fontSize: 16,
color: "white",
backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: 'none'
}}
onClick={() => {
if (Cloud) {
ReactGA.event({
category: "Billing",
action: "click_public_training_button",
});
}
navigate("/training")
}}
>
Public Training
</Button>
<Button
fullWidth
disabled={false}
variant="outlined"
color="primary"
style={{
marginTop: 10,
borderRadius: 25,
height: 40,
fontSize: 16,
color: "white",
backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)",
textTransform: 'none'
}}
onClick={() => {
if (Cloud) {
ReactGA.event({
category: "Billing",
action: "click_public_training_button",
});
}
setOpenPrivateTraining(true)
}}
>
Private Training
</Button>
<Dialog open={openPrivateTraining}
onClose={() => setOpenPrivateTraining(false)}
fullWidth
style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}
PaperProps={{
style: {
width: 500,
margin: 0,
}
}}
>
<DialogTitle style={{ marginTop: 10, textAlign: 'center', fontWeight: 'bold' }}>
Private Training
</DialogTitle>
<DialogContent style={{ padding: '24px', }}>
<Typography variant="body1" color="textSecondary" style={{ marginBottom: '16px', textAlign: 'left' }}>
Enter the total members for private training. Minimum 5 members required.
</Typography>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', marginTop: '16px' }}>
<Slider
value={PrivateTrainingMember}
onChange={(e, val) => setPrivateTrainingMember(val)}
aria-labelledby="continuous-slider"
step={1}
min={5}
max={50}
style={{ width: '80%', color: theme.palette.primary.main }}
marks
valueLabelDisplay="auto"
/>
</div>
<Typography variant="body1" color="textSecondary" style={{ marginTop: '24px', textAlign: 'left' }}>
If you have any additional requirements or questions, please leave a message below.
</Typography>
<TextField
variant="outlined"
fullWidth
multiline
rows={4}
placeholder="Your message"
style={{ marginTop: '16px', borderRadius: '8px' }}
onChange={(e) => setMessage(e.target.value)}
/>
<Button
variant="contained"
color="primary"
style={{ marginTop: '24px', display: 'block', marginLeft: 'auto', marginRight: 'auto', padding: '12px 24px', textTransform: 'none' }}
onClick={handlePrivateTraining}
>
Submit Request
</Button>
</DialogContent>
</Dialog>
</div>
</Paper>
)
}
const addDealModal = ( const addDealModal = (
<Dialog <Dialog
open={selectedDealModalOpen} open={selectedDealModalOpen}
@@ -1623,11 +1916,11 @@ const Billing = (props) => {
{userdata.support === true ? {userdata.support === true ?
<div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}> <div style={{ marginBottom: 10, marginTop: clickedFromOrgTab ? 16 : null, color: clickedFromOrgTab ? "#F1F1F1" : null }}>
For sales: Create&nbsp; For sales: Create&nbsp;
<a href={"https://docs.google.com/document/d/1N-ZJNn8lWaqiXITrqYcnTt53oXGLNYFEzc5PU-tdAps/copy" + selectedOrganization.id} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}> <a href={"https://docs.google.com/document/d/1N-ZJNn8lWaqiXITrqYcnTt53oXGLNYFEzc5PU-tdAps/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
EU contract EU contract
</a> </a>
&nbsp;or&nbsp; &nbsp;or&nbsp;
<a href={"https://docs.google.com/document/d/1cF-Cwxt1TcahlLrpl1GH2hFZO4gxppLeYjHW6QB0EzQ/copy" + selectedOrganization.id} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}> <a href={"https://docs.google.com/document/d/1cF-Cwxt1TcahlLrpl1GH2hFZO4gxppLeYjHW6QB0EzQ/copy"} target="_blank" rel="noopener noreferrer" style={{ textDecoration: "none", color: "#f85a3e" }}>
NOT EU contract NOT EU contract
</a> </a>
&nbsp; - &nbsp; &nbsp; - &nbsp;
@@ -1650,7 +1943,7 @@ const Billing = (props) => {
</Typography> </Typography>
: null} : null}
<div style={{ display: "flex", maxWidth: 768, minWidth: 768, }}> <div style={{ display: "flex", width: 1180, overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: 580 }} >
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null : {isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
<SubscriptionObject <SubscriptionObject
index={0} index={0}
@@ -1712,6 +2005,9 @@ const Billing = (props) => {
selectedOrganization={selectedOrganization} selectedOrganization={selectedOrganization}
/> : null} /> : null}
<TrainingService />
{isCloud && {isCloud &&
selectedOrganization.subscriptions !== undefined && selectedOrganization.subscriptions !== undefined &&
selectedOrganization.subscriptions !== null && selectedOrganization.subscriptions !== null &&
@@ -1966,9 +2262,9 @@ const Billing = (props) => {
</div> </div>
) : null*/} ) : null*/}
<div style={{ marginTop: 50, marginLeft: 10 }}> <div style={{ marginTop: 20, marginLeft: 10 }}>
<Typography <Typography
style={{ marginTop: 40, marginBottom: 5 }} style={{ marginBottom: 5 }}
variant="h4" variant="h4"
> >
Manage Billing Manage Billing
+1 -1
View File
@@ -690,7 +690,7 @@ const LicencePopup = (props) => {
const priceItem = window.location.origin === "https://shuffler.io" ? const priceItem = window.location.origin === "https://shuffler.io" ?
shuffleVariant === 0 ? "app_executions" : "cores" shuffleVariant === 0 ? "app_executions" : "cores"
: :
shuffleVariant === 0 ? "price_1PWI5zDzMUgUjxHSKkz0fGdN" : "price_1NXjQqDzMUgUjxHSg690R4FP" shuffleVariant === 0 ? "price_1PbO0cEJjT17t98NsfEMUlMn" : "price_1PbNnaEJjT17t98NLadq6Lhq"
const successUrl = `${window.location.origin}/admin?admin_tab=billing&payment=success` const successUrl = `${window.location.origin}/admin?admin_tab=billing&payment=success`
const failUrl = `${window.location.origin}/pricing?admin_tab=billing&payment=failure` const failUrl = `${window.location.origin}/pricing?admin_tab=billing&payment=failure`
+283 -235
View File
@@ -25,9 +25,10 @@ import {
Divider, Divider,
LinearProgress, LinearProgress,
AppBar, AppBar,
Dialog, Dialog,
DialogTitle, DialogTitle,
} from "@mui/material"; } from "@mui/material";
import { makeStyles } from '@mui/styles';
import { import {
Close as CloseIcon, Close as CloseIcon,
@@ -45,10 +46,80 @@ import {
Analytics as AnalyticsIcon, Analytics as AnalyticsIcon,
Lightbulb as LightbulbIcon, Lightbulb as LightbulbIcon,
ExpandMore as ExpandMoreIcon, ExpandMore as ExpandMoreIcon,
KeyboardArrowDown as KeyboardArrowDownIcon
} from "@mui/icons-material"; } from "@mui/icons-material";
import zIndex from "@mui/material/styles/zIndex.js";
const hoverColor = "#f85a3e"; const useStyles = makeStyles((theme) => ({
const hoverOutColor = "#e8eaf6"; menuButton: {
textTransform: "none !important",
fontStyle: "normal",
color: "#333",
textAlign: "center",
fontSize: "16px !important",
fontWeight: "500 !important",
display: "flex",
alignItems: "center",
'&:hover': {
backgroundColor: "transparent",
},
},
dropdownMenu: {
marginTop: theme.spacing(1),
borderRadius: "12px !important",
zIndex: 10,
"& .MuiPaper-root": {
border: "1px solid #f85a3e",
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
borderRadius: "12px !important",
top: -10,
overflow: "visible",
background: "#1A1A1A",
"&::before": {
content: '""',
display: "block",
position: "absolute",
top: -10,
left: "82%",
borderLeft: "10px solid transparent",
borderRight: "10px solid transparent",
borderBottom: "10px solid #f85a3e",
},
},
},
dropdownMenuItem: {
padding: theme.spacing(2, 3),
fontSize: "16px",
fontWeight: 400,
color: "#fff",
background: "#1A1A1A",
borderRadius: 16, // Ensure the border radius matches the container
transition: "background-color 0.3s, color 0.3s",
'&:hover': {
color: "#1A73E8",
background: "#3c3c3c",
},
},
menuList: {
display: "flex",
flexDirection: "row",
alignItems: "center",
padding: 0,
margin: 0,
listStyle: "none",
textTransform: "none",
},
cssStcg3yMenuList: {
borderRadius: "12px !important",
},
divider: {
width: "80%",
border: "0.5px solid #494949",
backgroundColor: "#fff",
alignItems: "center",
marginLeft: 17
},
}));
const Header = (props) => { const Header = (props) => {
const { const {
@@ -64,35 +135,62 @@ const Header = (props) => {
serverside, serverside,
billingInfo, billingInfo,
} = props; } = props;
const [HomeHoverColor, setHomeHoverColor] = useState(hoverOutColor);
const [SoarHoverColor, setSoarHoverColor] = useState(hoverOutColor);
const [LoginHoverColor, setLoginHoverColor] = useState(hoverOutColor);
const [DocsHoverColor, setDocsHoverColor] = useState(hoverOutColor);
const [HelpHoverColor, setHelpHoverColor] = useState(hoverOutColor);
const [isHeader, setIsHeader] = React.useState(false); const [isHeader, setIsHeader] = React.useState(false);
const [modalOpen, setModalOpen] = useState(false); const [modalOpen, setModalOpen] = useState(false);
const [tooltipOpen, setTooltipOpen] = useState(false);
const [anchorEl, setAnchorEl] = React.useState(null); const [anchorEl, setAnchorEl] = React.useState(null);
const [anchorElAvatar, setAnchorElAvatar] = React.useState(null); const [anchorElAvatar, setAnchorElAvatar] = React.useState(null);
const [subAnchorEl, setSubAnchorEl] = React.useState(null); const [subAnchorEl, setSubAnchorEl] = React.useState(null);
const [upgradeHovered, setUpgradeHovered] = React.useState(false); const [upgradeHovered, setUpgradeHovered] = React.useState(false);
const [showTopbar, setShowTopbar] = useState(false) const [showTopbar, setShowTopbar] = useState(false)
const stripeKey = typeof window === 'undefined' || window.location === undefined ? "" : window.location.origin === "https://shuffler.io" ? "pk_live_XAxwE2Fp9DEbEcNYw4UKmyby00vIlIPPRp" : "pk_test_EdxgKfqmQGXY5JLjdBqtuhCw00BHbiKJDB" const stripeKey = typeof window === 'undefined' || window.location === undefined ? "" : window.location.origin === "https://shuffler.io" ? "pk_live_XAxwE2Fp9DEbEcNYw4UKmyby00vIlIPPRp" : "pk_test_51PXYYMEJjT17t98NbDkojZ3DRvsFUQBs35LGMx3i436BXwEBVFKB9nCvHt0Q3M4MG3dz4mHheuWvfoYvpaL3GmsG00k1Rb2ksO"
let navigate = useNavigate(); let navigate = useNavigate();
const classes = useStyles();
const handleClick = (event) => { const handleClick = (event) => {
setAnchorEl(event.currentTarget); setAnchorEl(event.currentTarget);
}; };
const handleMenuOpen = (event) => {
setAnchorEl(event.currentTarget);
};
const handleMenuClose = () => {
setAnchorEl(null);
};
const handleMenuItemClick = (path) => {
navigate(path);
handleMenuClose();
};
const handleTooltipClose = () => {
setTooltipOpen(false);
};
const handleTooltipOpen = () => {
setTooltipOpen(true);
};
useEffect(() => { useEffect(() => {
const topbar = localStorage.getItem("topbar_closed") const topbar = localStorage.getItem("topbar_closed")
if (topbar === "true") { if (topbar === "true") {
setShowTopbar(false) setShowTopbar(false)
} else { } else {
setShowTopbar(true) setShowTopbar(true)
} }
}, []) }, [])
const hoverColor = "#f85a3e";
const hoverOutColor = "#e8eaf6";
const handleHover = (event) => {
event.target.style.color = hoverColor;
};
const handleHoverOut = (event) => {
event.target.style.color = hoverOutColor;
};
const handleClose = () => { const handleClose = () => {
setAnchorEl(null); setAnchorEl(null);
setAnchorElAvatar(null); setAnchorElAvatar(null);
@@ -103,6 +201,10 @@ const Header = (props) => {
const hrefStyle = { const hrefStyle = {
color: hoverOutColor, color: hoverOutColor,
textDecoration: "none", textDecoration: "none",
textTransform: "none",
fontStyle: "normal",
width: "100%",
fontSize: "16px",
}; };
const menuText = { const menuText = {
@@ -229,47 +331,6 @@ const Header = (props) => {
}); });
}; };
// Rofl this is weird
const handleDocsHover = () => {
setDocsHoverColor(hoverColor);
};
const handleDocsHoverOut = () => {
setDocsHoverColor(hoverOutColor);
};
const handleHomeHover = () => {
setHomeHoverColor(hoverColor);
};
const handleHelpHover = () => {
setHelpHoverColor(hoverColor);
};
const handleHelpHoverOut = () => {
setHelpHoverColor(hoverOutColor);
};
const handleSoarHover = () => {
setSoarHoverColor(hoverColor);
};
const handleSoarHoverOut = () => {
setSoarHoverColor(hoverOutColor);
};
const handleHomeHoverOut = () => {
setHomeHoverColor(hoverOutColor);
};
const handleLoginHover = () => {
setLoginHoverColor(hoverColor);
};
const handleLoginHoverOut = () => {
setLoginHoverColor(hoverOutColor);
};
const notificationWidth = 335 const notificationWidth = 335
const imagesize = 22; const imagesize = 22;
const boxColor = "#86c142"; const boxColor = "#86c142";
@@ -553,8 +614,8 @@ const Header = (props) => {
aria-haspopup="true" aria-haspopup="true"
onClick={(event) => { }} onClick={(event) => { }}
> >
<svg viewBox="0 0 256 199" width="256" height="199" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" style={{height: 30, width: 30, }}><path d="M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z" fill="#dadae1"/></svg> <svg viewBox="0 0 256 199" width="256" height="199" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid" style={{ height: 30, width: 30, }}><path d="M216.856 16.597A208.502 208.502 0 0 0 164.042 0c-2.275 4.113-4.933 9.645-6.766 14.046-19.692-2.961-39.203-2.961-58.533 0-1.832-4.4-4.55-9.933-6.846-14.046a207.809 207.809 0 0 0-52.855 16.638C5.618 67.147-3.443 116.4 1.087 164.956c22.169 16.555 43.653 26.612 64.775 33.193A161.094 161.094 0 0 0 79.735 175.3a136.413 136.413 0 0 1-21.846-10.632 108.636 108.636 0 0 0 5.356-4.237c42.122 19.702 87.89 19.702 129.51 0a131.66 131.66 0 0 0 5.355 4.237 136.07 136.07 0 0 1-21.886 10.653c4.006 8.02 8.638 15.67 13.873 22.848 21.142-6.58 42.646-16.637 64.815-33.213 5.316-56.288-9.08-105.09-38.056-148.36ZM85.474 135.095c-12.645 0-23.015-11.805-23.015-26.18s10.149-26.2 23.015-26.2c12.867 0 23.236 11.804 23.015 26.2.02 14.375-10.148 26.18-23.015 26.18Zm85.051 0c-12.645 0-23.014-11.805-23.014-26.18s10.148-26.2 23.014-26.2c12.867 0 23.236 11.804 23.015 26.2 0 14.375-10.148 26.18-23.015 26.18Z" fill="#dadae1" /></svg>
{/*#f865f2*/} {/*#f865f2*/}
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</a> </a>
@@ -690,67 +751,68 @@ const Header = (props) => {
textAlign: "center", textAlign: "center",
marginTop: "auto", marginTop: "auto",
marginBottom: "auto", marginBottom: "auto",
marginRight: 10, // marginRight: 10,
}; };
const modalView = const modalView =
<Dialog <Dialog
open={modalOpen} open={modalOpen}
onClose={() => { onClose={() => {
setModalOpen(false); setModalOpen(false);
}} }}
PaperProps={{ PaperProps={{
style: { style: {
color: "white", color: "white",
minWidth: 850, minWidth: 850,
minHeight: 370, minHeight: 370,
padding: 20, padding: 20,
backgroundColor: "rgba(0, 0, 0, 1)", backgroundColor: "rgba(0, 0, 0, 1)",
borderRadius: theme.palette.borderRadius, borderRadius: theme.palette.borderRadius,
}, },
}} }}
> >
<DialogTitle style={{ display: "flex" }}> <DialogTitle style={{ display: "flex" }}>
<span style={{ color: "white", fontSize: 24 }}> <span style={{ color: "white", fontSize: 24 }}>
Upgrade your plan Upgrade your plan
</span> </span>
<IconButton <IconButton
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
category: "header", category: "header",
action: "close_Upgread_popup", action: "close_Upgread_popup",
label: "", label: "",
})}; })
setModalOpen(false); };
}} setModalOpen(false);
style={{ }}
marginLeft: "auto", style={{
position: "absolute", marginLeft: "auto",
top: 20, position: "absolute",
right: 20, top: 20,
}} right: 20,
> }}
<CloseIcon /> >
</IconButton> <CloseIcon />
</DialogTitle> </IconButton>
<div style={{ paddingLeft: "30px", paddingRight: "30px" }}> </DialogTitle>
<LicencePopup <div style={{ paddingLeft: "30px", paddingRight: "30px" }}>
serverside={serverside} <LicencePopup
removeCookie={removeCookie} serverside={serverside}
isLoaded={isLoaded} removeCookie={removeCookie}
isLoggedIn={isLoggedIn} isLoaded={isLoaded}
globalUrl={globalUrl} isLoggedIn={isLoggedIn}
globalUrl={globalUrl}
billingInfo={billingInfo} billingInfo={billingInfo}
userdata={userdata} userdata={userdata}
stripeKey={stripeKey} stripeKey={stripeKey}
setModalOpen={setModalOpen} setModalOpen={setModalOpen}
{...props} {...props}
/> />
</div> </div>
</Dialog> </Dialog>
// Handle top bar or something // Handle top bar or something
const defaultTop = -2 const defaultTop = -2
@@ -792,13 +854,13 @@ const Header = (props) => {
</Link> </Link>
</ListItem> </ListItem>
</List> </List>
<List style={{ flex: 1.5, display: "flex", flexDirect: "row", marginTop: 10, itemAlign: "center", padding: 0 }} component="nav"> <List className={classes.menuList} component="nav">
<ListItem style={{ textAlign: "center", marginLeft: "0px" }}> <ListItem style={{ textAlign: "center", marginLeft: "0px" }}>
<Link to="/usecases" style={hrefStyle}> <Link to="/usecases" style={hrefStyle}>
<Button <Button
variant="text" variant="text"
color="secondary" color="secondary"
style={menuText} className={classes.menuButton}
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
@@ -813,44 +875,12 @@ const Header = (props) => {
</Button> </Button>
</Link> </Link>
</ListItem> </ListItem>
{isCloud ? ( <ListItem style={{ textAlign: "center", marginLeft: 0, paddingRight: 0 }}>
<ListItem
style={{
textAlign: "center",
marginLeft: "0px",
paddingRight: 0,
}}
>
<Link to="/pricing" style={hrefStyle}>
<Button
variant="text"
color="secondary"
style={menuText}
onClick={() => {
ReactGA.event({
category: "header",
action: "pricing_click",
label: "",
});
}}
>
Pricing
</Button>
</Link>
</ListItem>
) : null}
<ListItem
style={{
textAlign: "center",
marginLeft: 0,
paddingRight: 0,
}}
>
<Link rel="noopener noreferrer" to="/docs" style={hrefStyle}> <Link rel="noopener noreferrer" to="/docs" style={hrefStyle}>
<Button <Button
variant="text" variant="text"
color="secondary" color="secondary"
style={menuText} className={classes.menuButton}
onClick={() => { }} onClick={() => { }}
> >
Docs Docs
@@ -858,23 +888,62 @@ const Header = (props) => {
</Link> </Link>
</ListItem> </ListItem>
<ListItem <ListItem
style={{ style={{ textAlign: "center", marginLeft: "0px", paddingRight: 0 }}
textAlign: "center", // onMouseEnter={handleMenuOpen}
marginLeft: 0, // onMouseLeave={handleMenuClose}
paddingRight: 0,
}}
> >
<Button
variant="text"
color="secondary"
className={classes.menuButton}
style={{width:200}}
onClick={handleMenuOpen}
>
Pricing & Services
<KeyboardArrowDownIcon style={{ marginLeft: 4 }} />
</Button>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleMenuClose}
className={classes.dropdownMenu}
classes={{ paper: classes.dropdownMenu }}
MenuListProps={{ className: classes.cssStcg3yMenuList }}
>
{isCloud && (
<MenuItem className={classes.dropdownMenuItem} onClick={() => handleMenuItemClick('/pricing')}>
<Link to="/pricing" style={hrefStyle}>
Pricing
</Link>
</MenuItem>
)}
<div className={classes.divider} />
<MenuItem className={classes.dropdownMenuItem} onClick={() => handleMenuItemClick('/professional-support')}>
<Link to="/professional-support" style={hrefStyle}>
Professional Services
</Link>
</MenuItem>
<div className={classes.divider} />
<MenuItem className={classes.dropdownMenuItem} onClick={() => handleMenuItemClick('/training')}>
<Link to="/training" style={hrefStyle}>
Training Courses
</Link>
</MenuItem>
</Menu>
</ListItem>
{/* <ListItem style={{ textAlign: "center", marginLeft: 0, paddingRight: 0 }}>
<Link rel="noopener noreferrer" to="/training" style={hrefStyle}> <Link rel="noopener noreferrer" to="/training" style={hrefStyle}>
<Button <Button
variant="text" variant="text"
color="secondary" color="secondary"
style={menuText} className={classes.menuButton}
onClick={() => { }} onClick={() => { }}
> >
Training Training
</Button> </Button>
</Link> </Link>
</ListItem> </ListItem> */}
</List> </List>
<List <List
style={{ flex: 2, display: "flex", alignItems: "flex-start", padding: 0, }} style={{ flex: 2, display: "flex", alignItems: "flex-start", padding: 0, }}
@@ -950,7 +1019,7 @@ const Header = (props) => {
margin: "auto", margin: "auto",
}} }}
> >
<div style={{ flexDirection: "row" }}> <div style={{ flexDirection: "row", marginLeft: 0}}>
<List <List
style={{ style={{
height: 56, height: 56,
@@ -966,9 +1035,9 @@ const Header = (props) => {
<ListItem style={{ textAlign: "center", justifyContent: "center" }}> <ListItem style={{ textAlign: "center", justifyContent: "center" }}>
<Link to="/" style={hrefStyle}> <Link to="/" style={hrefStyle}>
<div <div
onMouseOver={handleHomeHover} onMouseOver={handleHover}
onMouseOut={handleHomeHoverOut} onMouseOut={handleHoverOut}
style={{ color: HomeHoverColor, cursor: "pointer" }} style={{ cursor: "pointer" }}
> >
<Grid container direction="row" alignItems="center"> <Grid container direction="row" alignItems="center">
<Grid item style={{}}> <Grid item style={{}}>
@@ -984,10 +1053,9 @@ const Header = (props) => {
<ListItem style={listItemStyle}> <ListItem style={listItemStyle}>
<Link to="/workflows" style={hrefStyle}> <Link to="/workflows" style={hrefStyle}>
<div <div
onMouseOver={handleSoarHover} onMouseOver={handleHover}
onMouseOut={handleSoarHoverOut} onMouseOut={handleHoverOut}
style={{ style={{
color: SoarHoverColor,
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
marginLeft: 25, marginLeft: 25,
@@ -1005,10 +1073,9 @@ const Header = (props) => {
<ListItem style={listItemStyle}> <ListItem style={listItemStyle}>
<Link to="/apps" style={hrefStyle}> <Link to="/apps" style={hrefStyle}>
<div <div
onMouseOver={handleHelpHover} onMouseOver={handleHover}
onMouseOut={handleHelpHoverOut} onMouseOut={handleHoverOut}
style={{ style={{
color: HelpHoverColor,
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
}} }}
@@ -1032,10 +1099,9 @@ const Header = (props) => {
<ListItem style={listItemStyle}> <ListItem style={listItemStyle}>
<Link to="/docs" style={hrefStyle}> <Link to="/docs" style={hrefStyle}>
<div <div
onMouseOver={handleDocsHover} onMouseOver={handleHover}
onMouseOut={handleDocsHoverOut} onMouseOut={handleHoverOut}
style={{ style={{
color: DocsHoverColor,
cursor: "pointer", cursor: "pointer",
display: "flex", display: "flex",
}} }}
@@ -1049,6 +1115,25 @@ const Header = (props) => {
</div> </div>
</Link> </Link>
</ListItem> </ListItem>
{/*
<ListItem style={listItemStyle}>
<Link to="/admin?admin_tab=billing" style={hrefStyle}>
<div
onMouseOver={handleHover}
onMouseOut={handleHoverOut}
style={{
cursor: "pointer",
display: "flex",
width:170
}}
>
<Typography style={{ marginTop: defaultTop }}>
Pricing & Services
</Typography>
</div>
</Link>
</ListItem>
*/}
</ListItem> </ListItem>
</List> </List>
</div> </div>
@@ -1260,7 +1345,7 @@ const Header = (props) => {
title={""} title={""}
placement="left" placement="left"
> >
<div style={{ display: "flex", marginLeft: 50, marginRight: 50, }}> <div style={{ display: "flex", marginLeft: 50, marginRight: 50, }}>
<AddIcon /> <AddIcon />
<span style={{ marginLeft: 8 }}> <span style={{ marginLeft: 8 }}>
Add suborgs Add suborgs
@@ -1285,14 +1370,17 @@ const Header = (props) => {
marginRight: 7, marginRight: 7,
marginTop: 0, marginTop: 0,
}} }}
title={upgradeHovered ? "Upgrade License" : ""}
open={tooltipOpen}
onClose={handleTooltipClose}
> >
<Link style={hrefStyle}> <Link style={hrefStyle}>
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
style={{ textTransform: "none" }} style={{ textTransform: "none" }}
onMouseOver={() => { setUpgradeHovered(true) }} onMouseOver={() => { setUpgradeHovered(true); handleTooltipOpen(); }}
onMouseOut={() => { setUpgradeHovered(false) }} onMouseOut={() => { setUpgradeHovered(false); handleTooltipClose(); }}
onClick={() => { onClick={() => {
if (isCloud) { if (isCloud) {
ReactGA.event({ ReactGA.event({
@@ -1304,11 +1392,11 @@ const Header = (props) => {
setModalOpen(true) setModalOpen(true)
}} }}
> >
{upgradeHovered ? {/* {upgradeHovered ?
"Upgrade License" "Upgrade License"
: : */}
"Upgrade" Upgrade
} {/* } */}
</Button> </Button>
</Link> </Link>
@@ -1397,9 +1485,9 @@ const Header = (props) => {
<ListItem style={{ textAlign: "center" }}> <ListItem style={{ textAlign: "center" }}>
<Link to="/" style={hrefStyle}> <Link to="/" style={hrefStyle}>
<div <div
onMouseOver={handleHomeHover} onMouseOver={handleHover}
onMouseOut={handleHomeHoverOut} onMouseOut={handleHoverOut}
style={{ color: HomeHoverColor, cursor: "pointer" }} style={{ cursor: "pointer" }}
> >
<Grid container direction="row" alignItems="center"> <Grid container direction="row" alignItems="center">
<Grid item> <Grid item>
@@ -1421,9 +1509,9 @@ const Header = (props) => {
<ListItem style={{ textAlign: "center" }}> <ListItem style={{ textAlign: "center" }}>
<Link to="/docs" style={hrefStyle}> <Link to="/docs" style={hrefStyle}>
<div <div
onMouseOver={handleSoarHover} onMouseOver={handleHover}
onMouseOut={handleSoarHoverOut} onMouseOut={handleHoverOut}
style={{ color: SoarHoverColor, cursor: "pointer" }} style={{ cursor: "pointer" }}
> >
About About
</div> </div>
@@ -1465,9 +1553,7 @@ const Header = (props) => {
<ListItem style={{ textAlign: "center" }}> <ListItem style={{ textAlign: "center" }}>
<Link to="/" style={hrefStyle}> <Link to="/" style={hrefStyle}>
<div <div
onMouseOver={handleHomeHover} style={{ cursor: "pointer" }}
onMouseOut={handleHomeHoverOut}
style={{ color: HomeHoverColor, cursor: "pointer" }}
> >
<Grid container direction="row" alignItems="center"> <Grid container direction="row" alignItems="center">
<Grid item> <Grid item>
@@ -1512,10 +1598,10 @@ const Header = (props) => {
> >
<ListItem style={{ flex: "1", textAlign: "center" }}> <ListItem style={{ flex: "1", textAlign: "center" }}>
<div <div
onMouseOver={handleLoginHover} onMouseOver={handleHover}
onMouseOut={handleLoginHoverOut} onMouseOut={handleHoverOut}
onClick={handleClickLogout} onClick={handleClickLogout}
style={{ color: LoginHoverColor, cursor: "pointer" }} style={{ cursor: "pointer" }}
> >
Logout Logout
</div> </div>
@@ -1541,50 +1627,12 @@ const Header = (props) => {
const topbarHeight = showTopbar ? 40 : 0 const topbarHeight = showTopbar ? 40 : 0
const topbar = !isCloud || !showTopbar ? null : const topbar = !isCloud || !showTopbar ? null :
curpath === "/" || curpath.includes("/docs") || curpath === "/pricing" || curpath === "/contact" || curpath === "/search" || curpath === "/usecases" || curpath === "/training" ? curpath === "/" || curpath.includes("/docs") || curpath === "/pricing" || curpath === "/contact" || curpath === "/search" || curpath === "/usecases" || curpath === "/training" || curpath === "/professional-support" ?
<span style={{ zIndex: 50001, }}> <span style={{ zIndex: 50001, }}>
<div style={{ position: "relative", height: topbarHeight, backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", overflow: "hidden", }}> <div style={{ position: "relative", height: topbarHeight, backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", overflow: "hidden", }}>
<Typography variant="body1" style={{ paddingTop: 7, margin: "auto", textAlign: "center", color: "white", }}> <Typography variant="body1" style={{ paddingTop: 7, margin: "auto", textAlign: "center", color: "white", }}>
{/* Shuffle 1.4.0 is out! Read more about&nbsp; */} {/* Shuffle 1.4.0 is out! Read more about&nbsp; */}
Early Success! More&nbsp; New Public&nbsp;
{/* <u>
<a href="https://github.com/Shuffle/Shuffle/releases/tag/v1.4.0" target="_blank" style={{ color: "inherit", }} onClick={() => {
ReactGA.event({
category: "landingpage",
action: "click_header_features",
label: "",
})
//if (window.drift !== undefined) {
// window.drift.api.startInteraction({ interactionId: 341911 })
//} else {
// console.log("Couldn't find drift in window.drift and not .drift-open-chat with querySelector: ", window.drift)
//}
}} style={{ cursor: "pointer", textDecoration: "none", color: "rgba(255,255,255,0.8)" }}>
Features
</a>
</u>
,&nbsp;
<u>
<span onClick={() => {
ReactGA.event({
category: "landingpage",
action: "click_header_pricing",
label: "",
})
navigate("/pricing")
//if (window.drift !== undefined) {
// window.drift.api.startInteraction({ interactionId: 341911 })
//} else {
// console.log("Couldn't find drift in window.drift and not .drift-open-chat with querySelector: ", window.drift)
//}
}} style={{ cursor: "pointer", textDecoration: "none", color: "rgba(255,255,255,0.8)" }}>
Pricing
</span>
</u>
&nbsp;and&nbsp; */}
<u> <u>
<span onClick={() => { <span onClick={() => {
ReactGA.event({ ReactGA.event({
@@ -1595,18 +1643,18 @@ const Header = (props) => {
navigate("/training") navigate("/training")
}} style={{ cursor: "pointer", textDecoration: "none", fontWeight:600, color: "rgba(255,255,255,0.8)" }}> }} style={{ cursor: "pointer", textDecoration: "none", fontWeight: 600, color: "rgba(255,255,255,0.8)" }}>
Public Trainings Training Dates Released
</span> </span>
</u> </u>
&nbsp;Ahead! &nbsp;Ahead!
</Typography> </Typography>
<IconButton color="secondary" style={{ position: "absolute", top: -3, right: 20, }} onClick={(event) => { <IconButton color="secondary" style={{ position: "absolute", top: -3, right: 20, }} onClick={(event) => {
setShowTopbar(false) setShowTopbar(false)
// Set storage that it's clicked // Set storage that it's clicked
localStorage.setItem("topbar_closed", "true") localStorage.setItem("topbar_closed", "true")
}}> }}>
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
</div> </div>
+1 -1
View File
@@ -356,7 +356,7 @@ const Priorities = (props) => {
dismissNotification(data.id); dismissNotification(data.id);
}} }}
> >
Dismiss Dismiss
</Button> </Button>
) : null} ) : null}
<Tooltip title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting." placement="top"> <Tooltip title="Disabling a notification makes it so similar notifications to this one will NOT be re-opened. It will NOT forward notifications to your notification workflow, but WILL still keep counting." placement="top">
+21
View File
@@ -27,6 +27,13 @@ const Priority = (props) => {
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
let navigate = useNavigate(); let navigate = useNavigate();
if (window.location.pathname === "/workflows") {
const hidePriorities = localStorage.getItem("hidePriorities", "true")
if (hidePriorities === "true") {
return null
}
}
var realignedSrc = false var realignedSrc = false
var realignedDst = false var realignedDst = false
let newdescription = priority.description let newdescription = priority.description
@@ -176,6 +183,20 @@ const Priority = (props) => {
<Button style={{borderRadius: 25, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, width: 100, height: 50, marginTop: 8, }} variant="text" color="secondary" onClick={() => { <Button style={{borderRadius: 25, fontSize:16, boxShadow: clickedFromOrgTab ? "none":null,textTransform: clickedFromOrgTab ? 'capitalize':null, width: 100, height: 50, marginTop: 8, }} variant="text" color="secondary" onClick={() => {
// dismiss -> get envs // dismiss -> get envs
changeRecommendation(priority, "dismiss") changeRecommendation(priority, "dismiss")
// Check window location if it's /workflows
if (window.location.pathname === "/workflows") {
// Set local storage to hide priorities for now
localStorage.setItem("hidePriorities", "true")
}
if (isCloud) {
ReactGA.event({
category: "recommendation",
action: `dismiss_${priority.name}`,
label: "",
})
}
}}> }}>
Dismiss Dismiss
</Button> </Button>
+1 -1
View File
@@ -124,7 +124,7 @@ const SearchField = props => {
); );
return ( return (
<div style={{ marginTop: "auto", marginLeft: !isLoggedIn ? 0 : 130 }}> <div style={{ marginTop: "auto", marginLeft: !isLoggedIn ? 0: "auto", marginRight: !isLoggedIn ? 0 : "auto", width: !isLoggedIn ? "auto" : 300, }}>
{modalView} {modalView}
<TextField <TextField
style={{ backgroundColor: "#212121", height: 48, borderRadius: rounded === true ? 25 : theme.palette.borderRadius, minWidth: fieldWidth, maxWidth: fieldWidth, }} style={{ backgroundColor: "#212121", height: 48, borderRadius: rounded === true ? 25 : theme.palette.borderRadius, minWidth: fieldWidth, maxWidth: fieldWidth, }}
@@ -153,7 +153,11 @@ const WorkflowValidationTimeline = (props) => {
// 1. Find startnode // 1. Find startnode
// 2. Map childnodes from it // 2. Map childnodes from it
const startnodeId = workflow.start var startnodeId = workflow.start
if (execution !== undefined && execution !== null) {
startnodeId = execution.start
}
// Find parent of startnodeId and if it's a webhook // Find parent of startnodeId and if it's a webhook
var relevantactions = [] var relevantactions = []
@@ -177,32 +181,38 @@ const WorkflowValidationTimeline = (props) => {
} }
} }
for (var key in workflow.actions) {
const action = workflow.actions[key]
if (action.id === startnodeId) {
action.order = 0
relevantactions.push(action)
continue
}
var parents = []
if (getParents !== undefined) {
parents = getParents(action)
} else {
parents = getParentNodes(workflow, action)
}
//const parents = getParentNodes(workflow, action)
//console.log("PARENTS", key, parents)
if (parents !== undefined && parents !== null && parents.length > 0) {
const parentfound = parents.find((element) => element.id === startnodeId)
if (parentfound !== undefined) {
// FIXME: add order here based on how many steps away from the startnode
// This just has the parent count
action.order = parents.length
if (getParents !== undefined) {
for (var key in workflow.actions) {
const action = workflow.actions[key]
if (action.id === startnodeId) {
action.order = 0
relevantactions.push(action) relevantactions.push(action)
continue
}
const parents = getParents(action)
//const parents = getParentNodes(workflow, action)
//console.log("PARENTS", key, parents)
if (parents !== undefined && parents !== null) {
const parentfound = parents.find((element) => element.id === startnodeId)
if (parentfound !== undefined) {
// FIXME: add order here based on how many steps away from the startnode
// This just has the parent count
action.order = parents.length
relevantactions.push(action)
}
} }
} }
} else { }
if (getParents === undefined) {
var newactions = []
for (var key in workflow.triggers) { for (var key in workflow.triggers) {
const trigger = workflow.triggers[key] const trigger = workflow.triggers[key]
if (trigger.trigger_type !== "SUBFLOW" && trigger.trigger_type !== "USERINPUT") { if (trigger.trigger_type !== "SUBFLOW" && trigger.trigger_type !== "USERINPUT") {
@@ -210,11 +220,12 @@ const WorkflowValidationTimeline = (props) => {
} }
if (workflow.actions.find((element) => element.id === trigger.id) === undefined) { if (workflow.actions.find((element) => element.id === trigger.id) === undefined) {
workflow.actions.push(trigger) newactions.push(trigger)
//workflow.actions.push(trigger)
} }
} }
relevantactions = workflow.actions relevantactions.push(...newactions)
} }
// Sort according to how many parents a node has. MAY be wrong~ // Sort according to how many parents a node has. MAY be wrong~
@@ -279,7 +290,10 @@ const WorkflowValidationTimeline = (props) => {
} }
previousTools = true previousTools = true
return null
if (startnodeId !== action.id) {
return null
}
} else { } else {
if (action.status === "SUCCESS") { if (action.status === "SUCCESS") {
nodecolor = green nodecolor = green
@@ -405,7 +419,7 @@ const WorkflowValidationTimeline = (props) => {
: :
<Tooltip title={ <Tooltip title={
<Typography variant="body1" style={{margin: 5, color: "white", }}> <Typography variant="body1" style={{margin: 5, color: "white", }}>
{founderror.length > 0 ? founderror : ``} {founderror.length > 0 ? founderror : `${action.app_name.replaceAll('_', ' ')}`}
</Typography> </Typography>
} placement="top"> } placement="top">
+2 -7
View File
@@ -7514,7 +7514,6 @@ const releaseToConnectLabel = "Release to Connect"
} }
} else if (action.app_name === "Integration Framework") { } else if (action.app_name === "Integration Framework") {
const iconInfo = GetIconInfo(action) const iconInfo = GetIconInfo(action)
console.log("FOUND INTEGRATION: iconInfo: ", iconInfo)
if (iconInfo !== undefined && iconInfo !== null) { if (iconInfo !== undefined && iconInfo !== null) {
action.fillGradient = iconInfo.fillGradient action.fillGradient = iconInfo.fillGradient
action.iconBackground = iconInfo.iconBackgroundColor action.iconBackground = iconInfo.iconBackgroundColor
@@ -12462,7 +12461,6 @@ const releaseToConnectLabel = "Release to Connect"
//setWorkflow(workflow); //setWorkflow(workflow);
} }
console.log("STARTNODE: ", startnode);
} else { } else {
console.log("WORKFLOW: ", workflow); console.log("WORKFLOW: ", workflow);
} }
@@ -16581,6 +16579,7 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
/*
if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { if (( event.ctrlKey || event.metaKey ) && event.shiftKey) {
console.log("Shift key pressed") console.log("Shift key pressed")
if (!workflow.public && executionModalOpen) { if (!workflow.public && executionModalOpen) {
@@ -16592,6 +16591,7 @@ const releaseToConnectLabel = "Release to Connect"
setExecutionModalView(0); setExecutionModalView(0);
} }
} }
*/
}; };
document.addEventListener('keydown', handleKeyDown); document.addEventListener('keydown', handleKeyDown);
@@ -21829,17 +21829,12 @@ const releaseToConnectLabel = "Release to Connect"
} }
} }
console.log("2 - SELECTED ACTION: ", selectedAction)
console.log("2 - DATA: ", data)
if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) { if (selectedAction.app_name === "Shuffle Tools" && selectedAction.name === "filter_list" && count === 0) {
const parsedvalue = data const parsedvalue = data
console.log("Parsed value: ", parsedvalue)
if (parsedvalue.includes("#")) { if (parsedvalue.includes("#")) {
const splitparsed = parsedvalue.split(".#.") const splitparsed = parsedvalue.split(".#.")
//console.log("Cant contain #: ", splitparsed) //console.log("Cant contain #: ", splitparsed)
if (splitparsed.length > 1) { if (splitparsed.length > 1) {
console.log("IN HERE AY")
//data.value = splitparsed[0] //data.value = splitparsed[0]
selectedAction.parameters[0].value = splitparsed[0] selectedAction.parameters[0].value = splitparsed[0]
+15 -12
View File
@@ -62,6 +62,7 @@ import {
TreeMapLabel, TreeMapLabel,
TreeMapRect, TreeMapRect,
} from 'reaviz'; } from 'reaviz';
import { isMobile } from "react-device-detect"
const useStyles = makeStyles({ const useStyles = makeStyles({
notchedOutline: { notchedOutline: {
@@ -381,7 +382,7 @@ const UsecaseListComponent = (props) => {
<Typography variant="h6"> <Typography variant="h6">
{usecase.name} {usecase.name}
</Typography> </Typography>
<Grid container spacing={3} style={{marginTop: 25}}> <Grid container spacing={3} style={{marginTop: isMobile ? null:25, padding: isMobile?20:null}}>
{usecase.list.map((subcase, subindex) => { {usecase.list.map((subcase, subindex) => {
const selectedItem = subindex === expandedItem && index === expandedIndex const selectedItem = subindex === expandedItem && index === expandedIndex
@@ -426,7 +427,7 @@ const UsecaseListComponent = (props) => {
const fixedName = subcase.name.toLowerCase().replace("_", " ") const fixedName = subcase.name.toLowerCase().replace("_", " ")
return ( return (
<Grid id={fixedName} item xs={selectedItem ? 12 : 4} key={subindex} style={{minHeight: 110,}} onClick={() => { <Grid id={fixedName} item xs={isMobile ? 12 : selectedItem ? 12 : 4} key={subindex} style={{minHeight: 110,}} onClick={() => {
if (fixedName === "reporting") { if (fixedName === "reporting") {
getUsecase(subcase, index, subindex) getUsecase(subcase, index, subindex)
return return
@@ -443,7 +444,7 @@ const UsecaseListComponent = (props) => {
}}> }}>
{!selectedItem ? {!selectedItem ?
<div style={{textAlign: "left", position: "relative",}}> <div style={{textAlign: "left", position: "relative",}}>
<Typography variant="h6" style={{maxWidth: 215}}> <Typography variant="h6" style={{maxWidth: isMobile? null:215}}>
<b>{subcase.name}</b> <b>{subcase.name}</b>
</Typography> </Typography>
{finished ? {finished ?
@@ -478,7 +479,7 @@ const UsecaseListComponent = (props) => {
<IconButton <IconButton
style={{ style={{
position: "absolute", position: "absolute",
bottom: -25, bottom: isMobile ? 11 :-20,
right: -15, right: -15,
}} }}
onClick={(e) => { onClick={(e) => {
@@ -503,7 +504,7 @@ const UsecaseListComponent = (props) => {
<IconButton <IconButton
style={{ style={{
position: "absolute", position: "absolute",
bottom: -65, bottom: isMobile ? -22 : 10,
right: -15, right: -15,
}} }}
onClick={(e) => { onClick={(e) => {
@@ -618,7 +619,7 @@ const UsecaseListComponent = (props) => {
</IconButton> </IconButton>
</Tooltip> </Tooltip>
</div> </div>
<div style={{marginTop: 25, display: "flex", minHeight: 400, maxHeight: 400, marginRight: 15, }}> <div style={{marginTop: isMobile? null:25, padding: isMobile?20:null, width: isMobile?"100%":null, display: isMobile ? null:"flex", minHeight: isMobile ? "auto":400, maxHeight: isMobile ? null:400, marginRight: isMobile?null:15 }}>
{editing ? {editing ?
<div style={{flex: 1, marginRight: 50, }}> <div style={{flex: 1, marginRight: 50, }}>
<TextField <TextField
@@ -979,7 +980,8 @@ const UsecaseListComponent = (props) => {
} }
<div style={{ <div style={{
height: 350, height: 350,
width: 350, width: isMobile? null:350,
marginTop: isMobile ? 50:null,
borderRadius: theme.palette.borderRadius, borderRadius: theme.palette.borderRadius,
border: "1px solid rgba(255,255,255,0.3)", border: "1px solid rgba(255,255,255,0.3)",
padding: 5, padding: 5,
@@ -1066,8 +1068,8 @@ const RadialChart = ({keys, setSelectedCategory}) => {
}}> }}>
<RadialAreaChart <RadialAreaChart
id="workflow_categories" id="workflow_categories"
height={500} height={isMobile ? 400:500}
width={500} width={isMobile ? null:500}
data={keys} data={keys}
axis={<RadialAxis type="category" />} axis={<RadialAxis type="category" />}
series={ series={
@@ -1675,15 +1677,15 @@ const Dashboard = (props) => {
console.log("USECASES: ", usecases) console.log("USECASES: ", usecases)
const data = const data =
<div className="content" style={{width: 1000, margin: "auto", paddingBottom: 200, textAlign: "center",}}> <div className="content" style={{width: isMobile ? "100%": 1000, margin: "auto", paddingBottom: 200, textAlign: "center",}}>
<div style={{width: 500, margin: "auto"}}> <div style={{width: isMobile ? null:500, margin: "auto"}}>
{keys.length > 0 ? {keys.length > 0 ?
<RadialChart keys={keys} setSelectedCategory={setSelectedUsecaseCategory} /> <RadialChart keys={keys} setSelectedCategory={setSelectedUsecaseCategory} />
: null} : null}
</div> </div>
{usecases !== null && usecases !== undefined && usecases.length > 0 ? {usecases !== null && usecases !== undefined && usecases.length > 0 ?
<div style={{ display: "flex", marginLeft: 180, }}> <div style={{ display: isMobile ? null:"flex", marginLeft: isMobile? null :180, }}>
{usecases.map((usecase, index) => { {usecases.map((usecase, index) => {
return ( return (
<Chip <Chip
@@ -1693,6 +1695,7 @@ const Dashboard = (props) => {
marginRight: 10, marginRight: 10,
paddingLeft: 5, paddingLeft: 5,
paddingRight: 5, paddingRight: 5,
marginTop: isMobile? 10:null,
height: 28, height: 28,
cursor: "pointer", cursor: "pointer",
border: `1px solid ${usecase.color}`, border: `1px solid ${usecase.color}`,
+9 -4
View File
@@ -513,10 +513,15 @@ export const validateJson = (showResult) => {
try { try {
for (const [key, value] of Object.entries(result)) { for (const [key, value] of Object.entries(result)) {
if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) { if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) {
//console.log("CHECKING STRING: ", value)
const inside_result = validateJson(value) const inside_result = validateJson(value)
if (inside_result.valid) { if (inside_result.valid) {
//console.log("INSIDE RESULT: ", inside_result.result)
if (typeof inside_result.result === "string") { if (typeof inside_result.result === "string") {
const newres = JSON.parse(inside_result.result) const newres = JSON.parse(inside_result.result)
result[key] = newres result[key] = newres
} else { } else {
result[key] = inside_result.result result[key] = inside_result.result
@@ -1037,9 +1042,9 @@ const Workflows = (props) => {
data.default_return_value, data.default_return_value,
{}, {},
false, false,
[], [],
"", "",
data.status, data.status,
) )
.then((response) => { .then((response) => {
if (response !== undefined) { if (response !== undefined) {