+65
-26
@@ -2,40 +2,79 @@
|
|||||||
# Done manually for now since GHCR isn't being pushed to easily with the current Github action CI. Nightly = Latest IF we run hotfixes on latest
|
# Done manually for now since GHCR isn't being pushed to easily with the current Github action CI. Nightly = Latest IF we run hotfixes on latest
|
||||||
|
|
||||||
### Pull latest from ghcr CI/CD
|
### Pull latest from ghcr CI/CD
|
||||||
#docker pull ghcr.io/shuffle/shuffle-app_sdk:nightly
|
docker pull ghcr.io/shuffle/shuffle-app_sdk:nightly
|
||||||
#docker pull ghcr.io/shuffle/shuffle-worker:nightly
|
docker pull ghcr.io/shuffle/shuffle-worker:nightly
|
||||||
#docker pull ghcr.io/shuffle/shuffle-orborus:nightly
|
docker pull ghcr.io/shuffle/shuffle-orborus:nightly
|
||||||
#docker pull ghcr.io/shuffle/shuffle-frontend:nightly
|
docker pull ghcr.io/shuffle/shuffle-frontend:nightly
|
||||||
#docker pull ghcr.io/shuffle/shuffle-backend:nightly
|
#docker pull ghcr.io/shuffle/shuffle-backend:nightly
|
||||||
|
#
|
||||||
|
### NIGHTLY releases
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/frikky/shuffle-app_sdk:nightly
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/frikky/shuffle-worker:nightly
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/frikky/shuffle-orborus:nightly
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:nightly
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:nightly
|
||||||
|
|
||||||
|
docker push ghcr.io/frikky/shuffle-app_sdk:nightly
|
||||||
|
docker push ghcr.io/frikky/shuffle-worker:nightly
|
||||||
|
docker push ghcr.io/frikky/shuffle-orborus:nightly
|
||||||
|
docker push ghcr.io/frikky/shuffle-frontend:nightly
|
||||||
|
docker push ghcr.io/frikky/shuffle-backend:nightly
|
||||||
|
|
||||||
### LATEST releases:
|
### LATEST releases:
|
||||||
#docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/shuffle/shuffle-app_sdk:latest
|
## shuffle/shuffle
|
||||||
#docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/shuffle/shuffle-worker:latest
|
docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/shuffle/shuffle-app_sdk:latest
|
||||||
#docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/shuffle/shuffle-orborus:latest
|
docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/shuffle/shuffle-worker:latest
|
||||||
#docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/shuffle/shuffle-frontend:latest
|
docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/shuffle/shuffle-orborus:latest
|
||||||
#docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/shuffle/shuffle-backend:latest
|
docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/shuffle/shuffle-frontend:latest
|
||||||
#
|
docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/shuffle/shuffle-backend:latest
|
||||||
#docker push ghcr.io/shuffle/shuffle-app_sdk:latest
|
|
||||||
#docker push ghcr.io/shuffle/shuffle-worker:latest
|
docker push ghcr.io/shuffle/shuffle-app_sdk:latest
|
||||||
#docker push ghcr.io/shuffle/shuffle-orborus:latest
|
docker push ghcr.io/shuffle/shuffle-worker:latest
|
||||||
#docker push ghcr.io/shuffle/shuffle-frontend:latest
|
docker push ghcr.io/shuffle/shuffle-orborus:latest
|
||||||
#docker push ghcr.io/shuffle/shuffle-backend:latest
|
docker push ghcr.io/shuffle/shuffle-frontend:latest
|
||||||
|
docker push ghcr.io/shuffle/shuffle-backend:latest
|
||||||
|
|
||||||
|
## frikky/shuffle
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/frikky/shuffle-app_sdk:latest
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/frikky/shuffle-worker:latest
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/frikky/shuffle-orborus:latest
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:latest
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:latest
|
||||||
|
|
||||||
|
docker push ghcr.io/frikky/shuffle-app_sdk:latest
|
||||||
|
docker push ghcr.io/frikky/shuffle-worker:latest
|
||||||
|
docker push ghcr.io/frikky/shuffle-orborus:latest
|
||||||
|
docker push ghcr.io/frikky/shuffle-frontend:latest
|
||||||
|
docker push ghcr.io/frikky/shuffle-backend:latest
|
||||||
|
|
||||||
|
|
||||||
### 1.1.0 releases:
|
### 1.1.0 releases:
|
||||||
#docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/shuffle/shuffle-app_sdk:1.1.0
|
## shuffle/shuffle
|
||||||
#docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/shuffle/shuffle-worker:1.1.0
|
docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/shuffle/shuffle-app_sdk:1.1.0
|
||||||
#docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/shuffle/shuffle-orborus:1.1.0
|
docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/shuffle/shuffle-worker:1.1.0
|
||||||
#docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/shuffle/shuffle-frontend:1.1.0
|
docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/shuffle/shuffle-orborus:1.1.0
|
||||||
#docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/shuffle/shuffle-backend:1.1.0
|
docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/shuffle/shuffle-frontend:1.1.0
|
||||||
#
|
docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/shuffle/shuffle-backend:1.1.0
|
||||||
#docker push ghcr.io/shuffle/shuffle-app_sdk:1.1.0
|
|
||||||
#docker push ghcr.io/shuffle/shuffle-worker:1.1.0
|
|
||||||
#docker push ghcr.io/shuffle/shuffle-orborus:1.1.0
|
|
||||||
#docker push ghcr.io/shuffle/shuffle-frontend:1.1.0
|
|
||||||
#docker push ghcr.io/shuffle/shuffle-backend:1.1.0
|
|
||||||
|
|
||||||
|
docker push ghcr.io/shuffle/shuffle-app_sdk:1.1.0
|
||||||
|
docker push ghcr.io/shuffle/shuffle-worker:1.1.0
|
||||||
|
docker push ghcr.io/shuffle/shuffle-orborus:1.1.0
|
||||||
|
docker push ghcr.io/shuffle/shuffle-frontend:1.1.0
|
||||||
|
docker push ghcr.io/shuffle/shuffle-backend:1.1.0
|
||||||
|
|
||||||
|
## frikky/shuffle
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-app_sdk:nightly ghcr.io/frikky/shuffle-app_sdk:1.1.0
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-worker:nightly ghcr.io/frikky/shuffle-worker:1.1.0
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-orborus:nightly ghcr.io/frikky/shuffle-orborus:1.1.0
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-frontend:nightly ghcr.io/frikky/shuffle-frontend:1.1.0
|
||||||
|
docker tag ghcr.io/shuffle/shuffle-backend:nightly ghcr.io/frikky/shuffle-backend:1.1.0
|
||||||
|
|
||||||
|
docker push ghcr.io/frikky/shuffle-app_sdk:1.1.0
|
||||||
|
docker push ghcr.io/frikky/shuffle-worker:1.1.0
|
||||||
|
docker push ghcr.io/frikky/shuffle-orborus:1.1.0
|
||||||
|
docker push ghcr.io/frikky/shuffle-frontend:1.1.0
|
||||||
|
docker push ghcr.io/frikky/shuffle-backend:1.1.0
|
||||||
|
|
||||||
### Manage worker-scale upload (Requires auth)
|
### Manage worker-scale upload (Requires auth)
|
||||||
# This is supposed to be unavailable, and only be downloadable by customers
|
# This is supposed to be unavailable, and only be downloadable by customers
|
||||||
|
|||||||
@@ -0,0 +1,317 @@
|
|||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import ReactGA from 'react-ga';
|
||||||
|
|
||||||
|
import { useTheme } from "@material-ui/core/styles";
|
||||||
|
import {
|
||||||
|
Paper,
|
||||||
|
Typography,
|
||||||
|
Divider,
|
||||||
|
Button,
|
||||||
|
Grid,
|
||||||
|
Card,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
|
||||||
|
import { useAlert } from "react-alert";
|
||||||
|
import { typecost, typecost_single, } from "../views/HandlePaymentNew.jsx";
|
||||||
|
|
||||||
|
const Billing = (props) => {
|
||||||
|
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, } = props;
|
||||||
|
console.log("Billing: ", billingInfo);
|
||||||
|
const theme = useTheme();
|
||||||
|
const alert = useAlert();
|
||||||
|
|
||||||
|
const stripe = typeof window === 'undefined' || window.location === undefined ? "" : props.stripeKey === undefined ? "" : window.Stripe ? window.Stripe(props.stripeKey) : ""
|
||||||
|
console.log("Stripe: ", stripe)
|
||||||
|
|
||||||
|
const paperStyle = {
|
||||||
|
padding: 20,
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: theme.palette.surfaceColor,
|
||||||
|
border: "1px solid rgba(255,255,255,0.3)",
|
||||||
|
marginRight: 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
const isCloud =
|
||||||
|
window.location.host === "localhost:3002" ||
|
||||||
|
window.location.host === "shuffler.io";
|
||||||
|
|
||||||
|
billingInfo.subscription = {
|
||||||
|
"active": true,
|
||||||
|
"name": "Pay as you go",
|
||||||
|
"price": typecost_single,
|
||||||
|
"currency": "USD",
|
||||||
|
"currency_text": "$",
|
||||||
|
"interval": "app run / month",
|
||||||
|
"description": "Pay as you go",
|
||||||
|
"features": [
|
||||||
|
"Includes 10.000 app run/month for free. ",
|
||||||
|
"Pay for what you use with no minimum commitment and cancel anytime.",
|
||||||
|
],
|
||||||
|
"limit": 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleStripeRedirect = () => {
|
||||||
|
//var priceItem = "price_1MRNF1DzMUgUjxHSfFTUb2Xh"
|
||||||
|
if (stripe == "") {
|
||||||
|
console.log("Stripe not loaded")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var priceItem = "price_1MROFrDzMUgUjxHShcSxgHO1"
|
||||||
|
|
||||||
|
const successUrl = `${window.location.origin}/admin?admin_tab=billing&payment=success`
|
||||||
|
const failUrl = `${window.location.origin}/admin?admin_tab=billing&payment=failure`
|
||||||
|
var checkoutObject = {
|
||||||
|
lineItems: [
|
||||||
|
{
|
||||||
|
price: priceItem,
|
||||||
|
quantity: 1
|
||||||
|
},
|
||||||
|
],
|
||||||
|
mode: "subscription",
|
||||||
|
billingAddressCollection: "auto",
|
||||||
|
successUrl: successUrl,
|
||||||
|
cancelUrl: failUrl,
|
||||||
|
clientReferenceId: props.userdata.active_org.id,
|
||||||
|
}
|
||||||
|
//submitType: "donate",
|
||||||
|
|
||||||
|
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 cancelSubscriptions = (subscription_id) => {
|
||||||
|
const orgId = selectedOrganization.id;
|
||||||
|
const data = {
|
||||||
|
subscription_id: subscription_id,
|
||||||
|
action: "cancel",
|
||||||
|
org_id: selectedOrganization.id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = globalUrl + `/api/v1/orgs/${orgId}/cancel`;
|
||||||
|
fetch(url, {
|
||||||
|
mode: "cors",
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
credentials: "include",
|
||||||
|
crossDomain: true,
|
||||||
|
withCredentials: true,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(function (response) {
|
||||||
|
if (response.status !== 200) {
|
||||||
|
console.log("Error in response");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handleGetOrg != undefined) {
|
||||||
|
handleGetOrg(selectedOrganization.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(function (responseJson) {
|
||||||
|
if (responseJson.success !== undefined && responseJson.success) {
|
||||||
|
alert.success("Successfully stopped subscription!");
|
||||||
|
} else {
|
||||||
|
alert.error("Failed stopping subscription. Please contact us.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
console.log("Error: ", error);
|
||||||
|
alert.error("Failed stopping subscription. Please contact us.");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubscriptionObject = (props) => {
|
||||||
|
const { globalUrl, userdata, serverside, billingInfo, stripeKey, selectedOrganization, handleGetOrg, subscription, } = props;
|
||||||
|
|
||||||
|
console.log("Sub: ", subscription)
|
||||||
|
var top_text = "Base Access"
|
||||||
|
if (subscription.limit === undefined && subscription.level !== undefined) {
|
||||||
|
|
||||||
|
subscription.name = "Enterprise"
|
||||||
|
subscription.currency_text = "$"
|
||||||
|
subscription.price = subscription.level*180
|
||||||
|
subscription.limit = subscription.level*100000
|
||||||
|
subscription.interval = subscription.recurrence
|
||||||
|
subscription.features = [
|
||||||
|
"Includes " + subscription.limit + " app runs/month. ",
|
||||||
|
"Multi-Tenancy and Region-Selection",
|
||||||
|
"And all other features from /pricing",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subscription.name === "Enterprise" && subscription.active === true) {
|
||||||
|
top_text = "Current Plan"
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Paper style={paperStyle}>
|
||||||
|
<div style={{display: "flex"}}>
|
||||||
|
<Typography variant="h6" style={{ marginTop: 10, marginBottom: 10 }}>
|
||||||
|
{top_text}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<Divider />
|
||||||
|
<div>
|
||||||
|
<Typography variant="body1" style={{ marginTop: 20, }}>
|
||||||
|
{subscription.name}
|
||||||
|
</Typography>
|
||||||
|
<div style={{display: "flex", }}>
|
||||||
|
<Typography variant="h6" style={{ marginTop: 10, }}>
|
||||||
|
{subscription.currency_text}{subscription.price}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="textSecondary" style={{ marginLeft: 10, marginTop: 15, marginBottom: 10 }}>
|
||||||
|
/ {subscription.interval}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 10, }}>
|
||||||
|
Features
|
||||||
|
</Typography>
|
||||||
|
<ul>
|
||||||
|
{subscription.features !== undefined && subscription.features !== null ?
|
||||||
|
subscription.features.map((feature, index) => {
|
||||||
|
return (
|
||||||
|
<li>
|
||||||
|
<Typography variant="body2" color="textPrimary" style={{ }}>
|
||||||
|
{feature}
|
||||||
|
</Typography>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{/*subscription.name === "Pay as you go" && subscription.limit <= 10000 ?
|
||||||
|
<span>
|
||||||
|
<Typography variant="body2" color="textSecondary" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||||
|
You are not subscribed to any plan and are using the free plan with max 10,000 apps per month. Activate billing to de-activate this limit.
|
||||||
|
</Typography>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={{ marginTop: 20, marginBottom: 10, }}
|
||||||
|
onClick={() => {
|
||||||
|
handleStripeRedirect()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Activate Billing
|
||||||
|
</Button>
|
||||||
|
</span>
|
||||||
|
: null*/}
|
||||||
|
</Paper>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Typography variant="h6" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||||
|
Billing
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" style={{ marginTop: 20, marginBottom: 10 }}>
|
||||||
|
We use Stripe to manage subscriptions and do not store any of your billing information. You can manage your subscription and billing information below.
|
||||||
|
</Typography>
|
||||||
|
<div style={{display: "flex", maxWidth: 768, minWidth: 768, }}>
|
||||||
|
{billingInfo.subscription !== undefined && billingInfo.subscription !== null ?
|
||||||
|
<SubscriptionObject
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
userdata={userdata}
|
||||||
|
serverside={serverside}
|
||||||
|
billingInfo={billingInfo}
|
||||||
|
stripeKey={stripeKey}
|
||||||
|
selectedOrganization={selectedOrganization}
|
||||||
|
subscription={billingInfo.subscription}
|
||||||
|
/>
|
||||||
|
: null}
|
||||||
|
{isCloud &&
|
||||||
|
selectedOrganization.subscriptions !== undefined &&
|
||||||
|
selectedOrganization.subscriptions !== null &&
|
||||||
|
selectedOrganization.subscriptions.length > 0 ?
|
||||||
|
|
||||||
|
selectedOrganization.subscriptions
|
||||||
|
.reverse()
|
||||||
|
.map((sub, index) => {
|
||||||
|
return (
|
||||||
|
<SubscriptionObject
|
||||||
|
globalUrl={globalUrl}
|
||||||
|
userdata={userdata}
|
||||||
|
serverside={serverside}
|
||||||
|
billingInfo={billingInfo}
|
||||||
|
stripeKey={stripeKey}
|
||||||
|
selectedOrganization={selectedOrganization}
|
||||||
|
subscription={sub}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
: null}
|
||||||
|
{/*
|
||||||
|
<Grid item key={index} xs={12/selectedOrganization.subscriptions.length}>
|
||||||
|
<Card
|
||||||
|
elevation={6}
|
||||||
|
style={
|
||||||
|
paperStyle
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<b>Quantity</b>: {sub.level}
|
||||||
|
<div />
|
||||||
|
<b>Recurrence</b>: {sub.recurrence}
|
||||||
|
<div />
|
||||||
|
{sub.active ? (
|
||||||
|
<div>
|
||||||
|
<b>Started</b>:{" "}
|
||||||
|
{new Date(sub.startdate * 1000).toISOString()}
|
||||||
|
<div />
|
||||||
|
<Button
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
style={{ marginTop: 15 }}
|
||||||
|
onClick={() => {
|
||||||
|
cancelSubscriptions(sub.reference);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel subscription
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div>
|
||||||
|
<b>Cancelled</b>:{" "}
|
||||||
|
{new Date(
|
||||||
|
sub.cancellationdate * 1000
|
||||||
|
).toISOString()}
|
||||||
|
<div />
|
||||||
|
<Typography color="textSecondary">
|
||||||
|
<b>Status</b>: Deactivated
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Billing;
|
||||||
@@ -129,7 +129,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
|
|
||||||
setFirstLoad(workflow.id)
|
setFirstLoad(workflow.id)
|
||||||
const newactions = [];
|
const newactions = [];
|
||||||
for (var key in workflow.actions) {
|
for (let [key, keyval] in workflow.actions.entries()) {
|
||||||
const action = workflow.actions[key];
|
const action = workflow.actions[key];
|
||||||
var newaction = {
|
var newaction = {
|
||||||
large_image: action.large_image,
|
large_image: action.large_image,
|
||||||
@@ -175,7 +175,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
) {
|
) {
|
||||||
// Check if configuration is filled or not
|
// Check if configuration is filled or not
|
||||||
var filled = true;
|
var filled = true;
|
||||||
for (var key in action.parameters) {
|
for (let [key,keyval] in action.parameters.entries()) {
|
||||||
if (action.parameters[key].configuration) {
|
if (action.parameters[key].configuration) {
|
||||||
//console.log("Found config: ", action.parameters[key])
|
//console.log("Found config: ", action.parameters[key])
|
||||||
if (
|
if (
|
||||||
@@ -216,7 +216,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
|
|
||||||
if (newaction.must_authenticate) {
|
if (newaction.must_authenticate) {
|
||||||
var authenticationOptions = [];
|
var authenticationOptions = [];
|
||||||
for (var key in appAuthentication) {
|
for (let [key,keyval] in appAuthentication.entries()) {
|
||||||
const auth = appAuthentication[key];
|
const auth = appAuthentication[key];
|
||||||
if (auth.app.name === app.name && auth.active) {
|
if (auth.app.name === app.name && auth.active) {
|
||||||
//console.log("Found auth: ", auth)
|
//console.log("Found auth: ", auth)
|
||||||
@@ -264,7 +264,8 @@ const ConfigureWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in workflow.workflow_variables) {
|
if (workflow.workflow_variables !== undefined && workflow.workflow_variables !== null && workflow.workflow_variables.length !== 0) {
|
||||||
|
for (let [key,keyval] in workflow.workflow_variables.entries()) {
|
||||||
const variable = workflow.workflow_variables[key];
|
const variable = workflow.workflow_variables[key];
|
||||||
if (
|
if (
|
||||||
variable.value === undefined ||
|
variable.value === undefined ||
|
||||||
@@ -274,10 +275,12 @@ const ConfigureWorkflow = (props) => {
|
|||||||
variable.value = "";
|
variable.value = "";
|
||||||
variable.index = key;
|
variable.index = key;
|
||||||
requiredVariables.push(variable);
|
requiredVariables.push(variable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in workflow.triggers) {
|
if (workflow.triggers !== undefined && workflow.triggers !== null && workflow.triggers.length !== 0) {
|
||||||
|
for (let [key,keyval] in workflow.triggers.entries()) {
|
||||||
var trigger = workflow.triggers[key];
|
var trigger = workflow.triggers[key];
|
||||||
trigger.index = key;
|
trigger.index = key;
|
||||||
|
|
||||||
@@ -299,7 +302,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
for (var subkey in tmpsteps) {
|
for (let [subkey,subkeyval] in tmpsteps.entries()) {
|
||||||
newactions[foundindex].steps.push(tmpsteps[subkey])
|
newactions[foundindex].steps.push(tmpsteps[subkey])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +329,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
|
|
||||||
requiredTriggers.push(trigger);
|
requiredTriggers.push(trigger);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
requiredTriggers.length === 0 &&
|
requiredTriggers.length === 0 &&
|
||||||
@@ -342,11 +346,11 @@ const ConfigureWorkflow = (props) => {
|
|||||||
|
|
||||||
if (appAuthentication.length !== previousAuth.length) {
|
if (appAuthentication.length !== previousAuth.length) {
|
||||||
var newactions = []
|
var newactions = []
|
||||||
for (var actionkey in requiredActions) {
|
for (let [actionkey, actionkeyval] in requiredActions.entries()) {
|
||||||
var newaction = requiredActions[actionkey];
|
var newaction = requiredActions[actionkey];
|
||||||
const app = newaction.app;
|
const app = newaction.app;
|
||||||
|
|
||||||
for (var key in appAuthentication) {
|
for (let [key,keyval] in appAuthentication.entries()) {
|
||||||
const auth = appAuthentication[key];
|
const auth = appAuthentication[key];
|
||||||
|
|
||||||
// Does this account for all the different ones of the same?
|
// Does this account for all the different ones of the same?
|
||||||
@@ -690,7 +694,7 @@ const ConfigureWorkflow = (props) => {
|
|||||||
if (workflow.actions !== null) {
|
if (workflow.actions !== null) {
|
||||||
//console.log(workflow.actions)
|
//console.log(workflow.actions)
|
||||||
alert.info("Setting action to version "+action.update_version)
|
alert.info("Setting action to version "+action.update_version)
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
if (workflow.actions[key].app_name === action.app_name && workflow.actions[key].app_version === action.app_version) {
|
if (workflow.actions[key].app_name === action.app_name && workflow.actions[key].app_version === action.app_version) {
|
||||||
workflow.actions[key].app_version = action.update_version
|
workflow.actions[key].app_version = action.update_version
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import React, {useState} from 'react';
|
||||||
|
import { useTheme } from '@material-ui/core/styles';
|
||||||
|
import {isMobile} from "react-device-detect";
|
||||||
|
import ReactGA from 'react-ga';
|
||||||
|
|
||||||
|
import {TextField, Typography, Button} from '@material-ui/core';
|
||||||
|
|
||||||
|
const Newsletter = (props) => {
|
||||||
|
const { globalUrl, } = props;
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
const [email, setEmail] = useState("");
|
||||||
|
const [msg, setMsg] = useState("");
|
||||||
|
const [buttonActive, setButtonActive] = useState(true);
|
||||||
|
const buttonStyle = {minWidth: 300, borderRadius: 30, height: 60, width: 140, margin: isMobile ? "15px auto 15px auto" : "20px 20px 20px 10px", fontSize: 18,}
|
||||||
|
|
||||||
|
const newsletterSignup = (inemail) => {
|
||||||
|
if (inemail.length < 4) {
|
||||||
|
setMsg("Invalid email")
|
||||||
|
setButtonActive(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setButtonActive(false)
|
||||||
|
const data = {"email": inemail}
|
||||||
|
const url = globalUrl+'/api/v1/functions/newsletter_signup'
|
||||||
|
fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(response =>
|
||||||
|
response.json().then(responseJson => {
|
||||||
|
setButtonActive(true)
|
||||||
|
setMsg(responseJson["reason"])
|
||||||
|
if (responseJson["success"] === false) {
|
||||||
|
} else {
|
||||||
|
setEmail("")
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.catch(error => {
|
||||||
|
setMsg("Something went wrong: ", error.toString())
|
||||||
|
setButtonActive(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{margin: "auto", color: "white", textAlign: "center",}}>
|
||||||
|
<Typography variant="h4" style={{marginTop: 35,}}>
|
||||||
|
Security Automation Newsletter
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="h6" style={{color: "#7d7f82", marginTop: 20, }}>
|
||||||
|
Defensive security is 99% noise. Join us to sift through it.
|
||||||
|
</Typography>
|
||||||
|
<div style={{}}>
|
||||||
|
<TextField
|
||||||
|
style={{minWidth: isMobile ? "90%" : 450, backgroundColor: theme.palette.inputColor, marginTop: 20, borderRadius: 10, }}
|
||||||
|
InputProps={{
|
||||||
|
style:{
|
||||||
|
borderRadius: 10,
|
||||||
|
height: 60,
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => {
|
||||||
|
setEmail(e.target.value)
|
||||||
|
}}
|
||||||
|
placeholder="Your email"
|
||||||
|
id="standard-required"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
style={buttonStyle}
|
||||||
|
disabled={!buttonActive}
|
||||||
|
onClick={() => {
|
||||||
|
newsletterSignup(email)
|
||||||
|
ReactGA.event({
|
||||||
|
category: "newsletter",
|
||||||
|
action: `signup_click`,
|
||||||
|
label: "",
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Sign up
|
||||||
|
</Button>
|
||||||
|
<div/>
|
||||||
|
{msg}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default Newsletter;
|
||||||
@@ -0,0 +1,702 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
|
||||||
|
import { makeStyles } from "@material-ui/styles";
|
||||||
|
import { useTheme } from "@material-ui/core/styles";
|
||||||
|
import { useAlert } from "react-alert";
|
||||||
|
|
||||||
|
import {
|
||||||
|
FormControl,
|
||||||
|
InputLabel,
|
||||||
|
Paper,
|
||||||
|
OutlinedInput,
|
||||||
|
Checkbox,
|
||||||
|
Card,
|
||||||
|
Tooltip,
|
||||||
|
FormControlLabel,
|
||||||
|
Typography,
|
||||||
|
Switch,
|
||||||
|
Select,
|
||||||
|
MenuItem,
|
||||||
|
Divider,
|
||||||
|
TextField,
|
||||||
|
Button,
|
||||||
|
Tabs,
|
||||||
|
Tab,
|
||||||
|
Grid,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
|
||||||
|
import IconButton from "@material-ui/core/IconButton";
|
||||||
|
import ExpandLessIcon from "@material-ui/icons/ExpandLess";
|
||||||
|
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
|
||||||
|
import SaveIcon from "@material-ui/icons/Save";
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
notchedOutline: {
|
||||||
|
borderColor: "#f85a3e !important",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const OrgHeaderexpanded = (props) => {
|
||||||
|
const {
|
||||||
|
userdata,
|
||||||
|
selectedOrganization,
|
||||||
|
setSelectedOrganization,
|
||||||
|
globalUrl,
|
||||||
|
isCloud,
|
||||||
|
adminTab,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
const theme = useTheme();
|
||||||
|
const alert = useAlert();
|
||||||
|
const classes = useStyles();
|
||||||
|
const defaultBranch = "master";
|
||||||
|
|
||||||
|
const [orgName, setOrgName] = React.useState(selectedOrganization.name);
|
||||||
|
const [orgDescription, setOrgDescription] = React.useState(
|
||||||
|
selectedOrganization.description
|
||||||
|
);
|
||||||
|
|
||||||
|
const [appDownloadUrl, setAppDownloadUrl] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? "https://github.com/frikky/shuffle-apps"
|
||||||
|
: selectedOrganization.defaults.app_download_repo === undefined ||
|
||||||
|
selectedOrganization.defaults.app_download_repo.length === 0
|
||||||
|
? "https://github.com/frikky/shuffle-apps"
|
||||||
|
: selectedOrganization.defaults.app_download_repo
|
||||||
|
);
|
||||||
|
const [appDownloadBranch, setAppDownloadBranch] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? defaultBranch
|
||||||
|
: selectedOrganization.defaults.app_download_branch === undefined ||
|
||||||
|
selectedOrganization.defaults.app_download_branch.length === 0
|
||||||
|
? defaultBranch
|
||||||
|
: selectedOrganization.defaults.app_download_branch
|
||||||
|
);
|
||||||
|
const [workflowDownloadUrl, setWorkflowDownloadUrl] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? "https://github.com/frikky/shuffle-apps"
|
||||||
|
: selectedOrganization.defaults.workflow_download_repo === undefined ||
|
||||||
|
selectedOrganization.defaults.workflow_download_repo.length === 0
|
||||||
|
? "https://github.com/frikky/shuffle-workflows"
|
||||||
|
: selectedOrganization.defaults.workflow_download_repo
|
||||||
|
);
|
||||||
|
const [workflowDownloadBranch, setWorkflowDownloadBranch] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? defaultBranch
|
||||||
|
: selectedOrganization.defaults.workflow_download_branch === undefined ||
|
||||||
|
selectedOrganization.defaults.workflow_download_branch.length === 0
|
||||||
|
? defaultBranch
|
||||||
|
: selectedOrganization.defaults.workflow_download_branch
|
||||||
|
);
|
||||||
|
const [ssoEntrypoint, setSsoEntrypoint] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.sso_entrypoint === undefined ||
|
||||||
|
selectedOrganization.sso_config.sso_entrypoint.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.sso_entrypoint
|
||||||
|
);
|
||||||
|
const [ssoCertificate, setSsoCertificate] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.sso_certificate === undefined ||
|
||||||
|
selectedOrganization.sso_config.sso_certificate.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.sso_certificate
|
||||||
|
);
|
||||||
|
const [notificationWorkflow, setNotificationWorkflow] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.notification_workflow === undefined ||
|
||||||
|
selectedOrganization.defaults.notification_workflow.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.notification_workflow
|
||||||
|
);
|
||||||
|
|
||||||
|
const [documentationReference, setDocumentationReference] = React.useState(
|
||||||
|
selectedOrganization.defaults === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.documentation_reference === undefined ||
|
||||||
|
selectedOrganization.defaults.documentation_reference.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.defaults.documentation_reference
|
||||||
|
);
|
||||||
|
const [openidClientId, setOpenidClientId] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.client_id === undefined ||
|
||||||
|
selectedOrganization.sso_config.client_id.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.client_id
|
||||||
|
);
|
||||||
|
const [openidClientSecret, setOpenidClientSecret] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.client_secret === undefined ||
|
||||||
|
selectedOrganization.sso_config.client_secret.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.client_secret
|
||||||
|
);
|
||||||
|
const [openidAuthorization, setOpenidAuthorization] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.openid_authorization === undefined ||
|
||||||
|
selectedOrganization.sso_config.openid_authorization.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.openid_authorization
|
||||||
|
);
|
||||||
|
const [openidToken, setOpenidToken] = React.useState(
|
||||||
|
selectedOrganization.sso_config === undefined
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.openid_token === undefined ||
|
||||||
|
selectedOrganization.sso_config.openid_token.length === 0
|
||||||
|
? ""
|
||||||
|
: selectedOrganization.sso_config.openid_token
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleEditOrg = (
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
orgId,
|
||||||
|
image,
|
||||||
|
defaults,
|
||||||
|
sso_config
|
||||||
|
) => {
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
name: name,
|
||||||
|
description: description,
|
||||||
|
org_id: orgId,
|
||||||
|
image: image,
|
||||||
|
defaults: defaults,
|
||||||
|
sso_config: sso_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`;
|
||||||
|
fetch(url, {
|
||||||
|
mode: "cors",
|
||||||
|
method: "POST",
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
credentials: "include",
|
||||||
|
crossDomain: true,
|
||||||
|
withCredentials: true,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json; charset=utf-8",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) =>
|
||||||
|
response.json().then((responseJson) => {
|
||||||
|
if (responseJson["success"] === false) {
|
||||||
|
alert.error("Failed updating org: ", responseJson.reason);
|
||||||
|
} else {
|
||||||
|
alert.success("Successfully edited org!");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.catch((error) => {
|
||||||
|
alert.error("Err: " + error.toString());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const orgSaveButton = (
|
||||||
|
<Tooltip title="Save any unsaved data" placement="bottom">
|
||||||
|
<Button
|
||||||
|
style={{ width: 150, height: 55, flex: 1 }}
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
disabled={
|
||||||
|
userdata === undefined ||
|
||||||
|
userdata === null ||
|
||||||
|
userdata.admin !== "true"
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
handleEditOrg(
|
||||||
|
orgName,
|
||||||
|
orgDescription,
|
||||||
|
selectedOrganization.id,
|
||||||
|
selectedOrganization.image,
|
||||||
|
{
|
||||||
|
app_download_repo: appDownloadUrl,
|
||||||
|
app_download_branch: appDownloadBranch,
|
||||||
|
workflow_download_repo: workflowDownloadUrl,
|
||||||
|
workflow_download_branch: workflowDownloadBranch,
|
||||||
|
notification_workflow: notificationWorkflow,
|
||||||
|
documentation_reference: documentationReference,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sso_entrypoint: ssoEntrypoint,
|
||||||
|
sso_certificate: ssoCertificate,
|
||||||
|
client_id: openidClientId,
|
||||||
|
client_secret: openidClientSecret,
|
||||||
|
openid_authorization: openidAuthorization,
|
||||||
|
openid_token: openidToken,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SaveIcon />
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ textAlign: "center" }}>
|
||||||
|
<Grid container spacing={3} style={{ textAlign: "left" }}>
|
||||||
|
<Grid item xs={12} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Notification Workflow ID</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="ID of the workflow to receive notifications"
|
||||||
|
value={notificationWorkflow}
|
||||||
|
onChange={(e) => {
|
||||||
|
setNotificationWorkflow(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Org Documentation reference</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="URL to an external reference for this implementation"
|
||||||
|
value={documentationReference}
|
||||||
|
onChange={(e) => {
|
||||||
|
setDocumentationReference(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
{isCloud ? null :
|
||||||
|
<Grid item xs={12} style={{marginTop: 50 }}>
|
||||||
|
<Typography variant="h4" style={{textAlign: "center",}}>OpenID connect</Typography>
|
||||||
|
<Grid container style={{marginTop: 10, }}>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Client ID</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
disabled={
|
||||||
|
selectedOrganization.manager_orgs !== undefined &&
|
||||||
|
selectedOrganization.manager_orgs !== null &&
|
||||||
|
selectedOrganization.manager_orgs.length > 0
|
||||||
|
}
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="The OpenID client ID from the identity provider"
|
||||||
|
value={openidClientId}
|
||||||
|
onChange={(e) => {
|
||||||
|
setOpenidClientId(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Client Secret (optional)</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
disabled={
|
||||||
|
selectedOrganization.manager_orgs !== undefined &&
|
||||||
|
selectedOrganization.manager_orgs !== null &&
|
||||||
|
selectedOrganization.manager_orgs.length > 0
|
||||||
|
}
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="The OpenID client secret - DONT use this if dealing with implicit auth / PKCE"
|
||||||
|
value={openidClientSecret}
|
||||||
|
onChange={(e) => {
|
||||||
|
setOpenidClientSecret(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid container style={{marginTop: 10, }}>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Authorization URL</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
placeholder="The OpenID authorization URL (usually ends with /authorize)"
|
||||||
|
value={openidAuthorization}
|
||||||
|
onChange={(e) => {
|
||||||
|
setOpenidAuthorization(e.target.value)
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Token URL</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
placeholder="The OpenID token URL (usually ends with /token)"
|
||||||
|
value={openidToken}
|
||||||
|
onChange={(e) => {
|
||||||
|
setOpenidToken(e.target.value)
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
}
|
||||||
|
{/*isCloud ? null : */}
|
||||||
|
<Grid item xs={12} style={{marginTop: 50,}}>
|
||||||
|
<Typography variant="h4" style={{textAlign: "center",}}>SAML SSO (v1.1)</Typography>
|
||||||
|
<Grid container style={{marginTop: 20, }}>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>SSO Entrypoint (IdP)</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
disabled={
|
||||||
|
selectedOrganization.manager_orgs !== undefined &&
|
||||||
|
selectedOrganization.manager_orgs !== null &&
|
||||||
|
selectedOrganization.manager_orgs.length > 0
|
||||||
|
}
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="The entrypoint URL from your provider"
|
||||||
|
value={ssoEntrypoint}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSsoEntrypoint(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>SSO Certificate (X509)</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
multiline={true}
|
||||||
|
rows={2}
|
||||||
|
placeholder="The X509 certificate to use"
|
||||||
|
value={ssoCertificate}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSsoCertificate(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
{isCloud ?
|
||||||
|
<Typography variant="body2" style={{textAlign: "left",}} color="textSecondary">
|
||||||
|
IdP URL for Shuffle: https://shuffler.io/api/v1/login_sso
|
||||||
|
</Typography>
|
||||||
|
: null}
|
||||||
|
</Grid>
|
||||||
|
{isCloud ? null : (
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>App Download URL</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="A description for the organization"
|
||||||
|
value={appDownloadUrl}
|
||||||
|
onChange={(e) => {
|
||||||
|
setAppDownloadUrl(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{isCloud ? null : (
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>App Download Branch</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="A description for the organization"
|
||||||
|
value={appDownloadBranch}
|
||||||
|
onChange={(e) => {
|
||||||
|
setAppDownloadBranch(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{isCloud ? null : (
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Workflow Download URL</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="A description for the organization"
|
||||||
|
value={workflowDownloadUrl}
|
||||||
|
onChange={(e) => {
|
||||||
|
setWorkflowDownloadUrl(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
{isCloud ? null : (
|
||||||
|
<Grid item xs={6} style={{}}>
|
||||||
|
<span>
|
||||||
|
<Typography>Workflow Download Branch</Typography>
|
||||||
|
<TextField
|
||||||
|
required
|
||||||
|
style={{
|
||||||
|
flex: "1",
|
||||||
|
marginTop: "5px",
|
||||||
|
marginRight: "15px",
|
||||||
|
backgroundColor: theme.palette.inputColor,
|
||||||
|
}}
|
||||||
|
fullWidth={true}
|
||||||
|
type="name"
|
||||||
|
id="outlined-with-placeholder"
|
||||||
|
margin="normal"
|
||||||
|
variant="outlined"
|
||||||
|
placeholder="A description for the organization"
|
||||||
|
value={workflowDownloadBranch}
|
||||||
|
onChange={(e) => {
|
||||||
|
setWorkflowDownloadBranch(e.target.value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
classes: {
|
||||||
|
notchedOutline: classes.notchedOutline,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
color: "white",
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div style={{ margin: "auto", textalign: "center", marginTop: 15, marginBottom: 15, }}>
|
||||||
|
{orgSaveButton}
|
||||||
|
</div>
|
||||||
|
{/*
|
||||||
|
<span style={{textAlign: "center"}}>
|
||||||
|
{expanded ?
|
||||||
|
<ExpandLessIcon />
|
||||||
|
:
|
||||||
|
<ExpandMoreIcon />
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
*/}
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrgHeaderexpanded;
|
||||||
@@ -277,7 +277,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("FOUNDACTION: ", foundAction);
|
console.log("FOUNDACTION: ", foundAction);
|
||||||
if (foundAction !== null && foundAction !== undefined) {
|
if (foundAction !== null && foundAction !== undefined) {
|
||||||
var foundparams = [];
|
var foundparams = [];
|
||||||
for (var paramkey in foundAction.parameters) {
|
for (let [paramkey,paramkeyval] in foundAction.parameters.entries()) {
|
||||||
const param = foundAction.parameters[paramkey];
|
const param = foundAction.parameters[paramkey];
|
||||||
|
|
||||||
const foundParam = selectedAction.parameters.find(
|
const foundParam = selectedAction.parameters.find(
|
||||||
@@ -401,7 +401,7 @@ const ParsedAction = (props) => {
|
|||||||
if (actionlist.length === 0) {
|
if (actionlist.length === 0) {
|
||||||
// FIXME: Have previous execution values in here
|
// FIXME: Have previous execution values in here
|
||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
if (
|
if (
|
||||||
workflowExecutions[key].execution_argument === undefined ||
|
workflowExecutions[key].execution_argument === undefined ||
|
||||||
workflowExecutions[key].execution_argument === null ||
|
workflowExecutions[key].execution_argument === null ||
|
||||||
@@ -451,7 +451,7 @@ const ParsedAction = (props) => {
|
|||||||
workflow.workflow_variables !== undefined &&
|
workflow.workflow_variables !== undefined &&
|
||||||
workflow.workflow_variables.length > 0
|
workflow.workflow_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.workflow_variables) {
|
for (let [key,keyval] in workflow.workflow_variables.entries()) {
|
||||||
const item = workflow.workflow_variables[key];
|
const item = workflow.workflow_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "workflow_variable",
|
type: "workflow_variable",
|
||||||
@@ -470,7 +470,7 @@ const ParsedAction = (props) => {
|
|||||||
workflow.execution_variables !== undefined &&
|
workflow.execution_variables !== undefined &&
|
||||||
workflow.execution_variables.length > 0
|
workflow.execution_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.execution_variables) {
|
for (let [key,keyval] in workflow.execution_variables.entries()) {
|
||||||
const item = workflow.execution_variables[key];
|
const item = workflow.execution_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "execution_variable",
|
type: "execution_variable",
|
||||||
@@ -488,7 +488,7 @@ const ParsedAction = (props) => {
|
|||||||
var parents = getParents(selectedAction);
|
var parents = getParents(selectedAction);
|
||||||
|
|
||||||
if (parents.length > 1) {
|
if (parents.length > 1) {
|
||||||
for (var key in parents) {
|
for (let [key,keyval] in parents.entries()) {
|
||||||
const item = parents[key];
|
const item = parents[key];
|
||||||
if (item.label === "Execution Argument") {
|
if (item.label === "Execution Argument") {
|
||||||
continue;
|
continue;
|
||||||
@@ -500,7 +500,7 @@ const ParsedAction = (props) => {
|
|||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
// Look for the ID
|
// Look for the ID
|
||||||
const found = false;
|
const found = false;
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
if (
|
if (
|
||||||
workflowExecutions[key].results === undefined ||
|
workflowExecutions[key].results === undefined ||
|
||||||
workflowExecutions[key].results === null
|
workflowExecutions[key].results === null
|
||||||
@@ -566,7 +566,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
if (found !== null && found !== undefined) {
|
if (found !== null && found !== undefined) {
|
||||||
var new_occurences = []
|
var new_occurences = []
|
||||||
for (var key in found) {
|
for (let [key,keyval] in found.entries()) {
|
||||||
if (found[key][0] !== "\\") {
|
if (found[key][0] !== "\\") {
|
||||||
new_occurences.push(found[key])
|
new_occurences.push(found[key])
|
||||||
}
|
}
|
||||||
@@ -579,7 +579,7 @@ const ParsedAction = (props) => {
|
|||||||
if (found !== null) {
|
if (found !== null) {
|
||||||
try {
|
try {
|
||||||
// When the found array is empty.
|
// When the found array is empty.
|
||||||
for (var i = 0; i < found.length; i++) {
|
for (let i = 0; i < found.length; i++) {
|
||||||
const variableSplit = found[i].split(".#")
|
const variableSplit = found[i].split(".#")
|
||||||
if ((variableSplit.length-1) > 1) {
|
if ((variableSplit.length-1) > 1) {
|
||||||
//console.log("Larger than 1: ", variableSplit)
|
//console.log("Larger than 1: ", variableSplit)
|
||||||
@@ -589,7 +589,7 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var foundSlice = false
|
var foundSlice = false
|
||||||
for (var j = 0; j < actionlist.length; j++) {
|
for (let j = 0; j < actionlist.length; j++) {
|
||||||
//console.log("ACTION: ", found[i], actionlist[j])
|
//console.log("ACTION: ", found[i], actionlist[j])
|
||||||
//console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase())
|
//console.log("ACTION :", found[i].split(".")[0].slice(1,).toLowerCase(), actionlist[j].autocomplete.toLowerCase())
|
||||||
if(found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){
|
if(found[i].split(".")[0].slice(1,).toLowerCase() == actionlist[j].autocomplete.toLowerCase()){
|
||||||
@@ -730,7 +730,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var curstring = "";
|
var curstring = "";
|
||||||
var record = false;
|
var record = false;
|
||||||
for (var key in selectedActionParameters[count].value) {
|
for (let [key,keyval] in selectedActionParameters[count].value.entries()) {
|
||||||
const item = selectedActionParameters[count].value[key];
|
const item = selectedActionParameters[count].value[key];
|
||||||
if (record) {
|
if (record) {
|
||||||
curstring += item;
|
curstring += item;
|
||||||
@@ -911,7 +911,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var curstring = ""
|
var curstring = ""
|
||||||
var record = false
|
var record = false
|
||||||
for (var key in selectedActionParameters[count].value) {
|
for (let [key,keyval] in selectedActionParameters[count].value.entries()) {
|
||||||
const item = selectedActionParameters[count].value[key]
|
const item = selectedActionParameters[count].value[key]
|
||||||
if (record) {
|
if (record) {
|
||||||
curstring += item
|
curstring += item
|
||||||
@@ -1187,7 +1187,7 @@ const ParsedAction = (props) => {
|
|||||||
renderInput={(params) => {
|
renderInput={(params) => {
|
||||||
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
||||||
const prefixes = ["Post", "Put", "Patch"]
|
const prefixes = ["Post", "Put", "Patch"]
|
||||||
for (var key in prefixes) {
|
for (let [key,keyval] in prefixes.entries()) {
|
||||||
if (params.inputProps.value.startsWith(prefixes[key])) {
|
if (params.inputProps.value.startsWith(prefixes[key])) {
|
||||||
params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1)
|
params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1)
|
||||||
if (params.inputProps.value.length > 1) {
|
if (params.inputProps.value.length > 1) {
|
||||||
@@ -1426,7 +1426,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
setHideBody(!hideBody);
|
setHideBody(!hideBody);
|
||||||
|
|
||||||
for (var key in selectedActionParameters) {
|
for (let [key,keyval] in selectedActionParameters.entries()) {
|
||||||
var currentItem = selectedActionParameters[key];
|
var currentItem = selectedActionParameters[key];
|
||||||
if (currentItem.name === "ssl_verify") {
|
if (currentItem.name === "ssl_verify") {
|
||||||
|
|
||||||
@@ -1472,10 +1472,10 @@ const ParsedAction = (props) => {
|
|||||||
openApiHelperText = "OpenAPI spec: fill the following fields.";
|
openApiHelperText = "OpenAPI spec: fill the following fields.";
|
||||||
//console.log("SHOULD ADD TO selectedActionParameters!: ", found, selectedActionParameters)
|
//console.log("SHOULD ADD TO selectedActionParameters!: ", found, selectedActionParameters)
|
||||||
var changed = false;
|
var changed = false;
|
||||||
for (var specKey in found) {
|
for (let [specKey,specKeyVal] in found.entries()) {
|
||||||
const tmpitem = found[specKey];
|
const tmpitem = found[specKey];
|
||||||
var skip = false;
|
var skip = false;
|
||||||
for (var innerkey in selectedActionParameters) {
|
for (let [innerkey,innerkeyval] in selectedActionParameters.entries()) {
|
||||||
if (selectedActionParameters[innerkey].name === tmpitem) {
|
if (selectedActionParameters[innerkey].name === tmpitem) {
|
||||||
skip = true;
|
skip = true;
|
||||||
break;
|
break;
|
||||||
@@ -1707,7 +1707,7 @@ const ParsedAction = (props) => {
|
|||||||
|
|
||||||
var foundnewline = false
|
var foundnewline = false
|
||||||
var allValues = []
|
var allValues = []
|
||||||
for (var key in splitdata) {
|
for (let [key,keyval] in splitdata.entries()) {
|
||||||
const line = splitdata[key]
|
const line = splitdata[key]
|
||||||
if (line === "") {
|
if (line === "") {
|
||||||
foundnewline = true
|
foundnewline = true
|
||||||
@@ -1777,7 +1777,7 @@ const ParsedAction = (props) => {
|
|||||||
const tmpsplit = selectedActionParameters[count].value.split("\n")
|
const tmpsplit = selectedActionParameters[count].value.split("\n")
|
||||||
var valsplit = []
|
var valsplit = []
|
||||||
var add_empty = false
|
var add_empty = false
|
||||||
for (var key in tmpsplit) {
|
for (let [key,keyval] in tmpsplit.entries()) {
|
||||||
if (tmpsplit[key] === "") {
|
if (tmpsplit[key] === "") {
|
||||||
add_empty = true
|
add_empty = true
|
||||||
continue
|
continue
|
||||||
@@ -1792,7 +1792,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("Split: ", valsplit)
|
console.log("Split: ", valsplit)
|
||||||
|
|
||||||
var newarr = []
|
var newarr = []
|
||||||
for (var key in valsplit) {
|
for (let [key,keyval] in valsplit.entries()) {
|
||||||
var line = valsplit[key]
|
var line = valsplit[key]
|
||||||
|
|
||||||
if (key == index) {
|
if (key == index) {
|
||||||
@@ -1832,7 +1832,7 @@ const ParsedAction = (props) => {
|
|||||||
var tmpsplit = selectedActionParameters[count].value.split("\n")
|
var tmpsplit = selectedActionParameters[count].value.split("\n")
|
||||||
var valsplit = []
|
var valsplit = []
|
||||||
var add_empty = false
|
var add_empty = false
|
||||||
for (var key in tmpsplit) {
|
for (let [key,keyval] in tmpsplit.entries()) {
|
||||||
if (tmpsplit[key] === "") {
|
if (tmpsplit[key] === "") {
|
||||||
add_empty = true
|
add_empty = true
|
||||||
continue
|
continue
|
||||||
@@ -1847,7 +1847,7 @@ const ParsedAction = (props) => {
|
|||||||
console.log("Split: ", valsplit)
|
console.log("Split: ", valsplit)
|
||||||
|
|
||||||
var newarr = []
|
var newarr = []
|
||||||
for (var key in valsplit) {
|
for (let [key,keyval] in valsplit.entries()) {
|
||||||
var line = valsplit[key]
|
var line = valsplit[key]
|
||||||
|
|
||||||
if (key == index) {
|
if (key == index) {
|
||||||
@@ -2094,7 +2094,7 @@ const ParsedAction = (props) => {
|
|||||||
: "$" + values[0].autocomplete;
|
: "$" + values[0].autocomplete;
|
||||||
|
|
||||||
toComplete = toComplete.toLowerCase().replaceAll(" ", "_");
|
toComplete = toComplete.toLowerCase().replaceAll(" ", "_");
|
||||||
for (var key in values) {
|
for (let [key,keyval] in values.entries()) {
|
||||||
if (key == 0 || values[key].autocomplete.length === 0) {
|
if (key == 0 || values[key].autocomplete.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2205,7 +2205,7 @@ const ParsedAction = (props) => {
|
|||||||
workflow.triggers !== null &&
|
workflow.triggers !== null &&
|
||||||
workflow.triggers.length > 0
|
workflow.triggers.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.triggers) {
|
for (let [key,keyval] in workflow.triggers.entries()) {
|
||||||
const item = workflow.triggers[key];
|
const item = workflow.triggers[key];
|
||||||
|
|
||||||
if (cy !== undefined) {
|
if (cy !== undefined) {
|
||||||
@@ -2727,7 +2727,7 @@ const ParsedAction = (props) => {
|
|||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
// Look for the ID
|
// Look for the ID
|
||||||
const found = false;
|
const found = false;
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
if (
|
if (
|
||||||
workflowExecutions[key].results === undefined ||
|
workflowExecutions[key].results === undefined ||
|
||||||
workflowExecutions[key].results === null
|
workflowExecutions[key].results === null
|
||||||
@@ -2971,8 +2971,8 @@ const ParsedAction = (props) => {
|
|||||||
//
|
//
|
||||||
// Should make it a function lol
|
// Should make it a function lol
|
||||||
if (workflow.branches !== undefined && workflow.branches !== null) {
|
if (workflow.branches !== undefined && workflow.branches !== null) {
|
||||||
for (var key in workflow.branches) {
|
for (let [key,keyval] in workflow.branches.entries()) {
|
||||||
for (var subkey in workflow.branches[key].conditions) {
|
for (let [subkey,subkeyval] in workflow.branches[key].conditions.entries()) {
|
||||||
const condition = workflow.branches[key].conditions[subkey]
|
const condition = workflow.branches[key].conditions[subkey]
|
||||||
const sourceparam = condition.source
|
const sourceparam = condition.source
|
||||||
const destinationparam = condition.destination
|
const destinationparam = condition.destination
|
||||||
@@ -3080,12 +3080,12 @@ const ParsedAction = (props) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
if (workflow.actions[key].id === selectedAction.id) {
|
if (workflow.actions[key].id === selectedAction.id) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var subkey in workflow.actions[key].parameters) {
|
for (let [subkey, subkeyval] in workflow.actions[key].parameters.entries()) {
|
||||||
const param = workflow.actions[key].parameters[subkey];
|
const param = workflow.actions[key].parameters[subkey];
|
||||||
if (!param.value.includes("$")) {
|
if (!param.value.includes("$")) {
|
||||||
continue
|
continue
|
||||||
@@ -3251,7 +3251,7 @@ const ParsedAction = (props) => {
|
|||||||
selectedAction.selectedAuthentication = {};
|
selectedAction.selectedAuthentication = {};
|
||||||
selectedAction.authentication_id = "";
|
selectedAction.authentication_id = "";
|
||||||
|
|
||||||
for (var key in selectedAction.parameters) {
|
for (let [key,keyval] in selectedAction.parameters.entries()) {
|
||||||
//console.log(selectedAction.parameters[key])
|
//console.log(selectedAction.parameters[key])
|
||||||
if (selectedAction.parameters[key].configuration) {
|
if (selectedAction.parameters[key].configuration) {
|
||||||
selectedAction.parameters[key].value = "";
|
selectedAction.parameters[key].value = "";
|
||||||
@@ -3568,7 +3568,7 @@ const ParsedAction = (props) => {
|
|||||||
if (method.length > 0 && data.description !== undefined && data.description !== null && data.description.includes("http")) {
|
if (method.length > 0 && data.description !== undefined && data.description !== null && data.description.includes("http")) {
|
||||||
var extraUrl = ""
|
var extraUrl = ""
|
||||||
const descSplit = data.description.split("\n")
|
const descSplit = data.description.split("\n")
|
||||||
for (var line in descSplit) {
|
for (let [line,lineval] in descSplit.entries()) {
|
||||||
if (descSplit[line].includes("http") && descSplit[line].includes("://")) {
|
if (descSplit[line].includes("http") && descSplit[line].includes("://")) {
|
||||||
const urlsplit = descSplit[line].split("/")
|
const urlsplit = descSplit[line].split("/")
|
||||||
try {
|
try {
|
||||||
@@ -3629,7 +3629,7 @@ const ParsedAction = (props) => {
|
|||||||
renderInput={(params) => {
|
renderInput={(params) => {
|
||||||
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
if (params.inputProps !== undefined && params.inputProps !== null && params.inputProps.value !== undefined && params.inputProps.value !== null) {
|
||||||
const prefixes = ["Post", "Put", "Patch"]
|
const prefixes = ["Post", "Put", "Patch"]
|
||||||
for (var key in prefixes) {
|
for (let [key,keyval] in prefixes.entries()) {
|
||||||
if (params.inputProps.value.startsWith(prefixes[key])) {
|
if (params.inputProps.value.startsWith(prefixes[key])) {
|
||||||
params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1)
|
params.inputProps.value = params.inputProps.value.replace(prefixes[key]+" ", "", -1)
|
||||||
if (params.inputProps.value.length > 1) {
|
if (params.inputProps.value.length > 1) {
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ import ParsedAction from "../components/ParsedAction.jsx";
|
|||||||
import PaperComponent from "../components/PaperComponent.jsx"
|
import PaperComponent from "../components/PaperComponent.jsx"
|
||||||
import ExtraApps from "../components/ExtraApps.jsx"
|
import ExtraApps from "../components/ExtraApps.jsx"
|
||||||
import EditWorkflow from "../components/EditWorkflow.jsx"
|
import EditWorkflow from "../components/EditWorkflow.jsx"
|
||||||
import AppStats from "../components/AppStats.jsx";
|
// import AppStats from "../components/AppStats.jsx";
|
||||||
|
|
||||||
const surfaceColor = "#27292D";
|
const surfaceColor = "#27292D";
|
||||||
const inputColor = "#383B40";
|
const inputColor = "#383B40";
|
||||||
@@ -202,7 +202,7 @@ export function removeParam(key, sourceURL) {
|
|||||||
|
|
||||||
if (queryString !== "") {
|
if (queryString !== "") {
|
||||||
params_arr = queryString.split("&");
|
params_arr = queryString.split("&");
|
||||||
for (var i = params_arr.length - 1; i >= 0; i -= 1) {
|
for (let i = params_arr.length - 1; i >= 0; i -= 1) {
|
||||||
param = params_arr[i].split("=")[0];
|
param = params_arr[i].split("=")[0];
|
||||||
if (param === key) {
|
if (param === key) {
|
||||||
params_arr.splice(i, 1);
|
params_arr.splice(i, 1);
|
||||||
@@ -496,7 +496,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var baseSubflow = {}
|
var baseSubflow = {}
|
||||||
const trigger = workflow.triggers[trigger_index];
|
const trigger = workflow.triggers[trigger_index];
|
||||||
if (trigger.parameters.length >= 3) {
|
if (trigger.parameters.length >= 3) {
|
||||||
for (var key in trigger.parameters) {
|
for (let [key,keyval] in trigger.parameters.entries()) {
|
||||||
const param = trigger.parameters[key];
|
const param = trigger.parameters[key];
|
||||||
|
|
||||||
if (param.name === "workflow") {
|
if (param.name === "workflow") {
|
||||||
@@ -878,7 +878,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (responseJson.results !== null && responseJson.results.length > 0) {
|
if (responseJson.results !== null && responseJson.results.length > 0) {
|
||||||
for (var key in responseJson.results) {
|
for (let [key,keyval] in responseJson.results.entries()) {
|
||||||
var item = responseJson.results[key];
|
var item = responseJson.results[key];
|
||||||
var currentnode = cy.getElementById(item.action.id);
|
var currentnode = cy.getElementById(item.action.id);
|
||||||
if (currentnode.length === 0) {
|
if (currentnode.length === 0) {
|
||||||
@@ -953,7 +953,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// FIXME - add outgoing nodes to executing
|
// FIXME - add outgoing nodes to executing
|
||||||
//const outgoingNodes = outgoingEdges.find().data().target
|
//const outgoingNodes = outgoingEdges.find().data().target
|
||||||
if (outgoingEdges.length > 0) {
|
if (outgoingEdges.length > 0) {
|
||||||
for (var i = 0; i < outgoingEdges.length; i++) {
|
for (let i = 0; i < outgoingEdges.length; i++) {
|
||||||
const edge = outgoingEdges[i];
|
const edge = outgoingEdges[i];
|
||||||
const targetnode = cy.getElementById(edge.data().target);
|
const targetnode = cy.getElementById(edge.data().target);
|
||||||
if (
|
if (
|
||||||
@@ -1029,7 +1029,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var curelements = cy.elements();
|
var curelements = cy.elements();
|
||||||
for (var i = 0; i < curelements.length; i++) {
|
for (let i = 0; i < curelements.length; i++) {
|
||||||
if (curelements[i].classes().includes("executing-highlight")) {
|
if (curelements[i].classes().includes("executing-highlight")) {
|
||||||
curelements[i].removeClass("executing-highlight");
|
curelements[i].removeClass("executing-highlight");
|
||||||
curelements[i].addClass("failure-highlight");
|
curelements[i].addClass("failure-highlight");
|
||||||
@@ -1104,26 +1104,26 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var newBranches = [];
|
var newBranches = [];
|
||||||
var newVBranches = [];
|
var newVBranches = [];
|
||||||
var newComments = [];
|
var newComments = [];
|
||||||
for (var key in cyelements) {
|
for (let cyelementsKey in cyelements) {
|
||||||
if (cyelements[key].data === undefined) {
|
if (cyelements[cyelementsKey].data === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = cyelements[key].data()["type"];
|
var type = cyelements[cyelementsKey].data()["type"];
|
||||||
if (type === undefined) {
|
if (type === undefined) {
|
||||||
if (
|
if (
|
||||||
cyelements[key].data().source === undefined ||
|
cyelements[cyelementsKey].data().source === undefined ||
|
||||||
cyelements[key].data().target === undefined
|
cyelements[cyelementsKey].data().target === undefined
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var parsedElement = {
|
var parsedElement = {
|
||||||
id: cyelements[key].data().id,
|
id: cyelements[cyelementsKey].data().id,
|
||||||
source_id: cyelements[key].data().source,
|
source_id: cyelements[cyelementsKey].data().source,
|
||||||
destination_id: cyelements[key].data().target,
|
destination_id: cyelements[cyelementsKey].data().target,
|
||||||
conditions: cyelements[key].data().conditions,
|
conditions: cyelements[cyelementsKey].data().conditions,
|
||||||
decorator: cyelements[key].data().decorator,
|
decorator: cyelements[cyelementsKey].data().decorator,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (parsedElement.decorator) {
|
if (parsedElement.decorator) {
|
||||||
@@ -1133,7 +1133,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (type === "ACTION") {
|
if (type === "ACTION") {
|
||||||
const cyelement = cyelements[key].data();
|
const cyelement = cyelements[cyelementsKey].data();
|
||||||
const elementid =
|
const elementid =
|
||||||
cyelement.id === undefined || cyelement.id === null
|
cyelement.id === undefined || cyelement.id === null
|
||||||
? cyelement["_id"]
|
? cyelement["_id"]
|
||||||
@@ -1145,10 +1145,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
(a["id"] === elementid || a["_id"] === elementid)
|
(a["id"] === elementid || a["_id"] === elementid)
|
||||||
);
|
);
|
||||||
if (curworkflowAction === undefined) {
|
if (curworkflowAction === undefined) {
|
||||||
curworkflowAction = cyelements[key].data();
|
curworkflowAction = cyelements[cyelementsKey].data();
|
||||||
}
|
}
|
||||||
|
|
||||||
curworkflowAction.position = cyelements[key].position();
|
curworkflowAction.position = cyelements[cyelementsKey].position();
|
||||||
|
|
||||||
// workaround to fix some edgecases
|
// workaround to fix some edgecases
|
||||||
if (
|
if (
|
||||||
@@ -1163,8 +1163,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
curworkflowAction.example === "" ||
|
curworkflowAction.example === "" ||
|
||||||
curworkflowAction.example === null
|
curworkflowAction.example === null
|
||||||
) {
|
) {
|
||||||
if (cyelements[key].data().example !== undefined) {
|
if (cyelements[cyelementsKey].data().example !== undefined) {
|
||||||
curworkflowAction.example = cyelements[key].data().example;
|
curworkflowAction.example = cyelements[cyelementsKey].data().example;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,8 +1174,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
// Cleans up OpenAPI items
|
// Cleans up OpenAPI items
|
||||||
var newparams = [];
|
var newparams = [];
|
||||||
for (var key in curworkflowAction.parameters) {
|
for (let parametersKey in curworkflowAction.parameters) {
|
||||||
const thisitem = curworkflowAction.parameters[key];
|
const thisitem = curworkflowAction.parameters[parametersKey];
|
||||||
if (thisitem.name.startsWith("${") && thisitem.name.endsWith("}")) {
|
if (thisitem.name.startsWith("${") && thisitem.name.endsWith("}")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1191,13 +1191,13 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var curworkflowTrigger = useworkflow.triggers.find(
|
var curworkflowTrigger = useworkflow.triggers.find(
|
||||||
(a) => a.id === cyelements[key].data()["id"]
|
(a) => a.id === cyelements[cyelementsKey].data()["id"]
|
||||||
);
|
);
|
||||||
if (curworkflowTrigger === undefined) {
|
if (curworkflowTrigger === undefined) {
|
||||||
curworkflowTrigger = cyelements[key].data();
|
curworkflowTrigger = cyelements[cyelementsKey].data();
|
||||||
}
|
}
|
||||||
|
|
||||||
curworkflowTrigger.position = cyelements[key].position();
|
curworkflowTrigger.position = cyelements[cyelementsKey].position();
|
||||||
if (curworkflowTrigger.canConnect === false) {
|
if (curworkflowTrigger.canConnect === false) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1209,11 +1209,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var curworkflowComment = useworkflow.comments.find(
|
var curworkflowComment = useworkflow.comments.find(
|
||||||
(a) => a.id === cyelements[key].data()["id"]
|
(a) => a.id === cyelements[cyelementsKey].data()["id"]
|
||||||
)
|
)
|
||||||
|
|
||||||
if (curworkflowComment === undefined) {
|
if (curworkflowComment === undefined) {
|
||||||
curworkflowComment = cyelements[key].data();
|
curworkflowComment = cyelements[cyelementsKey].data();
|
||||||
try {
|
try {
|
||||||
curworkflowComment.position.x = parseInt(curworkflowComment.position.x)
|
curworkflowComment.position.x = parseInt(curworkflowComment.position.x)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -1241,7 +1241,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
curworkflowComment.width = 200
|
curworkflowComment.width = 200
|
||||||
}
|
}
|
||||||
|
|
||||||
curworkflowComment.position = cyelements[key].position();
|
curworkflowComment.position = cyelements[cyelementsKey].position();
|
||||||
//console.log(curworkflowComment)
|
//console.log(curworkflowComment)
|
||||||
|
|
||||||
newComments.push(curworkflowComment);
|
newComments.push(curworkflowComment);
|
||||||
@@ -1335,19 +1335,19 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const cyelements = cy.elements();
|
const cyelements = cy.elements();
|
||||||
|
|
||||||
for (var i = 0; i < cyelements.length; i++) {
|
for (let i = 0; i < cyelements.length; i++) {
|
||||||
//cyelements[i].removeStyle();
|
//cyelements[i].removeStyle();
|
||||||
cyelements[i].data().is_valid = true;
|
cyelements[i].data().is_valid = true;
|
||||||
cyelements[i].data().errors = [];
|
cyelements[i].data().errors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
workflow.actions[key].is_valid = true;
|
workflow.actions[key].is_valid = true;
|
||||||
workflow.actions[key].errors = [];
|
workflow.actions[key].errors = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in workflow.errors) {
|
for (let [key,keyval] in workflow.errors.entries()) {
|
||||||
//alert.info(workflow.errors[key]);
|
//alert.info(workflow.errors[key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1373,7 +1373,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var firstnode = cy.getElementById(workflow.start);
|
var firstnode = cy.getElementById(workflow.start);
|
||||||
if (firstnode.length === 0) {
|
if (firstnode.length === 0) {
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
if (workflow.actions[key].isStartNode) {
|
if (workflow.actions[key].isStartNode) {
|
||||||
console.log("Updating startnode");
|
console.log("Updating startnode");
|
||||||
workflow.start = workflow.actions[key].id;
|
workflow.start = workflow.actions[key].id;
|
||||||
@@ -1420,7 +1420,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
stop()
|
stop()
|
||||||
|
|
||||||
var curelements = cy.elements();
|
var curelements = cy.elements();
|
||||||
for (var i = 0; i < curelements.length; i++) {
|
for (let i = 0; i < curelements.length; i++) {
|
||||||
curelements[i].addClass("not-executing-highlight");
|
curelements[i].addClass("not-executing-highlight");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1452,7 +1452,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setExecutionRequestStarted(false);
|
setExecutionRequestStarted(false);
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
for (var i = 0; i < curelements.length; i++) {
|
for (let i = 0; i < curelements.length; i++) {
|
||||||
curelements[i].removeClass("not-executing-highlight");
|
curelements[i].removeClass("not-executing-highlight");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1473,7 +1473,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setExecutionRequestStarted(false);
|
setExecutionRequestStarted(false);
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
for (var i = 0; i < curelements.length; i++) {
|
for (let i = 0; i < curelements.length; i++) {
|
||||||
curelements[i].removeClass("not-executing-highlight");
|
curelements[i].removeClass("not-executing-highlight");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1520,7 +1520,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
if (responseJson.success) {
|
if (responseJson.success) {
|
||||||
var newauth = [];
|
var newauth = [];
|
||||||
for (var key in responseJson.data) {
|
console.log("App auth: ", responseJson.data);
|
||||||
|
for (let [key,keyval] in responseJson.data.entries()) {
|
||||||
if (responseJson.data[key].defined === false) {
|
if (responseJson.data[key].defined === false) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1546,11 +1547,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
var tmpAuth = JSON.parse(JSON.stringify(responseJson.data));
|
var tmpAuth = JSON.parse(JSON.stringify(responseJson.data));
|
||||||
var latest = 0;
|
var latest = 0;
|
||||||
for (var key in tmpAuth) {
|
for (let [key,keyval] in tmpAuth.entries()) {
|
||||||
var item = tmpAuth[key];
|
var item = tmpAuth[key];
|
||||||
|
|
||||||
const newfields = {};
|
const newfields = {};
|
||||||
for (var filterkey in item.fields) {
|
for (let [filterkey, filterkeyval] in item.fields.entries()) {
|
||||||
newfields[item.fields[filterkey].key] =
|
newfields[item.fields[filterkey].key] =
|
||||||
item.fields[filterkey].value;
|
item.fields[filterkey].value;
|
||||||
}
|
}
|
||||||
@@ -1564,7 +1565,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
latest = item.edited;
|
latest = item.edited;
|
||||||
selectedAction.selectedAuthentication = item;
|
selectedAction.selectedAuthentication = item;
|
||||||
|
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
if (workflow.actions[key].app_name === selectedApp.name) {
|
if (workflow.actions[key].app_name === selectedApp.name) {
|
||||||
workflow.actions[key].selectedAuthentication = item;
|
workflow.actions[key].selectedAuthentication = item;
|
||||||
workflow.actions[key].authentication_id = item.id;
|
workflow.actions[key].authentication_id = item.id;
|
||||||
@@ -1816,7 +1817,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
//{appGroup.map((data, index) => {
|
//{appGroup.map((data, index) => {
|
||||||
//const [appGroup, setAppGroup] = React.useState([]);
|
//const [appGroup, setAppGroup] = React.useState([]);
|
||||||
var appsFound = []
|
var appsFound = []
|
||||||
for (var key in responseJson.actions) {
|
for (let [key,keyval] in responseJson.actions.entries()) {
|
||||||
const parsedAction = responseJson.actions[key]
|
const parsedAction = responseJson.actions[key]
|
||||||
if (parsedAction.large_image === undefined || parsedAction.large_image === null || parsedAction.large_image === "") {
|
if (parsedAction.large_image === undefined || parsedAction.large_image === null || parsedAction.large_image === "") {
|
||||||
continue
|
continue
|
||||||
@@ -1829,7 +1830,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setAppGroup(appsFound)
|
setAppGroup(appsFound)
|
||||||
|
|
||||||
appsFound = []
|
appsFound = []
|
||||||
for (var key in responseJson.triggers) {
|
for (let [key,keyval] in responseJson.triggers.entries()) {
|
||||||
const parsedAction = responseJson.triggers[key]
|
const parsedAction = responseJson.triggers[key]
|
||||||
if (appsFound.findIndex(data => data.app_name === parsedAction.app_name) < 0){
|
if (appsFound.findIndex(data => data.app_name === parsedAction.app_name) < 0){
|
||||||
appsFound.push(parsedAction)
|
appsFound.push(parsedAction)
|
||||||
@@ -2237,7 +2238,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const connected = event.target.connectedEdges().jsons()
|
const connected = event.target.connectedEdges().jsons()
|
||||||
for (var key in connected) {
|
if (connected.length > 0 && connected !== undefined) {
|
||||||
|
for (let [key,keyval] in connected.entries()) {
|
||||||
const edge = connected[key]
|
const edge = connected[key]
|
||||||
//console.log("EDGE:", edge)
|
//console.log("EDGE:", edge)
|
||||||
|
|
||||||
@@ -2256,6 +2258,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
currentedge.style('control-point-weight', edgeCurve.weight)
|
currentedge.style('control-point-weight', edgeCurve.weight)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (styledElements.length === 1) {
|
if (styledElements.length === 1) {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -2334,7 +2337,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
) {
|
) {
|
||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var key in allNodes) {
|
for (let [key,keyval] in allNodes.entries()) {
|
||||||
const currentNode = allNodes[key];
|
const currentNode = allNodes[key];
|
||||||
if (
|
if (
|
||||||
currentNode.data.attachedTo === nodedata.id &&
|
currentNode.data.attachedTo === nodedata.id &&
|
||||||
@@ -2401,8 +2404,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
if (nodedata.app_name !== undefined) {
|
if (nodedata.app_name !== undefined) {
|
||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
for (var key in allNodes) {
|
for (var key_ in allNodes) {
|
||||||
const currentNode = allNodes[key];
|
const currentNode = allNodes[key_];
|
||||||
if (currentNode.data.attachedTo === nodedata.id) {
|
if (currentNode.data.attachedTo === nodedata.id) {
|
||||||
cy.getElementById(currentNode.data.id).remove();
|
cy.getElementById(currentNode.data.id).remove();
|
||||||
}
|
}
|
||||||
@@ -2484,8 +2487,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
elementMouseIsOver.style.border = newBorder;
|
elementMouseIsOver.style.border = newBorder;
|
||||||
console.log("STYLED: ", styledElements);
|
console.log("STYLED: ", styledElements);
|
||||||
for (var key in styledElements) {
|
for (var styledElementsKey in styledElements) {
|
||||||
const curElement = document.getElementById(styledElements[key]);
|
const curElement = document.getElementById(styledElements[styledElementsKey]);
|
||||||
if (curElement !== null && curElement !== undefined) {
|
if (curElement !== null && curElement !== undefined) {
|
||||||
curElement.style.border = curElement.style.original_border;
|
curElement.style.border = curElement.style.original_border;
|
||||||
}
|
}
|
||||||
@@ -2497,8 +2500,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
elementMouseIsOver.id === "cytoscape_view" ||
|
elementMouseIsOver.id === "cytoscape_view" ||
|
||||||
elementMouseIsOver.id === ""
|
elementMouseIsOver.id === ""
|
||||||
) {
|
) {
|
||||||
for (var key in styledElements) {
|
for (var index in styledElements) {
|
||||||
const curElement = document.getElementById(styledElements[key]);
|
const curElement = document.getElementById(styledElements[index]);
|
||||||
if (curElement !== null && curElement !== undefined) {
|
if (curElement !== null && curElement !== undefined) {
|
||||||
curElement.style.border = curElement.style.original_border;
|
curElement.style.border = curElement.style.original_border;
|
||||||
}
|
}
|
||||||
@@ -2639,8 +2642,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
foundbranch.destination_id === parentNode.data("id")
|
foundbranch.destination_id === parentNode.data("id")
|
||||||
);
|
);
|
||||||
|
|
||||||
for (var key in sourcebranches) {
|
for (var sourceBranchesKey in sourcebranches) {
|
||||||
var newbranch = JSON.parse(JSON.stringify(sourcebranches[key]));
|
var newbranch = JSON.parse(JSON.stringify(sourcebranches[sourceBranchesKey]));
|
||||||
newbranch.id = uuidv4();
|
newbranch.id = uuidv4();
|
||||||
newbranch.source_id = newNodeData.id;
|
newbranch.source_id = newNodeData.id;
|
||||||
|
|
||||||
@@ -2653,9 +2656,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in destinationbranches) {
|
for (var destinationBranchesKey in destinationbranches) {
|
||||||
var newbranch = JSON.parse(
|
var newbranch = JSON.parse(
|
||||||
JSON.stringify(destinationbranches[key])
|
JSON.stringify(destinationbranches[destinationBranchesKey])
|
||||||
);
|
);
|
||||||
newbranch.id = uuidv4();
|
newbranch.id = uuidv4();
|
||||||
newbranch.destination_id = newNodeData.id;
|
newbranch.destination_id = newNodeData.id;
|
||||||
@@ -2732,19 +2735,19 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
console.log("FIND AN ACTION AMONG THE APPS THAT MATCHES NAME: ", parsedname)
|
console.log("FIND AN ACTION AMONG THE APPS THAT MATCHES NAME: ", parsedname)
|
||||||
|
|
||||||
curaction.matching_actions = []
|
curaction.matching_actions = []
|
||||||
for (var key in newapps) {
|
for (var newAppskey in newapps) {
|
||||||
for (var subkey in newapps[key].actions) {
|
for (let actionsSubkey in newapps[newAppskey].actions) {
|
||||||
const tmpaction = newapps[key].actions[subkey]
|
const tmpaction = newapps[newAppskey].actions[actionsSubkey]
|
||||||
if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) {
|
if (tmpaction.name.replaceAll(" ", "_").toLowerCase() === parsedname) {
|
||||||
console.log("MATCH!: ", newapps[key])
|
console.log("MATCH!: ", newapps[newAppskey])
|
||||||
curaction.matching_actions.push({
|
curaction.matching_actions.push({
|
||||||
"app_name": newapps[key].name,
|
"app_name": newapps[newAppskey].name,
|
||||||
"app_version": newapps[key].app_version,
|
"app_version": newapps[newAppskey].app_version,
|
||||||
"app_id": newapps[key].id,
|
"app_id": newapps[newAppskey].id,
|
||||||
"action": tmpaction,
|
"action": tmpaction,
|
||||||
"large_image": newapps[key].large_image,
|
"large_image": newapps[newAppskey].large_image,
|
||||||
"app_index": key,
|
"app_index": newAppskey,
|
||||||
"action_index": subkey,
|
"action_index": actionsSubkey,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2804,12 +2807,12 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const tmpAuth = JSON.parse(JSON.stringify(newAppAuth));
|
const tmpAuth = JSON.parse(JSON.stringify(newAppAuth));
|
||||||
//var tmpAuth = newAppAuth
|
//var tmpAuth = newAppAuth
|
||||||
|
|
||||||
for (var key in tmpAuth) {
|
for (var tmpAuthKey in tmpAuth) {
|
||||||
var item = tmpAuth[key];
|
var item = tmpAuth[tmpAuthKey];
|
||||||
|
|
||||||
const newfields = {};
|
const newfields = {};
|
||||||
for (var filterkey in item.fields) {
|
for (var fieldFilterKey in item.fields) {
|
||||||
newfields[item.fields[filterkey].key] = item.fields[filterkey].value;
|
newfields[item.fields[fieldFilterKey].key] = item.fields[fieldFilterKey].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.fields = newfields;
|
item.fields = newfields;
|
||||||
@@ -2840,20 +2843,20 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
curaction.parameters !== null &&
|
curaction.parameters !== null &&
|
||||||
curaction.parameters.length > 0
|
curaction.parameters.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in curaction.parameters) {
|
for (var curActionParamKey in curaction.parameters) {
|
||||||
if (
|
if (
|
||||||
curaction.parameters[key].options !== undefined &&
|
curaction.parameters[curActionParamKey].options !== undefined &&
|
||||||
curaction.parameters[key].options !== null &&
|
curaction.parameters[curActionParamKey].options !== null &&
|
||||||
curaction.parameters[key].options.length > 0 &&
|
curaction.parameters[curActionParamKey].options.length > 0 &&
|
||||||
curaction.parameters[key].value === ""
|
curaction.parameters[curActionParamKey].value === ""
|
||||||
) {
|
) {
|
||||||
curaction.parameters[key].value = curaction.parameters[key].options[0];
|
curaction.parameters[curActionParamKey].value = curaction.parameters[curActionParamKey].options[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log("Should check APP if it has the same params as ACTION")
|
console.log("Should check APP if it has the same params as ACTION")
|
||||||
for (var key in curapp.actions) {
|
for (var actionKey in curapp.actions) {
|
||||||
const tmpaction = curapp.actions[key]
|
const tmpaction = curapp.actions[actionKey]
|
||||||
if (tmpaction.name === curaction.name) {
|
if (tmpaction.name === curaction.name) {
|
||||||
console.log("Found action - needs change?", tmpaction)
|
console.log("Found action - needs change?", tmpaction)
|
||||||
if (tmpaction.parameters !== undefined && tmpaction.parameters !== null && tmpaction.parameters.length > 0) {
|
if (tmpaction.parameters !== undefined && tmpaction.parameters !== null && tmpaction.parameters.length > 0) {
|
||||||
@@ -3000,7 +3003,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var exampledata = item.example === undefined ? "" : item.example;
|
var exampledata = item.example === undefined ? "" : item.example;
|
||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
// Look for the ID
|
// Look for the ID
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
if (
|
if (
|
||||||
workflowExecutions[key].results === undefined ||
|
workflowExecutions[key].results === undefined ||
|
||||||
workflowExecutions[key].results === null
|
workflowExecutions[key].results === null
|
||||||
@@ -3147,7 +3150,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
selectedkey = `.${key}`;
|
selectedkey = `.${key}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var subitem in value) {
|
for (let [subitem,subitemval] in value.entries()) {
|
||||||
toreturn = GetParamMatch(
|
toreturn = GetParamMatch(
|
||||||
paramname,
|
paramname,
|
||||||
value[subitem],
|
value[subitem],
|
||||||
@@ -3198,8 +3201,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// 2. Check parents in order
|
// 2. Check parents in order
|
||||||
var exampledata = GetExampleResult({ id: "exec", name: "exec" });
|
var exampledata = GetExampleResult({ id: "exec", name: "exec" });
|
||||||
var parentlabel = "exec";
|
var parentlabel = "exec";
|
||||||
for (var paramkey in dstdata.parameters) {
|
for (var dstdataParamKey in dstdata.parameters) {
|
||||||
const param = dstdata.parameters[paramkey];
|
const param = dstdata.parameters[dstdataParamKey];
|
||||||
// Skip authentication params
|
// Skip authentication params
|
||||||
if (param.configuration) {
|
if (param.configuration) {
|
||||||
continue
|
continue
|
||||||
@@ -3213,17 +3216,17 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const foundresult = GetParamMatch(paramname, exampledata, "");
|
const foundresult = GetParamMatch(paramname, exampledata, "");
|
||||||
if (foundresult.length > 0) {
|
if (foundresult.length > 0) {
|
||||||
console.log("FOUND ReS for field: ", dstdata.parameters[paramkey].name, foundresult)
|
console.log("FOUND ReS for field: ", dstdata.parameters[dstdataParamKey].name, foundresult)
|
||||||
if (dstdata.parameters[paramkey].value.length === 0) {
|
if (dstdata.parameters[dstdataParamKey].value.length === 0) {
|
||||||
dstdata.parameters[paramkey].value = `$${parentlabel}${foundresult}`;
|
dstdata.parameters[dstdataParamKey].value = `$${parentlabel}${foundresult}`;
|
||||||
dstdata.parameters[paramkey].autocompleted = true
|
dstdata.parameters[dstdataParamKey].autocompleted = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var parents = getParents(dstdata);
|
var parents = getParents(dstdata);
|
||||||
if (parents.length > 1) {
|
if (parents.length > 1) {
|
||||||
for (var key in parents) {
|
for (let [key,keyval] in parents.entries()) {
|
||||||
const item = parents[key];
|
const item = parents[key];
|
||||||
if (item.label === "Execution Argument") {
|
if (item.label === "Execution Argument") {
|
||||||
continue;
|
continue;
|
||||||
@@ -3234,7 +3237,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
? ""
|
? ""
|
||||||
: item.label.toLowerCase().trim().replaceAll(" ", "_");
|
: item.label.toLowerCase().trim().replaceAll(" ", "_");
|
||||||
exampledata = GetExampleResult(item);
|
exampledata = GetExampleResult(item);
|
||||||
for (var paramkey in dstdata.parameters) {
|
for (let [paramkey,paramkeyval] in dstdata.parameters.entries()) {
|
||||||
const param = dstdata.parameters[paramkey];
|
const param = dstdata.parameters[paramkey];
|
||||||
// Skip authentication params
|
// Skip authentication params
|
||||||
if (param.configuration) {
|
if (param.configuration) {
|
||||||
@@ -3384,7 +3387,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// dest == dest && source == source
|
// dest == dest && source == source
|
||||||
// backend: check all children? to stop recursion
|
// backend: check all children? to stop recursion
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var key in workflow.branches) {
|
for (let [key,keyval] in workflow.branches.entries()) {
|
||||||
if (
|
if (
|
||||||
workflow.branches[key].destination_id === edge.source &&
|
workflow.branches[key].destination_id === edge.source &&
|
||||||
workflow.branches[key].source_id === edge.target
|
workflow.branches[key].source_id === edge.target
|
||||||
@@ -3519,7 +3522,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove bad startnode
|
// Remove bad startnode
|
||||||
for (var key in workflow.actions) {
|
for (let [key,keyval] in workflow.actions.entries()) {
|
||||||
const action = workflow.actions[key];
|
const action = workflow.actions[key];
|
||||||
if (action.isStartNode && workflow.start !== action.id) {
|
if (action.isStartNode && workflow.start !== action.id) {
|
||||||
action.isStartNode = false;
|
action.isStartNode = false;
|
||||||
@@ -3583,7 +3586,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
) {
|
) {
|
||||||
var newparameters = [];
|
var newparameters = [];
|
||||||
|
|
||||||
for (var subkey in nodedata.parameters) {
|
for (let [subkey,subkeyval] in nodedata.parameters.entries()) {
|
||||||
var newparam = JSON.parse(
|
var newparam = JSON.parse(
|
||||||
JSON.stringify(nodedata.parameters[subkey])
|
JSON.stringify(nodedata.parameters[subkey])
|
||||||
);
|
);
|
||||||
@@ -3676,7 +3679,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// Check if the source is trigger and can start
|
// Check if the source is trigger and can start
|
||||||
console.log("Removed: ", edge.data())
|
console.log("Removed: ", edge.data())
|
||||||
const allNodes = cy.nodes().jsons()
|
const allNodes = cy.nodes().jsons()
|
||||||
for (var key in allNodes) {
|
for (let [key,keyval] in allNodes.entries()) {
|
||||||
const curnode = allNodes[key]
|
const curnode = allNodes[key]
|
||||||
if (curnode.data.type !== "TRIGGER") {
|
if (curnode.data.type !== "TRIGGER") {
|
||||||
continue
|
continue
|
||||||
@@ -3768,8 +3771,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
if (data.app_name !== undefined) {
|
if (data.app_name !== undefined) {
|
||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
for (var key in allNodes) {
|
for (let allNodesKey in allNodes) {
|
||||||
const currentNode = allNodes[key];
|
const currentNode = allNodes[allNodesKey];
|
||||||
if (currentNode.data.attachedTo === data.id) {
|
if (currentNode.data.attachedTo === data.id) {
|
||||||
cy.getElementById(currentNode.data.id).remove();
|
cy.getElementById(currentNode.data.id).remove();
|
||||||
}
|
}
|
||||||
@@ -3948,7 +3951,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const parsedjson = JSON.parse(clipboard);
|
const parsedjson = JSON.parse(clipboard);
|
||||||
//console.log("Parsed: ", parsedjson)
|
//console.log("Parsed: ", parsedjson)
|
||||||
|
|
||||||
for (var key in parsedjson) {
|
for (let [key,keyval] in parsedjson.entries()) {
|
||||||
const item = parsedjson[key];
|
const item = parsedjson[key];
|
||||||
console.log("Adding: ", item);
|
console.log("Adding: ", item);
|
||||||
item.data.id = uuidv4()
|
item.data.id = uuidv4()
|
||||||
@@ -3996,7 +3999,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
.then((responseJson) => {
|
.then((responseJson) => {
|
||||||
var found = false;
|
var found = false;
|
||||||
var showEnvCnt = 0;
|
var showEnvCnt = 0;
|
||||||
for (var key in responseJson) {
|
for (let [key,keyval] in responseJson.entries()) {
|
||||||
if (responseJson[key].default && !found) {
|
if (responseJson[key].default && !found) {
|
||||||
setDefaultEnvironmentIndex(key);
|
setDefaultEnvironmentIndex(key);
|
||||||
found = true;
|
found = true;
|
||||||
@@ -4012,7 +4015,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
for (var key in responseJson) {
|
for (let [key,keyval] in responseJson.entries()) {
|
||||||
if (!responseJson[key].archived) {
|
if (!responseJson[key].archived) {
|
||||||
setDefaultEnvironmentIndex(key);
|
setDefaultEnvironmentIndex(key);
|
||||||
break;
|
break;
|
||||||
@@ -4051,11 +4054,18 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const animationDuration = 150;
|
const animationDuration = 150;
|
||||||
const onNodeHoverOut = (event) => {
|
const onNodeHoverOut = (event) => {
|
||||||
|
// console.log("Hover out: ", event.target.data());
|
||||||
|
|
||||||
const nodedata = event.target.data();
|
const nodedata = event.target.data();
|
||||||
|
// console.log("nodedata", nodedata);
|
||||||
|
// console.log("nodedata.app_name: ", nodedata.app_name);
|
||||||
if (nodedata.app_name !== undefined) {
|
if (nodedata.app_name !== undefined) {
|
||||||
|
|
||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
for (var key in allNodes) {
|
// console.log("allNodes: ", allNodes)
|
||||||
const currentNode = allNodes[key];
|
for (var nodekey in allNodes) {
|
||||||
|
const currentNode = allNodes[nodekey];
|
||||||
|
// console.log("Current node: ", currentNode);
|
||||||
if (
|
if (
|
||||||
currentNode.data.isButton &&
|
currentNode.data.isButton &&
|
||||||
currentNode.data.attachedTo !== nodedata.id
|
currentNode.data.attachedTo !== nodedata.id
|
||||||
@@ -4332,8 +4342,9 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
|
|
||||||
var found = false;
|
var found = false;
|
||||||
for (var key in allNodes) {
|
for (var _key in allNodes) {
|
||||||
const currentNode = allNodes[key];
|
const currentNode = allNodes[_key];
|
||||||
|
// console.log("CURRENT NODE: ", currentNode)
|
||||||
if (
|
if (
|
||||||
(currentNode.data.isButton || currentNode.data.isSuggestion) &&
|
(currentNode.data.isButton || currentNode.data.isSuggestion) &&
|
||||||
currentNode.data.attachedTo !== nodedata.id
|
currentNode.data.attachedTo !== nodedata.id
|
||||||
@@ -4794,8 +4805,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
// Verifies if a branch is valid and skips others
|
// Verifies if a branch is valid and skips others
|
||||||
var newedges = [];
|
var newedges = [];
|
||||||
for (var key in edges) {
|
for (var edgeKey in edges) {
|
||||||
var item = edges[key];
|
var item = edges[edgeKey];
|
||||||
if (item.data === undefined) {
|
if (item.data === undefined) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -4819,6 +4830,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const removeNode = (nodeId) => {
|
const removeNode = (nodeId) => {
|
||||||
const selectedNode = cy.getElementById(nodeId);
|
const selectedNode = cy.getElementById(nodeId);
|
||||||
|
// console.log("selected node in removenode", selectedNode);
|
||||||
if (selectedNode.data() === undefined) {
|
if (selectedNode.data() === undefined) {
|
||||||
console.log("No node to remove")
|
console.log("No node to remove")
|
||||||
return;
|
return;
|
||||||
@@ -5142,7 +5154,8 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
var mappedStartnode = ""
|
var mappedStartnode = ""
|
||||||
const alledges = cy.edges().jsons()
|
const alledges = cy.edges().jsons()
|
||||||
for (var key in alledges) {
|
if (alledges !== undefined && alledges !== null && alledges.length > 0) {
|
||||||
|
for (let [key,keyval] in alledges.entries()) {
|
||||||
const tmp = alledges[key]
|
const tmp = alledges[key]
|
||||||
console.log("TMP: ", tmp, tmp.data.source)
|
console.log("TMP: ", tmp, tmp.data.source)
|
||||||
if (tmp.data.source === trigger.id) {
|
if (tmp.data.source === trigger.id) {
|
||||||
@@ -5150,6 +5163,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
alert.info("Creating schedule with name " + trigger.name);
|
alert.info("Creating schedule with name " + trigger.name);
|
||||||
const data = {
|
const data = {
|
||||||
@@ -5920,11 +5934,11 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
|
const tmpAuth = JSON.parse(JSON.stringify(appAuthentication));
|
||||||
for (var key in tmpAuth) {
|
for (let [key,keyval] in tmpAuth.entries()) {
|
||||||
var item = tmpAuth[key];
|
var item = tmpAuth[key];
|
||||||
|
|
||||||
const newfields = {};
|
const newfields = {};
|
||||||
for (var filterkey in item.fields) {
|
for (let [filterkey,filterkeyval] in item.fields.entries()) {
|
||||||
newfields[item.fields[filterkey].key] = item.fields[filterkey].value;
|
newfields[item.fields[filterkey].key] = item.fields[filterkey].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5950,7 +5964,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
authenticationOptions !== null &&
|
authenticationOptions !== null &&
|
||||||
authenticationOptions.length > 0
|
authenticationOptions.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in authenticationOptions) {
|
for (let [key,keyval] in authenticationOptions.entries()) {
|
||||||
const option = authenticationOptions[key];
|
const option = authenticationOptions[key];
|
||||||
|
|
||||||
if (option.active && newAppData.authentication_id === "") {
|
if (option.active && newAppData.authentication_id === "") {
|
||||||
@@ -6362,7 +6376,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (newApps.length === 0) {
|
if (newApps.length === 0) {
|
||||||
const searchvalue = value.trim().toLowerCase();
|
const searchvalue = value.trim().toLowerCase();
|
||||||
newApps = allApps.filter((app) => {
|
newApps = allApps.filter((app) => {
|
||||||
for (var key in app.actions) {
|
for (let [key,keyval] in app.actions.entries()) {
|
||||||
const inneraction = app.actions[key];
|
const inneraction = app.actions[key];
|
||||||
if (inneraction.name.toLowerCase().includes(searchvalue)) {
|
if (inneraction.name.toLowerCase().includes(searchvalue)) {
|
||||||
return true;
|
return true;
|
||||||
@@ -6727,7 +6741,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var highest = "";
|
var highest = "";
|
||||||
|
|
||||||
const allitems = workflow.actions.concat(workflow.triggers);
|
const allitems = workflow.actions.concat(workflow.triggers);
|
||||||
for (var key in allitems) {
|
for (let [key,keyval] in allitems.entries()) {
|
||||||
const item = allitems[key];
|
const item = allitems[key];
|
||||||
if (
|
if (
|
||||||
item.app_name === appName &&
|
item.app_name === appName &&
|
||||||
@@ -6788,7 +6802,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// Simmple action swap autocompleter
|
// Simmple action swap autocompleter
|
||||||
if (oldaction.parameters !== undefined && newSelectedAction.parameters !== undefined && oldaction.id === newSelectedAction.id) {
|
if (oldaction.parameters !== undefined && newSelectedAction.parameters !== undefined && oldaction.id === newSelectedAction.id) {
|
||||||
var fileid_found = false
|
var fileid_found = false
|
||||||
for (var paramkey in oldaction.parameters) {
|
for (let [paramkey,paramkeyval] in oldaction.parameters.entries()) {
|
||||||
const param = oldaction.parameters[paramkey];
|
const param = oldaction.parameters[paramkey];
|
||||||
|
|
||||||
if (param.name === "file_id") {
|
if (param.name === "file_id") {
|
||||||
@@ -6902,7 +6916,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
// FIXME - should change icon-node (descriptor) as well
|
// FIXME - should change icon-node (descriptor) as well
|
||||||
const allNodes = cy.nodes().jsons();
|
const allNodes = cy.nodes().jsons();
|
||||||
for (var key in allNodes) {
|
for (let [key,keyval] in allNodes.entries()) {
|
||||||
const currentNode = allNodes[key];
|
const currentNode = allNodes[key];
|
||||||
if (
|
if (
|
||||||
currentNode.data.attachedTo === oldaction.id &&
|
currentNode.data.attachedTo === oldaction.id &&
|
||||||
@@ -6994,7 +7008,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
var iterations = 0;
|
var iterations = 0;
|
||||||
var maxiter = 10;
|
var maxiter = 10;
|
||||||
while (true) {
|
while (true) {
|
||||||
for (var key in allkeys) {
|
for (let [key,keyval] in allkeys.entries()) {
|
||||||
var currentnode = cy.getElementById(allkeys[key]);
|
var currentnode = cy.getElementById(allkeys[key]);
|
||||||
if (currentnode === undefined || currentnode === null) {
|
if (currentnode === undefined || currentnode === null) {
|
||||||
continue;
|
continue;
|
||||||
@@ -7022,7 +7036,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < incomingEdges.length; i++) {
|
for (let i = 0; i < incomingEdges.length; i++) {
|
||||||
var tmp = incomingEdges[i];
|
var tmp = incomingEdges[i];
|
||||||
if (tmp.data("decorator")) {
|
if (tmp.data("decorator")) {
|
||||||
continue
|
continue
|
||||||
@@ -7150,7 +7164,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.triggers[selectedTriggerIndex].parameters[2].value.split(",");
|
workflow.triggers[selectedTriggerIndex].parameters[2].value.split(",");
|
||||||
console.log(splitItems);
|
console.log(splitItems);
|
||||||
if (splitItems.includes(value)) {
|
if (splitItems.includes(value)) {
|
||||||
for (var i = 0; i < splitItems.length; i++) {
|
for (let i = 0; i < splitItems.length; i++) {
|
||||||
if (splitItems[i] === value) {
|
if (splitItems[i] === value) {
|
||||||
splitItems.splice(i, 1);
|
splitItems.splice(i, 1);
|
||||||
}
|
}
|
||||||
@@ -7159,7 +7173,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
splitItems.push(value);
|
splitItems.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < splitItems.length; i++) {
|
for (let i = 0; i < splitItems.length; i++) {
|
||||||
if (splitItems[i] === "") {
|
if (splitItems[i] === "") {
|
||||||
splitItems.splice(i, 1);
|
splitItems.splice(i, 1);
|
||||||
}
|
}
|
||||||
@@ -7241,7 +7255,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.workflow_variables !== undefined &&
|
workflow.workflow_variables !== undefined &&
|
||||||
workflow.workflow_variables.length > 0
|
workflow.workflow_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.workflow_variables) {
|
for (let [key,keyval] in workflow.workflow_variables.entries()) {
|
||||||
const item = workflow.workflow_variables[key];
|
const item = workflow.workflow_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "workflow_variable",
|
type: "workflow_variable",
|
||||||
@@ -7260,7 +7274,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.execution_variables !== undefined &&
|
workflow.execution_variables !== undefined &&
|
||||||
workflow.execution_variables.length > 0
|
workflow.execution_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.execution_variables) {
|
for (let [key,keyval] in workflow.execution_variables.entries()) {
|
||||||
const item = workflow.execution_variables[key];
|
const item = workflow.execution_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "execution_variable",
|
type: "execution_variable",
|
||||||
@@ -7276,7 +7290,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
const destAction = cy.getElementById(selectedEdge.target);
|
const destAction = cy.getElementById(selectedEdge.target);
|
||||||
var parents = getParents(destAction.data());
|
var parents = getParents(destAction.data());
|
||||||
if (parents.length > 1) {
|
if (parents.length > 1) {
|
||||||
for (var key in parents) {
|
for (let [key,keyval] in parents.entries()) {
|
||||||
const item = parents[key];
|
const item = parents[key];
|
||||||
if (item.label === "Execution Argument") {
|
if (item.label === "Execution Argument") {
|
||||||
continue;
|
continue;
|
||||||
@@ -7452,7 +7466,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.triggers !== null &&
|
workflow.triggers !== null &&
|
||||||
workflow.triggers.length > 0
|
workflow.triggers.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.triggers) {
|
for (let [key,keyval] in workflow.triggers.entries()) {
|
||||||
const item = workflow.triggers[key];
|
const item = workflow.triggers[key];
|
||||||
|
|
||||||
var node = cy.getElementById(item.id);
|
var node = cy.getElementById(item.id);
|
||||||
@@ -7469,8 +7483,10 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
const handleActionHover = (inside, actionId) => {
|
const handleActionHover = (inside, actionId) => {
|
||||||
var node = cy.getElementById(actionId);
|
var node = cy.getElementById(actionId);
|
||||||
|
console.log("Hovering over action: " + actionId)
|
||||||
if (node.length > 0) {
|
if (node.length > 0) {
|
||||||
if (inside) {
|
if (inside) {
|
||||||
|
console.log("Hovering over action: " + actionId)
|
||||||
node.addClass("shuffle-hover-highlight");
|
node.addClass("shuffle-hover-highlight");
|
||||||
} else {
|
} else {
|
||||||
node.removeClass("shuffle-hover-highlight");
|
node.removeClass("shuffle-hover-highlight");
|
||||||
@@ -8796,7 +8812,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.workflow_variables !== undefined &&
|
workflow.workflow_variables !== undefined &&
|
||||||
workflow.workflow_variables.length > 0
|
workflow.workflow_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.workflow_variables) {
|
for (let [key,keyval] in workflow.workflow_variables.entries()) {
|
||||||
const item = workflow.workflow_variables[key];
|
const item = workflow.workflow_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "workflow_variable",
|
type: "workflow_variable",
|
||||||
@@ -8815,7 +8831,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.execution_variables !== undefined &&
|
workflow.execution_variables !== undefined &&
|
||||||
workflow.execution_variables.length > 0
|
workflow.execution_variables.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.execution_variables) {
|
for (let [key,keyval] in workflow.execution_variables.entries()) {
|
||||||
const item = workflow.execution_variables[key];
|
const item = workflow.execution_variables[key];
|
||||||
actionlist.push({
|
actionlist.push({
|
||||||
type: "execution_variable",
|
type: "execution_variable",
|
||||||
@@ -8830,7 +8846,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
var parents = getParents(selectedTrigger);
|
var parents = getParents(selectedTrigger);
|
||||||
if (parents.length > 1) {
|
if (parents.length > 1) {
|
||||||
for (var key in parents) {
|
for (let [key,keyval] in parents.entries()) {
|
||||||
const item = parents[key];
|
const item = parents[key];
|
||||||
if (item.label === "Execution Argument") {
|
if (item.label === "Execution Argument") {
|
||||||
continue;
|
continue;
|
||||||
@@ -8840,7 +8856,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
// Find previous execution and their variables
|
// Find previous execution and their variables
|
||||||
if (workflowExecutions.length > 0) {
|
if (workflowExecutions.length > 0) {
|
||||||
// Look for the ID
|
// Look for the ID
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
if (
|
if (
|
||||||
workflowExecutions[key].results === undefined ||
|
workflowExecutions[key].results === undefined ||
|
||||||
workflowExecutions[key].results === null
|
workflowExecutions[key].results === null
|
||||||
@@ -8969,7 +8985,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
workflow.triggers !== null &&
|
workflow.triggers !== null &&
|
||||||
workflow.triggers.length > 0
|
workflow.triggers.length > 0
|
||||||
) {
|
) {
|
||||||
for (var key in workflow.triggers) {
|
for (let [key,keyval] in workflow.triggers.entries()) {
|
||||||
const item = workflow.triggers[key];
|
const item = workflow.triggers[key];
|
||||||
|
|
||||||
if (cy !== undefined) {
|
if (cy !== undefined) {
|
||||||
@@ -10554,7 +10570,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
console.log("Starting mail sub: ", workflow.triggers[selectedTriggerIndex].parameters[0].value, splitItem);
|
console.log("Starting mail sub: ", workflow.triggers[selectedTriggerIndex].parameters[0].value, splitItem);
|
||||||
for (var key in splitItem) {
|
for (let [key,keyval] in splitItem.entries()) {
|
||||||
const item = splitItem[key];
|
const item = splitItem[key];
|
||||||
const curfolder = triggerFolders.find((a) => a.displayName === item);
|
const curfolder = triggerFolders.find((a) => a.displayName === item);
|
||||||
if (curfolder === undefined) {
|
if (curfolder === undefined) {
|
||||||
@@ -12709,7 +12725,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
to_be_copied = "$" + base_node_name.toLowerCase().replaceAll(" ", "_");
|
to_be_copied = "$" + base_node_name.toLowerCase().replaceAll(" ", "_");
|
||||||
for (var key in copy.namespace) {
|
for (let [key,keyval] in copy.namespace.entries()) {
|
||||||
if (copy.namespace[key].includes("Results for")) {
|
if (copy.namespace[key].includes("Results for")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -12984,7 +13000,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
data.workflow.actions !== null
|
data.workflow.actions !== null
|
||||||
? data.workflow.actions.length
|
? data.workflow.actions.length
|
||||||
: 0;
|
: 0;
|
||||||
for (var key in data.workflow.triggers) {
|
for (let [key,keyval] in data.workflow.triggers.entries()) {
|
||||||
const trigger = data.workflow.triggers[key];
|
const trigger = data.workflow.triggers[key];
|
||||||
if (
|
if (
|
||||||
(trigger.app_name === "User Input" &&
|
(trigger.app_name === "User Input" &&
|
||||||
@@ -13037,7 +13053,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
setExecutionRunning(true);
|
setExecutionRunning(true);
|
||||||
setExecutionRequestStarted(false);
|
setExecutionRequestStarted(false);
|
||||||
} else {
|
} else {
|
||||||
for (var key in data.results) {
|
for (let [key,keyval] in data.results.entries()) {
|
||||||
if (data.results[key].status !== "SUCCESS") {
|
if (data.results[key].status !== "SUCCESS") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -13520,7 +13536,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
if (data.similar_actions !== undefined && data.similar_actions !== null) {
|
if (data.similar_actions !== undefined && data.similar_actions !== null) {
|
||||||
var minimumMatch = 85
|
var minimumMatch = 85
|
||||||
var matching_executions = []
|
var matching_executions = []
|
||||||
for (var k in data.similar_actions) {
|
for (let [k,kval] in data.similar_actions.entries()){
|
||||||
if (data.similar_actions.hasOwnProperty(k)) {
|
if (data.similar_actions.hasOwnProperty(k)) {
|
||||||
if (data.similar_actions[k].similarity > minimumMatch) {
|
if (data.similar_actions[k].similarity > minimumMatch) {
|
||||||
matching_executions.push(data.similar_actions[k].execution_id)
|
matching_executions.push(data.similar_actions[k].execution_id)
|
||||||
@@ -13866,7 +13882,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
const execution = workflowExecutions[key];
|
const execution = workflowExecutions[key];
|
||||||
const result = execution.results.find(
|
const result = execution.results.find(
|
||||||
(data) =>
|
(data) =>
|
||||||
@@ -13907,7 +13923,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
}}
|
}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
for (var key in workflowExecutions) {
|
for (let [key,keyval] in workflowExecutions.entries()) {
|
||||||
const execution = workflowExecutions[key];
|
const execution = workflowExecutions[key];
|
||||||
const result = execution.results.find(
|
const result = execution.results.find(
|
||||||
(data) =>
|
(data) =>
|
||||||
@@ -14581,7 +14597,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
authenticationOption.app.actions = [];
|
authenticationOption.app.actions = [];
|
||||||
|
|
||||||
for (var key in selectedApp.authentication.parameters) {
|
for (let [key,keyval] in selectedApp.authentication.parameters.entries()) {
|
||||||
if (
|
if (
|
||||||
authenticationOption.fields[
|
authenticationOption.fields[
|
||||||
selectedApp.authentication.parameters[key].name
|
selectedApp.authentication.parameters[key].name
|
||||||
@@ -14600,7 +14616,7 @@ 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 (var key in selectedApp.authentication.parameters) {
|
for (let [key,keyval] in selectedApp.authentication.parameters.entries()) {
|
||||||
if (
|
if (
|
||||||
authenticationOption.fields[
|
authenticationOption.fields[
|
||||||
selectedApp.authentication.parameters[key].name
|
selectedApp.authentication.parameters[key].name
|
||||||
@@ -14649,7 +14665,7 @@ const AngularWorkflow = (defaultprops) => {
|
|||||||
|
|
||||||
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
|
var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
|
||||||
var newFields = [];
|
var newFields = [];
|
||||||
for (const key in newAuthOption.fields) {
|
for (let [key,keyval] in newAuthOption.fields.entries()) {
|
||||||
const value = newAuthOption.fields[key];
|
const value = newAuthOption.fields[key];
|
||||||
newFields.push({
|
newFields.push({
|
||||||
key: key,
|
key: key,
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var newitem = data;
|
var newitem = data;
|
||||||
for (var key in paramsplit) {
|
for (let [key,keyval] in paramsplit.entries()) {
|
||||||
var tmpparam = paramsplit[key];
|
var tmpparam = paramsplit[key];
|
||||||
if (tmpparam === "#") {
|
if (tmpparam === "#") {
|
||||||
continue;
|
continue;
|
||||||
@@ -579,7 +579,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
console.log("Tags: ", data.tags)
|
console.log("Tags: ", data.tags)
|
||||||
if (data.tags !== undefined && data.tags.length > 0) {
|
if (data.tags !== undefined && data.tags.length > 0) {
|
||||||
var newtags = [];
|
var newtags = [];
|
||||||
for (var key in data.tags) {
|
for (let [key,keyval] in data.tags.entries()) {
|
||||||
if (data.tags[key].name.length > 50) {
|
if (data.tags[key].name.length > 50) {
|
||||||
console.log(
|
console.log(
|
||||||
"Skipping tag because it's too long: ",
|
"Skipping tag because it's too long: ",
|
||||||
@@ -685,7 +685,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
const pathsplit = path.split("/");
|
const pathsplit = path.split("/");
|
||||||
var categoryindex = -1;
|
var categoryindex = -1;
|
||||||
// Stupid way of finding a category/grouping
|
// Stupid way of finding a category/grouping
|
||||||
for (var key in pathsplit) {
|
for (let [key,keyval] in pathsplit.entries()) {
|
||||||
if (pathsplit[key].includes("_shuffle_replace_")) {
|
if (pathsplit[key].includes("_shuffle_replace_")) {
|
||||||
const regex = /_shuffle_replace_\d/i;
|
const regex = /_shuffle_replace_\d/i;
|
||||||
//console.log("NEW: ",
|
//console.log("NEW: ",
|
||||||
@@ -750,9 +750,9 @@ const AppCreator = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//console.log("Data: ", data)
|
//console.log("Data: ", data)
|
||||||
for (var subkey in methodvalue["requestBody"]["content"][
|
for (let [subkey,subkeyval] in methodvalue["requestBody"]["content"][
|
||||||
"application/json"
|
"application/json"
|
||||||
]["schema"]["required"]) {
|
]["schema"]["required"].entries()) {
|
||||||
const tmpitem =
|
const tmpitem =
|
||||||
methodvalue["requestBody"]["content"][
|
methodvalue["requestBody"]["content"][
|
||||||
"application/json"
|
"application/json"
|
||||||
@@ -771,7 +771,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
);
|
);
|
||||||
var newbody = {};
|
var newbody = {};
|
||||||
// Can handle default, required, description and type
|
// Can handle default, required, description and type
|
||||||
for (var propkey in retRef.properties) {
|
for (let [propkey,propkeyval] in retRef.properties.entries()) {
|
||||||
console.log("replace: ", propkey)
|
console.log("replace: ", propkey)
|
||||||
|
|
||||||
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
||||||
@@ -810,9 +810,9 @@ const AppCreator = (defaultprops) => {
|
|||||||
tmpobject[prop] = `\$\{${prop}\}`;
|
tmpobject[prop] = `\$\{${prop}\}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var subkey in methodvalue["requestBody"]["content"][
|
for (let [subkey,subkeyval] in methodvalue["requestBody"]["content"][
|
||||||
"application/xml"
|
"application/xml"
|
||||||
]["schema"]["required"]) {
|
]["schema"]["required"].entries()) {
|
||||||
const tmpitem =
|
const tmpitem =
|
||||||
methodvalue["requestBody"]["content"][
|
methodvalue["requestBody"]["content"][
|
||||||
"application/xml"
|
"application/xml"
|
||||||
@@ -917,7 +917,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
parameter["type"] === "object"
|
parameter["type"] === "object"
|
||||||
) {
|
) {
|
||||||
var newbody = {};
|
var newbody = {};
|
||||||
for (var propkey in parameter.properties) {
|
for (let [propkey,propkeyval] in parameter.properties.entries()) {
|
||||||
console.log("propkey2: ", propkey)
|
console.log("propkey2: ", propkey)
|
||||||
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
||||||
if (parameter.properties[propkey].type === undefined) {
|
if (parameter.properties[propkey].type === undefined) {
|
||||||
@@ -1046,7 +1046,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
parameter["type"] === "object"
|
parameter["type"] === "object"
|
||||||
) {
|
) {
|
||||||
var newbody = {};
|
var newbody = {};
|
||||||
for (var propkey in parameter.properties) {
|
for (let [propkey,propkeyval] in parameter.properties.entries()) {
|
||||||
console.log("propkey3: ", propkey)
|
console.log("propkey3: ", propkey)
|
||||||
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
||||||
if (
|
if (
|
||||||
@@ -1135,7 +1135,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
parameter["type"] === "object"
|
parameter["type"] === "object"
|
||||||
) {
|
) {
|
||||||
var newbody = {};
|
var newbody = {};
|
||||||
for (var propkey in parameter.properties) {
|
for (let [propkey,propkeyval] in parameter.properties.entries()) {
|
||||||
console.log("propkey4: ", propkey)
|
console.log("propkey4: ", propkey)
|
||||||
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
const parsedkey = propkey.replaceAll(" ", "_").toLowerCase();
|
||||||
if (
|
if (
|
||||||
@@ -1219,7 +1219,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
parameter["type"] === "object"
|
parameter["type"] === "object"
|
||||||
) {
|
) {
|
||||||
var newbody = {};
|
var newbody = {};
|
||||||
for (var propkey in parameter.properties) {
|
for (let [propkey,keyval] in parameter.properties.entries()) {
|
||||||
console.log("propkey5: ", propkey)
|
console.log("propkey5: ", propkey)
|
||||||
const parsedkey = propkey
|
const parsedkey = propkey
|
||||||
.replaceAll(" ", "_")
|
.replaceAll(" ", "_")
|
||||||
@@ -1287,7 +1287,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var key in methodvalue.parameters) {
|
for (let [key,keyval] in methodvalue.parameters.entries()) {
|
||||||
const parameter = handleGetRef(methodvalue.parameters[key], data);
|
const parameter = handleGetRef(methodvalue.parameters[key], data);
|
||||||
if (parameter.in === "query") {
|
if (parameter.in === "query") {
|
||||||
var tmpaction = {
|
var tmpaction = {
|
||||||
@@ -1334,7 +1334,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
if (Object.getOwnPropertyNames(wordlist).length === 0) {
|
if (Object.getOwnPropertyNames(wordlist).length === 0) {
|
||||||
for (let [newpath, pathvalue] of Object.entries(data.paths)) {
|
for (let [newpath, pathvalue] of Object.entries(data.paths)) {
|
||||||
const newpathsplit = newpath.split("/");
|
const newpathsplit = newpath.split("/");
|
||||||
for (var key in newpathsplit) {
|
for (let [key,keyval] in newpathsplit.entries()) {
|
||||||
const pathitem = newpathsplit[key].toLowerCase();
|
const pathitem = newpathsplit[key].toLowerCase();
|
||||||
if (wordlist[pathitem] === undefined) {
|
if (wordlist[pathitem] === undefined) {
|
||||||
wordlist[pathitem] = 1;
|
wordlist[pathitem] = 1;
|
||||||
@@ -1351,7 +1351,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
const urlsplit = path.split("/");
|
const urlsplit = path.split("/");
|
||||||
if (urlsplit.length > 0) {
|
if (urlsplit.length > 0) {
|
||||||
var curname = "";
|
var curname = "";
|
||||||
for (var key in urlsplit) {
|
for (let [key,keyval] in urlsplit.entries()) {
|
||||||
var subpath = urlsplit[key];
|
var subpath = urlsplit[key];
|
||||||
if (wordlist[subpath] > 2 || subpath.length < 1) {
|
if (wordlist[subpath] > 2 || subpath.length < 1) {
|
||||||
continue;
|
continue;
|
||||||
@@ -1413,7 +1413,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
const regex = /{\w+}/g;
|
const regex = /{\w+}/g;
|
||||||
const found = firstUrl.match(regex);
|
const found = firstUrl.match(regex);
|
||||||
if (found !== null) {
|
if (found !== null) {
|
||||||
for (var key in found) {
|
for (let [key,keyval] in found.entries()) {
|
||||||
const item = found[key].slice(1, found[key].length - 1);
|
const item = found[key].slice(1, found[key].length - 1);
|
||||||
const foundVar = data.servers[0].variables[item];
|
const foundVar = data.servers[0].variables[item];
|
||||||
if (foundVar["default"] !== undefined) {
|
if (foundVar["default"] !== undefined) {
|
||||||
@@ -1683,7 +1683,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
|
|
||||||
if (newWorkflowTags.length > 0) {
|
if (newWorkflowTags.length > 0) {
|
||||||
var newtags = [];
|
var newtags = [];
|
||||||
for (var key in newWorkflowTags) {
|
for (let [key,keyval] in newWorkflowTags.entries()) {
|
||||||
newtags.push({ name: newWorkflowTags[key] });
|
newtags.push({ name: newWorkflowTags[key] });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1696,7 +1696,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
|
|
||||||
// Handles actions
|
// Handles actions
|
||||||
var handledPaths = []
|
var handledPaths = []
|
||||||
for (var key in actions) {
|
for (let [key,keyval] in actions.entries()) {
|
||||||
var item = JSON.parse(JSON.stringify(actions[key]))
|
var item = JSON.parse(JSON.stringify(actions[key]))
|
||||||
if (item.errors.length > 0) {
|
if (item.errors.length > 0) {
|
||||||
alert.error("Saving with error in action " + item.name);
|
alert.error("Saving with error in action " + item.name);
|
||||||
@@ -1712,7 +1712,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
if (handledPaths.includes(pathjoin)) {
|
if (handledPaths.includes(pathjoin)) {
|
||||||
|
|
||||||
// Max 100 of same lol
|
// Max 100 of same lol
|
||||||
for (var i = 0; i < 100; i++) {
|
for (let i = 0; i < 100; i++) {
|
||||||
item.url = item.url+"_shuffle_replace_"+i
|
item.url = item.url+"_shuffle_replace_"+i
|
||||||
|
|
||||||
pathjoin = item.url+"_"+item.method.toLowerCase()
|
pathjoin = item.url+"_"+item.method.toLowerCase()
|
||||||
@@ -1822,7 +1822,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
if (item.queries.length > 0) {
|
if (item.queries.length > 0) {
|
||||||
var skipped = false;
|
var skipped = false;
|
||||||
var querynames = []
|
var querynames = []
|
||||||
for (var querykey in item.queries) {
|
for (let [querykey,querykeyval] in item.queries.entries()) {
|
||||||
const queryitem = item.queries[querykey];
|
const queryitem = item.queries[querykey];
|
||||||
|
|
||||||
if (queryitem === undefined || queryitem === null || queryitem.name === undefined || queryitem.name === null || queryitem.name === "") {
|
if (queryitem === undefined || queryitem === null || queryitem.name === undefined || queryitem.name === null || queryitem.name === "") {
|
||||||
@@ -1923,7 +1923,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
//data.paths[item.url][item.method.toLowerCase()].parameters.push(newitem)
|
//data.paths[item.url][item.method.toLowerCase()].parameters.push(newitem)
|
||||||
|
|
||||||
if (item.paths.length > 0) {
|
if (item.paths.length > 0) {
|
||||||
for (querykey in item.paths) {
|
for (let [querykey,querykeyval] in item.paths.entries()) {
|
||||||
const queryitem = item.paths[querykey];
|
const queryitem = item.paths[querykey];
|
||||||
|
|
||||||
if (queryitem.toLowerCase() == "url") {
|
if (queryitem.toLowerCase() == "url") {
|
||||||
@@ -1958,7 +1958,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
const values = getCurrentPaths(item.url);
|
const values = getCurrentPaths(item.url);
|
||||||
const paths = values[0];
|
const paths = values[0];
|
||||||
|
|
||||||
for (querykey in paths) {
|
for (let [querykey,querykeyval] in paths.entries()) {
|
||||||
const queryitem = paths[querykey];
|
const queryitem = paths[querykey];
|
||||||
newitem = {
|
newitem = {
|
||||||
in: "path",
|
in: "path",
|
||||||
@@ -1996,7 +1996,7 @@ const AppCreator = (defaultprops) => {
|
|||||||
// but it's the only way we can properly support e.g. GraphQL
|
// but it's the only way we can properly support e.g. GraphQL
|
||||||
// with good examples
|
// with good examples
|
||||||
var newbody = ""
|
var newbody = ""
|
||||||
for (var key in item.body) {
|
for (let [key,keyval] in item.body.entries()) {
|
||||||
if (item.body[key] === "$") {
|
if (item.body[key] === "$") {
|
||||||
if (key > 0) {
|
if (key > 0) {
|
||||||
//console.log("Found: ", item.body[key-1])
|
//console.log("Found: ", item.body[key-1])
|
||||||
@@ -2118,9 +2118,9 @@ const AppCreator = (defaultprops) => {
|
|||||||
const required = false;
|
const required = false;
|
||||||
|
|
||||||
const headersSplit = item.headers.split("\n");
|
const headersSplit = item.headers.split("\n");
|
||||||
for (var key in headersSplit) {
|
for (let [key,keyval] in headersSplit.entries()) {
|
||||||
const header = headersSplit[key];
|
const header = headersSplit[key];
|
||||||
var key = "";
|
// var key = "";
|
||||||
var value = "";
|
var value = "";
|
||||||
if (header.length > 0 && header.includes("= ")) {
|
if (header.length > 0 && header.includes("= ")) {
|
||||||
const headersplit = header.split("= ");
|
const headersplit = header.split("= ");
|
||||||
|
|||||||
@@ -0,0 +1,258 @@
|
|||||||
|
import React, {useState} from 'react';
|
||||||
|
import {isMobile} from "react-device-detect";
|
||||||
|
import {Link} from 'react-router-dom';
|
||||||
|
|
||||||
|
import {Divider, List, ListItem, ListItemText, Card, CardContent, Grid, Typography, Button, ButtonGroup, FormControl, Dialog, DialogTitle, DialogActions, DialogContent, Tooltip} from '@material-ui/core';
|
||||||
|
import {ExpandMore as ExpandMoreIcon, ExpandLess as ExpandLessIcon} from '@material-ui/icons';
|
||||||
|
|
||||||
|
const hrefStyle = {
|
||||||
|
textDecoration: "none",
|
||||||
|
color: "#f85a3e"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* More questions:
|
||||||
|
* What happens with IPv6 vs IPv6?
|
||||||
|
* How long can contracts be?
|
||||||
|
* Any discount? 20% with 1 year+
|
||||||
|
* How can we pay? Manual or not
|
||||||
|
* How is support handled?
|
||||||
|
* How big is the team EXACTLY?
|
||||||
|
* What are requirements for everything?
|
||||||
|
* What level of support does Fredrik/Shuffle provide to paying customers with enterprise license agreements?
|
||||||
|
* What’s their guaranteed response time? 2 hours, 4 hours, next business day? Support 365/24/7, or just weekdays?
|
||||||
|
* How can customers submit support requests? Email, phone, and/or web?
|
||||||
|
* Is there a support team, or is Fredrik the only support person right now?
|
||||||
|
* What’s the annual Shuffle release schedule / frequency? One major release once a year with minor releases quarterly?
|
||||||
|
* The ability to run our own, private instance of Shuffle in a public or private cloud, as well as on virtualized or bare metal, standalone/isolated servers is very important.
|
||||||
|
* We were wondering how the shuffle environment handles a playbook in production(workflow editing and testing phase) vs. in operations (playbook/workflow is operational in a SOC).
|
||||||
|
* Is Shuffle capable of pushing notifications/messages to REDPro if a playbook is Active, Inactive or in Error so it’s general status can be understood via the Playbook Library.
|
||||||
|
* Will cloud webhooks behave any differently from on premise webhooks if we are hosting our own cloud.
|
||||||
|
* If we are hosting on our own cloud and the cloud is not connected to the open internet, will there a be a work around for delivering app updates.
|
||||||
|
* What other maintenance and troubleshooting considerations should we be aware of in an isolated cloud environment
|
||||||
|
* Do you have any documentation for putting workflows into a github.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export const pricingFaq = [
|
||||||
|
{
|
||||||
|
"question": "What currency are your prices in?",
|
||||||
|
"answers": [
|
||||||
|
"They are in US Dollars.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Do you offer discounts or free trials?",
|
||||||
|
"answers": [
|
||||||
|
"We offer free trials, and may offer discounts and features for testing in certain scenarios.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "What payment methods do you offer?",
|
||||||
|
"answers": [
|
||||||
|
"We accept credit cards, Apple Pay, Google Pay and any other payment Stripe supports.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How can I switch to annual billing?",
|
||||||
|
"answers": [
|
||||||
|
"Contact us at <a href='/contact' style={hrefStyle}>Contact</a> page!",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "When does my membership get activated?",
|
||||||
|
"answers": [
|
||||||
|
"As soon as the payment is finished, you should see more features available in the Admin view.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How can I switch my plan?",
|
||||||
|
"answers": [
|
||||||
|
"Contact us at <a href='/contact' style={hrefStyle}>Contact</a> page!",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "What happens after payment is finished?",
|
||||||
|
"answers": [
|
||||||
|
"We will automatically and immediately apply all the featuers to your organization.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How can I cancel my plan?",
|
||||||
|
"answers": [
|
||||||
|
"As an Admin of your organization, you can manage it from the Admin page.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "What is your refund policy?",
|
||||||
|
"answers": [
|
||||||
|
"For monthly and yearly subscriptions, you have 48 hours after the transaction to request a refund. Note that we reserve the right to decline requests if we detect high activity on your account within this time." ,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Do you offer support?",
|
||||||
|
"answers": [
|
||||||
|
"Yes! We offer priority support with an SLA to our enterprise customers, and will answer any questions directed our way on the Contact page otherwise." ,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Can you help me automate my operations?",
|
||||||
|
"answers": [
|
||||||
|
"Yes! We offer support with setup, configuration, automation and app creation. This can be bought as an addition withour needing a subscription.",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
export const faqData = [
|
||||||
|
{
|
||||||
|
"question": "What is Niceable? What’s your mission?",
|
||||||
|
"answers": [
|
||||||
|
"Check out our cool <a href='/about' style={hrefStyle}>About</a> page!",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How does it work?",
|
||||||
|
"answers": [
|
||||||
|
"<a href='/' style={hrefStyle}>We've got you covered!</a>",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "When will winners be announced?",
|
||||||
|
"answers": [
|
||||||
|
"When the prizedraw's 'ticket threshold' is reached, all contributors will receive an email notification about when the live announcement of the winners—the prize winner and the winning charity—will take place. In general, the live announcement happens within 48 hours of the email notification being sent."
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How much goes to charity?",
|
||||||
|
"answers": [
|
||||||
|
"All prizedraws are guaranteed to give the majority of user contributions—more than 50%—to the winning charity. Individual prizedraw hosts (ie, prize vendors) may choose to take a smaller amount for themselves and give a larger percentage to the winning charity. In any case, we are the only prizedraw hosting platform that guarantees that the majority goes to charity. It’s the right thing to do."
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How are winning charities selected?",
|
||||||
|
"answers": [
|
||||||
|
"Charities are selected through a voting process that happens separately for each prizedraw. The community of contributors for a given prizedraw use our voting system to determine the best destination for their crowdsourced contribution. The current vote distribution can be seen on each prizedraw page’s charity leaderboard.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How are the charitable options chosen?",
|
||||||
|
"answers": [
|
||||||
|
"All of the charities that users can vote for have been selected based on them receiving top ratings from the most respected “charity evaluator” organizations. These assessments focus on transparency and financial optimization as well as the nature of their mission and demonstrated impact of their activities. Ultimately, however, YOUR assessment matters most. So, discuss with our community and then decide for yourself!",
|
||||||
|
"If you’d like to recommend a charity or you are part of a charity that’s interested in being featured on our site, please let us know <a href='mailto:adam@niceable.co' style={hrefStyle}>here (adam@niceable.co).</a>",
|
||||||
|
"In the future, additional charities will be added as options with the least voted for charities being replaced. That way, all of our charitable options will be ones that have been top rated by charity evaluator organizations and top vote getters from our wise and beloved Niceable users.",
|
||||||
|
"We are also working on adding lots of information and statistics about each charity to our site, something that our charitable partners are helping us with.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Can I “write-off” my contribution on my taxes?",
|
||||||
|
"answers": [
|
||||||
|
"That depends on where you live. We do not claim to be tax experts and do not offer any advice on such matters. Basically, in some places, you can. In others, you can't. Check with a licensed tax expert in your area.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Can I buy prizedraw prizes directly?",
|
||||||
|
"answers": [
|
||||||
|
"We encourage users to check out prizedraw hosts, many of whom promote our prizedraws and charitable partnerships through social media. They offer prizes because they want to support great charities and offer products and experiences to people who may not always have the money to buy their products directly. Making super nice(able) things accessible to you and everyone else is a major part of our mission and they help us do that.",
|
||||||
|
"The current constraints of capitalism are BS and we're out to change that. Thanks for being a hero! Our prizedraw hosts are reaching out to you and--unlike almost all other organizations--trust YOU to choose the most-worthy charity to support. So, we certainly encourage you to check out their other offerings. They are helping all of you make the impact that YOU want to make and may offer something super nice(able) that's also a perfect fit for you.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How do I enter a promocode?",
|
||||||
|
"answers": [
|
||||||
|
"If its your first time visiting us, you can do it in a Raffle on the right hand side. If you are already logged in, click the 'My account' button in the upper right corner of the screen. Then click the 'enter a promotional code, before submitting the code you have.",
|
||||||
|
"You should now have received more entries!",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "How do you select your vendors?",
|
||||||
|
"answers": [
|
||||||
|
"Currently, our #1 priority is learning more about YOU. What do our users want? What prizes, charities, site features and technology, support, etc.? Therefore, we are currently trying to maximize the diversity of our prizes to see what YOU value most. It’s about you, not us or our vendors.",
|
||||||
|
"Do you most value products and experiences that are ethically-produced? Crazy expensive? Mid-priced? Rare or one-of-a-kind? Created by independent vendors like artists and craftspeople? By everyday people offering services customized for you and you alone? Luxury brands? Houses? Vacations? Cutting-edge technology? Whatever you want, we’ll work hard to offer it. We believe that EVERYONE should be able to have super nice(able) things!",
|
||||||
|
"We are, however, limiting the number of active prizedraws that we have to ensure that these prizedraws fill up quickly, allowing prize winners and winning charities to enjoy their winnings sooner. In the future, we plan to offer many more prizedraws at one time.",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Can I host a prizedraw so that I can make some money, support great charities, and reach new audiences?",
|
||||||
|
"answers": [
|
||||||
|
"<a href='mailto:adam@niceable.co' style={hrefStyle}>Contact us here</Link> (adam@niceable.co)",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "Can I host a prizedraw and donate the prize (because I’m a super nice person)?",
|
||||||
|
"answers": [
|
||||||
|
"<a href='mailto:adam@niceable.co' style={hrefStyle}>Contact us here</Link> (adam@niceable.co)",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const Faq = (props) => {
|
||||||
|
const { theme } = props;
|
||||||
|
|
||||||
|
// Hahah, this is a hack fml
|
||||||
|
const HandleAnswer = (props) => {
|
||||||
|
const [answers, setAnswers] = useState("");
|
||||||
|
const current = props.current
|
||||||
|
|
||||||
|
const loadAnswers = () => {
|
||||||
|
if (answers === "") {
|
||||||
|
const data = current.answers.map(answer => {
|
||||||
|
return answer
|
||||||
|
})
|
||||||
|
|
||||||
|
setAnswers(data.join("<div/>"))
|
||||||
|
} else {
|
||||||
|
setAnswers("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const icon = answers === "" ? <ExpandMoreIcon /> : <ExpandLessIcon />
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem button onClick={() => loadAnswers()} style={{textAlign: "center"}}>
|
||||||
|
<div style={{marginRight: 5, }}>{icon}</div>
|
||||||
|
<ListItemText primary=<Typography variant="body1">{current.question}</Typography> secondary=<td style={{color: "rgba(255,255,255,0.8)"}} dangerouslySetInnerHTML={{__html: answers}} />/>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const width = isMobile ? "100%" : 1000
|
||||||
|
const FAQ =
|
||||||
|
<div elevation={1} style={{padding: isMobile ? "20px 0px 10px 0px" : 100, textAlign: "center", color: "rgba(255,255,255,0.9)", minWidth: width, maxWidth: width, margin: "auto"}}>
|
||||||
|
<Typography variant="h4" style={{textAlign: "center", marginBottom: 50, }}>
|
||||||
|
Frequently asked questions
|
||||||
|
</Typography>
|
||||||
|
<Grid container spacing={4} style={{textAlign: "center", width: isMobile?"100%":"100%"}}>
|
||||||
|
{pricingFaq.map((current) => {
|
||||||
|
return (
|
||||||
|
<Grid item xs={isMobile ? 12 : 6} key={current.question} style={{margin: "auto"}}>
|
||||||
|
<HandleAnswer current={current} />
|
||||||
|
<Divider style={{backgroundColor: "rgba(255,255,255,0.2)"}}/>
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Grid>
|
||||||
|
{/*
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="body1" color="textPrimary" style={{textAlign: "left", marginTop: 15, marginBottom: 5}}>
|
||||||
|
Thanks for reading! Have a super nice(able) time entering prizedraws for amazing prizes, enjoying our awesome community, and making the impact that YOU want to make in the world!
|
||||||
|
</Typography>
|
||||||
|
*/}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
const landingpageData =
|
||||||
|
<div style={{margin: "auto", maxWidth: isMobile ? "100%" : 2560, backgroundColor: theme.palette.inputColor}}>
|
||||||
|
{FAQ}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{landingpageData}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Faq;
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,203 @@
|
|||||||
|
import React, {useState } from 'react';
|
||||||
|
|
||||||
|
import ReactGA from 'react-ga';
|
||||||
|
import { useNavigate, Link, useParams } from "react-router-dom";
|
||||||
|
import {isMobile} from "react-device-detect";
|
||||||
|
|
||||||
|
import {Done as DoneIcon, Clear as ClearIcon} from '@material-ui/icons';
|
||||||
|
import {Paper, Divider, List, ListItem, ListItemText, Card, CardContent, Grid, Typography, Button, ButtonGroup, FormControl, Dialog, DialogTitle, DialogActions, DialogContent, Tooltip} from '@material-ui/core';
|
||||||
|
import FAQ from "./Faq.jsx";
|
||||||
|
import Newsletter from "../components/Newsletter.jsx";
|
||||||
|
|
||||||
|
// 1. Create 2-3 payment tiers (slider?)
|
||||||
|
// 2. Create a way to show them anywhere
|
||||||
|
//
|
||||||
|
// Site references:
|
||||||
|
// https://logz.io/pricing/
|
||||||
|
// https://www.avanan.com/pricing
|
||||||
|
const PaymentField = (props) => {
|
||||||
|
const { maxFields, theme, removeAdditions } = props
|
||||||
|
|
||||||
|
const parsedFields = maxFields === undefined ? 300 : maxFields
|
||||||
|
const [variant, setVariant] = useState(0)
|
||||||
|
const [paymentType, setPaymentType] = useState(0)
|
||||||
|
const [modalOpen, setModalOpen] = useState(false)
|
||||||
|
const [showPricing, ] = useState(true)
|
||||||
|
const [currentPrice, setCurrentPrice] = useState(129)
|
||||||
|
const [isLoaded, setIsLoaded] = useState(false)
|
||||||
|
const [errorMessage, setErrorMessage] = useState("")
|
||||||
|
let navigate = useNavigate();
|
||||||
|
|
||||||
|
if (typeof window === 'undefined' || window.location === undefined) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLoaded) {
|
||||||
|
setIsLoaded(true)
|
||||||
|
|
||||||
|
const tmpsearch = typeof window === 'undefined' || window.location === undefined ? "" : window.location.search
|
||||||
|
const tmpVar = new URLSearchParams(tmpsearch).get("variant")
|
||||||
|
if (tmpVar !== undefined && tmpVar !== null && tmpVar < 3) {
|
||||||
|
setVariant(parseInt(tmpVar))
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmpType = new URLSearchParams(tmpsearch).get("payment_type")
|
||||||
|
if (tmpType !== undefined && tmpType !== null && tmpType < 2) {
|
||||||
|
setPaymentType(parseInt(tmpType))
|
||||||
|
}
|
||||||
|
|
||||||
|
const modal = new URLSearchParams(tmpsearch).get("payment_modal")
|
||||||
|
if (modal !== undefined && modal !== null && modal === "open") {
|
||||||
|
setModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tmpView = new URLSearchParams(tmpsearch).get("view")
|
||||||
|
if (tmpView !== undefined && tmpView !== null && tmpView === "failure") {
|
||||||
|
setErrorMessage("Something went wrong with your payment. Please try again.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const billingInfo = <Typography variant="body2" color="textSecondary" style={{marginTop: 30,}} >Billed anually or monthly at 1.2x the cost</Typography>
|
||||||
|
const maxwidth = isMobile ? "91%" : 1024
|
||||||
|
const activeIcon = <DoneIcon style={{color: "green"}} />
|
||||||
|
const inActiveIcon = <ClearIcon style={{color: "red"}} />
|
||||||
|
|
||||||
|
const cardStyle = {
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
textAlign: "center",
|
||||||
|
backgroundColor: theme.palette.surfaceColor,
|
||||||
|
color: "white",
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxWidth = isMobile ? "100%" : 1000
|
||||||
|
const margin = isMobile ? 15 : 50
|
||||||
|
const paperWidth = isMobile ? "100%" : maxWidth-margin*2
|
||||||
|
const listItemStyle = isMobile ? {textAlign: "center"} : {}
|
||||||
|
const topRet =
|
||||||
|
<div style={{maxWidth: maxWidth, minWidth: maxWidth, margin: "auto", textAlign: isMobile ? "center" : "left",}}>
|
||||||
|
<div style={{margin: isMobile ? 20 : "0px 0px 80px 0px",}}>
|
||||||
|
<Typography variant="h4" style={{marginTop: 100, textAlign: "center",}}>
|
||||||
|
Our team is here to help you
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" style={{marginTop: 20, textAlign: "center",}}>
|
||||||
|
We solve any problem that arises in a security operations center using YOUR tools. Here's how.
|
||||||
|
</Typography>
|
||||||
|
<Paper style={{maxWidth: paperWidth, minWidth: paperWidth, marginBottom: margin/2, marginTop: margin, backgroundColor: theme.palette.surfaceColor, color: "white", padding: isMobile ? 0 : margin, display: "flex", flexDirection: isMobile ? "column": "row", }}>
|
||||||
|
<div style={{flex: 3, borderRight: "1px solid rgba(255,255,255,0.2)"}}>
|
||||||
|
<List style={{marginRight: isMobile ? 0 : 40,}}>
|
||||||
|
<ListItem button onClick={() => {navigate("/usecases")}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Free Usecases"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Hybrid integration"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {"https://discord.gg/B2CBzUm"}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Open Source community"} />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
<div style={{flex: 6, marginLeft: isMobile ? margin : 40, marginRight: isMobile ? margin: 0, marginTop: isMobile ? 30 : 0}}>
|
||||||
|
<Typography variant="h4" style={{}}>
|
||||||
|
Accessibility first
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" style={{marginTop: 20,}}>
|
||||||
|
Shuffle was built by and for security professionals. We aim to bring our unique toolbox to every operations center globally, enabling information sharing and collaboration at scale, whether in the cloud, or on-premises.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
<Paper style={{maxWidth: paperWidth, minWidth: paperWidth, marginBottom: margin/2, marginTop: margin, backgroundColor: theme.palette.surfaceColor, color: "white", padding: isMobile ? 0 : margin, display: "flex", flexDirection: isMobile ? "column": "row",}}>
|
||||||
|
<div style={{flex: 6, marginRight: 40, textAlign: "center",}}>
|
||||||
|
<Typography variant="h4" style={{}}>
|
||||||
|
Automation Services
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" style={{marginTop: 20,}}>
|
||||||
|
Our team of security and automation experts create workflows to automated your SOC end-to-end. In the case that apps are missing, we will create them for you and share with the community to everyones benefit.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div style={{flex: 3, borderLeft: "1px solid rgba(255,255,255,0.2)"}}>
|
||||||
|
<List style={{marginLeft: isMobile ? 0 : 40,}}>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Workflow Creation"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"App Creation"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Custom Development"} />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
<Paper style={{maxWidth: paperWidth, minWidth: paperWidth, marginBottom: margin/2, marginTop: margin, backgroundColor: theme.palette.surfaceColor, color: "white", padding: isMobile ? 0 : margin, display: "flex",flexDirection: isMobile ? "column": "row",}}>
|
||||||
|
<div style={{flex: 3, borderRight: "1px solid rgba(255,255,255,0.2)"}}>
|
||||||
|
<List style={{marginRight: 40,}}>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Quick response times"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Upgrades & configurations"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Business hour support"} />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
<div style={{flex: 6, marginLeft: isMobile ? 0 :40,}}>
|
||||||
|
<Typography variant="h4" style={{}}>
|
||||||
|
Support and Maintenance
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="textSecondary" style={{marginTop: 20,}}>
|
||||||
|
We recognize that support is a vital part of keeping operations stable and secure. That's why we're offering support of both the cloud platform and usage, as well as for the open source version of Shuffle.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
<Paper style={{maxWidth: paperWidth, minWidth: paperWidth, marginBottom: margin/2, marginTop: margin, backgroundColor: theme.palette.surfaceColor, color: "white", padding: isMobile ? 0 : margin, display: "flex",flexDirection: isMobile ? "column": "row",}}>
|
||||||
|
<div style={{flex: 6, marginRight: 40,}}>
|
||||||
|
<Typography variant="h4" style={{}}>
|
||||||
|
Training
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" style={{marginTop: 20,}}>
|
||||||
|
We teach you how to become a poweruser of Shuffle. It involves how to maintain, create, share and use it Shuffle, whether in a small operations center or as an MSSP.
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<div style={{flex: 3, borderLeft: "1px solid rgba(255,255,255,0.2)"}}>
|
||||||
|
<List style={{marginLeft: isMobile ? 0 : 40,}}>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Administration"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Configuration"} />
|
||||||
|
</ListItem>
|
||||||
|
<ListItem button onClick={() => {}} style={listItemStyle}>
|
||||||
|
<ListItemText primary={"Platform Development"} />
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
|
</div>
|
||||||
|
</Paper>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{paddingBottom: removeAdditions ? 0 : 100}}>
|
||||||
|
{topRet}
|
||||||
|
{removeAdditions === true ? null :
|
||||||
|
<span>
|
||||||
|
<FAQ theme={theme} type={"pricing"}/>
|
||||||
|
<div style={{marginTop: 100, marginBottom: 100,}}>
|
||||||
|
<Typography variant="h4">
|
||||||
|
Got other questions?
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body1" color="textSecondary" style={{marginBottom: 200}}>
|
||||||
|
If you got more questions about our pricing and plans, please <Link to="/contact" style={{textDecoration: "none", color: theme.palette.primary.main}}>contact us</Link> so we can help
|
||||||
|
</Typography>
|
||||||
|
<Newsletter />
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentField;
|
||||||
Reference in New Issue
Block a user