diff --git a/frontend/src/components/AppFramework.jsx b/frontend/src/components/AppFramework.jsx index 00ef41c0..3d786443 100644 --- a/frontend/src/components/AppFramework.jsx +++ b/frontend/src/components/AppFramework.jsx @@ -36,6 +36,7 @@ import edgehandles from "cytoscape-edgehandles"; import cytoscape from "cytoscape"; import { toast } from 'react-toastify'; +import { isMobile } from 'react-device-detect'; cytoscape.use(edgehandles) @@ -2152,7 +2153,7 @@ const AppFramework = (props) => { { Object.getOwnPropertyNames(discoveryData).length > 0 ? - + {paperTitle.length > 0 ? @@ -2321,7 +2322,7 @@ const AppFramework = (props) => { elements={elements} minZoom={0.35} 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} boxSelectionEnabled={false} panningEnabled={false} diff --git a/frontend/src/components/AppSearchButtons.jsx b/frontend/src/components/AppSearchButtons.jsx index 262843ad..6bc3179a 100644 --- a/frontend/src/components/AppSearchButtons.jsx +++ b/frontend/src/components/AppSearchButtons.jsx @@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react"; import theme from '../theme.jsx'; import ReactGA from 'react-ga4'; 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 aa from 'search-insights' import Deleteicon from '@mui/icons-material/Delete'; @@ -181,7 +181,7 @@ const AppSearchButtons = (props) => { width: 319, height: 395, flexShrink: 0, - marginLeft: 70, + marginLeft: isMobile? null:70, marginTop: 68, position: "absolute", zIndex: 100, diff --git a/frontend/src/components/Billing.jsx b/frontend/src/components/Billing.jsx index f7598852..97b6cd16 100644 --- a/frontend/src/components/Billing.jsx +++ b/frontend/src/components/Billing.jsx @@ -41,11 +41,12 @@ import { Close as CloseIcon, Delete, RestaurantRounded, + Cloud, } from "@mui/icons-material"; //import { useAlert 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 DeleteIcon from '@mui/icons-material/Delete'; @@ -173,10 +174,10 @@ const Billing = (props) => { const paperStyle = { padding: 20, - height: "100%", - minHeight: 280, - maxWidth: 400, - width: "100%", + // maxWidth: 400, + width: 340, + height: 480, + // width: "100%", backgroundColor: theme.palette.platformColor, borderRadius: theme.palette.borderRadius * 2, border: "1px solid rgba(255,255,255,0.3)", @@ -470,9 +471,11 @@ const Billing = (props) => { style: { pointerEvents: "auto", color: "white", - minWidth: 750, + // minWidth: 750, + width: 340, padding: 30, - maxHeight: 700, + // maxHeight: 700, + height: 480, overflowY: "auto", overflowX: "hidden", zIndex: 10012, @@ -546,7 +549,7 @@ const Billing = (props) => { -
+
{top_text === "Base Cloud Access" && 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." : - 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, 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.` }
- + Billing email: {BillingEmail} {userdata.has_card_available === true && ( @@ -741,7 +744,7 @@ const Billing = (props) => { boxShadow: 'none', border: 'none', cursor: 'pointer', - transition: 'background-color 0.3s, color 0.3s' + transition: 'background-color 0.3s, color 0.3s', }} > Change @@ -813,12 +816,13 @@ const Billing = (props) => { variant="outlined" color="primary" style={{ - marginTop: 10, + marginTop: !userdata.has_card_available ? 20 : 10, borderRadius: 25, height: 40, - fontSize: 14, + fontSize: 16, color: "white", backgroundImage: userdata.has_card_available ? null : "linear-gradient(to right, #f86a3e, #f34079)", + textTransform: "none", }} onClick={() => { @@ -847,9 +851,10 @@ const Billing = (props) => { marginTop: 10, borderRadius: 25, height: 40, - fontSize: 14, + fontSize: 16, color: "white", backgroundImage: "linear-gradient(to right, #f86a3e, #f34079)", + textTransform: 'none' }} onClick={() => { if (isCloud) { @@ -904,9 +909,11 @@ const Billing = (props) => { const [editConsultation, setEditConsultation] = 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 [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 formatedMinutes = String(inputMinutes).padStart(2, "0") @@ -959,13 +966,17 @@ const Billing = (props) => { return response.json(); }) .then((responseJson) => { - console.log("Response from consultation save: ", responseJson); if (responseJson.success === true) { toast.success("Consultation hours saved successfully"); setEditConsultation(false); } else { toast.error("Failed saving consultation hours."); } + if (inputHour > 0 || inputMinutes > 0) { + setGetProfessionalServices(true) + } else { + setGetProfessionalServices(false) + } }) .catch((error) => { console.log("Error: ", error); @@ -1001,7 +1012,6 @@ const Billing = (props) => { return response.json(); }) .then((responseJson) => { - console.log("Response from consultation save: ", responseJson); if (responseJson.success === true) { toast.success("Thank you for your request. We will get back to you soon."); 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 ( {
- 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. -
+
{editConsultation ? <> { variant="contained" color="primary" onClick={handleCancel} + style={{ textTransform: 'none' }} > Cancel @@ -1082,48 +1098,113 @@ const Billing = (props) => { variant="contained" color="primary" onClick={toggleEditMode} + style={{ textTransform: 'none' }} > Edit )} - {editConsultation && } + {editConsultation && }
: null} - + Features
  • - Debug/Create workflows with our experts + Build custom apps, integrations, and worklows for your specific use cases or applications
  • - Ask questions and get help with your workflows and integrations by our experts + Help solve / debug / update / add features and capabilities of the platform
- +
+ + { setClickOnBuy(false) }}> + + 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. + + + + + + + + + + + +
setOpenUpgradePlan(false)} fullWidth @@ -1140,20 +1221,21 @@ const Billing = (props) => { - Enter the total hours of consultation you want to include in your plan. + Enter the total hours of consultation you want.
setConsultationHours(val)} aria-labelledby="continuous-slider" - step={5} - min={5} - max={50} - style={{ width: '80%', color: theme.palette.primary.main }} // Adding primary color for better visibility + step={1} + min={1} + max={(inputHour === "0" && inputMinutes > 0) ? 1 : inputHour} + style={{ width: '80%', color: theme.palette.primary.main }} marks valueLabelDisplay="auto" /> +
If you have any additional requirements or questions, please leave a message below. @@ -1163,17 +1245,17 @@ const Billing = (props) => { fullWidth multiline rows={4} - placeholder="Your message" + placeholder="What kind of services are you looking for?" style={{ marginTop: '16px', borderRadius: '8px' }} onChange={(e) => setMessage(e.target.value)} />
@@ -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 ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + > + + Training + + + + Become a Shuffle Expert + +
+ + Public Training + +
    +
  • + + Public course on Automation for Security Professionals + +
  • +
  • + + Covers Shuffle Platform, Apps, Workflows, Usecases, JSON, Liquid Formatting, and more. + +
  • +
+ + Private Training + +
    +
  • + + Everything from Public Training + +
  • +
  • + + Customized for your team’s usecases, date and time, location, and more. + +
  • +
+
+
+ + + setOpenPrivateTraining(false)} + fullWidth + style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }} + PaperProps={{ + style: { + width: 500, + margin: 0, + } + }} + > + + Private Training + + + + Enter the total members for private training. Minimum 5 members required. + +
+ setPrivateTrainingMember(val)} + aria-labelledby="continuous-slider" + step={1} + min={5} + max={50} + style={{ width: '80%', color: theme.palette.primary.main }} + marks + valueLabelDisplay="auto" + /> + +
+ + If you have any additional requirements or questions, please leave a message below. + + setMessage(e.target.value)} + /> + +
+
+
+
+ ) + } + const addDealModal = ( { {userdata.support === true ?
For sales: Create  - + EU contract  or  - + NOT EU contract   -   @@ -1650,7 +1943,7 @@ const Billing = (props) => { : null} -
+
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null : { selectedOrganization={selectedOrganization} /> : null} + + + {isCloud && selectedOrganization.subscriptions !== undefined && selectedOrganization.subscriptions !== null && @@ -1966,9 +2262,9 @@ const Billing = (props) => {
) : null*/} -
+
Manage Billing diff --git a/frontend/src/components/LicencePopup.jsx b/frontend/src/components/LicencePopup.jsx index 014fa46f..7fa355e0 100644 --- a/frontend/src/components/LicencePopup.jsx +++ b/frontend/src/components/LicencePopup.jsx @@ -690,7 +690,7 @@ const LicencePopup = (props) => { const priceItem = window.location.origin === "https://shuffler.io" ? 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 failUrl = `${window.location.origin}/pricing?admin_tab=billing&payment=failure` diff --git a/frontend/src/components/NewHeader.jsx b/frontend/src/components/NewHeader.jsx index fa626601..ee486357 100644 --- a/frontend/src/components/NewHeader.jsx +++ b/frontend/src/components/NewHeader.jsx @@ -25,9 +25,10 @@ import { Divider, LinearProgress, AppBar, - Dialog, - DialogTitle, + Dialog, + DialogTitle, } from "@mui/material"; +import { makeStyles } from '@mui/styles'; import { Close as CloseIcon, @@ -45,10 +46,80 @@ import { Analytics as AnalyticsIcon, Lightbulb as LightbulbIcon, ExpandMore as ExpandMoreIcon, + KeyboardArrowDown as KeyboardArrowDownIcon } from "@mui/icons-material"; +import zIndex from "@mui/material/styles/zIndex.js"; -const hoverColor = "#f85a3e"; -const hoverOutColor = "#e8eaf6"; +const useStyles = makeStyles((theme) => ({ + 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 { @@ -64,35 +135,62 @@ const Header = (props) => { serverside, billingInfo, } = 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 [modalOpen, setModalOpen] = useState(false); + const [tooltipOpen, setTooltipOpen] = useState(false); const [anchorEl, setAnchorEl] = React.useState(null); const [anchorElAvatar, setAnchorElAvatar] = React.useState(null); const [subAnchorEl, setSubAnchorEl] = React.useState(null); const [upgradeHovered, setUpgradeHovered] = React.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(); + const classes = useStyles(); const handleClick = (event) => { 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(() => { - const topbar = localStorage.getItem("topbar_closed") - if (topbar === "true") { - setShowTopbar(false) - } else { - setShowTopbar(true) - } + const topbar = localStorage.getItem("topbar_closed") + if (topbar === "true") { + setShowTopbar(false) + } else { + 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 = () => { setAnchorEl(null); setAnchorElAvatar(null); @@ -103,6 +201,10 @@ const Header = (props) => { const hrefStyle = { color: hoverOutColor, textDecoration: "none", + textTransform: "none", + fontStyle: "normal", + width: "100%", + fontSize: "16px", }; 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 imagesize = 22; const boxColor = "#86c142"; @@ -553,8 +614,8 @@ const Header = (props) => { aria-haspopup="true" onClick={(event) => { }} > - - {/*#f865f2*/} + + {/*#f865f2*/} @@ -690,67 +751,68 @@ const Header = (props) => { textAlign: "center", marginTop: "auto", marginBottom: "auto", - marginRight: 10, + // marginRight: 10, }; - const modalView = - { - setModalOpen(false); - }} - PaperProps={{ - style: { - color: "white", - minWidth: 850, - minHeight: 370, - padding: 20, - backgroundColor: "rgba(0, 0, 0, 1)", - borderRadius: theme.palette.borderRadius, - }, - }} - > - - - Upgrade your plan - - { - if (isCloud) { + const modalView = + { + setModalOpen(false); + }} + PaperProps={{ + style: { + color: "white", + minWidth: 850, + minHeight: 370, + padding: 20, + backgroundColor: "rgba(0, 0, 0, 1)", + borderRadius: theme.palette.borderRadius, + }, + }} + > + + + Upgrade your plan + + { + if (isCloud) { ReactGA.event({ category: "header", action: "close_Upgread_popup", label: "", - })}; - setModalOpen(false); - }} - style={{ - marginLeft: "auto", - position: "absolute", - top: 20, - right: 20, - }} - > - - - -
- + + + +
+ -
-
+ userdata={userdata} + stripeKey={stripeKey} + setModalOpen={setModalOpen} + {...props} + /> +
+
// Handle top bar or something const defaultTop = -2 @@ -792,13 +854,13 @@ const Header = (props) => { - + - {isCloud ? ( - - - - - - ) : null} - + + + {isCloud && ( + handleMenuItemClick('/pricing')}> + + Pricing + + + )} +
+ handleMenuItemClick('/professional-support')}> + + Professional Services + + +
+ handleMenuItemClick('/training')}> + + Training Courses + + +
+
+ {/* - +
*/}
{ margin: "auto", }} > -
+
{
@@ -984,10 +1053,9 @@ const Header = (props) => {
{
{
{
+ {/* + + +
+ + Pricing & Services + +
+ +
+ */}
@@ -1260,7 +1345,7 @@ const Header = (props) => { title={""} placement="left" > -
+
Add suborgs @@ -1285,14 +1370,17 @@ const Header = (props) => { marginRight: 7, marginTop: 0, }} + title={upgradeHovered ? "Upgrade License" : ""} + open={tooltipOpen} + onClose={handleTooltipClose} > @@ -1397,9 +1485,9 @@ const Header = (props) => {
@@ -1421,9 +1509,9 @@ const Header = (props) => {
About
@@ -1465,9 +1553,7 @@ const Header = (props) => {
@@ -1512,10 +1598,10 @@ const Header = (props) => { >
Logout
@@ -1541,50 +1627,12 @@ const Header = (props) => { const topbarHeight = showTopbar ? 40 : 0 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" ?
{/* Shuffle 1.4.0 is out! Read more about  */} - Early Success! More  - {/* - { - 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 - - - ,  - - { - 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 - - -  and  */} + New Public  { ReactGA.event({ @@ -1595,18 +1643,18 @@ const Header = (props) => { navigate("/training") - }} style={{ cursor: "pointer", textDecoration: "none", fontWeight:600, color: "rgba(255,255,255,0.8)" }}> - Public Trainings + }} style={{ cursor: "pointer", textDecoration: "none", fontWeight: 600, color: "rgba(255,255,255,0.8)" }}> + Training Dates Released  Ahead! - { - setShowTopbar(false) + { + setShowTopbar(false) - // Set storage that it's clicked - localStorage.setItem("topbar_closed", "true") - }}> + // Set storage that it's clicked + localStorage.setItem("topbar_closed", "true") + }}>
diff --git a/frontend/src/components/Priorities.jsx b/frontend/src/components/Priorities.jsx index 289d2b7c..0663ee93 100644 --- a/frontend/src/components/Priorities.jsx +++ b/frontend/src/components/Priorities.jsx @@ -356,7 +356,7 @@ const Priorities = (props) => { dismissNotification(data.id); }} > - Dismiss + Dismiss ) : null} diff --git a/frontend/src/components/Priority.jsx b/frontend/src/components/Priority.jsx index 67d56af7..29e1b0c6 100644 --- a/frontend/src/components/Priority.jsx +++ b/frontend/src/components/Priority.jsx @@ -27,6 +27,13 @@ const Priority = (props) => { const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; let navigate = useNavigate(); + if (window.location.pathname === "/workflows") { + const hidePriorities = localStorage.getItem("hidePriorities", "true") + if (hidePriorities === "true") { + return null + } + } + var realignedSrc = false var realignedDst = false let newdescription = priority.description @@ -176,6 +183,20 @@ const Priority = (props) => { diff --git a/frontend/src/components/Searchfield.jsx b/frontend/src/components/Searchfield.jsx index dc5f9179..c389f88d 100644 --- a/frontend/src/components/Searchfield.jsx +++ b/frontend/src/components/Searchfield.jsx @@ -124,7 +124,7 @@ const SearchField = props => { ); return ( -
+
{modalView} { // 1. Find startnode // 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 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) - 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) { const trigger = workflow.triggers[key] 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) { - 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~ @@ -279,7 +290,10 @@ const WorkflowValidationTimeline = (props) => { } previousTools = true - return null + + if (startnodeId !== action.id) { + return null + } } else { if (action.status === "SUCCESS") { nodecolor = green @@ -405,7 +419,7 @@ const WorkflowValidationTimeline = (props) => { : - {founderror.length > 0 ? founderror : ``} + {founderror.length > 0 ? founderror : `${action.app_name.replaceAll('_', ' ')}`} } placement="top"> diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 6ead5cf0..651092c2 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -7514,7 +7514,6 @@ const releaseToConnectLabel = "Release to Connect" } } else if (action.app_name === "Integration Framework") { const iconInfo = GetIconInfo(action) - console.log("FOUND INTEGRATION: iconInfo: ", iconInfo) if (iconInfo !== undefined && iconInfo !== null) { action.fillGradient = iconInfo.fillGradient action.iconBackground = iconInfo.iconBackgroundColor @@ -12465,7 +12464,6 @@ const releaseToConnectLabel = "Release to Connect" //setWorkflow(workflow); } - console.log("STARTNODE: ", startnode); } else { console.log("WORKFLOW: ", workflow); } @@ -14826,6 +14824,7 @@ const releaseToConnectLabel = "Release to Connect" setSelectedTrigger(trigger); setWorkflow(workflow); saveWorkflow(workflow); + setSelectedTrigger({}) }) .catch((error) => { @@ -16584,6 +16583,7 @@ const releaseToConnectLabel = "Release to Connect" } } + /* if (( event.ctrlKey || event.metaKey ) && event.shiftKey) { console.log("Shift key pressed") if (!workflow.public && executionModalOpen) { @@ -16595,6 +16595,7 @@ const releaseToConnectLabel = "Release to Connect" setExecutionModalView(0); } } + */ }; document.addEventListener('keydown', handleKeyDown); @@ -21832,17 +21833,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) { const parsedvalue = data - console.log("Parsed value: ", parsedvalue) if (parsedvalue.includes("#")) { const splitparsed = parsedvalue.split(".#.") //console.log("Cant contain #: ", splitparsed) if (splitparsed.length > 1) { - console.log("IN HERE AY") //data.value = splitparsed[0] selectedAction.parameters[0].value = splitparsed[0] diff --git a/frontend/src/views/Usecases.jsx b/frontend/src/views/Usecases.jsx index f131455d..16c20375 100644 --- a/frontend/src/views/Usecases.jsx +++ b/frontend/src/views/Usecases.jsx @@ -62,6 +62,7 @@ import { TreeMapLabel, TreeMapRect, } from 'reaviz'; +import { isMobile } from "react-device-detect" const useStyles = makeStyles({ notchedOutline: { @@ -381,7 +382,7 @@ const UsecaseListComponent = (props) => { {usecase.name} - + {usecase.list.map((subcase, subindex) => { const selectedItem = subindex === expandedItem && index === expandedIndex @@ -426,7 +427,7 @@ const UsecaseListComponent = (props) => { const fixedName = subcase.name.toLowerCase().replace("_", " ") return ( - { + { if (fixedName === "reporting") { getUsecase(subcase, index, subindex) return @@ -443,7 +444,7 @@ const UsecaseListComponent = (props) => { }}> {!selectedItem ?
- + {subcase.name} {finished ? @@ -478,7 +479,7 @@ const UsecaseListComponent = (props) => { { @@ -503,7 +504,7 @@ const UsecaseListComponent = (props) => { { @@ -618,7 +619,7 @@ const UsecaseListComponent = (props) => {
-
+
{editing ?
{ }
{ }}> } series={ @@ -1675,15 +1677,15 @@ const Dashboard = (props) => { console.log("USECASES: ", usecases) const data = -
-
+
+
{keys.length > 0 ? : null}
{usecases !== null && usecases !== undefined && usecases.length > 0 ? -
+
{usecases.map((usecase, index) => { return ( { marginRight: 10, paddingLeft: 5, paddingRight: 5, + marginTop: isMobile? 10:null, height: 28, cursor: "pointer", border: `1px solid ${usecase.color}`, diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index 816f17c5..75d3b799 100755 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -513,10 +513,15 @@ export const validateJson = (showResult) => { try { for (const [key, value] of Object.entries(result)) { if (typeof value === "string" && (value.startsWith("{") || value.startsWith("["))) { + //console.log("CHECKING STRING: ", value) + const inside_result = validateJson(value) if (inside_result.valid) { + //console.log("INSIDE RESULT: ", inside_result.result) + if (typeof inside_result.result === "string") { - const newres = JSON.parse(inside_result.result) + const newres = JSON.parse(inside_result.result) + result[key] = newres } else { result[key] = inside_result.result @@ -1037,9 +1042,9 @@ const Workflows = (props) => { data.default_return_value, {}, false, - [], - "", - data.status, + [], + "", + data.status, ) .then((response) => { if (response !== undefined) {