diff --git a/frontend/src/components/SubflowSuggestions.jsx b/frontend/src/components/SubflowSuggestions.jsx new file mode 100644 index 00000000..01ad8f96 --- /dev/null +++ b/frontend/src/components/SubflowSuggestions.jsx @@ -0,0 +1,566 @@ +import React, { useEffect } from "react"; + +import { makeStyles } from "@mui/styles"; +import theme from '../theme.jsx'; +import { toast } from "react-toastify" + +import AuthenticationData from "../components/AuthenticationWindow.jsx" + +import { + Chip, + Modal, + Button, + Typography, + FormControl, + TextField, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Select, + MenuItem, + Box, + Divider, + InputLabel, + Stack, +} from '@mui/material'; + +const useStyles = makeStyles({ + notchedOutline: { + borderColor: "#f85a3e !important", + }, +}) + +const SubflowSuggestions = (props) => { + const { + type, + globalUrl, + workflows, + notificationWorkflow, + selectedOrganization, + } = props + + const classes = useStyles(); + + const [notificationWorkflowModal, setNotificationWorkflowModal] = React.useState(false); + const [selectedAppDetails, setSelectedAppDetails] = React.useState({}); + const [notificationWorkflowTestModal, setNotificationWorkflowTestModal] = React.useState(false); + const [selectedAuth, setSelectedAuth] = React.useState(''); + const [emailData,setEmailData] = React.useState([]); + const [notificationAppDetails, setNotificationAppDetails] = React.useState([]); + const [generatedWorkflow, setGeneatedWorkflow] = React.useState({}); + const [textFieldValue, setTextFieldValue] = React.useState(""); + const [textFieldOneValue, setTextFieldOneValue] = React.useState(""); + + // getting comms & cases app from app framework + var notificationAppList = []; + if (selectedOrganization.security_framework.cases && selectedOrganization.security_framework.cases.name.length > 0) { + notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.cases); + } + if (selectedOrganization.security_framework.communication && selectedOrganization.security_framework.communication.name.length > 0) { + notificationAppList = notificationAppList.concat(selectedOrganization.security_framework.communication); + } + + useEffect(() => { + let nameList = notificationAppList.length > 0? notificationAppList.map(item => item.name): ["email"]; + prepareNotificationAppList(nameList) + }, [notificationAppList,workflows]); + + const executeTestWorkflow = (workflowid) => { + const data = { "execution_argument": '{"title":"THIS IS TEST ALERT","description":"TEST ALERT FROM SHUFFLE","reference_url": "shuffler.io"}' } + + fetch(globalUrl + `/api/v1/workflows/${workflowid}/execute`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + toast("Failed setting notification workflow: ", response.reason); + console.log("Status not 200 for workflows :O!"); + return; + } + toast("Notification workflow ran successfully"); + return response.json(); + }).catch((error) => { + console.log("Error getting workflows: " + error); + }) + } + + + const testWorkflowModal = notificationWorkflowTestModal ? + { + setNotificationWorkflowTestModal(false); + }} + > + + {/* +
+ Notification workflow +
+
*/} + + We have updated the Notification workflow. Do you want to test it? + + + + + +
+
: null + + // fixxxxxxxxxxxxxxxxxxxx + const checkIfAlreadyGenerated = (appList, workflows) => { + + var workflowName = workflows.find(workflow => workflow.id === notificationWorkflow) + if (workflowName) { + workflowName = workflowName.name + } + else { + console.log("no workflow set") + return + } + if (workflowName) { + const parts = workflowName.split(' '); + console.log("parts", parts) + if (parts[0].toString() === "[GENERATED]" && parts.length > 1) { + console.log("parts1", parts[1]) + if ((appList.includes(parts[1]))) { + console.log("workflow already generated") + setGeneatedWorkflow({"app_name": parts[1]}) + } + } + } + else { + return + } + } + + const mergeAuthData = (result, responseJson) => { + const updatedResult = result.map(item => { + const matches = responseJson.filter(authItem => authItem.app.name === item.name); + return { + ...item, + authentication_data: matches.length > 0 ? matches : null + } + }) + + return updatedResult + } + + const prepareNotificationAppList = (appList) => { + var result = [] + fetch(globalUrl + "/api/v1/apps", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }).then((response) => { + if (response.status !== 200) { + toast("Failed getting app ids: ", response.reason); + console.log("Status not 200 for app ids :O!"); + return; + } + return response.json(); + }).then((responseJson) => { + if (responseJson !== undefined) { + const filteredApps = responseJson.filter(app => appList.includes(app.name)); + const emailData = responseJson.filter(app => app.name === "email") + setEmailData(emailData) + const appDetails = filteredApps.map(app => ({ name: app.name, id: app.id })); //mapped apps with IDs as sometime Ids were not correct in security framework + // console.log("appDetails: ", appDetails) + // result = appDetails + + fetch(globalUrl + "/api/v1/apps/authentication", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + toast(`Failed getting auth for : `, response.reason); + console.log("Status not 200 for app auth :O!"); + return; + } + return response.json(); + }).then((responseJson) => { + if (!responseJson.success) { + console.log("Could not get app auth") + return; + } + // console.log("responseJson of auth: ", responseJson.data) + result = mergeAuthData(appDetails, responseJson.data) + // console.log("merged auth data: ", result) + // console.log("result", result) + result.map(item => { + fetch(globalUrl + `/api/v1/apps/${item.id}/config`, { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }).then((response) => { + if (response.status !== 200) { + toast(`Failed getting config for ${item.id}: `, response.reason); + console.log("Status not 200 for app config :O!"); + return; + } + return response.json(); + }).then((responseJson) => { + if (!responseJson.success) { + console.log("Could not get app config") + return; + } + var decodedString = JSON.parse(atob(responseJson.app)); + // console.log("dcodedString: ",decodedString) + item.auth_config = decodedString.authentication + item.large_image = decodedString.large_image + setNotificationAppDetails(result) + console.log("notificationAppDetails: ", notificationAppDetails) + }).then(()=>{ + checkIfAlreadyGenerated(appList,workflows); + + }).catch((error) => { + console.log("Error getting app config: " + error); + toast("Error getting app config: " + error); + }) + }) + }) + } + }).catch((error) => { + console.log("Error getting app ids: " + error); + }) + } + + const renderChips = (apps) => { + return ( + + {apps.map((app) => ( + { + console.log(`Clicked ${app.name}`) + console.log("app: ",app) + setSelectedAppDetails(app) + if (app.authentication_data && app.authentication_data.length > 0){ //fixxxxxxxx + console.log("authdata: ",app.authentication_data[0]) + setSelectedAuth(app.authentication_data[app.authentication_data.length-1].id) + } + setNotificationWorkflowModal(true) + // getAppAuth(app.name) + console.log("selectedAppDEtails",selectedAppDetails) + }} + avatar={{app.name}} + + /> + ))} + + ) + } + + const generateEmailNotificationWorkflow = async (appname,appImage,shuffleAPIKey,recepients) => { + //currently only supports figure out a way to support more apps + const workflowName = `[GENERATED] ${appname} notification workflow` + const workflowDescription = "Generated by Shuffle for sending info/error notifications." + const data = { + "name": workflowName, + "description": workflowDescription, + } + + fetch(globalUrl + "/api/v1/workflows", { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + toast("Failed setting notification workflow: ", response.reason); + console.log("Status not 200 for workflows :O!"); + return; + } + return response.json(); + }).then((responseJson)=>{ + if (responseJson !== undefined) { + console.log("Notification workflow created successfully") + var workflow_id = responseJson.id + if (appname.toLowerCase() === "email"){ + console.log("updating workflow for email") + var workflowBody = { + "name": workflowName, + "Description": workflowDescription, + "id": workflow_id, + "actions": [ + { + "app_name": "email", + "name": "send_email_shuffle", + "large_image":appImage, + "isStartNode": true, + "label": "send_email_shuffle", + "app_version": "1.3.0", + "parameters": [ + { + "name": "apikey", + "value": shuffleAPIKey + }, + { + "name": "recipients", + "value": recepients + }, + { + "name": "subject", + "value": "$exec.title" + }, + { + "name":"body", + "value":"$exec.description" + } + ] + } + ] + } + } + fetch(globalUrl + `/api/v1/workflows/${workflow_id}`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(workflowBody), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + toast("Failed setting notification workflow: ", response.reason); + console.log("Status not 200 for workflows :O!"); + return; + } + return response.json(); + }).then((responseJson)=>{ + if (responseJson !== undefined) { + if (type === "notification") { + console.log("FIXME: Notification workflow updated successfully") + toast("FIXME: Notification workflow updated successfully") + } + } + }) + } + }).catch((error) => { + console.log("Error setting workflows: " + error); + }) +} + + + + + + + const modalView = notificationWorkflowModal ? ( + { + setNotificationWorkflowModal(false); + }} + > + + +
+ {`Configure ${selectedAppDetails.name} workflow`} +
+
+ + + {console.log("len Selected app details: ", selectedAppDetails)} + {(selectedAppDetails.authentication_data || (selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false) || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ? + <> + + {(selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ? "No authentication required": + <> + + Pick an authentication method from the list + + + Available authentications + + } + + + + Provide additional required details: + + { + setTextFieldOneValue(e.target.value) + }} + InputProps={{ + classes: { + notchedOutline: classes.notchedOutline, + }, + style: { + color: "white", + }, + }} /> + { + setTextFieldValue(e.target.value) + }} + InputProps={{ + classes: { + notchedOutline: classes.notchedOutline, + }, + style: { + color: "white", + }, + }} /> + + : + <> + 0) ? false : true} + // // setAuthenticationModalOpen={false} + selectedApp={{...selectedAppDetails,authentication: selectedAppDetails.auth_config}} + // getAppAuthentication={selectedAppDetails.name} + /> + + } + + + + + +
+
+) : null + + return ( +
+ {modalView} + + {/*{testWorkflowModal} */} +
+ {renderChips(notificationAppDetails.length > 0 ? notificationAppDetails : emailData)} +
+
+ ) +} + +export default SubflowSuggestions;