Tons of frontend bugfixes from cloud sync
This commit is contained in:
@@ -891,7 +891,7 @@ const Billing = memo((props) => {
|
|||||||
</span>
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
{showSupport ?
|
{/* {showSupport ?
|
||||||
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
<Button variant="outlined" color="primary" style={{ marginTop: 20, marginBottom: 10, }} onClick={() => {
|
||||||
if (window.drift !== undefined) {
|
if (window.drift !== undefined) {
|
||||||
//window.drift.api.startInteraction({ interactionId: 340045 })
|
//window.drift.api.startInteraction({ interactionId: 340045 })
|
||||||
@@ -902,7 +902,7 @@ const Billing = memo((props) => {
|
|||||||
}}>
|
}}>
|
||||||
Get Support
|
Get Support
|
||||||
</Button>
|
</Button>
|
||||||
: null}
|
: null} */}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -2021,7 +2021,7 @@ const Billing = memo((props) => {
|
|||||||
|
|
||||||
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : "100%", marginTop: 20}} >
|
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : "100%", marginTop: 20}} >
|
||||||
<div style={{ display: "flex", flexDirection: "column", width: "100%", }}>
|
<div style={{ display: "flex", flexDirection: "column", width: "100%", }}>
|
||||||
{isCloud &&
|
{/* {isCloud &&
|
||||||
selectedOrganization.subscriptions !== undefined &&
|
selectedOrganization.subscriptions !== undefined &&
|
||||||
selectedOrganization.subscriptions !== null &&
|
selectedOrganization.subscriptions !== null &&
|
||||||
selectedOrganization.subscriptions.length > 0 &&
|
selectedOrganization.subscriptions.length > 0 &&
|
||||||
@@ -2043,7 +2043,7 @@ const Billing = memo((props) => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
: null}
|
: null} */}
|
||||||
|
|
||||||
<div style={{ display: "flex", flexDirection: "row", width: "100%", marginTop: 20, marginBottom: 20, maxWidth: 860, }}>
|
<div style={{ display: "flex", flexDirection: "row", width: "100%", marginTop: 20, marginBottom: 20, maxWidth: 860, }}>
|
||||||
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
|
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ? isChildOrg ? null :
|
||||||
|
|||||||
@@ -151,13 +151,16 @@ const CacheView = memo((props) => {
|
|||||||
if (fileCategories.length === 1 && fileCategories[0] === "default") {
|
if (fileCategories.length === 1 && fileCategories[0] === "default") {
|
||||||
var newcategories = ["default"]
|
var newcategories = ["default"]
|
||||||
for (var key in responseJson.keys) {
|
for (var key in responseJson.keys) {
|
||||||
if (responseJson.keys[key].category !== undefined && responseJson.keys[key].category !== null && responseJson.keys[key].category !== "" && !fileCategories.includes(responseJson.keys[key].category)) {
|
var category = responseJson.keys[key].category
|
||||||
newcategories.push(responseJson.keys[key].category);
|
if (category !== undefined && category !== null && category !== ""){
|
||||||
|
category = category.replaceAll(" ", "_")
|
||||||
|
|
||||||
|
if (!newcategories.includes(category)) {
|
||||||
|
newcategories.push(category)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("CATEGORIES: ", newcategories)
|
|
||||||
|
|
||||||
setFileCategories(newcategories)
|
setFileCategories(newcategories)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,6 +360,7 @@ const CacheView = memo((props) => {
|
|||||||
<span style={{ color: "white" }}>
|
<span style={{ color: "white" }}>
|
||||||
{ editCache ? "Edit Key" : "Add Key"}{selectedCategory === "" || selectedCategory === "default" ? "" : ` in category '${selectedCategory}'`}
|
{ editCache ? "Edit Key" : "Add Key"}{selectedCategory === "" || selectedCategory === "default" ? "" : ` in category '${selectedCategory}'`}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
<div style={{ paddingLeft: "30px", paddingRight: '30px', backgroundColor: "#212121", }}>
|
||||||
Key
|
Key
|
||||||
@@ -1041,13 +1045,13 @@ const CacheView = memo((props) => {
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={data?.org_id !== selectedOrganization.id ? "You can not delete this key as it is controlled by parent organization." : "Delete this key" }
|
title={selectedOrganization?.id !== undefined && data?.org_id !== selectedOrganization.id ? "You can not delete this key as it is controlled by parent organization." : "Delete this key" }
|
||||||
aria-label={"Delete"}
|
aria-label={"Delete"}
|
||||||
>
|
>
|
||||||
<span>
|
<span>
|
||||||
<IconButton
|
<IconButton
|
||||||
style={{ padding: "6px" }}
|
style={{ padding: "6px" }}
|
||||||
disabled={data.org_id !== selectedOrganization.id ? true : false}
|
disabled={selectedOrganization?.id === undefined ? false : data.org_id !== selectedOrganization.id ? true : false}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
deleteCache(orgId, data.key);
|
deleteCache(orgId, data.key);
|
||||||
//deleteFile(orgId);
|
//deleteFile(orgId);
|
||||||
|
|||||||
@@ -774,8 +774,8 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
}, [window?.location?.pathname]);
|
}, [window?.location?.pathname]);
|
||||||
|
|
||||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
const showPartnerLogo = userdata?.org_status?.includes("integration_partner") && userdata?.active_org?.image !== undefined && userdata?.active_org?.image !== null && userdata?.active_org?.image.length > 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -836,11 +836,13 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link to="/">
|
<Link to={isCloud && !showPartnerLogo ? "/" : "/workflows"}>
|
||||||
<img
|
<img
|
||||||
src={ShuffleLogo}
|
src={
|
||||||
|
showPartnerLogo ? userdata?.active_org?.image : ShuffleLogo
|
||||||
|
}
|
||||||
alt="Shuffle Logo"
|
alt="Shuffle Logo"
|
||||||
style={{ width: 24, height: 24 }}
|
style={{ width: showPartnerLogo ? 30 : 24, height: showPartnerLogo ? 30 : 24 }}
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -1611,7 +1613,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
||||||
{expandLeftNav &&
|
{userdata?.licensed !== true && !userdata?.org_status?.includes("integration_partner") && expandLeftNav &&
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
style={{marginBottom: 15, borderWidth: 2, }}
|
style={{marginBottom: 15, borderWidth: 2, }}
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import {
|
|||||||
CardContent,
|
CardContent,
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
DialogContentText,
|
DialogContentText,
|
||||||
|
ToggleButton,
|
||||||
|
ToggleButtonGroup,
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
|
|
||||||
import { useNavigate, Link } from "react-router-dom";
|
import { useNavigate, Link } from "react-router-dom";
|
||||||
@@ -87,29 +89,80 @@ const LicencePopup = (props) => {
|
|||||||
const [calculatedCores, setCalculatedCores] = useState('600')
|
const [calculatedCores, setCalculatedCores] = useState('600')
|
||||||
const [onpremSelectedValue, setOnpremSelectedValue] = useState(8)
|
const [onpremSelectedValue, setOnpremSelectedValue] = useState(8)
|
||||||
|
|
||||||
const payasyougo = "Pay as you go"
|
const [billingCycle, setBillingCycle] = useState("annual")
|
||||||
|
const [scaleValue, setScaleValue] = useState(
|
||||||
|
new URLSearchParams(window.location.search).get("app_runs") ||
|
||||||
|
(userdata?.app_execution_limit / 1000) + 50 || 10
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setScaleValue((userdata?.app_execution_limit / 1000) + 50 || 10)
|
||||||
|
}, [userdata])
|
||||||
|
|
||||||
|
const getPrice = (basePrice) => {
|
||||||
|
return Math.round(billingCycle === "annual" ? basePrice * 0.9 : basePrice); // 10% discount for annual
|
||||||
|
};
|
||||||
|
|
||||||
const stripe = typeof window === 'undefined' || window.location === undefined ? "" : props.stripeKey === undefined ? "" : window.Stripe ? window.Stripe(props.stripeKey) : ""
|
const stripe = typeof window === 'undefined' || window.location === undefined ? "" : props.stripeKey === undefined ? "" : window.Stripe ? window.Stripe(props.stripeKey) : ""
|
||||||
|
|
||||||
|
// Handle slider change for Scale plan
|
||||||
|
const handleScaleChange = (event, newValue) => {
|
||||||
|
setScaleValue(newValue);
|
||||||
|
|
||||||
|
// Add app runs to URL query params
|
||||||
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||||
|
urlSearchParams.set("app_runs", newValue); // Convert to actual app runs (k to actual number)
|
||||||
|
const newUrl = `${window.location.pathname}?${urlSearchParams.toString()}`;
|
||||||
|
window.history.replaceState({}, "", newUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle billing cycle change
|
||||||
|
const handleBillingCycleChange = (event, newValue) => {
|
||||||
|
if (newValue !== null) {
|
||||||
|
setBillingCycle(newValue);
|
||||||
|
|
||||||
|
if(isCloud){
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Billingpage',
|
||||||
|
action: 'Billing Cycle Changed',
|
||||||
|
label: `${billingCycle} -> ${newValue}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add billing cycle to URL query params
|
||||||
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||||
|
urlSearchParams.set("billing_cycle", newValue);
|
||||||
|
const newUrl = `${
|
||||||
|
window.location.pathname
|
||||||
|
}?${urlSearchParams.toString()}`;
|
||||||
|
window.history.replaceState({}, "", newUrl);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const payasyougo = "Pay as you go"
|
||||||
|
|
||||||
const paperStyle = {
|
const paperStyle = {
|
||||||
padding: 20,
|
padding: 20,
|
||||||
|
paddingBottom: 30,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
height: "100%"
|
height: "100%"
|
||||||
}
|
}
|
||||||
|
|
||||||
billingInfo.subscription = {
|
billingInfo.subscription = {
|
||||||
"active": true,
|
"active": true,
|
||||||
"name": "Pay as you go",
|
"name": userdata?.app_execution_limit === 10000 ? "10,000 App Runs" : "2,000 App Runs",
|
||||||
"price": typecost_single,
|
"price": "Free",
|
||||||
"currency": "USD",
|
"currency": "Free",
|
||||||
"currency_text": "$",
|
"currency_text": "",
|
||||||
"interval": "app run / month",
|
"interval": "",
|
||||||
"description": "Pay as you go",
|
"description": "Pay as you go",
|
||||||
"features": [
|
"features": [
|
||||||
"Basic Support",
|
"Community Support",
|
||||||
"Includes 10.000 app run/month for free. ",
|
`Includes ${userdata?.app_execution_limit === 10000 ? "10,000" : "2,000"} app run/month for free. `,
|
||||||
"Pay for what you use with no minimum commitment and cancel anytime."
|
"Get all 2500+ Apps and 10 Workflows",
|
||||||
|
"Invite up to 5 users"
|
||||||
],
|
],
|
||||||
"limit": 10000,
|
"limit": userdata?.app_execution_limit === 10000 ? 10000 : 2000,
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendSignatureRequest = (subscription) => {
|
const sendSignatureRequest = (subscription) => {
|
||||||
@@ -151,32 +204,32 @@ const LicencePopup = (props) => {
|
|||||||
const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed)
|
const [tosChecked, setTosChecked] = React.useState(subscription.eula_signed)
|
||||||
const [hovered, setHovered] = React.useState(false)
|
const [hovered, setHovered] = React.useState(false)
|
||||||
const [newBillingEmail, setNewBillingEmail] = useState('');
|
const [newBillingEmail, setNewBillingEmail] = useState('');
|
||||||
var top_text = "Base Cloud Access"
|
var top_text = "Starter Plan"
|
||||||
if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) {
|
// if (subscription.limit === undefined && subscription.level === undefined || subscription.level === null || subscription.level === 0) {
|
||||||
subscription.name = "Enterprise"
|
// subscription.name = "Enterprise"
|
||||||
subscription.currency_text = "$"
|
// subscription.currency_text = "$"
|
||||||
subscription.price = subscription.level * 180
|
// subscription.price = subscription.level * 180
|
||||||
subscription.limit = subscription.level * 100000
|
// subscription.limit = subscription.level * 100000
|
||||||
subscription.interval = subscription.recurrence
|
// subscription.interval = subscription.recurrence
|
||||||
subscription.features = [
|
// subscription.features = [
|
||||||
"Includes " + subscription.limit + " app runs/month. ",
|
// "Includes " + subscription.limit + " app runs/month. ",
|
||||||
"Multi-Tenancy and Region-Selection",
|
// "Multi-Tenancy and Region-Selection",
|
||||||
"And all other features from /pricing",
|
// "And all other features from /pricing",
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (userdata?.app_execution_limit >= 300000) {
|
// if (userdata?.app_execution_limit >= 300000) {
|
||||||
subscription.name = "Enterprise"
|
// subscription.name = "Enterprise"
|
||||||
subscription.currency_text = "$"
|
// subscription.currency_text = "$"
|
||||||
subscription.price = typecost_single
|
// subscription.price = typecost_single
|
||||||
subscription.limit = userdata?.app_execution_limit
|
// subscription.limit = userdata?.app_execution_limit
|
||||||
subscription.interval = "app run / month"
|
// subscription.interval = "app run / month"
|
||||||
subscription.features = [
|
// subscription.features = [
|
||||||
"Includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. ",
|
// "Includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. ",
|
||||||
"Multi-Tenancy and Region-Selection",
|
// "Multi-Tenancy and Region-Selection",
|
||||||
"And all other features from /pricing",
|
// "And all other features from /pricing",
|
||||||
]
|
// ]
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
var newPaperstyle = JSON.parse(JSON.stringify(paperStyle))
|
var newPaperstyle = JSON.parse(JSON.stringify(paperStyle))
|
||||||
@@ -189,12 +242,12 @@ const LicencePopup = (props) => {
|
|||||||
var showSupport = false
|
var showSupport = false
|
||||||
if (subscription.name.includes("default")) {
|
if (subscription.name.includes("default")) {
|
||||||
top_text = "Custom Contract"
|
top_text = "Custom Contract"
|
||||||
newPaperstyle.border = "1px solid #f85a3e"
|
// newPaperstyle.border = "1px solid #f85a3e"
|
||||||
showSupport = true
|
showSupport = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subscription.name.includes("App Run Units")) {
|
if (subscription.name.includes("App Run Units")) {
|
||||||
top_text = "Cloud Access"
|
top_text = "Scale Plan"
|
||||||
showSupport = true
|
showSupport = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -357,7 +410,11 @@ const LicencePopup = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
{subscription.active === true && !isScale && <Button style={{ backgroundColor: '#2F2F2F', color: "white", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', width: 144, height: 40 }}>Current Plan</Button> }
|
{subscription.active === true && !isScale && <Button style={{ backgroundColor: '#2f2f2f', color: "#ffffff", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', fontSize: 13 }}
|
||||||
|
variant="contained"
|
||||||
|
color="primary">
|
||||||
|
Current Plan
|
||||||
|
</Button>}
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
{top_text === "Base Cloud Access" && userdata.has_card_available === true && !isScale ?
|
{top_text === "Base Cloud Access" && userdata.has_card_available === true && !isScale ?
|
||||||
<Chip
|
<Chip
|
||||||
@@ -381,7 +438,7 @@ const LicencePopup = (props) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
/>
|
/>
|
||||||
: null}
|
: null}
|
||||||
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, whiteSpace: 'nowrap' }}>
|
<Typography variant="h6" style={{ marginTop: 25, marginBottom: 10, flex: 5, whiteSpace: 'nowrap' }}>
|
||||||
{top_text}
|
{top_text}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@@ -396,7 +453,7 @@ const LicencePopup = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
: null}
|
: null}
|
||||||
{isCloud && highlight === true && top_text !== "Base Cloud Access" ?
|
{isCloud && highlight === true && top_text !== "Starter Plan" ?
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title="Sign EULA"
|
title="Sign EULA"
|
||||||
placement="top"
|
placement="top"
|
||||||
@@ -426,7 +483,7 @@ const LicencePopup = (props) => {
|
|||||||
{subscription.currency_text}{subscription.price}
|
{subscription.currency_text}{subscription.price}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="body1" color="textSecondary" style={{ marginLeft: 10, marginTop: 15, marginBottom: 10 }}>
|
<Typography variant="body1" color="textSecondary" style={{ marginLeft: 10, marginTop: 15, marginBottom: 10 }}>
|
||||||
/ {subscription.interval}
|
{subscription.interval.length > 0 ? `/ ${subscription.interval}` : ""}
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null}
|
||||||
@@ -517,23 +574,17 @@ const LicencePopup = (props) => {
|
|||||||
: null}
|
: null}
|
||||||
</ul>
|
</ul>
|
||||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||||
{subscription.name.includes("Scale") ?
|
{
|
||||||
""
|
|
||||||
:
|
|
||||||
|
|
||||||
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 ?
|
||||||
userdata?.app_execution_limit && userdata?.app_execution_limit >= 300000 ?
|
userdata?.app_execution_limit && userdata?.app_execution_limit !== 10000 ?
|
||||||
"You have subscribed to the Enterprise plan, which includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. You can increase the limit by upgrading current plan. Contact support@shuffler.io for more information." :
|
"You have already subscribed to the Scale plan, which includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. You can increase the limit by upgrading current plan. Contact support@shuffler.io for more information." :
|
||||||
`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 using free Starter plan with max ${userdata?.app_execution_limit === 10000 ? "10,000" : "2,000"} runs per month. Upgrade to increase 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>
|
||||||
{isCloud && (userdata.has_card_available === true || selectedOrganization?.Billing?.Email?.length > 0 )?
|
{/* {isCloud && (userdata.has_card_available === true || selectedOrganization?.Billing?.Email?.length > 0 )?
|
||||||
<div>
|
<div>
|
||||||
<span>Billing email: {BillingEmail}</span>
|
<span>Billing email: {BillingEmail}</span>
|
||||||
<Button
|
<Button
|
||||||
@@ -611,15 +662,14 @@ const LicencePopup = (props) => {
|
|||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
: null}
|
: null} */}
|
||||||
</div>
|
</div>
|
||||||
{isCloud ? (
|
{isCloud ? (
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
disabled={false}
|
|
||||||
color="primary"
|
color="primary"
|
||||||
style={{
|
style={{
|
||||||
marginTop: !userdata.has_card_available ? 20 : 10,
|
marginTop: !userdata.has_card_available ? 25 : 10,
|
||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
height: 40,
|
height: 40,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
@@ -630,20 +680,15 @@ const LicencePopup = (props) => {
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isCloud) {
|
console.log("Subscription: ", subscription.name)
|
||||||
handlePayasyougo(userdata, selectedOrganization, BillingEmail)
|
if(!subscription.name.includes("App Run Units")) {
|
||||||
//navigate("/pricing?tab=cloud&highlight=true")
|
window.open("https://discord.gg/B2CBzUm", "_blank")
|
||||||
} else {
|
} else {
|
||||||
//window.open("https://shuffler.io/pricing?tab=onprem&highlight=true", "_blank")
|
window.open("mailto:support@shuffler.io", "_blank")
|
||||||
handlePayasyougo()
|
}
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{userdata.has_card_available === true ?
|
Get Support
|
||||||
"Manage Card Details"
|
|
||||||
:
|
|
||||||
"Add Card Details"
|
|
||||||
}
|
|
||||||
</Button> ) : null}
|
</Button> ) : null}
|
||||||
<Button
|
<Button
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -709,42 +754,42 @@ const LicencePopup = (props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
console.log("New variant: ", shuffleVariant)
|
// console.log("New variant: ", shuffleVariant)
|
||||||
|
|
||||||
if (shuffleVariant === 1) {
|
// if (shuffleVariant === 1) {
|
||||||
setCalculatedCost("$960")
|
// setCalculatedCost("$960")
|
||||||
setSelectedValue(8)
|
// setSelectedValue(8)
|
||||||
} else {
|
// } else {
|
||||||
if (userdata && userdata?.app_execution_limit) {
|
// if (userdata && userdata?.app_execution_limit) {
|
||||||
if (userdata.app_execution_limit >= 300000 && userdata.app_execution_limit < 400000) {
|
// if (userdata.app_execution_limit >= 30000 && userdata.app_execution_limit < 40000) {
|
||||||
setSelectedValue(400)
|
// setSelectedValue(400)
|
||||||
setCalculatedCost("$1280")
|
// setCalculatedCost("$1280")
|
||||||
}else if (userdata?.app_execution_limit >= 400000 && userdata?.app_execution_limit < 500000) {
|
// }else if (userdata?.app_execution_limit >= 40000 && userdata?.app_execution_limit < 50000) {
|
||||||
setSelectedValue(500)
|
// setSelectedValue(500)
|
||||||
setCalculatedCost("$1600")
|
// setCalculatedCost("$1600")
|
||||||
} else if (userdata?.app_execution_limit >= 500000 && userdata?.app_execution_limit < 600000) {
|
// } else if (userdata?.app_execution_limit >= 500000 && userdata?.app_execution_limit < 600000) {
|
||||||
setSelectedValue(600)
|
// setSelectedValue(600)
|
||||||
setCalculatedCost("$1920")
|
// setCalculatedCost("$1920")
|
||||||
} else if (userdata?.app_execution_limit >= 600000 && userdata?.app_execution_limit < 700000) {
|
// } else if (userdata?.app_execution_limit >= 60000 && userdata?.app_execution_limit < 70000) {
|
||||||
setSelectedValue(700)
|
// setSelectedValue(700)
|
||||||
setCalculatedCost("$2240")
|
// setCalculatedCost("$2240")
|
||||||
} else if (userdata?.app_execution_limit >= 700000 && userdata?.app_execution_limit < 800000) {
|
// } else if (userdata?.app_execution_limit >= 70000 && userdata?.app_execution_limit < 80000) {
|
||||||
setSelectedValue(800)
|
// setSelectedValue(800)
|
||||||
setCalculatedCost("$2560")
|
// setCalculatedCost("$2560")
|
||||||
} else if (userdata?.app_execution_limit >= 800000 && userdata?.app_execution_limit < 900000) {
|
// } else if (userdata?.app_execution_limit >= 80000 && userdata?.app_execution_limit < 90000) {
|
||||||
setSelectedValue(900)
|
// setSelectedValue(900)
|
||||||
setCalculatedCost("$2880")
|
// setCalculatedCost("$2880")
|
||||||
}else {
|
// }else {
|
||||||
setCalculatedCost("$960")
|
// setCalculatedCost("$960")
|
||||||
setSelectedValue(300)
|
// setSelectedValue(300)
|
||||||
}
|
// }
|
||||||
}else {
|
// }else {
|
||||||
setCalculatedCost("$960")
|
// setCalculatedCost("$960")
|
||||||
setSelectedValue(300)
|
// setSelectedValue(300)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}, [shuffleVariant])
|
// }, [userdata])
|
||||||
|
|
||||||
if (typeof window === 'undefined' || window.location === undefined) {
|
if (typeof window === 'undefined' || window.location === undefined) {
|
||||||
return null
|
return null
|
||||||
@@ -900,71 +945,121 @@ const LicencePopup = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log("Priceitem: ", shuffleVariant)
|
console.log("Priceitem: ", shuffleVariant)
|
||||||
|
// const isLoggedInHandler = () => {
|
||||||
|
// if (calculatedCost === payasyougo) {
|
||||||
|
// handlePayasyougo(props.userdata)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const priceItem =
|
||||||
|
// window.location.origin === "https://shuffler.io/" || "https://sandbox.shuffler.io/"
|
||||||
|
// ? shuffleVariant === 0
|
||||||
|
// ? "price_1PWI3uDzMUgUjxHSffUBwWCy"
|
||||||
|
// : "price_1PWI8EDzMUgUjxHSfEhUB7oL"
|
||||||
|
|
||||||
|
// : shuffleVariant === 0
|
||||||
|
// ? "price_1PZPSSEJjT17t98NLJoTMYja"
|
||||||
|
// : "price_1PZPQuEJjT17t98N3yORUtd9";
|
||||||
|
|
||||||
|
// const successUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=success`
|
||||||
|
// const failUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=failure`
|
||||||
|
// const quantity = shuffleVariant === 0 ? selectedValue / 100 : selectedValue
|
||||||
|
|
||||||
|
// console.log("Priceitem: ", priceItem, quantity, shuffleVariant)
|
||||||
|
// var checkoutObject = {
|
||||||
|
// lineItems: [
|
||||||
|
// {
|
||||||
|
// price: priceItem,
|
||||||
|
// quantity: quantity,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// mode: "subscription",
|
||||||
|
// billingAddressCollection: "auto",
|
||||||
|
// successUrl: successUrl,
|
||||||
|
// cancelUrl: failUrl,
|
||||||
|
// clientReferenceId: props.userdata.active_org.id,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (stripe === undefined || stripe === null || stripe.redirectToCheckout === undefined) {
|
||||||
|
// window.open("https://shuffler.io/admin?admin_tab=billingstats&payment=stripe_error", "_self")
|
||||||
|
// }
|
||||||
|
|
||||||
|
// stripe.redirectToCheckout(checkoutObject)
|
||||||
|
// .then(function (result) {
|
||||||
|
// console.log("SUCCESS STRIPE?: ", result)
|
||||||
|
|
||||||
|
// ReactGA.event({
|
||||||
|
// category: "pricing",
|
||||||
|
// action: "add_card_success",
|
||||||
|
// label: "",
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// .catch(function (error) {
|
||||||
|
// console.error("STRIPE ERROR: ", error)
|
||||||
|
|
||||||
|
// ReactGA.event({
|
||||||
|
// category: "pricing",
|
||||||
|
// action: "add_card_error",
|
||||||
|
// label: "",
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
|
||||||
const isLoggedInHandler = () => {
|
const isLoggedInHandler = () => {
|
||||||
if (calculatedCost === payasyougo) {
|
var priceItem;
|
||||||
handlePayasyougo(props.userdata)
|
if (window.location.origin === "https://shuffler.io" || window.location.origin === "https://sandbox.shuffler.io") {
|
||||||
return
|
priceItem = billingCycle === "monthly" ? "price_1R66rbEJjT17t98NHIQ78nrz" : "price_1R671UEJjT17t98NzfqWvSG7"
|
||||||
|
} else if (window.location.origin === "http://localhost:3002") {
|
||||||
|
priceItem = billingCycle === "monthly" ? "price_1R678hEJjT17t98Nai5J50gs" : "price_1R6c84EJjT17t98NR68gUfT7"
|
||||||
|
}
|
||||||
|
|
||||||
|
const successUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=success`;
|
||||||
|
const failUrl = `${window.location.origin}/pricing?admin_tab=billingstats&payment=failure`;
|
||||||
|
|
||||||
|
let quantity;
|
||||||
|
|
||||||
|
if (billingCycle === "monthly") {
|
||||||
|
quantity = scaleValue / 10
|
||||||
|
} else {
|
||||||
|
quantity = (scaleValue / 10) * 12
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redirectToCheckout(priceItem, quantity, successUrl, failUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const redirectToCheckout = (priceItem, quantity, successUrl, failUrl) => {
|
||||||
|
const checkoutObject = {
|
||||||
|
lineItems: [
|
||||||
|
{
|
||||||
|
price: priceItem,
|
||||||
|
quantity: quantity,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mode: "subscription",
|
||||||
|
billingAddressCollection: "auto",
|
||||||
|
successUrl: successUrl,
|
||||||
|
cancelUrl: failUrl,
|
||||||
|
clientReferenceId: userdata.active_org.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("OBJECT: ", priceItem, checkoutObject);
|
||||||
|
|
||||||
|
stripe
|
||||||
|
.redirectToCheckout(checkoutObject)
|
||||||
|
.then(function (result) {
|
||||||
|
console.log("SUCCESS STRIPE?: ", result);
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.error("STRIPE ERROR: ", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const priceItem =
|
console.log("Selected Organization: ", selectedOrganization.subscriptions)
|
||||||
window.location.origin === "https://shuffler.io/" || "https://sandbox.shuffler.io/"
|
|
||||||
? shuffleVariant === 0
|
|
||||||
? "price_1PWI3uDzMUgUjxHSffUBwWCy"
|
|
||||||
: "price_1PWI8EDzMUgUjxHSfEhUB7oL"
|
|
||||||
|
|
||||||
: shuffleVariant === 0
|
|
||||||
? "price_1PZPSSEJjT17t98NLJoTMYja"
|
|
||||||
: "price_1PZPQuEJjT17t98N3yORUtd9";
|
|
||||||
|
|
||||||
const successUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=success`
|
|
||||||
const failUrl = `${window.location.origin}/admin?admin_tab=billingstats&payment=failure`
|
|
||||||
const quantity = shuffleVariant === 0 ? selectedValue / 100 : selectedValue
|
|
||||||
|
|
||||||
console.log("Priceitem: ", priceItem, quantity, shuffleVariant)
|
|
||||||
var checkoutObject = {
|
|
||||||
lineItems: [
|
|
||||||
{
|
|
||||||
price: priceItem,
|
|
||||||
quantity: quantity,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
mode: "subscription",
|
|
||||||
billingAddressCollection: "auto",
|
|
||||||
successUrl: successUrl,
|
|
||||||
cancelUrl: failUrl,
|
|
||||||
clientReferenceId: props.userdata.active_org.id,
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stripe === undefined || stripe === null || stripe.redirectToCheckout === undefined) {
|
|
||||||
window.open("https://shuffler.io/admin?admin_tab=billingstats&payment=stripe_error", "_self")
|
|
||||||
}
|
|
||||||
|
|
||||||
stripe.redirectToCheckout(checkoutObject)
|
|
||||||
.then(function (result) {
|
|
||||||
console.log("SUCCESS STRIPE?: ", result)
|
|
||||||
|
|
||||||
ReactGA.event({
|
|
||||||
category: "pricing",
|
|
||||||
action: "add_card_success",
|
|
||||||
label: "",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
console.error("STRIPE ERROR: ", error)
|
|
||||||
|
|
||||||
ReactGA.event({
|
|
||||||
category: "pricing",
|
|
||||||
action: "add_card_error",
|
|
||||||
label: "",
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Grid container spacing={2} columns={16} style={{ flexDirection: "row", flexWrap: "nowrap", borderRadius: '16px', display: "flex", }}>
|
<Grid container spacing={2} columns={16} style={{ flexDirection: "row", flexWrap: "nowrap", borderRadius: '16px', display: "flex"}}>
|
||||||
<Grid item xs={8}>
|
<Grid item xs={8}>
|
||||||
{isCloud && billingInfo.subscription !== undefined && billingInfo.subscription !== null ?
|
{selectedOrganization.subscriptions === undefined || selectedOrganization.subscriptions === null || selectedOrganization.subscriptions.length === 0 ?
|
||||||
<SubscriptionObject
|
<SubscriptionObject
|
||||||
index={0}
|
index={0}
|
||||||
globalUrl={globalUrl}
|
globalUrl={globalUrl}
|
||||||
@@ -976,7 +1071,29 @@ const LicencePopup = (props) => {
|
|||||||
subscription={billingInfo.subscription}
|
subscription={billingInfo.subscription}
|
||||||
highlight={selectedOrganization.subscriptions === undefined || selectedOrganization.subscriptions === null || selectedOrganization.subscriptions.length === 0}
|
highlight={selectedOrganization.subscriptions === undefined || selectedOrganization.subscriptions === null || selectedOrganization.subscriptions.length === 0}
|
||||||
/>
|
/>
|
||||||
: !isCloud ?
|
:
|
||||||
|
selectedOrganization.subscriptions !== undefined &&
|
||||||
|
selectedOrganization.subscriptions !== null &&
|
||||||
|
selectedOrganization.subscriptions.length > 0 ?
|
||||||
|
selectedOrganization.subscriptions
|
||||||
|
.reverse()
|
||||||
|
.map((sub, index) => {
|
||||||
|
return (
|
||||||
|
<SubscriptionObject
|
||||||
|
index={index + 1}
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
userdata={userdata}
|
||||||
|
serverside={serverside}
|
||||||
|
billingInfo={billingInfo}
|
||||||
|
stripeKey={stripeKey}
|
||||||
|
selectedOrganization={selectedOrganization}
|
||||||
|
subscription={sub}
|
||||||
|
highlight={true}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
{!isCloud ?
|
||||||
<span style={{ display: "flex", }}>
|
<span style={{ display: "flex", }}>
|
||||||
<SubscriptionObject
|
<SubscriptionObject
|
||||||
index={0}
|
index={0}
|
||||||
@@ -1044,61 +1161,184 @@ const LicencePopup = (props) => {
|
|||||||
})
|
})
|
||||||
: null} */}
|
: null} */}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={8}>
|
<Grid item xs={8} sx={{ height: "100%" }}>
|
||||||
<Grid style={{}}>
|
<Grid style={{}}>
|
||||||
{errorMessage.length > 0 ? <Typography variant="h4">Error: {errorMessage}</Typography> : null}
|
{errorMessage.length > 0 ? <Typography variant="h4">Error: {errorMessage}</Typography> : null}
|
||||||
<Card style={{
|
<Card style={{
|
||||||
padding: 20,
|
padding: 20,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
background:
|
||||||
border: !isScale ? "1px solid #f85a3e" : 'none',
|
"linear-gradient(to right, #212121, #212121) padding-box, linear-gradient(90deg, #F86744 0%, #F34475 100%) border-box",
|
||||||
|
borderWidth: "2px",
|
||||||
|
borderStyle: "solid",
|
||||||
|
borderColor: "transparent",
|
||||||
}}>
|
}}>
|
||||||
<div>
|
<div
|
||||||
{ !isScale && <Button style={{ backgroundColor: 'rgba(255, 132, 68, 0.2)', color: "#FF8444", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', }}
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: 25,
|
||||||
|
marginLeft: -2,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button style={{ backgroundColor: 'rgba(255, 132, 68, 0.2)', color: "#FF8444", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', fontSize: 13 }}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary">Recommended </Button> }
|
color="primary">Recommended
|
||||||
|
</Button>
|
||||||
|
{
|
||||||
|
billingCycle === "annual" &&
|
||||||
|
(
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
background: "rgba(248, 103, 68, 0.1)",
|
||||||
|
py: 0.5,
|
||||||
|
px: 1.5,
|
||||||
|
borderRadius: "8px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
background:
|
||||||
|
"linear-gradient(90deg, #FF8544 0%, #FB47A0 100%)",
|
||||||
|
WebkitBackgroundClip: "text",
|
||||||
|
WebkitTextFillColor: "transparent",
|
||||||
|
backgroundClip: "text",
|
||||||
|
fontSize: {
|
||||||
|
xs: "12px",
|
||||||
|
md: "14px",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
10% OFF
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: 10,
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6" style={{ }}>
|
||||||
|
{scaleValue > 300 ? "Enterprise Plan" : "Scale Plan"}
|
||||||
|
</Typography>
|
||||||
|
<Box sx={{ display: "flex", justifyContent: "center" }}>
|
||||||
|
<ToggleButtonGroup
|
||||||
|
value={billingCycle}
|
||||||
|
exclusive
|
||||||
|
onChange={handleBillingCycleChange}
|
||||||
|
aria-label="billing cycle"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
||||||
|
fontFamily: theme.typography.fontFamily,
|
||||||
|
borderRadius: "30px",
|
||||||
|
marginTop: -1,
|
||||||
|
padding: "3px",
|
||||||
|
"& .MuiToggleButton-root": {
|
||||||
|
border: "none",
|
||||||
|
borderRadius: "30px",
|
||||||
|
color: "#fff",
|
||||||
|
padding: "6px 22px",
|
||||||
|
textTransform: "none",
|
||||||
|
fontSize: {
|
||||||
|
xs: "12px",
|
||||||
|
},
|
||||||
|
"&.Mui-selected": {
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
fontFamily: theme.typography.fontFamily,
|
||||||
|
color: "#1A1A1A",
|
||||||
|
fontWeight: "bold",
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "#fff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"&:hover": {
|
||||||
|
backgroundColor: "rgba(255, 255, 255, 0.2)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ToggleButton value="monthly" aria-label="monthly">
|
||||||
|
Monthly
|
||||||
|
</ToggleButton>
|
||||||
|
<ToggleButton value="annual" aria-label="annual">
|
||||||
|
Annual
|
||||||
|
</ToggleButton>
|
||||||
|
</ToggleButtonGroup>
|
||||||
|
</Box>
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, }}>{shuffleVariant === 1 ? "Scale" : "Enterprise"}</Typography>
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20 }}>
|
<Typography variant="body1" color="textSecondary" style={{ marginTop: 20 }}>
|
||||||
{shuffleVariant === 0 ?
|
App Runs Units
|
||||||
"SaaS / Cloud - Per Month"
|
|
||||||
:
|
|
||||||
"Open Source + Scale License"
|
|
||||||
}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography style={{ minHeight: 46, cursor: calculatedCores === "Get A Quote" ? "pointer" : "inherit", }} onClick={() => {
|
<div style={{ display: "flex", flexDirection: "row", alignItems: "center", gap: 10 , marginTop: 10 }}>
|
||||||
|
<Typography style={{
|
||||||
if (calculatedCores === "Get A Quote") {
|
fontSize: 24,
|
||||||
console.log("Clicked on get a quote")
|
marginTop: 7,
|
||||||
if (window.drift !== undefined) {
|
marginBottom: 10,
|
||||||
window.drift.api.startInteraction({ interactionId: 340785 })
|
fontWeight: "500",
|
||||||
}
|
}}
|
||||||
}
|
>
|
||||||
}}>{calculatedCost}</Typography>
|
{scaleValue > 300 ? "Let's Talk" : `$${getPrice(32) * (scaleValue / 10)}`}
|
||||||
<Typography variant="body1" color="textSecondary" style={{}}>For {shuffleVariant === 1 ? `${selectedValue} CPU cores` : `${selectedValue}k App Runs`}: </Typography>
|
</Typography>
|
||||||
<div style={{ textAlign: "center" }}>
|
<Typography
|
||||||
|
color="text.secondary"
|
||||||
<Slider
|
sx={{
|
||||||
aria-label="Small steps"
|
fontSize: "14px",
|
||||||
style={{ width: "80%", margin: "auto" }}
|
marginBottom: "-2px",
|
||||||
onChange={(event, newValue) => {
|
marginLeft: scaleValue > 300 ? 1 : 0,
|
||||||
handleChange(event, newValue)
|
|
||||||
}}
|
}}
|
||||||
marks
|
>
|
||||||
value={selectedValue}
|
{scaleValue > 300 ? `for ${scaleValue > 500 ? "500k+" : `${scaleValue}k`} App Runs` : `/month for ${scaleValue}k App Runs`}
|
||||||
step={shuffleVariant === 0 ? 100 : 4}
|
</Typography>
|
||||||
min={shuffleVariant === 0 ? 100 : 8}
|
|
||||||
max={shuffleVariant === 0 ? 1000 : 32}
|
|
||||||
valueLabelDisplay="auto"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
<Box sx={{ px: 1 }}>
|
||||||
|
<Slider
|
||||||
|
value={scaleValue}
|
||||||
|
onChange={handleScaleChange}
|
||||||
|
aria-labelledby="scale-slider"
|
||||||
|
valueLabelDisplay="auto"
|
||||||
|
valueLabelFormat={(value) => {
|
||||||
|
if(value === 510){
|
||||||
|
return "500k+"
|
||||||
|
}
|
||||||
|
return `${value}k`
|
||||||
|
}}
|
||||||
|
step={10}
|
||||||
|
min={10}
|
||||||
|
max={510}
|
||||||
|
marks
|
||||||
|
sx={{
|
||||||
|
color: "#ff8544",
|
||||||
|
"& .MuiSlider-thumb": {
|
||||||
|
width: 15,
|
||||||
|
height: 15,
|
||||||
|
},
|
||||||
|
"& .MuiSlider-valueLabel": {
|
||||||
|
backgroundColor: "rgba(33, 33, 33, 1)",
|
||||||
|
color: "rgba(241, 241, 241, 1)",
|
||||||
|
fontSize: 14,
|
||||||
|
borderRadius: "4px",
|
||||||
|
border: "1px solid rgba(73, 73, 73, 1)",
|
||||||
|
fontFamily: theme?.typography?.fontFamily,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<span>{defaultTaskIcon}</span>
|
<span>{defaultTaskIcon}</span>
|
||||||
<Typography style={{ fontSize: 14, marginLeft: 8 }}>Priority Support</Typography>
|
<Typography style={{ fontSize: 14, marginLeft: 8 }}>Standard Email Support</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Divider />
|
<Divider />
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
@@ -1117,7 +1357,7 @@ const LicencePopup = (props) => {
|
|||||||
<Divider />
|
<Divider />
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||||
<span>{defaultTaskIcon}</span>
|
<span>{defaultTaskIcon}</span>
|
||||||
<Typography style={{ fontSize: 14, marginLeft: 8 }}>Help with Workflow and App development</Typography>
|
<Typography style={{ fontSize: 14, marginLeft: 8 }}>30 Days workflow run history</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginTop: 20, }} />
|
<div style={{ marginTop: 20, }} />
|
||||||
@@ -1136,7 +1376,7 @@ const LicencePopup = (props) => {
|
|||||||
|
|
||||||
navigate("/pricing")
|
navigate("/pricing")
|
||||||
} else {
|
} else {
|
||||||
window.open("https://shuffler.io/pricing?tab=onprem", "_blank")
|
window.open("https://shuffler.io/pricing?tab=Self-Hosted", "_blank")
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -1149,6 +1389,10 @@ const LicencePopup = (props) => {
|
|||||||
style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
|
style={{ borderRadius: 4, textTransform: "capitalize", color: "#1a1a1a", backgroundColor: "#ff8544", width: "100%", fontSize: 16}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isCloud) {
|
if (isCloud) {
|
||||||
|
if(scaleValue > 300){
|
||||||
|
navigate("/contact?category=cloud_enterprise_plan")
|
||||||
|
return;
|
||||||
|
}
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: "header",
|
category: "header",
|
||||||
action: "upgread_clicks_popup",
|
action: "upgread_clicks_popup",
|
||||||
@@ -1170,7 +1414,7 @@ const LicencePopup = (props) => {
|
|||||||
}}
|
}}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
||||||
Upgrade
|
{scaleValue > 300 ? "Let's Talk" : "Upgrade"}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
|
|||||||
@@ -1363,7 +1363,6 @@ const Navbar = (props) => {
|
|||||||
sx={buttonStyles}
|
sx={buttonStyles}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if(isCloud) {
|
if(isCloud) {
|
||||||
// navigate("/new-pricing");
|
|
||||||
navigate("/pricing");
|
navigate("/pricing");
|
||||||
ReactGA.event({
|
ReactGA.event({
|
||||||
category: "navbar",
|
category: "navbar",
|
||||||
@@ -1371,7 +1370,7 @@ const Navbar = (props) => {
|
|||||||
label: "go_to_pricing",
|
label: "go_to_pricing",
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
window.open("https://shuffler.io/pricing?env=Self-hosted", '_blank');
|
window.open("https://shuffler.io/pricing?env=Self-Hosted", '_blank');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -538,7 +538,7 @@ const OrgHeaderexpandedNew = (props) => {
|
|||||||
renderValue={(selected) => selected.join(', ')}
|
renderValue={(selected) => selected.join(', ')}
|
||||||
MenuProps={MenuProps}
|
MenuProps={MenuProps}
|
||||||
>
|
>
|
||||||
{["contacted", "lead", "demo done", "pov", "customer", "open source", "student", "internal", "creator", "tech partner", "old customer", "old lead"].map((name) => (
|
{["contacted", "lead", "demo done", "pov", "customer", "open source", "student", "internal", "creator", "tech partner", "integration partner", "distribution partner", "service partner", "old customer", "old lead"].map((name) => (
|
||||||
<MenuItem key={name} value={name}>
|
<MenuItem key={name} value={name}>
|
||||||
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
|
<Checkbox checked={selectedStatus.indexOf(name) > -1} />
|
||||||
<ListItemText primary={name} />
|
<ListItemText primary={name} />
|
||||||
|
|||||||
@@ -682,11 +682,14 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
// Process workflowExecutions
|
// Process workflowExecutions
|
||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
|
var appended = false
|
||||||
|
var foundvalue = ""
|
||||||
for (let execution of workflowExecutions) {
|
for (let execution of workflowExecutions) {
|
||||||
const execArg = execution.execution_argument;
|
const execArg = execution.execution_argument;
|
||||||
if (execArg && execArg.length > 0) {
|
if (execArg && execArg.length > 0) {
|
||||||
const valid = validateJson(execArg);
|
const valid = validateJson(execArg);
|
||||||
if (valid.valid) {
|
if (valid.valid) {
|
||||||
|
appended = true
|
||||||
newActionList.push({
|
newActionList.push({
|
||||||
type: "Runtime Argument",
|
type: "Runtime Argument",
|
||||||
name: "Runtime Argument",
|
name: "Runtime Argument",
|
||||||
@@ -697,9 +700,23 @@ const ParsedAction = (props) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
break
|
break
|
||||||
|
} else {
|
||||||
|
foundvalue = execArg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!appended && foundvalue !== undefined && foundvalue !== "") {
|
||||||
|
newActionList.push({
|
||||||
|
type: "Runtime Argument",
|
||||||
|
name: "Runtime Argument",
|
||||||
|
highlight: "exec",
|
||||||
|
autocomplete: "exec",
|
||||||
|
|
||||||
|
value: foundvalue,
|
||||||
|
example: foundvalue,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add default Runtime Argument if none were added
|
// Add default Runtime Argument if none were added
|
||||||
@@ -788,6 +805,8 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
labels.push(parentNode.label);
|
labels.push(parentNode.label);
|
||||||
|
|
||||||
|
var secondaryExample = ""
|
||||||
let exampleData = parentNode.example ?? "";
|
let exampleData = parentNode.example ?? "";
|
||||||
if (parentNode?.app_name === "http") {
|
if (parentNode?.app_name === "http") {
|
||||||
exampleData = ""
|
exampleData = ""
|
||||||
@@ -798,9 +817,13 @@ const ParsedAction = (props) => {
|
|||||||
const foundResult = exec.results?.find(result => result?.action?.id === parentNode?.id);
|
const foundResult = exec.results?.find(result => result?.action?.id === parentNode?.id);
|
||||||
if (foundResult) {
|
if (foundResult) {
|
||||||
const valid = validateJson(foundResult.result);
|
const valid = validateJson(foundResult.result);
|
||||||
if (valid.valid && valid.result.success !== false) {
|
if (valid.valid) {
|
||||||
exampleData = valid.result
|
if (valid.result.success !== false) {
|
||||||
break
|
exampleData = valid.result
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
secondaryExample = foundResult.result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -834,6 +857,10 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exampleData === "" && secondaryExample !== "") {
|
||||||
|
exampleData = secondaryExample
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentNode.label === undefined) {
|
if (parentNode.label === undefined) {
|
||||||
@@ -1178,7 +1205,9 @@ const ParsedAction = (props) => {
|
|||||||
selectedAction.parameters[1].value = splitparsed[1]
|
selectedAction.parameters[1].value = splitparsed[1]
|
||||||
|
|
||||||
if (splitparsed.length > 2) {
|
if (splitparsed.length > 2) {
|
||||||
toast.warn("Filter list only supports filtering at the first level. If you want multi-level filtering, please use the 'execute python' action with the 'filter a list' function in the code editor.")
|
toast.warn("Filter list only supports filtering on the first list. If you want multi-level filtering, please use the 'execute python' action with the 'filter a list' function in the code editor.", {
|
||||||
|
autoClose: 10000,
|
||||||
|
})
|
||||||
} else if (selectedAction.parameters[1].value.includes(".#")) {
|
} else if (selectedAction.parameters[1].value.includes(".#")) {
|
||||||
toast.warn("This filter may not work due to using .# indexing. Please use the 'execute python' action and try the 'filter a list' function in the code editor.")
|
toast.warn("This filter may not work due to using .# indexing. Please use the 'execute python' action and try the 'filter a list' function in the code editor.")
|
||||||
}
|
}
|
||||||
@@ -1830,28 +1859,37 @@ const ParsedAction = (props) => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<Button
|
<Tooltip
|
||||||
color="secondary"
|
title={
|
||||||
variant="outlined"
|
<Typography variant="body2" style={{margin: 3, }}>
|
||||||
style={{
|
Rerun this action with results from previous executions. Built for testing individual actions in the middle of workflows.
|
||||||
marginTop: "auto",
|
</Typography>
|
||||||
marginBottom: "auto",
|
}
|
||||||
height: 30,
|
placement="top"
|
||||||
marginLeft: 115,
|
|
||||||
textTransform: "none",
|
|
||||||
}}
|
|
||||||
disabled={autoCompleting}
|
|
||||||
onClick={() => {
|
|
||||||
if (runFromHere !== undefined) {
|
|
||||||
runFromHere(selectedAction)
|
|
||||||
} else {
|
|
||||||
toast.error("Function not available. Please contact support@shuffler.io")
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<PlayArrowIcon style={{marginRight: 5, }}/>
|
<Button
|
||||||
Rerun
|
color="secondary"
|
||||||
</Button>
|
variant="outlined"
|
||||||
|
style={{
|
||||||
|
marginTop: "auto",
|
||||||
|
marginBottom: "auto",
|
||||||
|
height: 30,
|
||||||
|
marginLeft: 115,
|
||||||
|
textTransform: "none",
|
||||||
|
}}
|
||||||
|
disabled={autoCompleting}
|
||||||
|
onClick={() => {
|
||||||
|
if (runFromHere !== undefined) {
|
||||||
|
runFromHere(selectedAction)
|
||||||
|
} else {
|
||||||
|
toast.error("Function not available. Please contact support@shuffler.io")
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<PlayArrowIcon style={{marginRight: 5, }}/>
|
||||||
|
Rerun
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
{(selectedAction?.generated === true && selectedAction?.app_version === "1.0.0") || (selectedAction?.app_name === "Shuffle Tools" && selectedAction?.app_version !== "1.2.0") ?
|
{(selectedAction?.generated === true && selectedAction?.app_version === "1.0.0") || (selectedAction?.app_name === "Shuffle Tools" && selectedAction?.app_version !== "1.2.0") ?
|
||||||
<Button
|
<Button
|
||||||
@@ -4561,6 +4599,7 @@ const ParsedAction = (props) => {
|
|||||||
minWidth: 250,
|
minWidth: 250,
|
||||||
maxWidth: 250,
|
maxWidth: 250,
|
||||||
marginRight: 0,
|
marginRight: 0,
|
||||||
|
paddingLeft: 12,
|
||||||
}}
|
}}
|
||||||
value={innerdata}
|
value={innerdata}
|
||||||
onMouseOver={() => handleMouseover()}
|
onMouseOver={() => handleMouseover()}
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ const TenantsTab = memo((props) => {
|
|||||||
const [cloudSyncModalOpen, setCloudSyncModalOpen] = React.useState(false);
|
const [cloudSyncModalOpen, setCloudSyncModalOpen] = React.useState(false);
|
||||||
const [modalOpen, setModalOpen] = React.useState(false);
|
const [modalOpen, setModalOpen] = React.useState(false);
|
||||||
const [parentOrg, setParentOrg] = React.useState(null);
|
const [parentOrg, setParentOrg] = React.useState(null);
|
||||||
const [parentOrgFlag, setParentOrgFlag] = React.useState(null);
|
const [parentOrgFlag, setParentOrgFlag] = React.useState("gb");
|
||||||
|
const [parentOrgRegionName, setParentOrgRegionName] = React.useState("UK");
|
||||||
const [loadOrgs, setLoadOrgs] = React.useState(true);
|
const [loadOrgs, setLoadOrgs] = React.useState(true);
|
||||||
const [, forceUpdate] = React.useState();
|
const [, forceUpdate] = React.useState();
|
||||||
const itemColor = "black";
|
const itemColor = "black";
|
||||||
@@ -82,9 +83,10 @@ const TenantsTab = memo((props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
setParentOrgFlag(regionCode);
|
setParentOrgFlag(regionCode);
|
||||||
|
setParentOrgRegionName(regiontag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [parentOrg]);
|
}, [parentOrg, parentOrgFlag]);
|
||||||
|
|
||||||
var syncList = [
|
var syncList = [
|
||||||
{
|
{
|
||||||
@@ -164,7 +166,8 @@ const TenantsTab = memo((props) => {
|
|||||||
regionCode = "ca";
|
regionCode = "ca";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setParentOrgFlag(regionCode);
|
setParentOrgFlag(regionCode);
|
||||||
|
setParentOrgRegionName(regiontag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1026,7 +1029,7 @@ const TenantsTab = memo((props) => {
|
|||||||
src={`https://flagcdn.com/w20/${parentOrgFlag}.png`}
|
src={`https://flagcdn.com/w20/${parentOrgFlag}.png`}
|
||||||
style={{ width: "30px", height: "20px", marginRight: "5px" }}
|
style={{ width: "30px", height: "20px", marginRight: "5px" }}
|
||||||
/>
|
/>
|
||||||
<ListItemText primary={parentOrgFlag?.toUpperCase()} />
|
<ListItemText primary={parentOrgRegionName?.toUpperCase()} />
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
style={{ display: "table-cell", padding: 8, verticalAlign: "middle" }}
|
style={{ display: "table-cell", padding: 8, verticalAlign: "middle" }}
|
||||||
|
|||||||
@@ -248,6 +248,14 @@ const UserManagmentTab = memo((props) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.target.value.includes("ALL")) {
|
||||||
|
toast.info("Adding to available all sub-organizations. This may take a minute.")
|
||||||
|
event.target.value = selectedOrganization.child_orgs.map((org) => org.id)
|
||||||
|
} else if (event.target.value.includes("None")) {
|
||||||
|
toast.info("Removing from all sub-organizations. This may take a minute")
|
||||||
|
event.target.value = []
|
||||||
|
}
|
||||||
|
|
||||||
console.log("event: ", event.target.value);
|
console.log("event: ", event.target.value);
|
||||||
setMatchingOrganizations(event.target.value);
|
setMatchingOrganizations(event.target.value);
|
||||||
// Workaround for empty orgs
|
// Workaround for empty orgs
|
||||||
@@ -286,6 +294,14 @@ const UserManagmentTab = memo((props) => {
|
|||||||
}}
|
}}
|
||||||
MenuProps={MenuProps}
|
MenuProps={MenuProps}
|
||||||
>
|
>
|
||||||
|
<MenuItem key={-2} value={"None"}>
|
||||||
|
<Checkbox checked={false} />
|
||||||
|
<ListItemText primary={"None"} />
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key={-1} value={"ALL"}>
|
||||||
|
<Checkbox checked={false} />
|
||||||
|
<ListItemText primary={"ALL"} />
|
||||||
|
</MenuItem>
|
||||||
{selectedOrganization.child_orgs.map((org, index) => (
|
{selectedOrganization.child_orgs.map((org, index) => (
|
||||||
<MenuItem key={index} value={org.id}>
|
<MenuItem key={index} value={org.id}>
|
||||||
<Checkbox checked={matchingOrganizations.indexOf(org.id) > -1} />
|
<Checkbox checked={matchingOrganizations.indexOf(org.id) > -1} />
|
||||||
|
|||||||
@@ -608,8 +608,6 @@ const WorkflowValidationTimeline = (props) => {
|
|||||||
const ballsize = 8
|
const ballsize = 8
|
||||||
const topMargin = 20
|
const topMargin = 20
|
||||||
|
|
||||||
console.log("CHIP: ", index, chipColor, chipBackground)
|
|
||||||
|
|
||||||
const chipStyle = {
|
const chipStyle = {
|
||||||
height: 40,
|
height: 40,
|
||||||
minWidth: 125,
|
minWidth: 125,
|
||||||
|
|||||||
@@ -76,6 +76,18 @@ const Admin2 = (props) => {
|
|||||||
leads.push("tech partner");
|
leads.push("tech partner");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (responseJson.lead_info.integration_partner) {
|
||||||
|
leads.push("integration partner");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseJson.lead_info.distribution_partner) {
|
||||||
|
leads.push("distribution partner");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseJson.lead_info.service_partner) {
|
||||||
|
leads.push("service partner");
|
||||||
|
}
|
||||||
|
|
||||||
if (responseJson.lead_info.creator) {
|
if (responseJson.lead_info.creator) {
|
||||||
leads.push("creator");
|
leads.push("creator");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -475,6 +475,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const [authGroups, setAuthGroups] = React.useState([])
|
const [authGroups, setAuthGroups] = React.useState([])
|
||||||
|
|
||||||
const curpath = typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname;
|
const curpath = typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname;
|
||||||
|
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
||||||
|
|
||||||
|
|
||||||
// 0 = normal, 1 = just done, 2 = normal
|
// 0 = normal, 1 = just done, 2 = normal
|
||||||
@@ -913,7 +914,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Found app, but no actions: ", foundapp)
|
//console.log("Found app, but no actions: ", foundapp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cy !== undefined && cy !== null) {
|
if (cy !== undefined && cy !== null) {
|
||||||
@@ -1794,7 +1795,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const newkeys = sortByKey(responseJson.executions, "-started_at");
|
const newkeys = sortByKey(responseJson.executions, "-started_at");
|
||||||
setWorkflowExecutions(newkeys);
|
setWorkflowExecutions(newkeys);
|
||||||
|
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
||||||
if (execution_id !== undefined && execution_id !== null && execution_id.length > 0 && (tmpView === undefined || tmpView === null || tmpView.length === 0)) {
|
if (execution_id !== undefined && execution_id !== null && execution_id.length > 0 && (tmpView === undefined || tmpView === null || tmpView.length === 0)) {
|
||||||
tmpView = execution_id;
|
tmpView = execution_id;
|
||||||
@@ -1850,7 +1850,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
var tmpView = new URLSearchParams(cursearch).get("execution_id");
|
||||||
if (tmpView === undefined || tmpView === null || tmpView.length === 0) {
|
if (tmpView === undefined || tmpView === null || tmpView.length === 0) {
|
||||||
const execution_id = tmpView;
|
const execution_id = tmpView;
|
||||||
@@ -1893,7 +1892,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
//toast("Failed loading the workflow run")
|
//toast("Failed loading the workflow run")
|
||||||
console.log("Status not 200 for stream results :O!");
|
console.log("Status not 200 for stream results :O!");
|
||||||
|
|
||||||
//const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
//const newitem = removeParam("execution_id", cursearch);
|
//const newitem = removeParam("execution_id", cursearch);
|
||||||
//navigate(curpath + newitem)
|
//navigate(curpath + newitem)
|
||||||
}
|
}
|
||||||
@@ -2821,9 +2819,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Based on the previous execution id
|
// Based on the previous execution id
|
||||||
console.log("WORKFLOW EXEC: ", workflowExecutions)
|
|
||||||
// Look for the "execution_id" parameter
|
// Look for the "execution_id" parameter
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
const execFound = new URLSearchParams(cursearch).get("execution_id");
|
const execFound = new URLSearchParams(cursearch).get("execution_id");
|
||||||
if (execFound !== undefined && execFound !== null && execFound.length > 0) {
|
if (execFound !== undefined && execFound !== null && execFound.length > 0) {
|
||||||
toast.info("Rerunning based on previously watched execution id")
|
toast.info("Rerunning based on previously watched execution id")
|
||||||
@@ -2878,7 +2874,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
return
|
return
|
||||||
} else if (responseJson?.success === true && responseJson?.execution_id !== undefined && responseJson?.execution_id !== null && responseJson?.execution_id.length > 0) {
|
} else if (responseJson?.success === true && responseJson?.execution_id !== undefined && responseJson?.execution_id !== null && responseJson?.execution_id.length > 0) {
|
||||||
navigate(`?execution_id=${responseJson.execution_id}`)
|
navigate(`?execution_id=${responseJson.execution_id}&node=${curAction.id}&rerun=true`)
|
||||||
setExecutionRequest({
|
setExecutionRequest({
|
||||||
execution_id: responseJson.execution_id,
|
execution_id: responseJson.execution_id,
|
||||||
authorization: responseJson.authorization,
|
authorization: responseJson.authorization,
|
||||||
@@ -4316,7 +4312,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
// Check for execution_id in URL
|
// Check for execution_id in URL
|
||||||
// don't redirect if it exists
|
// don't redirect if it exists
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
var execFound = new URLSearchParams(cursearch).get("execution_id");
|
var execFound = new URLSearchParams(cursearch).get("execution_id");
|
||||||
var sessionToken = new URLSearchParams(cursearch).get("session_token");
|
var sessionToken = new URLSearchParams(cursearch).get("session_token");
|
||||||
if (execFound === null && sessionToken === null) {
|
if (execFound === null && sessionToken === null) {
|
||||||
@@ -4978,7 +4973,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule" || nodedata.app_name === "Gmail" || nodedata.app_name === "Office365") {
|
if (nodedata.app_name === "Webhook" || nodedata.app_name === "Schedule") {
|
||||||
if (!found) {
|
if (!found) {
|
||||||
//console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
//console.log("Find amount of executions for the specific nodetype: ", nodedata.app_name, "Executions: ", workflowExecutions)
|
||||||
// Find how many executions it has
|
// Find how many executions it has
|
||||||
@@ -5007,6 +5002,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Readding the icon after moving the node
|
// Readding the icon after moving the node
|
||||||
|
/*
|
||||||
if (!found) {
|
if (!found) {
|
||||||
const iconInfo = GetIconInfo(nodedata);
|
const iconInfo = GetIconInfo(nodedata);
|
||||||
const svg_pin = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
|
const svg_pin = `<svg width="${svgSize}" height="${svgSize}" viewBox="0 0 ${svgSize} ${svgSize}" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="${iconInfo.icon}" fill="${iconInfo.iconColor}"></path></svg>`;
|
||||||
@@ -5034,6 +5030,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
} else {
|
} else {
|
||||||
//console.log("Node already exists - don't add descriptor node");
|
//console.log("Node already exists - don't add descriptor node");
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7636,25 +7633,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 86:
|
case 86:
|
||||||
if (event.ctrlKey) {
|
console.log("CTRL+V? ctrl: ", event.ctrlKey)
|
||||||
//console.log("CTRL+V")
|
if (event.ctrlKey) {
|
||||||
// The below parts are handled in the function handlePaste()
|
// Paste is handled in the handlePaste() function.
|
||||||
/*
|
|
||||||
const clipboard = navigator.clipboard
|
|
||||||
if (clipboard === undefined || window === undefined || window === null) {
|
|
||||||
toast("Can only use cliboard over HTTPS (port 3443)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("CLIPBOARD: ", window.clipboardData)
|
|
||||||
const pastedData = window.clipboardData.getData('Text');
|
|
||||||
console.log("PASTED: ", pastedData)
|
|
||||||
|
|
||||||
|
|
||||||
//var tmpAuth = JSON.parse(JSON.stringify(appAuthentication))
|
|
||||||
var jsonvalid = true
|
|
||||||
var parsedjson = []
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 88:
|
case 88:
|
||||||
@@ -7678,30 +7659,28 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handlePaste = (event) => {
|
const handlePaste = (event) => {
|
||||||
if (
|
console.log("PASTE EVENT: ", event)
|
||||||
event.path !== undefined &&
|
if (event.path !== undefined && event.path !== null && event.path.length > 0) {
|
||||||
event.path !== null &&
|
|
||||||
event.path.length > 0
|
|
||||||
) {
|
|
||||||
if (event.path[0].localName !== "body") {
|
if (event.path[0].localName !== "body") {
|
||||||
return;
|
console.log("Skipping paste because body is not targeted")
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
console.log("Paste target: ", event?.target)
|
||||||
event.target !== undefined &&
|
/*
|
||||||
event.target !== null
|
if (event.target !== undefined && event.target !== null) {
|
||||||
) {
|
|
||||||
if (event.target.localName !== "body") {
|
if (event.target.localName !== "body") {
|
||||||
|
console.log("Skipping paste because body is not targeted (2). Target: ", event?.target?.localName)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Does this stop things?
|
||||||
event.preventDefault();
|
//event.preventDefault()
|
||||||
const clipboard = (event.originalEvent || event).clipboardData.getData(
|
const clipboard = (event.originalEvent || event).clipboardData.getData("text/plain")
|
||||||
"text/plain"
|
console.log("CLIPBOARD TO PASTE: ", clipboard)
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const allnodes = cy.nodes().jsons()
|
const allnodes = cy.nodes().jsons()
|
||||||
@@ -9710,8 +9689,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setLeftSideBarOpenByClick(false)
|
setLeftSideBarOpenByClick(false)
|
||||||
localStorage.setItem("expandLeftNav", false)
|
localStorage.setItem("expandLeftNav", false)
|
||||||
|
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
|
|
||||||
// FIXME: Don't check specific one here
|
// FIXME: Don't check specific one here
|
||||||
const tmpExec = new URLSearchParams(cursearch).get("execution_highlight");
|
const tmpExec = new URLSearchParams(cursearch).get("execution_highlight");
|
||||||
if (
|
if (
|
||||||
@@ -11553,7 +11530,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const positionInfo = document.activeElement.getBoundingClientRect()
|
const positionInfo = document.activeElement.getBoundingClientRect()
|
||||||
const outerlistitemStyle = {
|
const outerlistitemStyle = {
|
||||||
width: "100%",
|
width: "90%",
|
||||||
overflowX: "hidden",
|
overflowX: "hidden",
|
||||||
overflowY: "hidden",
|
overflowY: "hidden",
|
||||||
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
borderBottom: "1px solid rgba(255,255,255,0.4)",
|
||||||
@@ -15106,28 +15083,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
<b>Select a workflow to run</b>
|
<b>Select a workflow to run</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workflow.triggers[selectedTriggerIndex].parameters[0].value
|
|
||||||
.length === 0 ? null : workflow.triggers[selectedTriggerIndex]
|
|
||||||
.parameters[0].value === props.match.params.key ?
|
|
||||||
null
|
|
||||||
: (
|
|
||||||
<div style={{ marginLeft: 5, flex: 1 }}>
|
|
||||||
<a
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href={`/workflows/${workflow.triggers[selectedTriggerIndex].parameters[0].value}`}
|
|
||||||
target="_blank"
|
|
||||||
style={{
|
|
||||||
textDecoration: "none",
|
|
||||||
color: "#FF8544",
|
|
||||||
marginLeft: 5,
|
|
||||||
marginTop: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<OpenInNewIcon />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workflows === undefined ||
|
{workflows === undefined ||
|
||||||
@@ -15239,13 +15194,36 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
renderInput={(params) => {
|
renderInput={(params) => {
|
||||||
return (
|
return (
|
||||||
<TextField
|
<div style={{ display: "flex", }}>
|
||||||
style={theme.palette.textFieldStyle}
|
<TextField
|
||||||
{...params}
|
style={theme.palette.textFieldStyle}
|
||||||
label="Find your workflow"
|
{...params}
|
||||||
variant="outlined"
|
label="Find your workflow"
|
||||||
/>
|
variant="outlined"
|
||||||
);
|
/>
|
||||||
|
{workflow.triggers[selectedTriggerIndex].parameters[0].value
|
||||||
|
.length === 0 ? null : workflow.triggers[selectedTriggerIndex]
|
||||||
|
.parameters[0].value === props.match.params.key ?
|
||||||
|
null
|
||||||
|
: (
|
||||||
|
<div style={{ marginLeft: 5, }}>
|
||||||
|
<a
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={`/workflows/${workflow.triggers[selectedTriggerIndex].parameters[0].value}`}
|
||||||
|
target="_blank"
|
||||||
|
style={{
|
||||||
|
textDecoration: "none",
|
||||||
|
color: "#FF8544",
|
||||||
|
marginLeft: 5,
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<OpenInNewIcon />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -17465,12 +17443,32 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
renderInput={(params) => {
|
renderInput={(params) => {
|
||||||
return (
|
return (
|
||||||
<TextField
|
<div style={{display: "flex", }}>
|
||||||
style={theme.palette.textFieldStyle}
|
<TextField
|
||||||
{...params}
|
style={theme.palette.textFieldStyle}
|
||||||
label="Find the workflow you want to trigger"
|
{...params}
|
||||||
variant="outlined"
|
label="Find the workflow you want to trigger"
|
||||||
/>
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{subworkflow === null || subworkflow === undefined || subworkflow?.id === undefined || subworkflow?.id === null || subworkflow?.id.length === 0 ? null :
|
||||||
|
<Tooltip title="Show subflow in new window" placement="top">
|
||||||
|
<a
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={`/workflows/${subworkflow.id}`}
|
||||||
|
target="_blank"
|
||||||
|
style={{
|
||||||
|
textDecoration: "none",
|
||||||
|
color: "#FF8544",
|
||||||
|
marginLeft: 5,
|
||||||
|
marginTop: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<OpenInNewIcon />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -17542,7 +17540,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow?.triggers[selectedTriggerIndex].parameters[2] &&
|
workflow?.triggers[selectedTriggerIndex].parameters[2] &&
|
||||||
workflow?.triggers[selectedTriggerIndex].parameters[2].value &&
|
workflow?.triggers[selectedTriggerIndex].parameters[2].value &&
|
||||||
(
|
(
|
||||||
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ||
|
|
||||||
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("sms")
|
workflow?.triggers[selectedTriggerIndex].parameters[2].value.includes("sms")
|
||||||
) ? (
|
) ? (
|
||||||
<TextField
|
<TextField
|
||||||
@@ -19306,7 +19303,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (!workflow.public && executionModalOpen) {
|
if (!workflow.public && executionModalOpen) {
|
||||||
setExecutionRunning(false);
|
setExecutionRunning(false);
|
||||||
stop()
|
stop()
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
const newitem = removeParam("execution_id", cursearch);
|
const newitem = removeParam("execution_id", cursearch);
|
||||||
navigate(curpath + newitem)
|
navigate(curpath + newitem)
|
||||||
setExecutionModalView(0);
|
setExecutionModalView(0);
|
||||||
@@ -19359,7 +19355,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (!workflow.public && executionModalOpen) {
|
if (!workflow.public && executionModalOpen) {
|
||||||
setExecutionRunning(false);
|
setExecutionRunning(false);
|
||||||
stop()
|
stop()
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
const newitem = removeParam("execution_id", cursearch);
|
const newitem = removeParam("execution_id", cursearch);
|
||||||
navigate(curpath + newitem)
|
navigate(curpath + newitem)
|
||||||
setExecutionModalView(0);
|
setExecutionModalView(0);
|
||||||
@@ -20424,7 +20419,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
>
|
>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title="Expand result window"
|
title="Expand debug window"
|
||||||
placement="top"
|
placement="top"
|
||||||
style={{ zIndex: 10011 }}
|
style={{ zIndex: 10011 }}
|
||||||
>
|
>
|
||||||
@@ -20930,6 +20925,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const envStatus = !(executionData.workflow !== undefined && executionData.workflow !== null && executionData.workflow.actions !== undefined && executionData.workflow.actions !== null && executionData.workflow.actions.length > 0) ? "loading" : "success"
|
const envStatus = !(executionData.workflow !== undefined && executionData.workflow !== null && executionData.workflow.actions !== undefined && executionData.workflow.actions !== null && executionData.workflow.actions.length > 0) ? "loading" : "success"
|
||||||
|
|
||||||
var executionDelay = -75
|
var executionDelay = -75
|
||||||
|
|
||||||
const executionModal = (
|
const executionModal = (
|
||||||
<Drawer
|
<Drawer
|
||||||
anchor={"right"}
|
anchor={"right"}
|
||||||
@@ -20937,7 +20933,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
setExecutionModalOpen(false)
|
setExecutionModalOpen(false)
|
||||||
|
|
||||||
//const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
//const newitem = removeParam("execution_id", cursearch);
|
//const newitem = removeParam("execution_id", cursearch);
|
||||||
//navigate(curpath + newitem)
|
//navigate(curpath + newitem)
|
||||||
}}
|
}}
|
||||||
@@ -21369,7 +21364,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
<h2
|
<h2
|
||||||
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
|
style={{ color: "rgba(255,255,255,0.5)", cursor: "pointer" }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
const newitem = removeParam("execution_id", cursearch);
|
const newitem = removeParam("execution_id", cursearch);
|
||||||
navigate(curpath + newitem)
|
navigate(curpath + newitem)
|
||||||
setExecutionRunning(false);
|
setExecutionRunning(false);
|
||||||
@@ -21397,7 +21391,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
Rerun workflow. Uses same startnode as the original. Runs from scratch.
|
Rerun workflow. Uses same startnode as the original. Runs from scratch.
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
placement="top"
|
placement="left"
|
||||||
style={{ zIndex: 50000 }}
|
style={{ zIndex: 50000 }}
|
||||||
>
|
>
|
||||||
<span style={{}}>
|
<span style={{}}>
|
||||||
@@ -21752,6 +21746,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<div style={{ display: "flex", marginTop: 10, marginBottom: 30 }}>
|
<div style={{ display: "flex", marginTop: 10, marginBottom: 30 }}>
|
||||||
<div>
|
<div>
|
||||||
{executionData.status !== undefined &&
|
{executionData.status !== undefined &&
|
||||||
@@ -21774,6 +21769,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
executionData.results === undefined ||
|
executionData.results === undefined ||
|
||||||
executionData.results === null ||
|
executionData.results === null ||
|
||||||
@@ -21794,6 +21790,14 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const showRerun = new URLSearchParams(cursearch).get("rerun")
|
||||||
|
if (showRerun === "true") {
|
||||||
|
const showNode = new URLSearchParams(cursearch).get("node")
|
||||||
|
if (data.action.id !== showNode) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: The latter replace doens't really work if ' is used in a string
|
// FIXME: The latter replace doens't really work if ' is used in a string
|
||||||
var showResult = data.result.trim();
|
var showResult = data.result.trim();
|
||||||
const validate = validateJson(showResult);
|
const validate = validateJson(showResult);
|
||||||
@@ -21873,10 +21877,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action.app_name === "User Input") {
|
if (data?.action?.app_name === "User Input" || data?.action?.name === "run_userinput") {
|
||||||
actionimg = (
|
actionimg = (
|
||||||
<img
|
<img
|
||||||
alt={"Shuffle Subflow"}
|
alt={"User Input Trigger"}
|
||||||
src={triggers[4].large_image}
|
src={triggers[4].large_image}
|
||||||
style={{
|
style={{
|
||||||
marginRight: 20,
|
marginRight: 20,
|
||||||
@@ -21987,7 +21991,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cursearch = typeof window === "undefined" || window.location === undefined ? "" : window.location.search;
|
|
||||||
const chosenNodeId = new URLSearchParams(cursearch).get("node");
|
const chosenNodeId = new URLSearchParams(cursearch).get("node");
|
||||||
const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id
|
const highlightNode = chosenNodeId !== null && chosenNodeId !== undefined && chosenNodeId !== "" && chosenNodeId === data.action.id
|
||||||
var relevant_errors = []
|
var relevant_errors = []
|
||||||
@@ -22081,7 +22084,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
color="primary"
|
color="primary"
|
||||||
title={
|
title={
|
||||||
<Typography variant="body1">
|
<Typography variant="body1">
|
||||||
Expand result window. Errors: {relevant_errors.length}
|
Expand debug window. Errors: {relevant_errors.length}
|
||||||
</Typography>
|
</Typography>
|
||||||
}
|
}
|
||||||
placement="top"
|
placement="top"
|
||||||
@@ -22720,7 +22723,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
{curapp === null ? null : (
|
{curapp === null ? null : (
|
||||||
<img
|
<img
|
||||||
alt={selectedResult.action.app_name}
|
alt={selectedResult.action.app_name}
|
||||||
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult.action.app_name === "shuffle-subflow" ? triggers[3].large_image : selectedResult.action.app_name === "User Input" ? triggers[4].large_image : selectedResult.action !== undefined && selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp !== undefined ? curapp.large_image : theme.palette.defaultImage}
|
src={selectedResult === undefined ? theme.palette.defaultImage : selectedResult?.action?.name === "run_userinput" ? triggers[4].large_image : selectedResult.action.app_name === "shuffle-subflow" ? triggers[3].large_image : selectedResult.action !== undefined && selectedResult.action.large_image !== undefined && selectedResult.action.large_image !== null && selectedResult.action.large_image !== "" ? selectedResult.action.large_image : curapp !== undefined ? curapp.large_image : theme.palette.defaultImage}
|
||||||
style={{
|
style={{
|
||||||
marginRight: 20,
|
marginRight: 20,
|
||||||
width: imgsize,
|
width: imgsize,
|
||||||
@@ -23485,11 +23488,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// Automatically mapping fields that already exist (predefined).
|
// Automatically mapping fields that already exist (predefined).
|
||||||
// Warning if fields are NOT filled
|
// Warning if fields are NOT filled
|
||||||
for (let paramkey in selectedApp.authentication.parameters) {
|
for (let paramkey in selectedApp.authentication.parameters) {
|
||||||
if (
|
if (authenticationOption.fields[selectedApp.authentication.parameters[paramkey].name].length === 0) {
|
||||||
authenticationOption.fields[
|
|
||||||
selectedApp.authentication.parameters[paramkey].name
|
|
||||||
].length === 0
|
|
||||||
) {
|
|
||||||
if (
|
if (
|
||||||
selectedApp.authentication.parameters[paramkey].value !== undefined &&
|
selectedApp.authentication.parameters[paramkey].value !== undefined &&
|
||||||
selectedApp.authentication.parameters[paramkey].value !== null &&
|
selectedApp.authentication.parameters[paramkey].value !== null &&
|
||||||
@@ -23538,8 +23538,30 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
|
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
|
||||||
var newFields = [];
|
var newFields = [];
|
||||||
|
|
||||||
|
var warningsent = false
|
||||||
for (let authkey in newAuthOption.fields) {
|
for (let authkey in newAuthOption.fields) {
|
||||||
const value = newAuthOption.fields[authkey];
|
var value = newAuthOption.fields[authkey];
|
||||||
|
|
||||||
|
if (value?.toLowerCase().includes("secret. replace")) {
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
if (authkey === "url") {
|
||||||
|
// Use default value of the url
|
||||||
|
const urlparam = selectedApp.authentication.parameters.find((data) => data.name === "url")
|
||||||
|
if (urlparam !== undefined && urlparam !== null) {
|
||||||
|
if (urlparam.example !== undefined && urlparam.example !== null && urlparam.example.length > 0) {
|
||||||
|
value = urlparam.example
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!warningsent) {
|
||||||
|
warningsent = true
|
||||||
|
toast("Warning: As you didn't fill in all fields, be aware that the authentication may fail.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newFields.push({
|
newFields.push({
|
||||||
"key": authkey,
|
"key": authkey,
|
||||||
"value": value,
|
"value": value,
|
||||||
@@ -23692,18 +23714,18 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
type={
|
type={
|
||||||
data.example !== undefined && data.example.includes("***")
|
data.example !== undefined && data.example.includes("**")
|
||||||
? "password"
|
? "password"
|
||||||
: "text"
|
: "text"
|
||||||
}
|
}
|
||||||
color="primary"
|
color="primary"
|
||||||
defaultValue={
|
defaultValue={
|
||||||
data.value !== undefined && data.value !== null && !data.value.includes("Secret. Replace") ? data.value : ""
|
data.value !== undefined && data.value !== null && !data.value.includes("Secret. Replace") ? data.value :
|
||||||
|
data?.example !== undefined && data?.example !== null && data?.example !== "" && !data?.example.includes("*") ? data.example : ""
|
||||||
}
|
}
|
||||||
placeholder={data.example}
|
placeholder={data.example}
|
||||||
onChange={(event) => {
|
onChange={(event) => {
|
||||||
authenticationOption.fields[data.name] =
|
authenticationOption.fields[data.name] = event.target.value;
|
||||||
event.target.value;
|
|
||||||
}}
|
}}
|
||||||
id={`${data.name}_auth`}
|
id={`${data.name}_auth`}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import RecentWorkflow from "../components/RecentWorkflow.jsx";
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
Fade,
|
||||||
Select,
|
Select,
|
||||||
IconButton,
|
IconButton,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
@@ -462,6 +463,8 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
} else {
|
} else {
|
||||||
console.log("Started execution")
|
console.log("Started execution")
|
||||||
|
|
||||||
|
start()
|
||||||
|
setExecutionRunning(true);
|
||||||
if (answer !== undefined && answer !== null) {
|
if (answer !== undefined && answer !== null) {
|
||||||
console.log("Skipping start")
|
console.log("Skipping start")
|
||||||
} else {
|
} else {
|
||||||
@@ -1055,7 +1058,7 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
if (parsedresult.click_info !== undefined && parsedresult.click_info !== null) {
|
if (parsedresult.click_info !== undefined && parsedresult.click_info !== null) {
|
||||||
if (parsedresult.click_info.user !== undefined && parsedresult.click_info.user !== null && parsedresult.click_info.user.length > 0) {
|
if (parsedresult.click_info.user !== undefined && parsedresult.click_info.user !== null && parsedresult.click_info.user.length > 0) {
|
||||||
setMessage("Already answered by " + parsedresult.click_info.user)
|
setMessage("Answered by " + parsedresult.click_info.user)
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -1325,7 +1328,8 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
answer !== undefined && answer !== null ? null :
|
(answer !== undefined && answer !== null) || message !== "" ? null :
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
Runtime Argument
|
Runtime Argument
|
||||||
<div style={{marginBottom: 5}}>
|
<div style={{marginBottom: 5}}>
|
||||||
@@ -1334,7 +1338,13 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
style={{backgroundColor: theme.palette.inputColor, marginTop: 5, }}
|
style={{backgroundColor: theme.palette.inputColor, marginTop: 5, }}
|
||||||
multiLine
|
multiLine
|
||||||
maxRows={2}
|
maxRows={2}
|
||||||
|
type="text"
|
||||||
|
autoComplete="off"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
|
autocomplete: "off",
|
||||||
|
form: {
|
||||||
|
autocomplete: "off",
|
||||||
|
},
|
||||||
style:{
|
style:{
|
||||||
height: "50px",
|
height: "50px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -1375,9 +1385,11 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
{message}. You may close this window.
|
{message}. You may close this window.
|
||||||
</Typography>
|
</Typography>
|
||||||
:
|
:
|
||||||
<Typography variant="body1" style={{textAlign: "center", marginTop: 30, marginBottom: 20, }}>
|
<Fade in={true} timeout={2500}>
|
||||||
{disabledButtons ? "Answered. You may close this window." : ""}
|
<Typography variant="body1" style={{textAlign: "center", marginTop: 30, marginBottom: 20, }}>
|
||||||
</Typography>
|
{disabledButtons ? "Answered. You may close this window." : ""}
|
||||||
|
</Typography>
|
||||||
|
</Fade>
|
||||||
}
|
}
|
||||||
|
|
||||||
{disabledButtons ? null :
|
{disabledButtons ? null :
|
||||||
@@ -1387,14 +1399,22 @@ const RunWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<div fullWidth style={{width: "100%", marginTop: 10, marginBottom: 10, display: "flex", }}>
|
<div fullWidth style={{width: "100%", marginTop: 10, marginBottom: 10, display: "flex", }}>
|
||||||
<Button fullWidth id="continue_execution" variant="contained" disabled={!handleValidateForm(executionArgument) || disabledButtons} color="primary" style={{flex: 1,}} onClick={() => {
|
<Button
|
||||||
setButtonClicked("FINISHED")
|
fullWidth
|
||||||
setExecutionData({
|
id="continue_execution"
|
||||||
status: "FINISHED",
|
variant="contained"
|
||||||
})
|
disabled={!handleValidateForm(executionArgument) || disabledButtons}
|
||||||
|
color="primary"
|
||||||
|
style={{flex: 1,}}
|
||||||
|
onClick={() => {
|
||||||
|
setButtonClicked("FINISHED")
|
||||||
|
setExecutionData({
|
||||||
|
status: "FINISHED",
|
||||||
|
})
|
||||||
|
|
||||||
onSubmit(null, execution_id, authorization, true)
|
onSubmit(null, execution_id, authorization, true)
|
||||||
}}>Continue</Button>
|
}}>
|
||||||
|
Continue</Button>
|
||||||
<Typography variant="body1" style={{marginLeft: 3, marginRight: 3, marginTop: 3, }}>
|
<Typography variant="body1" style={{marginLeft: 3, marginRight: 3, marginTop: 3, }}>
|
||||||
or
|
or
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -661,7 +661,7 @@ const Workflows2 = (props) => {
|
|||||||
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1);
|
const [mouseHoverIndex, setMouseHoverIndex] = useState(-1);
|
||||||
const [isLoadingWorkflow, setIsLoadingWorkflow] = useState(false);
|
const [isLoadingWorkflow, setIsLoadingWorkflow] = useState(false);
|
||||||
const [isLoadingPublicWorkflow, setIsLoadingPublicWorkflow] = useState(false);
|
const [isLoadingPublicWorkflow, setIsLoadingPublicWorkflow] = useState(false);
|
||||||
const [view, setView] = useState("grid");
|
const [view, setView] = useState(localStorage?.getItem("workflowView") || "grid");
|
||||||
const classes = useStyles(theme)
|
const classes = useStyles(theme)
|
||||||
const imgSize = 60;
|
const imgSize = 60;
|
||||||
|
|
||||||
@@ -2074,55 +2074,6 @@ const Workflows2 = (props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const hasWorkflows = workflows === undefined || workflows === null || workflows.length === 0
|
const hasWorkflows = workflows === undefined || workflows === null || workflows.length === 0
|
||||||
const NewWorkflowPaper = () => {
|
|
||||||
const [hover, setHover] = React.useState(false);
|
|
||||||
|
|
||||||
const innerColor = "rgba(255,255,255,0.3)"
|
|
||||||
|
|
||||||
const setupPaperStyle = {
|
|
||||||
minHeight: paperAppStyle.minHeight,
|
|
||||||
maxWidth: "100%",
|
|
||||||
minWidth: paperAppStyle.width,
|
|
||||||
color: innerColor,
|
|
||||||
padding: paperAppStyle.padding,
|
|
||||||
display: "flex",
|
|
||||||
boxSizing: "border-box",
|
|
||||||
position: "relative",
|
|
||||||
border: hasWorkflows ? `2px solid #f85a3e` : `2px solid ${innerColor}`,
|
|
||||||
cursor: "pointer",
|
|
||||||
backgroundColor: hover ? "rgba(39,41,45,0.5)" : "rgba(39,41,45,1)",
|
|
||||||
borderRadius: paperAppStyle.borderRadius,
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid item xs={isMobile ? 12 : hasWorkflows ? 12 : 4} style={{ padding: "12px 10px 12px 10px" }}>
|
|
||||||
<Paper
|
|
||||||
square
|
|
||||||
style={setupPaperStyle}
|
|
||||||
onClick={() => {
|
|
||||||
setModalOpen(true)
|
|
||||||
setIsEditing(false)
|
|
||||||
}}
|
|
||||||
onMouseOver={() => {
|
|
||||||
setHover(true);
|
|
||||||
}}
|
|
||||||
onMouseOut={() => {
|
|
||||||
setHover(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Tooltip title={`New Workflow`} placement="bottom">
|
|
||||||
<span style={{ textAlign: "center", minWidth: 240, margin: "auto" }}>
|
|
||||||
<AddCircleIcon style={{ height: 65, width: 65 }} />
|
|
||||||
<Typography variant="h6" style={{ color: innerColor, margin: "auto" }}>
|
|
||||||
New Workflow
|
|
||||||
</Typography>
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
</Paper>
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const getWorkflowAppgroup = (data) => {
|
const getWorkflowAppgroup = (data) => {
|
||||||
if (currTab !== 2) {
|
if (currTab !== 2) {
|
||||||
if (data.actions === undefined || data.actions === null) {
|
if (data.actions === undefined || data.actions === null) {
|
||||||
@@ -2517,6 +2468,7 @@ const Workflows2 = (props) => {
|
|||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<Grid
|
<Grid
|
||||||
item
|
item
|
||||||
style={{ display: "flex", flexDirection: "column", width: "100%", fontFamily: theme?.typography?.fontFamily }}
|
style={{ display: "flex", flexDirection: "column", width: "100%", fontFamily: theme?.typography?.fontFamily }}
|
||||||
@@ -2612,8 +2564,7 @@ const Workflows2 = (props) => {
|
|||||||
to={
|
to={
|
||||||
type === "public" ? parsedUrl : data.workflow_as_code ? `/workflows/${data.id}/code` : `/workflows/${data.id}`
|
type === "public" ? parsedUrl : data.workflow_as_code ? `/workflows/${data.id}/code` : `/workflows/${data.id}`
|
||||||
}
|
}
|
||||||
style={{ textDecoration: "none", color: "inherit" }}
|
style={{ textDecoration: "none", color: "inherit", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", maxWidth: "90%", display: "block" }} >
|
||||||
>
|
|
||||||
{parsedName}
|
{parsedName}
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ go 1.23.0
|
|||||||
|
|
||||||
toolchain go1.23.6
|
toolchain go1.23.6
|
||||||
|
|
||||||
//replace github.com/shuffle/shuffle-shared => ../../../../shuffle-shared
|
replace github.com/shuffle/shuffle-shared => ../../../../shuffle-shared
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/docker/docker v27.5.0+incompatible
|
github.com/docker/docker v27.5.0+incompatible
|
||||||
|
|||||||
@@ -787,15 +787,19 @@ func handleBackendImageDownload(ctx context.Context, images string) error {
|
|||||||
newImages = append(newImages, curimage)
|
newImages = append(newImages, curimage)
|
||||||
|
|
||||||
// Force remove the current image to avoid cached layers
|
// Force remove the current image to avoid cached layers
|
||||||
_, err := dockercli.ImageRemove(ctx, curimage, image.RemoveOptions{
|
if swarmConfig == "run" || swarmConfig == "swarm" {
|
||||||
Force: true,
|
_, err := dockercli.ImageRemove(ctx, curimage, image.RemoveOptions{
|
||||||
PruneChildren: true,
|
Force: true,
|
||||||
})
|
PruneChildren: true,
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[ERROR] Failed removing image for re-download: %s", err)
|
log.Printf("[ERROR] Failed removing image for re-download: %s", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("[DEBUG] Removed image: %s", curimage)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[DEBUG] Removed image: %s", curimage)
|
log.Printf("[DEBUG] Skipping image removal for %s as swarmConfig is not set to run or swarm. Value: %#v", curimage, swarmConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, curimage)
|
err = shuffle.DownloadDockerImageBackend(&http.Client{Timeout: imagedownloadTimeout}, curimage)
|
||||||
@@ -2261,9 +2265,6 @@ func main() {
|
|||||||
log.Printf("[INFO] Re-downloading new image(s): %#v", incRequest.ExecutionArgument)
|
log.Printf("[INFO] Re-downloading new image(s): %#v", incRequest.ExecutionArgument)
|
||||||
|
|
||||||
if len(incRequest.ExecutionArgument) > 0 {
|
if len(incRequest.ExecutionArgument) > 0 {
|
||||||
// FIXME: Wait X seconds before running this as the image build may not be done yet. This is shitty, but may be ok to do in Orborus. Easy fix for the future: Just let it run through jobs 5-10 times before actually picking it up
|
|
||||||
|
|
||||||
// Run after 25 seconds in the goroutine instead
|
|
||||||
go handleBackendImageDownload(ctx, incRequest.ExecutionArgument)
|
go handleBackendImageDownload(ctx, incRequest.ExecutionArgument)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("[ERROR] No image name provided for download. Removing job from queue.")
|
log.Printf("[ERROR] No image name provided for download. Removing job from queue.")
|
||||||
|
|||||||
Reference in New Issue
Block a user