import React, { useState, useEffect } from "react"; import { toast } from "react-toastify" import theme from '../theme.jsx'; import AuthenticationOauth2 from "../components/Oauth2Auth.jsx"; import { validateJson, GetIconInfo } from "../views/Workflows.jsx"; import { Tooltip, Typography, Button, Divider, MenuItem, Select, Chip, TextField, CircularProgress, } from "@mui/material" import { CheckCircleOutline as CheckCircleOutlineIcon, ErrorOutline as ErrorOutlineIcon, } from "@mui/icons-material" import { green, red, } from "../views/AngularWorkflow.jsx" const FixWorkflowValidationErrors = (props) => { const { globalUrl, workflow, setWorkflow, setUpdateParent, } = props; const [appsLoading, setAppsLoading] = useState(false) const [apps, setApps] = useState([]) const [appAuth, setAppAuth] = useState([]) const [_, setUpdate] = useState(0) const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io" || window.location.host === "migration.shuffler.io"; if (workflow === undefined || workflow === null) { console.error("Workflow is undefined") return null } if (workflow.validation === undefined || workflow.validation === null) { console.error("Workflow validation is undefined") return null } if (workflow.validation.valid === true) { console.error("Workflow is valid - nothing to do for errors") return null } if (setWorkflow === undefined || setWorkflow === null) { console.error("No setWorkflow") return null } const fetchApps = () => { if (appsLoading === true) { return } setAppsLoading(true) const url = `${globalUrl}/api/v1/apps` fetch(url,{ method: "GET", credentials: "include" }) .then(response => response.json()) .then(data => { setAppsLoading(false) if (data.success === false) { return } setApps(data) }) .catch(error => { setAppsLoading(false) console.error("Error: ", error) }) } // Save the workflow as well const saveWorkflow = (workflow) => { if (workflow.id === undefined || workflow.id === null) { toast("Workflow ID is missing during save. Please try again") return } const url = `${globalUrl}/api/v1/workflows/${workflow.id}` fetch(url, { method: "PUT", headers: { "Content-Type": "application/json", Accept: "application/json", }, credentials: "include", body: JSON.stringify(workflow), }) .then(response => response.json()) .then(data => { if (data.success === false) { toast("Failed to save workflow") return } }) .catch(error => { toast("Failed to save workflow: " + error.toString()) }) } const fetchAuthentication = (reset, updateAction, closeMenu, action_id) => { if (appsLoading === true) { return } const url = `${globalUrl}/api/v1/apps/authentication` fetch(url,{ method: "GET", credentials: "include" }) .then(response => response.json()) .then(data => { if (data.success === false) { return } const authlist = data.data setAppAuth(authlist) if (updateAction === true) { console.log("Updating action: ", action_id) // Find the action in the workflow and set auth for it var foundActionIndex = -1 for (var i = 0; i < workflow.actions.length; i++) { if (workflow.actions[i].id === action_id) { foundActionIndex = i break } } if (foundActionIndex === -1) { console.error("Failed to find action in workflow") return } const appId = workflow.actions[foundActionIndex].app_id var lastauth = -1 for (var authKey in authlist) { if (authlist[authKey].app_id !== appId) { continue } if (authlist[authKey].created > lastauth) { lastauth = authlist[authKey].created } else { continue } console.log("FOUND AUTH: ", authlist[authKey]) workflow.actions[foundActionIndex].authentication_id = authlist[authKey].id } if (setWorkflow !== undefined) { setWorkflow(workflow) } } }) .catch(error => { console.error("Auth loading error: ", error) }) } if (apps !== undefined && apps !== null && apps.length === 0 && appsLoading === false) { fetchApps() fetchAuthentication() } const setSelectedAction = (action) => { if (workflow === undefined || workflow === null) { return null } if (workflow.actions === undefined || workflow.actions === null || workflow.actions.length === 0) { return null } if (setWorkflow === undefined || setWorkflow === null) { return null } for (var i = 0; i < workflow.actions.length; i++) { if (workflow.actions[i].id === action.id) { workflow.actions[i] = action // Update any action with the same app_id to have same auth for (var j = 0; j < workflow.actions.length; j++) { if (workflow.actions[j].app_id === action.app_id) { workflow.actions[j].authentication_id = action.authentication_id workflow.actions[j].selectedAuthentication = action.selectedAuthentication } } break } } setWorkflow(workflow) } const ErrorItem = (props) => { const { apps, error, index } = props const [validating, setValidating] = useState(false) const [actionRunInfo, setActionRunInfo] = useState({}) if (error === undefined || error === null) { return null } if (apps === undefined || apps === null || apps.length === 0) { return null } const validateApp = (app, action) => { if (validating) { return } setValidating(true) // FIXME: Run execution: // 1. Should set app authentication validation if (isCloud) { action.environment = "Cloud" } else { action.environment = "Shuffle" } /* setExecutionResult({ valid: false, result: baseResult, }) setExecuting(true); */ setActionRunInfo({}) const url = `${globalUrl}/api/v1/apps/${app.id}/run?validation=true` fetch(url, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json", }, body: JSON.stringify(action), credentials: "include", }) .then((response) => { if (response.status !== 200) { console.log("Status not 200 for stream results :O!"); } return response.json(); }) .then((responseJson) => { setValidating(false) setActionRunInfo(responseJson) //console.log("RESPONSE: ", responseJson) if ( responseJson.success === true && responseJson.result !== null && responseJson.result !== undefined && responseJson.result.length > 0 ) { //toast(" } }) .catch((error) => { toast("Execution error: " + error.toString()); setValidating(false) }) } var authReturn = null var validationReturn = null var foundApp = { "name": "", "id": "", } var foundAction = { "name": "", "label": "", "id": "", "app_id": "", "app_name": "", } var selectedImage = null var resolveButton = null if (error.app_id !== undefined && error.app_id !== null) { for (var i = 0; i < apps.length; i++) { if (apps[i].id === error.app_id) { foundApp = apps[i] break } } if (!foundApp) { toast("Couldn't find relevant app. Is it activated?") return "Failed to find app" } selectedImage = } if (error.action_id !== undefined && error.action_id !== null && workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { for (var i = 0; i < workflow.actions.length; i++) { if (workflow.actions[i].id === error.action_id) { foundAction = workflow.actions[i] break } } } const validationIcon = Object.getOwnPropertyNames(actionRunInfo).length === 0 ? null : {actionRunInfo.result} } placement="bottom" > {actionRunInfo.validation.valid === true ? : } const authenticationType = foundApp.authentication if (error.type === "configuration" || error.type === "authentication") { // FIXME: Check the error if (appAuth === undefined || appAuth === null) { return "Loading auth" } var relevantAuthentication = [] var foundAuth = {} for (var key in appAuth) { if (appAuth[key].app.id !== error.app_id) { continue } foundAuth = appAuth[key] relevantAuthentication.push(appAuth[key]) } if (foundAction.selectedAuthentication === undefined || foundAction.selectedAuthentication === null) { foundAction.selectedAuthentication = {} } console.log("FOUNDACTION: ", foundAction, foundAuth) var authFound = false if (foundAuth.id !== undefined && foundAuth.id !== null && foundAuth.id.length > 0) { var authGroups = [] // Choose from a dropdown authReturn = } // FIXME: Validate the CURRENT authentication that has been chosen? if (foundApp.authentication === undefined || foundApp.authentication === null) { toast("Authentication error: No authentication found") authReturn = "Failed to find auth" } if (authReturn === null && foundApp.authentication.type === "oauth2" || foundApp.authentication.type === "oauth2-app") { authReturn = } else if (authReturn === null) { authReturn = "Other auth - Not implemented" } validationReturn = authReturn === null || foundAuth.id === undefined || foundAuth.id === null || foundAuth.id.length === 0 || !authFound ? null : //resolveButton = !(Object.getOwnPropertyNames(actionRunInfo).length === 0 || actionRunInfo.validation.valid === true) ? null : resolveButton = } return (
{authReturn}
{validationReturn} {resolveButton}
) } console.log("Workflow validation: ", workflow.validation) return (
{workflow.errors !== undefined && workflow.errors !== null ?
General errors: {workflow.errors.length} {workflow.errors.map((error, index) => { return (
- {error}
) })}
: null} {workflow.validation.errors !== undefined && workflow.validation.errors !== null ?
Validation errors: {workflow.validation.errors.length} {workflow.validation.errors.map((error, index) => { return (
) })}
: null} Apps loaded: {apps.length}
) } export default FixWorkflowValidationErrors