Multiple diff fixes for multi tenant workflows
This commit is contained in:
@@ -18,7 +18,7 @@ require (
|
|||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shuffle/shuffle-shared v0.8.7
|
github.com/shuffle/shuffle-shared v0.8.12
|
||||||
golang.org/x/crypto v0.32.0
|
golang.org/x/crypto v0.32.0
|
||||||
google.golang.org/api v0.176.1
|
google.golang.org/api v0.176.1
|
||||||
google.golang.org/grpc v1.68.1
|
google.golang.org/grpc v1.68.1
|
||||||
|
|||||||
@@ -356,6 +356,8 @@ github.com/shuffle/shuffle-shared v0.8.5 h1:c98AMOzIrDXmgQrKyf1HJ9wZwAwB02LPRvf9
|
|||||||
github.com/shuffle/shuffle-shared v0.8.5/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
github.com/shuffle/shuffle-shared v0.8.5/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
||||||
github.com/shuffle/shuffle-shared v0.8.6 h1:chnGJRKsO1gR5Vt/8hp5SQg1yP8/DmiK8sRhWVaTgEg=
|
github.com/shuffle/shuffle-shared v0.8.6 h1:chnGJRKsO1gR5Vt/8hp5SQg1yP8/DmiK8sRhWVaTgEg=
|
||||||
github.com/shuffle/shuffle-shared v0.8.6/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
github.com/shuffle/shuffle-shared v0.8.6/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
||||||
|
github.com/shuffle/shuffle-shared v0.8.12 h1:fg6jGAuevOGLgR7kpoZDJh//tzFjrEqj/bpxRFzxUTw=
|
||||||
|
github.com/shuffle/shuffle-shared v0.8.12/go.mod h1:bBXhEsPKjxln0mFnSeri7gIJ3tL/636Sh5NyTyNrvIQ=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
|
|||||||
@@ -1032,10 +1032,14 @@ func deleteWorkflow(resp http.ResponseWriter, request *http.Request) {
|
|||||||
|
|
||||||
log.Printf("[INFO] Should have deleted workflow %s (%s)", workflow.Name, fileId)
|
log.Printf("[INFO] Should have deleted workflow %s (%s)", workflow.Name, fileId)
|
||||||
|
|
||||||
cacheKey := fmt.Sprintf("%s_workflows", user.Id)
|
shuffle.DeleteCache(ctx, fmt.Sprintf("%s_workflows", user.Id))
|
||||||
shuffle.DeleteCache(ctx, cacheKey)
|
|
||||||
shuffle.DeleteCache(ctx, fmt.Sprintf("%s_workflows", user.ActiveOrg.Id))
|
shuffle.DeleteCache(ctx, fmt.Sprintf("%s_workflows", user.ActiveOrg.Id))
|
||||||
|
shuffle.DeleteCache(ctx, fmt.Sprintf("%s_%s", user.Username, fileId))
|
||||||
log.Printf("[DEBUG] Cleared workflow cache for %s (%s)", user.Username, user.Id)
|
log.Printf("[DEBUG] Cleared workflow cache for %s (%s)", user.Username, user.Id)
|
||||||
|
shuffle.DeleteCache(ctx, fmt.Sprintf("workflow_%s_childworkflows", workflow.ID))
|
||||||
|
if len(workflow.ParentWorkflowId) > 0 {
|
||||||
|
shuffle.DeleteCache(ctx, fmt.Sprintf("workflow_%s_childworkflows", workflow.ParentWorkflowId))
|
||||||
|
}
|
||||||
|
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(`{"success": true}`))
|
resp.Write([]byte(`{"success": true}`))
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ const Billing = memo((props) => {
|
|||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
const [deleteAlertIndex, setDeleteAlertIndex] = useState(-1);
|
const [deleteAlertIndex, setDeleteAlertIndex] = useState(-1);
|
||||||
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
const [deleteAlertVerification, setDeleteAlertVerification] = useState(false);
|
||||||
|
const [isScale, setIsScale] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
if (userdata.app_execution_limit !== undefined && userdata.app_execution_usage !== undefined) {
|
||||||
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
|
const percentage = (userdata.app_execution_usage / userdata.app_execution_limit) * 100;
|
||||||
@@ -176,11 +178,10 @@ const Billing = memo((props) => {
|
|||||||
padding: 20,
|
padding: 20,
|
||||||
// maxWidth: 400,
|
// maxWidth: 400,
|
||||||
width: 340,
|
width: 340,
|
||||||
height: 480,
|
height: 'auto',
|
||||||
// width: "100%",
|
// width: "100%",
|
||||||
backgroundColor: theme.palette.backgroundColor,
|
backgroundColor: "#1e1e1e",
|
||||||
borderRadius: theme.palette?.borderRadius * 2,
|
borderRadius: 10,
|
||||||
border: "1px solid rgba(255,255,255,0.3)",
|
|
||||||
marginRight: 10,
|
marginRight: 10,
|
||||||
marginTop: 15,
|
marginTop: 15,
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ const Billing = memo((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 rgba(255,255,255,0.3)"
|
// newPaperstyle.border = "1px solid rgba(255,255,255,0.3)"
|
||||||
showSupport = true
|
showSupport = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,16 +378,17 @@ const Billing = memo((props) => {
|
|||||||
|
|
||||||
if (subscription.name.includes("Scale")) {
|
if (subscription.name.includes("Scale")) {
|
||||||
top_text = "Scale access"
|
top_text = "Scale access"
|
||||||
|
setIsScale(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (highlight === true) {
|
if (highlight === true) {
|
||||||
// Add an "Upgrade now" button
|
// Add an "Upgrade now" button
|
||||||
newPaperstyle.border = "1px solid rgba(255,255,255,0.3)"
|
// newPaperstyle.border = "1px solid rgba(255,255,255,0.3)"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hovered) {
|
// if (hovered) {
|
||||||
newPaperstyle.backgroundColor = "#2b2b2b"
|
// newPaperstyle.backgroundColor = "#2b2b2b"
|
||||||
}
|
// }
|
||||||
|
|
||||||
const handleClickOpen = () => {
|
const handleClickOpen = () => {
|
||||||
setOpenChangeEmailBox(true);
|
setOpenChangeEmailBox(true);
|
||||||
@@ -556,6 +558,7 @@ const Billing = memo((props) => {
|
|||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
<Button style={{ backgroundColor: '#2F2F2F', color: "white", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', width: 144, height: 40 }}>Current Plan</Button>
|
||||||
<div style={{ display: "flex", width: 340 }}>
|
<div style={{ display: "flex", width: 340 }}>
|
||||||
{top_text === "Base Cloud Access" && userdata.has_card_available === true ?
|
{top_text === "Base Cloud Access" && userdata.has_card_available === true ?
|
||||||
<Chip
|
<Chip
|
||||||
@@ -659,8 +662,8 @@ const Billing = memo((props) => {
|
|||||||
<TextField
|
<TextField
|
||||||
value={feature.split("Worker License: ")[1]}
|
value={feature.split("Worker License: ")[1]}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: theme.palette.inputColor,
|
backgroundColor: theme.palette.textFieldStyle.backgroundColor,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.textFieldStyle.borderRadius,
|
||||||
}}
|
}}
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
onClick={() => { }}
|
onClick={() => { }}
|
||||||
@@ -2013,7 +2016,33 @@ const Billing = memo((props) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
<div style={{ display: "flex", width: clickedFromOrgTab ? "100%" : "auto", overflowX: 'auto', overflowY: 'hidden', scrollbarWidth: 'thin', scrollbarColor: '#494949 #2f2f2f', height: isChildOrg ? 0 : "100%", maxWidth: 860, 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%", }}>
|
||||||
|
{isCloud &&
|
||||||
|
selectedOrganization.subscriptions !== undefined &&
|
||||||
|
selectedOrganization.subscriptions !== null &&
|
||||||
|
selectedOrganization.subscriptions.length > 0 &&
|
||||||
|
!isChildOrg ?
|
||||||
|
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}
|
||||||
|
|
||||||
|
<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 :
|
||||||
<LicencePopup
|
<LicencePopup
|
||||||
serverside={serverside}
|
serverside={serverside}
|
||||||
@@ -2026,6 +2055,7 @@ const Billing = memo((props) => {
|
|||||||
isCloud={isCloud}
|
isCloud={isCloud}
|
||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
stripeKey={stripeKey}
|
stripeKey={stripeKey}
|
||||||
|
isScale={isScale}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
: !isCloud ?
|
: !isCloud ?
|
||||||
@@ -2061,6 +2091,7 @@ const Billing = memo((props) => {
|
|||||||
isCloud={isCloud}
|
isCloud={isCloud}
|
||||||
userdata={userdata}
|
userdata={userdata}
|
||||||
stripeKey={stripeKey}
|
stripeKey={stripeKey}
|
||||||
|
isScale={isScale}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* <SubscriptionObject
|
{/* <SubscriptionObject
|
||||||
@@ -2084,30 +2115,9 @@ const Billing = memo((props) => {
|
|||||||
/> */}
|
/> */}
|
||||||
</span>
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{isCloud &&
|
|
||||||
selectedOrganization.subscriptions !== undefined &&
|
|
||||||
selectedOrganization.subscriptions !== null &&
|
|
||||||
selectedOrganization.subscriptions.length > 0 &&
|
|
||||||
!isChildOrg ?
|
|
||||||
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}
|
|
||||||
{/*
|
{/*
|
||||||
<Grid item key={index} xs={12/selectedOrganization.subscriptions.length}>
|
<Grid item key={index} xs={12/selectedOrganization.subscriptions.length}>
|
||||||
<Card
|
<Card
|
||||||
@@ -2153,7 +2163,6 @@ const Billing = memo((props) => {
|
|||||||
*/}
|
*/}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/*isCloud &&
|
{/*isCloud &&
|
||||||
selectedOrganization.partner_info !== undefined &&
|
selectedOrganization.partner_info !== undefined &&
|
||||||
selectedOrganization.partner_info.reseller === true ? (
|
selectedOrganization.partner_info.reseller === true ? (
|
||||||
|
|||||||
@@ -577,12 +577,20 @@ const EditWorkflow = (props) => {
|
|||||||
<Typography variant="h4" style={{ marginTop: 50, }}>
|
<Typography variant="h4" style={{ marginTop: 50, }}>
|
||||||
Multi-Tenancy, Backups & Security
|
Multi-Tenancy, Backups & Security
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
<Typography variant="body2" color="textSecondary" style={{ marginTop: 30, marginBottom: 10, }}>
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 30, marginBottom: 10, }}>
|
||||||
Multi-Tenant Workflows. Make one workflow, and keep a separate, synced copy in all your tenants. Control distributed auth, runtime locations, files, datastore keys etc. (contact support@shuffler.io if you want a demo. Please try it!)
|
Control mechanisms for multi-tenancy, backups, and security.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{userdata !== undefined && userdata !== null && userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0 ?
|
<Typography variant="h6" style={{ marginTop: 50, }}>
|
||||||
|
Multi-Tenant Workflows
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, marginBottom: 10, }}>
|
||||||
|
Make one workflow, and keep a separate, synced copy in your other tenants. Control distributed auth, runtime locations, files, datastore keys etc. Can only distribute from parent org to child org. Need help trying it? <a href="https://shuffler.io/contact" target="_blank" style={{color: "#f85a3e", textDecoration: "none",}}>Contact us for a demo</a>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{userdata !== undefined && userdata !== null && userdata.orgs !== undefined && userdata.orgs !== null && userdata.orgs.length > 0 ?
|
||||||
|
|
||||||
userdata.orgs.filter(org => org.creator_org === userdata.active_org.id).length === 0 ?
|
userdata.orgs.filter(org => org.creator_org === userdata.active_org.id).length === 0 ?
|
||||||
userdata.active_org.creator_org === undefined || userdata.active_org.creator_org === null || userdata.active_org.creator_org === "" ?
|
userdata.active_org.creator_org === undefined || userdata.active_org.creator_org === null || userdata.active_org.creator_org === "" ?
|
||||||
<Typography variant="body2" style={{ marginTop: 10, color: "rgba(255,255,255,0.7)" }}>
|
<Typography variant="body2" style={{ marginTop: 10, color: "rgba(255,255,255,0.7)" }}>
|
||||||
@@ -600,6 +608,7 @@ const EditWorkflow = (props) => {
|
|||||||
multiple
|
multiple
|
||||||
style={{ marginTop: 10, }}
|
style={{ marginTop: 10, }}
|
||||||
value={innerWorkflow.suborg_distribution === undefined || innerWorkflow.suborg_distribution === null ? ["none"] : innerWorkflow.suborg_distribution}
|
value={innerWorkflow.suborg_distribution === undefined || innerWorkflow.suborg_distribution === null ? ["none"] : innerWorkflow.suborg_distribution}
|
||||||
|
disabled={workflow?.parentorg_workflow !== undefined && workflow?.parentorg_workflow !== null && workflow?.parentorg_workflow.length > 0}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
var newvalue = e.target.value
|
var newvalue = e.target.value
|
||||||
if (newvalue.length > 1 && newvalue[0] === "none") {
|
if (newvalue.length > 1 && newvalue[0] === "none") {
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ import { handlePayasyougo } from "../views/HandlePaymentNew.jsx"
|
|||||||
import Billing from "./Billing.jsx";
|
import Billing from "./Billing.jsx";
|
||||||
|
|
||||||
const LicencePopup = (props) => {
|
const LicencePopup = (props) => {
|
||||||
const { globalUrl, userdata, serverside, billingInfo, stripeKey, setModalOpen, isLoggedIn, isMobile, selectedOrganization, isCloud } = props;
|
const { globalUrl, userdata, serverside, billingInfo, stripeKey, setModalOpen, isScale, isLoggedIn, isMobile, selectedOrganization, isCloud } = props;
|
||||||
//const alert = useAlert();
|
//const alert = useAlert();
|
||||||
let navigate = useNavigate();
|
let navigate = useNavigate();
|
||||||
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
|
const [selectedDealModalOpen, setSelectedDealModalOpen] = React.useState(false);
|
||||||
@@ -165,11 +165,25 @@ const LicencePopup = (props) => {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userdata?.app_execution_limit >= 300000) {
|
||||||
|
subscription.name = "Enterprise"
|
||||||
|
subscription.currency_text = "$"
|
||||||
|
subscription.price = typecost_single
|
||||||
|
subscription.limit = userdata?.app_execution_limit
|
||||||
|
subscription.interval = "app run / month"
|
||||||
|
subscription.features = [
|
||||||
|
"Includes " + (userdata?.app_execution_limit/1000) + "K app runs/month. ",
|
||||||
|
"Multi-Tenancy and Region-Selection",
|
||||||
|
"And all other features from /pricing",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var newPaperstyle = JSON.parse(JSON.stringify(paperStyle))
|
var newPaperstyle = JSON.parse(JSON.stringify(paperStyle))
|
||||||
if (subscription.name === "Enterprise" && subscription.active === true) {
|
if (subscription.name === "Enterprise" && subscription.active === true) {
|
||||||
top_text = "Current Plan"
|
top_text = "Enterprise Plan"
|
||||||
|
|
||||||
newPaperstyle.border = "1px solid #f85a3e"
|
// newPaperstyle.border = "1px solid #f85a3e"
|
||||||
}
|
}
|
||||||
|
|
||||||
var showSupport = false
|
var showSupport = false
|
||||||
@@ -255,7 +269,7 @@ const LicencePopup = (props) => {
|
|||||||
style={{ borderRadius: theme.palette?.borderRadius, }}
|
style={{ borderRadius: theme.palette?.borderRadius, }}
|
||||||
placement="bottom"
|
placement="bottom"
|
||||||
>
|
>
|
||||||
<div style={{}}>
|
<div style={{ backgroundColor: "#1e1e1e"}}>
|
||||||
<Paper
|
<Paper
|
||||||
style={newPaperstyle}
|
style={newPaperstyle}
|
||||||
// onMouseEnter={() => setHovered(true)}
|
// onMouseEnter={() => setHovered(true)}
|
||||||
@@ -343,9 +357,9 @@ const LicencePopup = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<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: "white", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', width: 144, height: 40 }}>Current Plan</Button> }
|
||||||
<div style={{ display: "flex" }}>
|
<div style={{ display: "flex" }}>
|
||||||
{top_text === "Base Cloud Access" && userdata.has_card_available === true ?
|
{top_text === "Base Cloud Access" && userdata.has_card_available === true && !isScale ?
|
||||||
<Chip
|
<Chip
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: "#f86a3e",
|
backgroundColor: "#f86a3e",
|
||||||
@@ -511,7 +525,10 @@ const LicencePopup = (props) => {
|
|||||||
"While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month."
|
"While you have a card attached to your account, Shuffle will no longer prevent workflows from running. Billing will occur at the start of each month."
|
||||||
:
|
:
|
||||||
isCloud ?
|
isCloud ?
|
||||||
`You are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
|
userdata?.app_execution_limit && userdata?.app_execution_limit >= 300000 ?
|
||||||
|
"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 are not subscribed to any plan and are using the free plan with max 10,000 app runs per month. Upgrade to deactivate this limit.`
|
||||||
|
|
||||||
:
|
:
|
||||||
`You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.`
|
`You are not subscribed to any plan and are using the free, open source plan. This plan has no enforced limits, but scale issues may occur due to CPU congestion.`
|
||||||
}
|
}
|
||||||
@@ -699,8 +716,33 @@ const LicencePopup = (props) => {
|
|||||||
setCalculatedCost("$960")
|
setCalculatedCost("$960")
|
||||||
setSelectedValue(8)
|
setSelectedValue(8)
|
||||||
} else {
|
} else {
|
||||||
setCalculatedCost("$960")
|
if (userdata && userdata?.app_execution_limit) {
|
||||||
setSelectedValue(300)
|
if (userdata.app_execution_limit >= 300000 && userdata.app_execution_limit < 400000) {
|
||||||
|
setSelectedValue(400)
|
||||||
|
setCalculatedCost("$1280")
|
||||||
|
}else if (userdata?.app_execution_limit >= 400000 && userdata?.app_execution_limit < 500000) {
|
||||||
|
setSelectedValue(500)
|
||||||
|
setCalculatedCost("$1600")
|
||||||
|
} else if (userdata?.app_execution_limit >= 500000 && userdata?.app_execution_limit < 600000) {
|
||||||
|
setSelectedValue(600)
|
||||||
|
setCalculatedCost("$1920")
|
||||||
|
} else if (userdata?.app_execution_limit >= 600000 && userdata?.app_execution_limit < 700000) {
|
||||||
|
setSelectedValue(700)
|
||||||
|
setCalculatedCost("$2240")
|
||||||
|
} else if (userdata?.app_execution_limit >= 700000 && userdata?.app_execution_limit < 800000) {
|
||||||
|
setSelectedValue(800)
|
||||||
|
setCalculatedCost("$2560")
|
||||||
|
} else if (userdata?.app_execution_limit >= 800000 && userdata?.app_execution_limit < 900000) {
|
||||||
|
setSelectedValue(900)
|
||||||
|
setCalculatedCost("$2880")
|
||||||
|
}else {
|
||||||
|
setCalculatedCost("$960")
|
||||||
|
setSelectedValue(300)
|
||||||
|
}
|
||||||
|
}else {
|
||||||
|
setCalculatedCost("$960")
|
||||||
|
setSelectedValue(300)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [shuffleVariant])
|
}, [shuffleVariant])
|
||||||
|
|
||||||
@@ -977,7 +1019,7 @@ const LicencePopup = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
{isCloud &&
|
{/* {isCloud &&
|
||||||
selectedOrganization.subscriptions !== undefined &&
|
selectedOrganization.subscriptions !== undefined &&
|
||||||
selectedOrganization.subscriptions !== null &&
|
selectedOrganization.subscriptions !== null &&
|
||||||
selectedOrganization.subscriptions.length > 0 ?
|
selectedOrganization.subscriptions.length > 0 ?
|
||||||
@@ -998,7 +1040,7 @@ const LicencePopup = (props) => {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
: null}
|
: null} */}
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={8}>
|
<Grid item xs={8}>
|
||||||
<Grid style={{}}>
|
<Grid style={{}}>
|
||||||
@@ -1006,12 +1048,12 @@ const LicencePopup = (props) => {
|
|||||||
<Card style={{
|
<Card style={{
|
||||||
padding: 20,
|
padding: 20,
|
||||||
borderRadius: theme.palette?.borderRadius,
|
borderRadius: theme.palette?.borderRadius,
|
||||||
border: "1px solid #f85a3e",
|
border: !isScale ? "1px solid #f85a3e" : 'none',
|
||||||
}}>
|
}}>
|
||||||
<div>
|
<div>
|
||||||
<Button style={{ backgroundColor: 'rgba(255, 132, 68, 0.2)', color: "#FF8444", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', }}
|
{ !isScale && <Button style={{ backgroundColor: 'rgba(255, 132, 68, 0.2)', color: "#FF8444", textTransform: "capitalize", borderRadius: 200, boxShadow: 'none', }}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary">Recommended </Button>
|
color="primary">Recommended </Button> }
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, }}>{shuffleVariant === 1 ? "Scale" : "Enterprise"}</Typography>
|
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10, flex: 5, }}>{shuffleVariant === 1 ? "Scale" : "Enterprise"}</Typography>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const menuData = {
|
|||||||
title: "Shuffle",
|
title: "Shuffle",
|
||||||
description:
|
description:
|
||||||
"The most versatile automation engine with focus on security.",
|
"The most versatile automation engine with focus on security.",
|
||||||
icon: "images/logos/orange_logo.svg",
|
icon: "images/icons/shuffleLogo.svg",
|
||||||
path: "/docs/about",
|
path: "/docs/about",
|
||||||
gaData: {
|
gaData: {
|
||||||
category: "navbar",
|
category: "navbar",
|
||||||
|
|||||||
@@ -575,11 +575,17 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}, [editWorkflowModalOpen])
|
}, [editWorkflowModalOpen])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(selectedTrigger?.trigger_type === "SUBFLOW"){
|
// Check if selectedTriggerIndex is a number >= 0
|
||||||
|
if (isNaN(selectedTriggerIndex) || selectedTriggerIndex < 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedTrigger?.trigger_type === "SUBFLOW" && selectedTriggerIndex !== undefined && selectedTriggerIndex !== null && workflow?.triggers[selectedTriggerIndex].parameters.length > 1) {
|
||||||
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[1].value || "")
|
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[1].value || "")
|
||||||
} else if(selectedTrigger?.trigger_type === "USERINPUT"){
|
} else if (selectedTrigger?.trigger_type === "USERINPUT" && selectedTriggerIndex !== undefined && selectedTriggerIndex !== null && workflow?.triggers[selectedTriggerIndex].parameters.length > 0) {
|
||||||
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[0].value || "Do you want to continue the workflow? Start parameters: $exec")
|
setSelectedTriggerValue(workflow.triggers[selectedTriggerIndex].parameters[0].value || "Do you want to continue the workflow? Start parameters: $exec")
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [selectedTriggerIndex, selectedTrigger, workflow])
|
}, [selectedTriggerIndex, selectedTrigger, workflow])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -948,11 +954,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (workflow.actions?.length == 1) {
|
if (workflow?.actions?.length == 1) {
|
||||||
if (workflow.actions[0].app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
|
if (workflow?.actions[0].app_id == "3e320a20966d33c9b7e6790b2705f0bf") {
|
||||||
setWorkflowAsCode(true);
|
setWorkflowAsCode(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (workflow?.suborg_distribution !== undefined && workflow?.suborg_distribution !== null && workflow?.suborg_distribution.length > 0) {
|
||||||
|
getChildWorkflows(workflow.id)
|
||||||
|
}
|
||||||
}, [workflow]);
|
}, [workflow]);
|
||||||
|
|
||||||
// Event for making sure app is correct
|
// Event for making sure app is correct
|
||||||
@@ -1496,6 +1506,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
headers["Org-Id"] = workflow.org_id
|
headers["Org-Id"] = workflow.org_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setWorkflows([])
|
||||||
|
|
||||||
fetch(globalUrl + "/api/v1/workflows?subflow=true", {
|
fetch(globalUrl + "/api/v1/workflows?subflow=true", {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: headers,
|
headers: headers,
|
||||||
@@ -1512,7 +1524,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (responseJson !== undefined) {
|
if (responseJson !== undefined) {
|
||||||
|
|
||||||
// Sets up subflow trigger with the right info
|
// Sets up subflow trigger with the right info
|
||||||
if (trigger_index > -1) {
|
if (isNaN(trigger_index) === false && trigger_index > -1) {
|
||||||
|
|
||||||
var baseSubflow = {}
|
var baseSubflow = {}
|
||||||
const trigger = workflow.triggers[trigger_index];
|
const trigger = workflow.triggers[trigger_index];
|
||||||
@@ -2494,15 +2506,19 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (cy !== undefined && cy !== null) {
|
if (cy !== undefined && cy !== null) {
|
||||||
// scale: 0.3,
|
// scale: 0.3,
|
||||||
// bg: "#27292d",
|
// bg: "#27292d",
|
||||||
if (cy.png !== undefined && cy.png !== null) {
|
if (cy?.png !== undefined && cy?.png !== null) {
|
||||||
const cyImageData = cy.png({
|
try {
|
||||||
output: "base64uri",
|
const cyImageData = cy.png({
|
||||||
maxWidth: 480,
|
output: "base64uri",
|
||||||
maxHeight: 270,
|
maxWidth: 480,
|
||||||
})
|
maxHeight: 270,
|
||||||
|
})
|
||||||
|
|
||||||
if (cyImageData !== undefined && cyImageData !== null && cyImageData.length > 0) {
|
if (cyImageData !== undefined && cyImageData !== null && cyImageData.length > 0) {
|
||||||
useworkflow.image = cyImageData
|
useworkflow.image = cyImageData
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to get image data: ", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3914,6 +3930,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const findWorkflowDiff = (parentWorkflow, childWorkflow) => {
|
const findWorkflowDiff = (parentWorkflow, childWorkflow) => {
|
||||||
|
// Ensures new memory is used
|
||||||
|
parentWorkflow = JSON.parse(JSON.stringify(parentWorkflow))
|
||||||
|
childWorkflow = JSON.parse(JSON.stringify(childWorkflow))
|
||||||
|
|
||||||
var diff = {
|
var diff = {
|
||||||
"different": false,
|
"different": false,
|
||||||
"environment": false,
|
"environment": false,
|
||||||
@@ -3931,9 +3951,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
return diff
|
return diff
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var parentEnvironment = ""
|
var parentEnvironment = ""
|
||||||
var childEnvironment = ""
|
var childEnvironment = ""
|
||||||
|
|
||||||
|
if (parentWorkflow.triggers !== undefined && parentWorkflow.triggers !== null && parentWorkflow.triggers.length > 0) {
|
||||||
|
parentWorkflow.actions = parentWorkflow.actions.concat(parentWorkflow.triggers)
|
||||||
|
}
|
||||||
|
|
||||||
for (var parentKey in parentWorkflow.actions) {
|
for (var parentKey in parentWorkflow.actions) {
|
||||||
const parentAction = parentWorkflow.actions[parentKey]
|
const parentAction = parentWorkflow.actions[parentKey]
|
||||||
if (parentAction.environment !== undefined && parentAction.environment !== null && parentAction.environment !== "") {
|
if (parentAction.environment !== undefined && parentAction.environment !== null && parentAction.environment !== "") {
|
||||||
@@ -3945,6 +3969,19 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var found = false
|
var found = false
|
||||||
|
if (childWorkflow.triggers !== undefined && childWorkflow.triggers !== null && childWorkflow.triggers.length > 0) {
|
||||||
|
for (var triggerKey in childWorkflow.triggers) {
|
||||||
|
if (childWorkflow.triggers[triggerKey].replacement_for_trigger !== parentAction.id) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewrapping the ID just in case
|
||||||
|
childWorkflow.triggers[triggerKey].id = childWorkflow.triggers[triggerKey].replacement_for_trigger
|
||||||
|
childWorkflow.actions.push(childWorkflow.triggers[triggerKey])
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (var childKey in childWorkflow.actions) {
|
for (var childKey in childWorkflow.actions) {
|
||||||
const childAction = childWorkflow.actions[childKey]
|
const childAction = childWorkflow.actions[childKey]
|
||||||
if (childAction.environment !== undefined && childAction.environment !== null && childAction.environment !== "") {
|
if (childAction.environment !== undefined && childAction.environment !== null && childAction.environment !== "") {
|
||||||
@@ -3991,6 +4028,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var parentworkflow = ""
|
||||||
|
var parentstartnode = ""
|
||||||
|
var childworkflow = ""
|
||||||
|
var childstartnode = ""
|
||||||
for (var parentParamIndex in parentAction.parameters) {
|
for (var parentParamIndex in parentAction.parameters) {
|
||||||
const parentParam = parentAction.parameters[parentParamIndex]
|
const parentParam = parentAction.parameters[parentParamIndex]
|
||||||
for (var childParamIndex in childAction.parameters) {
|
for (var childParamIndex in childAction.parameters) {
|
||||||
@@ -3999,20 +4040,38 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (childParam.name === "workflow" || childParam.name === "subflow") {
|
||||||
|
parentworkflow = parentParam.value
|
||||||
|
childworkflow = childParam.value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childParam.name == "startnode") {
|
||||||
|
parentstartnode = parentParam.value
|
||||||
|
childstartnode = childParam.value
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if (childParam.value !== parentParam.value) {
|
if (childParam.value !== parentParam.value) {
|
||||||
actionDiff.parameters.push(childParam.name)
|
actionDiff.parameters.push(childParam.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parentworkflow !== childworkflow && parentstartnode !== childstartnode) {
|
||||||
|
actionDiff.parameters.push("subflow")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (actionDiff.parameters.length > 0) {
|
if (actionDiff.parameters.length > 0) {
|
||||||
actionDiff.params = true
|
actionDiff.params = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (!found) {
|
if (!found) {
|
||||||
actionDiff.new = true
|
actionDiff.new = true
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (actionDiff !== undefined && actionDiff !== null && Object.keys(actionDiff).length > 1) {
|
if (actionDiff !== undefined && actionDiff !== null && Object.keys(actionDiff).length > 1) {
|
||||||
actionDiff.label = parentAction.label.replaceAll("_", " ")
|
actionDiff.label = parentAction.label.replaceAll("_", " ")
|
||||||
@@ -6305,11 +6364,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0 && originalWorkflow.org_id !== undefined && originalWorkflow.org_id !== null && originalWorkflow.org_id.length > 0 && workflow.org_id === originalWorkflow.org_id) {
|
if (workflow.org_id !== undefined && workflow.org_id !== null && workflow.org_id.length > 0 && originalWorkflow.org_id !== undefined && originalWorkflow.org_id !== null && originalWorkflow.org_id.length > 0 && workflow.org_id === originalWorkflow.org_id) {
|
||||||
// Allows a parent workflow to control the schedule
|
// Allows a parent workflow to control the schedule
|
||||||
} else if (data.replacement_for_trigger !== undefined && data.replacement_for_trigger !== null && data.replacement_for_trigger.length > 0) {
|
} else if (data.replacement_for_trigger !== undefined && data.replacement_for_trigger !== null && data.replacement_for_trigger.length > 0) {
|
||||||
toast.warning("This schedule is controlled by the parent workflow. If you want additional schedule control, please add a custom schedule to this workflow.", {
|
|
||||||
autoClose: 30000,
|
// No custom control on cloud
|
||||||
})
|
if (isCloud) {
|
||||||
event.target.unselect()
|
toast.warning("This schedule is controlled by the parent workflow. If you want additional schedule control, please add a custom schedule to this workflow.", {
|
||||||
return
|
autoClose: 30000,
|
||||||
|
})
|
||||||
|
event.target.unselect()
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (data.app_name === "Webhook" && trigger_index >= 0) {
|
} else if (data.app_name === "Webhook" && trigger_index >= 0) {
|
||||||
@@ -6885,7 +6948,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
)
|
)
|
||||||
if (targetnode !== -1) {
|
if (targetnode !== -1) {
|
||||||
if (workflow.triggers[targetnode].app_name === "User Input" || workflow.triggers[targetnode].app_name === "Shuffle Workflow" || workflow.triggers[targetnode].app_name === "Shuffle Subflow") {
|
if (workflow.triggers[targetnode].app_name === "User Input" || workflow.triggers[targetnode].app_name === "Shuffle Workflow" || workflow.triggers[targetnode].app_name === "Shuffle Subflow") {
|
||||||
console.log("User Input or Shuffle Workflow")
|
//console.log("User Input or Shuffle Workflow")
|
||||||
} else {
|
} else {
|
||||||
toast("Can't have triggers as target of branch")
|
toast("Can't have triggers as target of branch")
|
||||||
event.target.remove()
|
event.target.remove()
|
||||||
@@ -9217,11 +9280,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
insertedNodes = insertedNodes.concat(newedges);
|
insertedNodes = insertedNodes.concat(newedges);
|
||||||
setWorkflow(inputworkflow);
|
setWorkflow(inputworkflow)
|
||||||
|
|
||||||
// Reset view for cytoscape
|
// Reset view for cytoscape
|
||||||
if (cy !== undefined && cy !== null) {
|
if (cy !== undefined && cy !== null) {
|
||||||
cy.add(insertedNodes)
|
try {
|
||||||
|
cy.add(insertedNodes)
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error adding nodes to cytoscape (6): ", error)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cy.fit(null, 250)
|
cy.fit(null, 250)
|
||||||
@@ -9300,12 +9367,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (selectedNode.data("id") === selectedAction.id) {
|
|
||||||
// setSelectedApp({});
|
|
||||||
// setSelectedAction({});
|
|
||||||
//setSelectedTrigger({});
|
|
||||||
//setSelectedTriggerIndex({});
|
|
||||||
//}
|
|
||||||
const parsedSelection = cy.$(":selected");
|
const parsedSelection = cy.$(":selected");
|
||||||
if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") {
|
if (selectedNode.data().decorator === true && selectedNode.data("type") !== "COMMENT") {
|
||||||
toast("This node can't be deleted.");
|
toast("This node can't be deleted.");
|
||||||
@@ -9505,7 +9566,6 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (firstrequest) {
|
if (firstrequest) {
|
||||||
setFirstrequest(false)
|
setFirstrequest(false)
|
||||||
getWorkflow(props.match.params.key, {})
|
getWorkflow(props.match.params.key, {})
|
||||||
getChildWorkflows(props.match.params.key)
|
|
||||||
getRevisionHistory(props.match.params.key)
|
getRevisionHistory(props.match.params.key)
|
||||||
loadTriggers()
|
loadTriggers()
|
||||||
getApps()
|
getApps()
|
||||||
@@ -14891,12 +14951,15 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ flex: "10" }}>
|
<div style={{ flex: "10" }}>
|
||||||
<b>Select a workflow to execute </b>
|
<b>Select a workflow to run</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{workflow.triggers[selectedTriggerIndex].parameters[0].value
|
{workflow.triggers[selectedTriggerIndex].parameters[0].value
|
||||||
.length === 0 ? null : workflow.triggers[selectedTriggerIndex]
|
.length === 0 ? null : workflow.triggers[selectedTriggerIndex]
|
||||||
.parameters[0].value === props.match.params.key ? null : (
|
.parameters[0].value === props.match.params.key ?
|
||||||
|
null
|
||||||
|
: (
|
||||||
<div style={{ marginLeft: 5, flex: 1 }}>
|
<div style={{ marginLeft: 5, flex: 1 }}>
|
||||||
<a
|
<a
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
@@ -14917,8 +14980,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
{workflows === undefined ||
|
{workflows === undefined ||
|
||||||
workflows === null ||
|
workflows === null ||
|
||||||
workflows.length === 0 ? null : (
|
workflows.length === 0 ?
|
||||||
|
<CircularProgress color="secondary" style={{ margin: "auto", marginTop: 10, width: 25, height: 25, }} />
|
||||||
|
: (
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
id="subflow_search"
|
id="subflow_search"
|
||||||
autoHighlight
|
autoHighlight
|
||||||
@@ -18175,6 +18239,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
value={workflow.org_id}
|
value={workflow.org_id}
|
||||||
disabled={savingState !== 0 || suborgWorkflows?.length === 0 || allTriggers === undefined}
|
disabled={savingState !== 0 || suborgWorkflows?.length === 0 || allTriggers === undefined}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
if (cy !== undefined && cy !== null) {
|
||||||
|
cy.nodes().unselect()
|
||||||
|
}
|
||||||
|
|
||||||
if (lastSaved === false && originalWorkflow.id === workflow.id) {
|
if (lastSaved === false && originalWorkflow.id === workflow.id) {
|
||||||
setSuborgWorkflows([])
|
setSuborgWorkflows([])
|
||||||
|
|
||||||
|
|||||||
@@ -427,14 +427,14 @@ const LoginPage = props => {
|
|||||||
window.location.pathname = "/workflows"
|
window.location.pathname = "/workflows"
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkAdmin = () => {
|
const checkAdmin = () => {
|
||||||
const url = globalUrl + "/api/v1/checkusers";
|
const url = globalUrl + "/api/v1/checkusers";
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((response) =>
|
.then((response) =>
|
||||||
response.json().then((responseJson) => {
|
response.json().then((responseJson) => {
|
||||||
if (responseJson["success"] === false) {
|
if (responseJson["success"] === false) {
|
||||||
@@ -459,7 +459,7 @@ const LoginPage = props => {
|
|||||||
navigate("/adminsetup")
|
navigate("/adminsetup")
|
||||||
}, 2500)
|
}, 2500)
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
const onSubmit = (e) => {
|
const onSubmit = (e) => {
|
||||||
@@ -952,7 +952,7 @@ const LoginPage = props => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{zoom: 0.8, paddingTop: 150, paddingBottom: 90 }}>
|
<div style={{zoom: 0.8, paddingTop: 75, paddingBottom: 90 }}>
|
||||||
{loadedCheck}
|
{loadedCheck}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1946,7 +1946,10 @@ const Workflows = (props) => {
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
console.log("Status not 200 for setting workflows :O!");
|
console.log("Status not 200 for setting workflows :O!");
|
||||||
toast("Failed deleting workflow. Do you have access?");
|
|
||||||
|
if (bulk !== true) {
|
||||||
|
toast(`Failed deleting workflow ${id}. Do you have access?`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bulk !== true) {
|
if (bulk !== true) {
|
||||||
toast(`Deleted workflow ${id}. Child Workflows in Suborgs were also removed.`)
|
toast(`Deleted workflow ${id}. Child Workflows in Suborgs were also removed.`)
|
||||||
|
|||||||
@@ -2043,7 +2043,10 @@ const Workflows2 = (props) => {
|
|||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
console.log("Status not 200 for setting workflows :O!");
|
console.log("Status not 200 for setting workflows :O!");
|
||||||
toast("Failed deleting workflow. Do you have access?");
|
|
||||||
|
if (bulk !== true) {
|
||||||
|
toast("Failed deleting workflow. Do you have access?");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bulk !== true) {
|
if (bulk !== true) {
|
||||||
toast(`Deleted workflow ${id}. Child Workflows in Suborgs were also removed.`)
|
toast(`Deleted workflow ${id}. Child Workflows in Suborgs were also removed.`)
|
||||||
@@ -2821,7 +2824,7 @@ const Workflows2 = (props) => {
|
|||||||
|
|
||||||
{(data.sharing !== undefined && data.sharing !== null && data.sharing === "form") || (data?.form_control?.input_markdown !== undefined && data?.form_control?.input_markdown !== null && data?.form_control?.input_markdown !== "") && type !== "public" ?
|
{(data.sharing !== undefined && data.sharing !== null && data.sharing === "form") || (data?.form_control?.input_markdown !== undefined && data?.form_control?.input_markdown !== null && data?.form_control?.input_markdown !== "") && type !== "public" ?
|
||||||
<Tooltip title="Edit Form" placement="top">
|
<Tooltip title="Edit Form" placement="top">
|
||||||
<div style={{ position: "absolute", top: 45, right: 8, }}>
|
<div style={{ position: "absolute", top: 50, right: 8, }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="more"
|
aria-label="more"
|
||||||
aria-controls="long-menu"
|
aria-controls="long-menu"
|
||||||
@@ -2838,8 +2841,8 @@ const Workflows2 = (props) => {
|
|||||||
: null}
|
: null}
|
||||||
|
|
||||||
{(data?.validation?.validation_ran === true && data?.validation?.valid === false && data?.validation?.errors?.length > 0 ) ?
|
{(data?.validation?.validation_ran === true && data?.validation?.valid === false && data?.validation?.errors?.length > 0 ) ?
|
||||||
<Tooltip title={`Explore more than ${data?.validation?.errors?.length} errors. When the last execution finishes without errors AND notifications stop occuring, this icon disappears.`} placement="top">
|
<Tooltip title={`Explore more than ${data?.validation?.errors?.length} notifications. When the last execution finishes without errors AND notifications stop occuring, this icon disappears.`} placement="top">
|
||||||
<div style={{ position: "absolute", top: 45, right: 8, }}>
|
<div style={{ position: "absolute", top: 85, right: 8, }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
aria-label="more"
|
aria-label="more"
|
||||||
aria-controls="long-menu"
|
aria-controls="long-menu"
|
||||||
@@ -2858,8 +2861,8 @@ const Workflows2 = (props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
|
||||||
: null}
|
: null}
|
||||||
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Paper>
|
</Paper>
|
||||||
</div>
|
</div>
|
||||||
@@ -3235,6 +3238,7 @@ const Workflows2 = (props) => {
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
}
|
}
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip
|
||||||
color="primary"
|
color="primary"
|
||||||
title="Amount of triggers"
|
title="Amount of triggers"
|
||||||
|
|||||||
Reference in New Issue
Block a user