Minor fixes

This commit is contained in:
Frikky
2024-05-13 14:34:36 +02:00
parent 7873294bf2
commit 3b0ecbb550
4 changed files with 50 additions and 559 deletions
+3 -3
View File
@@ -989,7 +989,7 @@ const AppGrid = (props) => {
}}
autoComplete="off"
color="primary"
placeholder="Search more than 2500 Apps"
placeholder="Search your Activated or Self-built apps"
id="shuffle_search_field"
onChange={(event) => {
setSearchQuery(event.currentTarget.value);
@@ -1008,7 +1008,7 @@ const AppGrid = (props) => {
useEffect(() => {
if (currTab === 2) {
const baseUrl = globalUrl;
const userAppsUrl = `${baseUrl}/api/v1/users/apps`;
const userAppsUrl = `${baseUrl}/api/v1/users/me/apps`;
fetch(userAppsUrl, {
method: "GET",
credentials: "include",
@@ -1559,8 +1559,8 @@ const AppGrid = (props) => {
//Component to fetch all apps created by user and Org
const UserAndOrgApps = ({ selectedCategoryForUsersAndOgsApps, selectedTagsForUserAndOrgApps, selectedOptionOfCreatedWith, setselectedCategoryForUsersAndOgsApps, setSelectedTagsForUserAndOrgApps, setSelectedOptionOfCreatedWith }) => {
const [searchQuery, setSearchQuery] = useState("");
const [searchQuery, setSearchQuery] = useState("");
const [appsToShow, setAppsToShow] = useState([]);
useEffect(() => {
if (currTab === 1) {
+20 -532
View File
@@ -5,7 +5,7 @@ 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 SubflowSuggestions from "../components/SubflowSuggestions.jsx";
import {
FormControl,
@@ -45,7 +45,7 @@ const useStyles = makeStyles({
notchedOutline: {
borderColor: "#f85a3e !important",
},
});
})
const OrgHeaderexpanded = (props) => {
const {
@@ -113,6 +113,7 @@ const OrgHeaderexpanded = (props) => {
? ""
: selectedOrganization.sso_config.sso_certificate
);
const [notificationWorkflow, setNotificationWorkflow] = React.useState(
selectedOrganization.defaults === undefined
? ""
@@ -120,7 +121,7 @@ const OrgHeaderexpanded = (props) => {
selectedOrganization.defaults.notification_workflow.length === 0
? ""
: selectedOrganization.defaults.notification_workflow
);
)
const [documentationReference, setDocumentationReference] = React.useState(
selectedOrganization.defaults === undefined
@@ -166,25 +167,6 @@ const OrgHeaderexpanded = (props) => {
const [workflows, setWorkflows] = React.useState([])
const [workflow, setWorkflow] = React.useState({})
// notification workflow
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({});
// for jira & email modal
const [textFieldValue, setTextFieldValue] = React.useState("");
const [textFieldOneValue, setTextFieldOneValue] = React.useState("");
useEffect(() => {
let nameList = notificationAppList.length > 0? notificationAppList.map(item => item.name): ["email"];
prepareNotificationAppList(nameList)
}, [notificationAppList,workflows]);
const getAvailableWorkflows = (trigger_index) => {
fetch(globalUrl + "/api/v1/workflows", {
method: "GET",
@@ -351,142 +333,13 @@ const OrgHeaderexpanded = (props) => {
})
}
// 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 = []
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(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)
}).then(async()=>{
await 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 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 = `[GENERATED] ${appname} notification workflow`
@@ -615,379 +468,7 @@ const generateNotificationWorkflow = async (appname,appImage,appAuthId,projectId
})
}
const generateEmailNotificationWorkflow = async (appname,appImage,shuffleAPIKey,recepients) => {
//currently only supports figure out a way to support more apps
var workflowName = `[GENERATED] ${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 testWorkflowModal = notificationWorkflowTestModal ?
(<Dialog
open={notificationWorkflowTestModal}
PaperProps={{
style: {
backgroundColor: theme.palette.surfaceColor,
color: "white",
minWidth: 500,
},
}}
onClose={() => {
setNotificationWorkflowTestModal(false);
}}
>
<FormControl>
{/* <DialogTitle>
<div style={{ color: "rgba(255,255,255,0.9)" }}>
Notification workflow
</div>
</DialogTitle> */}
<DialogContent style={{ color: "rgba(255,255,255,0.65)" }}>
We have updated the Notification workflow. Do you want to test it?
</DialogContent>
<DialogActions>
<Button
style={{ borderRadius: "0px" }}
onClick={() => {
setNotificationWorkflowTestModal(false);
}}
color="primary"
>
No
</Button>
<Button
variant="contained"
style={{ borderRadius: "0px" }}
onClick={() => {
executeTestWorkflow(selectedOrganization.defaults.notification_workflow);
setNotificationWorkflowTestModal(false);
}}
color="primary"
>
Yes
</Button>
</DialogActions>
</FormControl>
</Dialog>) : null
const modalView = notificationWorkflowModal ? (
<Dialog
open={notificationWorkflowModal}
PaperProps={{
style: {
backgroundColor: theme.palette.grey,
minWidth: 500,
},
}}
onClose={() => {
setNotificationWorkflowModal(false);
}}
>
<FormControl>
<DialogTitle>
<div style={{ color: "rgba(255,255,255,0.9)" }}>
{`Configure ${selectedAppDetails.name} workflow`}
</div>
</DialogTitle>
<DialogContent style={{ color: "rgba(255,255,255,0.65)", overflowY: 'auto', maxHeight: '450px' }}>
<Divider style={{ marginBottom: '1em', backgroundColor: 'rgba(255,255,255,0.12)' }} />
{console.log("len Selected app details: ", selectedAppDetails)}
{(selectedAppDetails.authentication_data || (selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false) || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ?
<>
<Box mb={2}>
{(selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ? "No authentication required":
<>
<Typography variant="body1" style={{ marginBottom: '0.5rem' }}>
Pick an authentication method from the list
</Typography>
<FormControl fullWidth style={{ marginBottom: 10 }}>
<InputLabel id="demo-simple-select-label">Available authentications</InputLabel>
<Select
labelId="demo-simple-select-label"
id="demo-simple-select"
value={selectedAuth}
disabled = {(selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false))}
onChange={(event) => {setSelectedAuth(event.target.value)
console.log("event.target.value: ",event.target.value)
console.log("Selected auth: ", selectedAuth)
}}
label="Available authentications"
required={true}
>
{(selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ? "No authentication required" : selectedAppDetails.authentication_data.map((option) => (
<MenuItem key={option.id} value={option.id}>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<Chip label={option.app.app_version} variant="outlined" />
{option.label}
</div>
</MenuItem>))}
</Select>
</FormControl></>}
</Box>
<Box mt={2}>
<Typography variant="body1">
Provide additional required details:
</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={ selectedAppDetails.name.toLowerCase() === "jira" ? "Project key" : "Shuffle API key"}
// value={webhookInputValue}
onChange={(e) => {
setTextFieldOneValue(e.target.value)
}}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
},
style: {
color: "white",
},
}} />
<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={selectedAppDetails.name.toLowerCase() === "jira" ? "Issue type" : "Recepients (comma separated)"}
// value={webhookInputValue}
onChange={(e) => {
setTextFieldValue(e.target.value)
}}
InputProps={{
classes: {
notchedOutline: classes.notchedOutline,
},
style: {
color: "white",
},
}} />
</Box>
</> :
<>
<AuthenticationData
app={selectedAppDetails}
// globalUrl={globalUrl}
authenticationModalOpen={(selectedAppDetails.authentication_data && selectedAppDetails.authentication_data.length > 0) ? false : true}
// // setAuthenticationModalOpen={false}
selectedApp={{...selectedAppDetails,authentication: selectedAppDetails.auth_config}}
// getAppAuthentication={selectedAppDetails.name}
/>
</>
}
</DialogContent>
<DialogActions>
<Button
style={{ borderRadius: "0px" }}
onClick={() => {
setNotificationWorkflowModal(false);
}}
color="primary"
>
Cancel
</Button>
<Button
variant="contained"
style={{ borderRadius: "0px" }}
// disabled={(authOptions.length > 0 ? false : true) || !notificationWorkflowModalValid}
onClick={async () => {
// var workflowUpdate = await setTeamsWorkflow(webhookInputValue)
console.log("Selectedappdetails: ", selectedAppDetails)
selectedAppDetails.name == "email" ? generateEmailNotificationWorkflow(selectedAppDetails.name, selectedAppDetails.large_image,textFieldOneValue, textFieldValue) :
generateNotificationWorkflow(selectedAppDetails.name, selectedAppDetails.large_image,selectedAuth, textFieldOneValue, textFieldValue)
setNotificationWorkflowModal(false);
}}
color="primary"
>
Submit
</Button>
</DialogActions>
</FormControl>
</Dialog >
) : null
const checkIfAlreadyGenerated = async (appList, workflows) => { // fixxxxxxxxxxxxxxxxxxxxx
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 renderChips = (apps) => {
return (
<Stack direction="row" spacing={1}>
{apps.map((app) => (
<Chip
key={app.id}
label={app.name}
variant={generatedWorkflow.app_name === app.name? "filled":"outlined"}
disabled={generatedWorkflow.app_name === app.name ? true:false}
onClick={() => {
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={<img src={app.large_image} alt={app.name} style={{ width: 24, height: 24, borderRadius: '50%' }} />}
/>
))}
</Stack>
);
};
return (
<div style={{ textAlign: "center" }}>
@@ -995,11 +476,18 @@ const renderChips = (apps) => {
<Grid item xs={12} style={{}}>
<span>
<Typography>Notification Workflow</Typography>
{modalView}
{/*{testWorkflowModal} */}
<div style={{ marginBottom: '10px' }}>
{renderChips(notificationAppDetails.length > 0 ? notificationAppDetails : emailData)}
</div>
{/*
<SubflowSuggestions
globalUrl={globalUrl}
selectedOrganization={selectedOrganization}
workflows={workflows}
notificationWorkflow={notificationWorkflow}
type={"notification"}
/>
*/}
<div style={{display: "flex", flexDirection: "row", alignItems: "center"}}>
{workflows !== undefined && workflows !== null && workflows.length > 0 ?
<Autocomplete