import React, { useEffect } from "react"; import { makeStyles } from "@mui/styles"; import theme from '../theme.jsx'; import { toast } from "react-toastify" import Chip from '@mui/material/Chip'; import Stack from '@mui/material/Stack'; import AuthenticationData from "./AuthenticationWindow"; import { FormControl, InputLabel, Paper, OutlinedInput, Checkbox, Card, Tooltip, FormControlLabel, Typography, Switch, Select, MenuItem, Divider, TextField, Button, Tabs, Tab, Grid, IconButton, Autocomplete, Dialog, DialogTitle, DialogActions, DialogContent, Box } from "@mui/material"; import { ExpandLess as ExpandLessIcon, ExpandMore as ExpandMoreIcon, Save as SaveIcon, } from "@mui/icons-material"; const useStyles = makeStyles({ notchedOutline: { borderColor: "#f85a3e !important", }, }); const OrgHeaderexpanded = (props) => { const { userdata, selectedOrganization, setSelectedOrganization, globalUrl, isCloud, adminTab, } = props; 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 [workflows, setWorkflows] = React.useState([]) const [workflow, setWorkflow] = React.useState({}) // notification workflow const [notificationApp, setNotificationApp] = React.useState("") const [notificationWorkflowModal, setNotificationWorkflowModal] = React.useState(false); const [selectedAppDetails, setSelectedAppDetails] = React.useState({}); const [notificationWorkflowTestModal, setNotificationWorkflowTestModal] = React.useState(false); const [webhookInputValue, setWebhookInputValue] = React.useState(""); const [authOptions, setAuthOptions] = React.useState([]); const [selectedAuth, setSelectedAuth] = React.useState(''); // const [selectedAppAuth, setSelectedAppAuth] = React.useState({}); // for getting selected app auth parameters const [authenticationModal, setAuthenticationModal] = React.useState(false); const [notificationAppDetails, setNotificationAppDetails] = React.useState([]); // const [tempResult, setTempResult] = React.useState([]) // useEffect(() => { // if (authOptions.length < 1) { // {getAppConfig(selectedAppDetails.id)} // } // }, [authOptions.length]); // not using this now useEffect(() => { if (notificationAppList.length > 0) { (async () => { const nameList = notificationAppList.map(item => item.name); await prepareNotificationAppList(nameList); })(); } }, [notificationAppList]); // for jira & email modal const [textFieldValue, setTextFieldValue] = React.useState(""); const [textFieldOneValue, setTextFieldOneValue] = React.useState(""); const getAvailableWorkflows = (trigger_index) => { fetch(globalUrl + "/api/v1/workflows", { 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; } return response.json(); }) .then((responseJson) => { if (responseJson !== undefined) { setWorkflows(responseJson) if (selectedOrganization.defaults !== undefined && selectedOrganization.defaults.notification_workflow !== undefined) { const workflow = responseJson.find((workflow) => workflow.id === selectedOrganization.defaults.notification_workflow) if (workflow !== undefined && workflow !== null) { setWorkflow(workflow) } } } }) .catch((error) => { console.log("Error getting workflows: " + error); }) } useEffect(() => { getAvailableWorkflows() }, []) 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) { toast("Failed updating org: ", responseJson.reason); } else { toast("Successfully edited org!"); } }) ) .catch((error) => { toast("Err: " + error.toString()); }); }; const handleWorkflowSelectionUpdate = (e, isUserinput) => { if (e.target.value === undefined || e.target.value === null || e.target.value.id === undefined) { console.log("Returning as there's no id") return null } setWorkflow(e.target.value) setNotificationWorkflow(e.target.value.id) toast("Updated notification workflow. Don't forget to save!") } const orgSaveButton = (
); const getAppIDs = async (appList) => { 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) { // console.log("App ids: ", responseJson) // console.log("App list: ", appList) const filteredApps = responseJson.filter(app => appList.includes(app.name)); const appDetails = filteredApps.map(app => ({ name: app.name, id: app.id })); return appDetails // console.log("App IDs: ", appDetails) } }).catch((error) => { console.log("Error getting app ids: " + error); }) } // 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); } 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 = async (appList) => { // getting App ID,Authentication fields and saved auths for each app var result = [] if (appList.length > 0) { 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 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(async (responseJson) => { if (!responseJson.success) { console.log("Could not get app auth") return; } // console.log("responseJson of auth: ", responseJson.data) result = await 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) // setSelectedAppAuth(decodedString.authentication) }).catch((error) => { console.log("Error getting app config: " + error); toast("Error getting app config: " + error); }) }) // get auth config for each app as it is required to render the modal when auth is not available }) } }).catch((error) => { console.log("Error getting app ids: " + error); }) } } const executeTestWorkflow = async (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 generateNotificationWorkflow = async (appname,appImage,appAuthId,projectId,issuetype) => { //currently only supports JIRA figure out a way to support more apps var workflowName = `[GENARATED] ${appname} notification workflow` var workflowDescription = "Generated by Shuffle for sending info/error notifications." var 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() === "jira"){ console.log("updating workflow for JIRA") var workflowBody = { "name": workflowName, "Description": workflowDescription, "id": workflow_id, "actions": [ { "app_name": "Jira", "name": "post_create_issue", "authentication_id":appAuthId, "large_image":appImage, "isStartNode": true, "label": "create_issue", "app_version": "1.1.0", "parameters": [ { "name": "body", "value": `{"fields": { "project": {"key": "${projectId}"},"summary": "$exec.title","issuetype": {"name": "${issuetype}"},"description": {"content": [{"content":[{"type":"text","text":"$exec.description"}],"type": "paragraph"}],"type": "doc","version": 1}}}` }, { "name": "username_basic", "value": "" }, { "name": "password_basic", "value": "" }, { "name": "url", "value": "" }, { "name": "headers", "value": "Content-type=application/json \nAccept=application/json" }, { "name": "queries", "value": "" }, { "name": "ssl_verify", "value": "False" } ] } ] } } 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) { 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: workflow_id, documentation_reference: documentationReference, }, { sso_entrypoint: ssoEntrypoint, sso_certificate: ssoCertificate, client_id: openidClientId, client_secret: openidClientSecret, openid_authorization: openidAuthorization, openid_token: openidToken, } ) console.log("Notification workflow updated successfully") toast("Notification workflow updated successfully") } }) } }).catch((error) => { console.log("Error setting workflows: " + error); }) } const generateEmailNotificationWorkflow = async (appname,appImage,shuffleAPIKey,recepients) => { //currently only supports figure out a way to support more apps var workflowName = `[GENARATED] ${appname} notification workflow` var workflowDescription = "Generated by Shuffle for sending info/error notifications." var 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) { 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: workflow_id, documentation_reference: documentationReference, }, { sso_entrypoint: ssoEntrypoint, sso_certificate: ssoCertificate, client_id: openidClientId, client_secret: openidClientSecret, openid_authorization: openidAuthorization, openid_token: openidToken, } ) console.log("Notification workflow updated successfully") toast("Notification workflow updated successfully") } }) } }).catch((error) => { console.log("Error setting workflows: " + error); }) } const getAppAuth = async (appName) => { 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 ${appName}: `, 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; } var authList = responseJson.data.filter(entry => entry.app.name === appName) console.log("authList: ", authList) setAuthOptions(authList); }).catch((error) => { console.log("Error getting app auth: " + error); }) } const getAppConfig = async (appId) => { fetch(globalUrl + `/api/v1/apps/${appId}/config`, { method: "GET", headers: { "Content-Type": "application/json", Accept: "application/json", }, credentials: "include", }).then((response) => { if (response.status !== 200) { toast(`Failed getting config for ${appId}: `, 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) return decodedString.authentication // setSelectedAppAuth(decodedString.authentication) }).catch((error) => { console.log("Error getting app config: " + error); }) } const testWorkflowModal = notificationWorkflowTestModal ? ( { setNotificationWorkflowTestModal(false); }} > {/*
Notification workflow
*/} We have updated the Notification workflow. Do you want to test it?
) : null const notificationWorkflowModalValid = () => { return selectedAuth && webhookInputValue; }; const modalView = notificationWorkflowModal ? ( { setNotificationWorkflowModal(false); }} >
{`Configure ${selectedAppDetails.name} workflow`}
{console.log("len Selected app details: ", selectedAppDetails)} {(selectedAppDetails.authentication_data || selectedAppDetails.auth_config.required == false) ? <> {selectedAppDetails.auth_config.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 const renderChips = (apps) => { if (!apps || apps.length === 0) { return ( { console.log(`Clicked EMAIL`) setSelectedAppDetails("email") setNotificationWorkflowModal(true) // setNotificationWorkflowModal(true) }} avatar={{"email} /> ) } return ( {apps.map((app) => ( { console.log(`Clicked ${app.name}`) setSelectedAppDetails(app) setNotificationWorkflowModal(true) // getAppAuth(app.name) console.log("selectedAppDEtails",selectedAppDetails) }} avatar={{app.name}} /> ))} ); }; return (
Notification Workflow {modalView} {/*{testWorkflowModal} */}
{renderChips(notificationAppDetails)}
{/* Add a Workflow that receives notifications from Shuffle when an error occurs in one of your workflows */}
{workflows !== undefined && workflows !== null && workflows.length > 0 ? { if ( option === undefined || option === null || option.name === undefined || option.name === null ) { return "No Workflow Selected"; } const newname = ( option.name.charAt(0).toUpperCase() + option.name.substring(1) ).replaceAll("_", " "); return newname; }} options={workflows} fullWidth style={{ backgroundColor: theme.palette.inputColor, height: 50, borderRadius: theme.palette.borderRadius, }} onChange={(event, newValue) => { console.log("Found value: ", newValue) var parsedinput = { target: { value: newValue } } // For variables if (typeof newValue === 'string' && newValue.startsWith("$")) { parsedinput = { target: { value: { "name": newValue, "id": newValue, "actions": [], "triggers": [], } } } } handleWorkflowSelectionUpdate(parsedinput) }} renderOption={(props, data, state) => { if (data.id === workflow.id) { data = workflow; } return ( {data.image !== undefined && data.image !== null && data.image.length > 0 ? {data.name} : null} Choose {data.name} } placement="bottom"> { var parsedinput = { target: { value: data } } handleWorkflowSelectionUpdate(parsedinput) }} > {data.name} ) }} renderInput={(params) => { return ( ); }} /> : { setNotificationWorkflow(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> }
{orgSaveButton}
Org Documentation reference { setDocumentationReference(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> {isCloud ? null : OpenID connect Client ID 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", }, }} /> Client Secret (optional) 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", }, }} /> Authorization URL { setOpenidAuthorization(e.target.value) }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> Token URL { setOpenidToken(e.target.value) }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> } {/*isCloud ? null : */} SAML SSO (v1.1) SSO Entrypoint (IdP) 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", }, }} /> SSO Certificate (X509) { setSsoCertificate(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> {isCloud ? IdP URL for Shuffle: https://shuffler.io/api/v1/login_sso : null} {isCloud ? null : ( App Download URL { setAppDownloadUrl(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> )} {isCloud ? null : ( App Download Branch { setAppDownloadBranch(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> )} {isCloud ? null : ( Workflow Download URL { setWorkflowDownloadUrl(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> )} {isCloud ? null : ( Workflow Download Branch { setWorkflowDownloadBranch(e.target.value); }} InputProps={{ classes: { notchedOutline: classes.notchedOutline, }, style: { color: "white", }, }} /> )}
{orgSaveButton}
{/* {expanded ? : } */}
) } export default OrgHeaderexpanded;