import React, { useState, useEffect } from "react";
import { toast } from "react-toastify"
import theme from '../theme.jsx';
import { useNavigate, Link, useParams } from "react-router-dom";
import AppSearchButtons from "../components/AppSearchButtons.jsx";
import { isMobile } from "react-device-detect";
import RenderCytoscape from "../components/RenderCytoscape.jsx";
import {
Button,
Typography,
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Drawer,
CircularProgress,
IconButton,
Tooltip,
} from "@mui/material";
import {
Check as CheckIcon,
TrendingFlat as TrendingFlatIcon,
Close as CloseIcon,
East as EastIcon,
} from '@mui/icons-material';
import WorkflowTemplatePopup2 from "./WorkflowTemplatePopup.jsx";
import ConfigureWorkflow from "../components/ConfigureWorkflow.jsx";
const WorkflowTemplatePopup = (props) => {
const { userdata, appFramework, globalUrl, img1, srcapp, img2, dstapp, title, description, visualOnly, apps, isLoggedIn, isHomePage, getAppFramework, } = props;
const [isActive, setIsActive] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [modalOpen, setModalOpen] = useState(false);
const [errorMessage, setErrorMessage] = useState("");
const [workflowLoading, setWorkflowLoading] = useState(false);
const [workflow, setWorkflow] = useState({});
const [showLoginButton, setShowLoginButton] = useState(false);
const [appAuthentication, setAppAuthentication] = React.useState(undefined);
const [missingSource, setMissingSource] = React.useState(undefined)
const [missingDestination, setMissingDestination] = React.useState(undefined);
const [configurationFinished, setConfigurationFinished] = React.useState(false);
const [appSetupDone, setAppSetupDone] = React.useState(false)
const [requestSent, setRequestSent] = React.useState(false)
const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io";
let navigate = useNavigate();
useEffect(() => {
if (modalOpen !== true) {
return
}
if (!srcapp.includes(":default") && !dstapp.includes(":default")) {
if (appSetupDone === false && setAppSetupDone !== undefined) {
setAppSetupDone(true)
}
getGeneratedWorkflow()
}
if (missingSource !== undefined && missingDestination !== undefined) {
if (appSetupDone === false && setAppSetupDone !== undefined) {
setAppSetupDone(true)
}
}
if (getAppFramework !== undefined) {
setTimeout(() => {
getAppFramework()
}, 500)
}
}, [modalOpen, missingSource, missingDestination])
const imagestyleWrapper = {
height: 40,
width: 40,
borderRadius: 40,
border: isHomePage ? null : "1px solid rgba(255,255,255,0.3)",
overflow: "hidden",
display: "flex",
}
const imagestyleWrapperDefault = {
height: 40,
width: 40,
borderRadius: 40,
border: isHomePage ? null : "1px solid rgba(255,255,255,0.3)",
overflow: "hidden",
display: "flex",
}
const imagestyle = {
height: 40,
width: 40,
borderRadius: 40,
border: isHomePage ? null : "1px solid rgba(255,255,255,0.3)",
overflow: "hidden",
}
const imagestyleDefault = {
display: "block",
marginLeft: 12,
marginTop: 11,
height: 35,
width: "auto",
}
if (title === undefined || title === null || title === "") {
console.log("No title for workflow template popup!");
return null
}
const getWorkflow = (workflowId) => {
fetch(`${globalUrl}/api/v1/workflows/${workflowId}`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for framework!");
}
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
console.log("Error in workflow loading for ID ", workflowId)
} else {
setWorkflow(responseJson)
}
})
.catch((error) => {
console.log("err in framework: ", error.toString());
setWorkflowLoading(false)
})
}
const loadAppAuth = () => {
// Check if it exists, and has keys
if (userdata === undefined || userdata === null || Object.keys(userdata).length === 0) {
setErrorMessage("You need to be logged in to try the pre-built Workflow Templates.")
setShowLoginButton(true)
// Send the user to the login screen after 3 seconds
setTimeout(() => {
// Make it cancel if the state modalOpen changes
if (modalOpen === false) {
return
}
navigate("/login?view=" + window.location.pathname + window.location.search)
}, 4500)
return
}
fetch(`${globalUrl}/api/v1/apps/authentication`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for setting app auth :O!");
}
return response.json();
})
.then((responseJson) => {
if (!responseJson.success) {
toast("Failed to get app auth: " + responseJson.reason);
return
}
var newauth = [];
for (let authkey in responseJson.data) {
if (responseJson.data[authkey].defined === false) {
continue;
}
newauth.push(responseJson.data[authkey]);
}
setAppAuthentication(newauth);
})
.catch((error) => {
//toast(error.toString());
console.log("New auth error: ", error.toString());
});
}
// Can create and set workflows
const reloadWorkflow = (workflow_id) => {
const new_url = `${globalUrl}/api/v1/workflows/${workflow_id}`
return fetch(new_url, {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for workflows :O!");
return;
}
//setSubmitLoading(false);
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
toast("Error setting workflow: ", responseJson.reason)
} else {
toast("Error setting workflow.")
}
return
} else if (responseJson.id !== undefined && responseJson.id !== null && responseJson.id !== "") {
setWorkflow(responseJson)
}
return responseJson;
})
.catch((error) => {
toast("Failed reloading configured workflow: ", error.toString());
});
};
// Can create and set workflows
const saveWorkflow = (workflowdata) => {
const new_url = `${globalUrl}/api/v1/workflows?set_auth=true`
return fetch(new_url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(workflowdata),
credentials: "include",
})
.then((response) => {
if (response.status !== 200) {
console.log("Status not 200 for workflows :O!");
return;
}
//setSubmitLoading(false);
return response.json();
})
.then((responseJson) => {
if (responseJson.success === false) {
if (responseJson.reason !== undefined) {
toast("Error setting workflow: ", responseJson.reason)
} else {
toast("Error setting workflow.")
}
return
}
// In case it got a new id, this is to make sure it loads with the correct config
if (responseJson.id !== undefined && responseJson.id !== null && responseJson.id !== "") {
reloadWorkflow(responseJson.id)
}
return responseJson;
})
.catch((error) => {
toast("Failed generating workflow: ", error.toString());
});
};
const getGeneratedWorkflow = () => {
// POST
// https://shuffler.io/api/v1/workflows/merge
// destination: {app_id: "b9c2feaf99b6309dabaeaa8518c61d3d", app_name: "Servicenow_API", app_version: "",…}
// id: ""
// middle:[]
// name: "Email analysis"
// source:{app_id: "accdaaf2eeba6a6ed43b2efc0112032d", app_name
if (requestSent === true) {
return
}
if (srcapp.includes(":default") || dstapp.includes(":default")) {
toast("You need to select both a source and destination app before generating this workflow.")
if (srcapp.includes(":default")) {
setMissingSource({
"type": srcapp.split(":")[0],
})
}
if (dstapp.includes(":default")) {
setMissingDestination({
"type": dstapp.split(":")[0],
})
}
return
}
setWorkflowLoading(true)
const newsrcapp = srcapp
const newdstapp = dstapp
const mergedata = {
name: title,
id: "",
source: {
app_name: newsrcapp,
},
middle: [],
destination: {
app_name: newdstapp,
},
}
setRequestSent(true)
const url = isCloud ? `${globalUrl}/api/v1/workflows/merge` : `https://shuffler.io/api/v1/workflows/merge`
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
credentials: "include",
body: JSON.stringify(mergedata),
})
.then((response) => {
if (response.status !== 200) {
//console.log("Status not 200 for framework!");
setRequestSent(false)
}
setWorkflowLoading(false)
return response.json();
})
.then((responseJson) => {
if (responseJson.id !== undefined && responseJson.id !== null && responseJson.id !== "" && responseJson.name !== undefined && responseJson.name !== null && responseJson.name !== "") {
console.log("Success in workflow template (prebuilt): ", responseJson);
setWorkflow(responseJson)
// Sets it in the database properly
saveWorkflow(responseJson)
return
}
if (responseJson.success === false) {
//console.log("Error in workflow template: ", responseJson.error);
setRequestSent(false)
const defaultMessage = "Failed to generate workflow the workflow - the Shuffle team has been notified. Contact support@shuffler.io for further assistance."
if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason !== "") {
setErrorMessage(defaultMessage + "\n\n" + responseJson.reason)
} else {
setErrorMessage(defaultMessage)
}
setIsActive(true)
//setTimeout(() => {
// setModalOpen(false)
//}, 5000)
} else {
console.log("Success in workflow template: ", responseJson);
setIsActive(true)
if (responseJson.workflow_id === "") {
console.log("Failed to build workflow for these tools. Closing in 3 seconds.")
return
}
getWorkflow(responseJson.workflow_id)
}
})
.catch((error) => {
console.log("err in framework: ", error.toString());
setRequestSent(false)
setWorkflowLoading(false)
})
}
if (modalOpen === true && !srcapp.includes(":default") && !dstapp.includes(":default")) {
if (appSetupDone === false && setAppSetupDone !== undefined) {
setAppSetupDone(true)
}
if (workflow.id === undefined && workflowLoading === false && errorMessage === "") {
getGeneratedWorkflow()
}
}
const isFinished = () => {
// Look for configuration fields being done in the current modal
// 1. Start by finding the modal
const template = document.getElementById("workflow-template")
if (template === null || template == undefined) {
return true
}
// Find item in template with id app-config
const appconfig = template.getElementsByClassName("app-config")
if (appconfig === null || appconfig == undefined) {
return true
}
return false
}
const ModalView = () => {
if (modalOpen === false) {
return null
}
const divHeight = 500
const divWidth = 500
return (