diff --git a/frontend/src/components/Oauth2Auth.jsx b/frontend/src/components/Oauth2Auth.jsx index 1ebf81dd..f0c20a64 100755 --- a/frontend/src/components/Oauth2Auth.jsx +++ b/frontend/src/components/Oauth2Auth.jsx @@ -476,15 +476,15 @@ const AuthenticationOauth2 = (props) => { var defaultPrompt = "login" if (prompt !== undefined && prompt !== null && prompt.length > 0) { defaultPrompt = prompt - } + } - var url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=${defaultPrompt}&scope=${resources}&state=${state}&access_type=offline`; + var url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=${defaultPrompt}&scope=${resources}&state=${state}&access_type=offline`; - if (admin_consent === true) { - console.log("Running Oauth2 WITH admin consent") - //url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=consent&scope=${resources}&state=${state}&access_type=offline`; - url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=admin_consent&scope=${resources}&state=${state}&access_type=offline`; - } + if (admin_consent === true) { + console.log("Running Oauth2 WITH admin consent") + //url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=consent&scope=${resources}&state=${state}&access_type=offline`; + url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&prompt=admin_consent&scope=${resources}&state=${state}&access_type=offline`; + } // Force new consent //const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&prompt=consent&state=${state}&access_type=offline`; @@ -997,7 +997,6 @@ const AuthenticationOauth2 = (props) => { color: "white", padding: 5, minWidth: 300, - maxWidth: 300, }} onChange={(e, value) => { //handleScopeChange(e) diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index 3fb82bc3..8546e887 100755 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -3745,7 +3745,7 @@ If you're interested, please let me know a time that works for you, or set up a aria-label="disabled tabs example" > Edit Details /> - Cloud Synchronization /> + Org Limits & Cloud Sync /> Priorities /> Billing & Stats /> Branding (Beta) /> diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index bc863f68..f9218bc2 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -2144,23 +2144,25 @@ const releaseToConnectLabel = "Release to Connect" const executeWorkflow = (executionArgument, startNode, hasSaved) => { + if (hasSaved === false) { + setExecutionRequestStarted(true) + saveWorkflow(workflow, executionArgument, startNode); + //console.log("FIXME: Might have forgotten to save before executing."); + return; + } + + if (workflow.public) { + toast("Save it to get a new version"); + } + + var returncheck = monitorUpdates(); + if (!returncheck) { + toast("No startnode set."); + return; + } + ReactDOM.unstable_batchedUpdates(() => { - if (hasSaved === false) { - setExecutionRequestStarted(true); - saveWorkflow(workflow, executionArgument, startNode); - //console.log("FIXME: Might have forgotten to save before executing."); - return; - } - if (workflow.public) { - toast("Save it to get a new version"); - } - - var returncheck = monitorUpdates(); - if (!returncheck) { - toast("No startnode set."); - return; - } setVisited([]) setExecutionRequest({}) @@ -2168,38 +2170,49 @@ const releaseToConnectLabel = "Release to Connect" // FIXME: Check if any node contains $exec in a param // If they do, show a popup asking if they want to execute it without an execution argument, or to use a previous one - if (executionArgument === undefined || executionArgument === null || executionArgument.length === 0 && workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { - var foundmissing = false - for (let actionkey in workflow.actions) { - if (workflow.actions[actionkey].parameters === undefined || workflow.actions[actionkey].parameters === null || workflow.actions[actionkey].parameters.length === 0) { - continue - } + if (executionArgument === undefined || executionArgument === null || executionArgument.length === 0) - for (let paramkey in workflow.actions[actionkey].parameters) { - const param = workflow.actions[actionkey].parameters[paramkey] - if (param.value === undefined || param.value === null || param.value.length === 0) { + if (workflow.actions !== undefined && workflow.actions !== null && workflow.actions.length > 0) { + var foundmissing = false + for (let actionkey in workflow.actions) { + if (workflow.actions[actionkey].parameters === undefined || workflow.actions[actionkey].parameters === null || workflow.actions[actionkey].parameters.length === 0) { continue } - if (param.value.indexOf("$exec") !== -1) { - foundmissing = true + for (let paramkey in workflow.actions[actionkey].parameters) { + const param = workflow.actions[actionkey].parameters[paramkey] + if (param.value === undefined || param.value === null || param.value.length === 0) { + continue + } + + if (param.value.indexOf("$exec") !== -1) { + foundmissing = true + break + } + } + + if (foundmissing) { break } } if (foundmissing) { - break + //toast("This workflow contains a node that requires an execution argument. Please provide one.") + if (workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0) { + setExecutionRequestStarted(false) + setExecutionArgumentModalOpen(true) + return + } + + if (workflowExecutions.length > 0) { + setExecutionRequestStarted(false) + setExecutionArgumentModalOpen(true) + + return + } } } - if (foundmissing) { - //toast("This workflow contains a node that requires an execution argument. Please provide one.") - setExecutionRequestStarted(false) - setExecutionArgumentModalOpen(true) - return - } - } - var curelements = cy.elements(); for (let i = 0; i < curelements.length; i++) { curelements[i].addClass("not-executing-highlight"); @@ -10738,7 +10751,7 @@ const releaseToConnectLabel = "Release to Connect" padding: 30, pointerEvents: "auto", color: "white", - minWidth: isMobile ? "90%" : 800, + minWidth: isMobile ? "90%" : 650, border: theme.palette.defaultBorder, }, }} @@ -10754,77 +10767,120 @@ const releaseToConnectLabel = "Release to Connect" style={{ zIndex: 5000, position: "absolute", top: 34, right: 34 }} onClick={(e) => { e.preventDefault(); - setExecutionArgumentModalOpen(false); + setExecutionArgumentModalOpen(false) }} > - Provide a runtime argument + Provide an execution argument - - At least one node in this workflow requires a runtime argument ($exec). Please select one below, or provide a custom one in the text field next to the run button. - - {/* -
- - { - setExecutionText(e.target.value); - }} - /> - -
- */} - - {availableArguments.length > 0 ? -
- - Previously used arguments: - - {availableArguments.map((data) => { - return ( - { - setExecutionText(data) - executeWorkflow(data, workflow.start, lastSaved); - setExecutionArgumentModalOpen(false) + {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? +
+ {workflow.input_questions.map((question, index) => { + + return ( +
+ {question.name} + -
- - {data} - - - ) - })} -
- : null} + fullWidth={true} + placeholder="" + id="emailfield" + margin="normal" + variant="outlined" + onBlur={(e) => { + var newtext = {} + if (executionText.length > 0) { + try { + newtext = JSON.parse(executionText) + // Check if list or object, then make it object only + if (Array.isArray(newtext)) { + newtext = {} + } + } catch (e) { + console.log("Error parsing JSON: ", e) + } + } - + newtext[question.value] = e.target.value + setExecutionText(JSON.stringify(newtext)) + }} + /> +
+ ) + })} + + +
+ : +
+ + At least one node in this workflow requires an execution argument ($exec). Please select one below, or provide a custom one in the text field next to the run button. + + + + {availableArguments.length > 0 ? +
+ + Previously used arguments: + + {availableArguments.map((data) => { + return ( + { + setExecutionText(data) + executeWorkflow(data, workflow.start, lastSaved); + + setExecutionArgumentModalOpen(false) + }} + > +
+ + {data} + + + ) + })} +
+ : null} + + +
+ } @@ -14811,6 +14867,7 @@ const releaseToConnectLabel = "Release to Connect"
) : null} + {workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[selectedTriggerIndex].parameters[2].value.includes("email") ? ( @@ -14842,6 +14899,7 @@ const releaseToConnectLabel = "Release to Connect" }} /> ) : null} + {workflow.triggers[selectedTriggerIndex].parameters[2] !== undefined && workflow.triggers[ @@ -14874,6 +14932,39 @@ const releaseToConnectLabel = "Release to Connect" ) : null}
+ +
+ Enabled Input-Questions + {workflow.input_questions !== undefined && workflow.input_questions !== null && workflow.input_questions.length > 0 ? +
+ {workflow.input_questions.map((question, index) => { + const selectionClick = () => { + console.log("Clicked input question: ", question) + console.log("PARAMS: ", workflow.triggers[selectedTriggerIndex].parameters) + } + + return ( +
{ + selectionClick() + }}> + + + {question.name} + +
+ ) + })} +
+ : +
{ + setEditWorkflowModalOpen(true) + }}> + No Input-Questions found. Click to add them! +
+ } +
const PipelineSidebar = Object.getOwnPropertyNames(selectedTrigger).length === 0 || workflow.triggers[selectedTriggerIndex] === undefined && selectedTrigger.trigger_type !== "SCHEDULE" ? null : @@ -16441,7 +16532,7 @@ const releaseToConnectLabel = "Release to Connect" - ); + ) return (
diff --git a/frontend/src/views/LoginPage.jsx b/frontend/src/views/LoginPage.jsx index d3c529b3..52b9cd1d 100755 --- a/frontend/src/views/LoginPage.jsx +++ b/frontend/src/views/LoginPage.jsx @@ -166,7 +166,7 @@ const LoginDialog = (props) => { } else { if (responseJson["reason"] === "MFA_REDIRECT") { setLoginInfo( - "MFA required. Please the 6-digit code from your authenticator" + "MFA required. Please enter the 6-digit code from your authenticator" ); setMFAField(true); return; diff --git a/frontend/src/views/Workflows.jsx b/frontend/src/views/Workflows.jsx index ffdf0ec4..0b642d56 100755 --- a/frontend/src/views/Workflows.jsx +++ b/frontend/src/views/Workflows.jsx @@ -976,15 +976,16 @@ const Workflows = (props) => { }, 1000); } else if (selectedWorkflowIndexes.length > 0) { // Do backwards so it doesn't change + toast("Starting deletion of workflows. This might take a while.") for (var i = selectedWorkflowIndexes.length - 1; i >= 0; i--) { const workflow = filteredWorkflows[selectedWorkflowIndexes[i]-1] if (workflow !== undefined && workflow !== null && workflow.id !== undefined && workflow.id !== null) { - deleteWorkflow(workflow.id); + deleteWorkflow(workflow.id, true) } } setTimeout(() => { - getAvailableWorkflows(); + getAvailableWorkflows() }, 1000); setSelectedWorkflowIndexes([]); @@ -1115,7 +1116,7 @@ const Workflows = (props) => { }) } - const getAvailableWorkflows = () => { + const getAvailableWorkflows = (amount) => { var storageWorkflows = [] try { const storagewf = localStorage.getItem("workflows") @@ -1132,7 +1133,12 @@ const Workflows = (props) => { //console.log("Failed to get workflows from localstorage: ", e) } - fetch(globalUrl + "/api/v1/workflows", { + var url = `${globalUrl}/api/v1/workflows` + if (amount !== undefined && amount !== null) { + url += `?top=${amount}` + } + + fetch(url, { method: "GET", headers: { "Content-Type": "application/json", @@ -1338,8 +1344,21 @@ const Workflows = (props) => { setView(tmpView); } + const urlSearchParams = new URLSearchParams(window.location.search); + const params = Object.fromEntries(urlSearchParams.entries()); + const foundTab = params["top"]; + if (foundTab !== null && foundTab !== undefined) { + // Check if it's a number + if (isNaN(foundTab)) { + getAvailableWorkflows() + } else { + getAvailableWorkflows(foundTab) + } + } else { + getAvailableWorkflows() + } + getApps() - getAvailableWorkflows(); getFramework() } }, []) @@ -1836,7 +1855,7 @@ const Workflows = (props) => { }) } - const deleteWorkflow = (id) => { + const deleteWorkflow = (id, bulk) => { fetch(globalUrl + "/api/v1/workflows/" + id, { method: "DELETE", headers: { @@ -1850,15 +1869,19 @@ const Workflows = (props) => { console.log("Status not 200 for setting workflows :O!"); toast("Failed deleting workflow. Do you have access?"); } else { - toast("Deleted workflow " + id); + if (bulk !== true) { + toast("Deleted workflow " + id); + } } return response.json(); }) .then(() => { - setTimeout(() => { - getAvailableWorkflows(); - }, 1000); + if (bulk !== true) { + setTimeout(() => { + getAvailableWorkflows(); + }, 1000); + } }) .catch((error) => { toast(error.toString()); @@ -2962,7 +2985,7 @@ const Workflows = (props) => { className={classes.datagrid} rows={rows} columns={columns} - pageSize={25} + pageSize={100} checkboxSelection autoHeight density="standard"