diff --git a/backend/go-app/main.go b/backend/go-app/main.go index b5c795ad..413cb49b 100755 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -4908,7 +4908,7 @@ func initHandlers() { r.HandleFunc("/api/v1/triggers/outlook/{key}", shuffle.HandleGetSpecificTrigger).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/triggers/gmail/register", shuffle.HandleNewGmailRegister).Methods("GET", "OPTIONS") r.HandleFunc("/api/v1/triggers/gmail/getFolders", shuffle.HandleGetGmailFolders).Methods("GET", "OPTIONS") - + r.HandleFunc("/api/v1/triggers", shuffle.HandleGetTriggers).Methods("GET", "OPTIONS") //r.HandleFunc("/api/v1/triggers/gmail/routing", handleGmailRouting).Methods("POST", "OPTIONS") r.HandleFunc("/api/v1/triggers/gmail/{key}", shuffle.HandleGetSpecificTrigger).Methods("GET", "OPTIONS") diff --git a/frontend/src/views/Admin.jsx b/frontend/src/views/Admin.jsx index c8d012e0..a678bf3b 100755 --- a/frontend/src/views/Admin.jsx +++ b/frontend/src/views/Admin.jsx @@ -201,7 +201,9 @@ const Admin = (props) => { const [showApiKey, setShowApiKey] = useState(false); const [billingInfo, setBillingInfo] = React.useState({}); const [selectedStatus, setSelectedStatus] = React.useState([]); - + const [webHooks, setWebHooks] = React.useState([]); + const [allSchedules, setAllSchedules] = React.useState([]); + const [pipelines, setPipelines] = React.useState([]); const [, forceUpdate] = React.useState(); const [showDeleteAccountTextbox, setShowDeleteAccountTextbox] = @@ -247,7 +249,11 @@ const Admin = (props) => { ) { handleGetSubOrgs(userdata.active_org.id); } else console.log("error in user data"); - }, [userdata]); + }, [userdata]); + + useEffect(() => { + handleGetAllTriggers() + }, []); const isCloud = window.location.host === "localhost:3002" || @@ -731,6 +737,32 @@ If you're interested, please let me know a time that works for you, or set up a }); }; + const handleGetAllTriggers = () => { + fetch(globalUrl + "/api/v1/triggers", { + method: "GET", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for getting all triggers"); + } + + return response.json(); + }) + .then((responseJson) => { + setWebHooks(responseJson.webhooks || []); // Handling the case where the result is null or undefined + setAllSchedules(responseJson.schedules || []); + // setPipelines(responseJson.pipelines || []); + }) + .catch((error) => { + toast(error.toString()); + }); + }; + const deleteSchedule = (data) => { // FIXME - add some check here ROFL console.log("INPUT: ", data); @@ -756,11 +788,11 @@ If you're interested, please let me know a time that works for you, or set up a if (responseJson["success"] === false) { toast("Failed stopping schedule"); } else { - setTimeout(() => { - getSchedules(); - }, 1500); - //toast("Successfully stopped schedule!") + toast("Successfully stopped schedule!"); } + + setTimeout(handleGetAllTriggers, 1000); + }), ) .catch((error) => { @@ -768,6 +800,189 @@ If you're interested, please let me know a time that works for you, or set up a }); }; + const startSchedule = (trigger) => { + if (trigger.name.length <= 0) { + toast("Error: name can't be empty"); + return; + } + + toast("Creating schedule"); + const data = { + name: trigger.name, + frequency: trigger.frequency, + execution_argument: trigger.argument, + environment: trigger.environment, + id: trigger.id, + start: trigger.start_node, + }; + + fetch(`${globalUrl}/api/v1/workflows/${trigger.workflow_id}/schedule`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for stream results :O!"); + } + + return response.json(); + }) + .then((responseJson) => { + if (!responseJson.success) { + toast("Failed to set schedule: " + responseJson.reason); + } else { + toast("Successfully created schedule"); + } + setTimeout(handleGetAllTriggers, 1000); + }) + .catch((error) => { + //toast(error.toString()); + console.log("Get schedule error: ", error.toString()); + }); + }; + + const deleteWebhook = (trigger) => { + if (trigger === undefined) { + return; + } + + fetch(globalUrl + "/api/v1/hooks/" + trigger.id + "/delete", { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for stream results :O!"); + } + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success) { + toast("Successfully stopped webhook"); + } else { + if (responseJson.reason !== undefined) { + toast("Failed stopping webhook: " + responseJson.reason); + } + } + setTimeout(handleGetAllTriggers, 1000); + }) + .catch((error) => { + toast( + "Delete webhook error. Contact support or check logs if this persists.", + ); + }); + }; + + const startWebHook = (trigger) => { + const hookname = trigger.info.name; + if (hookname.length === 0) { + toast("Missing name"); + return; + } + + if (trigger.id.length !== 36) { + toast("Missing id"); + return; + } + + toast("Starting webhook"); + + const data = { + name: hookname, + type: "webhook", + id: trigger.id, + workflow: trigger.workflows[0], + start: trigger.start, + environment: trigger.environment, + auth: trigger.auth, + custom_response: trigger.custom_response, + version: trigger.version, + version_timeout: 15, + }; + + console.log("Trigger data: ", data); + + fetch(globalUrl + "/api/v1/hooks/new", { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => response.json()) + .then((responseJson) => { + if (responseJson.success) { + // Set the status + toast("Successfully started webhook"); + } else { + toast("Failed starting webhook: " + responseJson.reason); + } + setTimeout(handleGetAllTriggers, 1000); + }) + .catch((error) => { + //console.log(error.toString()); + console.log("New webhook error: ", error.toString()); + }); + }; + + const changePipelineState = (pipeline, state) => { + if (state.trim() === "") { + toast("state is not defined"); + return; + } + + const data = { + name: pipeline.name, + type: state, + environment: pipeline.environment, + workflow_id: pipeline.workflow_id, + trigger_id: pipeline.trigger_id, + }; + + if (state === "start") toast("starting the pipeline"); + else toast("stopping the pipeline"); + + const url = `${globalUrl}/api/v1/triggers/pipeline`; + fetch(url, { + method: "POST", + headers: { + "Content-Type": "application/json", + Accept: "application/json", + }, + body: JSON.stringify(data), + credentials: "include", + }) + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for stream results :O!"); + toast("Failed to update the pipeline state"); + } + + return response.json(); + }) + .then((responseJson) => { + if (!responseJson.success) { + toast("Failed to update the pipeline: " + responseJson.reason); + } else { + if (state === "start") toast("Successfully created pipeline"); + else toast("Sucessfully stopped the pipeline"); + } + }) + .catch((error) => { + //toast(error.toString()); + console.log("Get schedule error: ", error.toString()); + }); + }; + if ( userdata.support === true && selectedOrganization.id !== "" && @@ -4384,7 +4599,7 @@ If you're interested, please let me know a time that works for you, or set up a /> ); - const schedulesView = + const schedulesView = curTab === 5 ? (
@@ -4408,88 +4623,357 @@ If you're interested, please let me know a time that works for you, or set up a backgroundColor: theme.palette.inputColor, }} /> - - - - - - - - - - {schedules === undefined || schedules === null - ? null - : schedules.map((schedule, index) => { - var bgColor = "#27292d"; - if (index % 2 === 0) { - bgColor = "#1f2023"; - } - - return ( - - 0 ? ( - schedule.frequency - ) : ( - {schedule.seconds} seconds - ) - } - /> - - - {schedule.workflow_id} - - } - /> - - - - - - ); - })} - + {schedule.workflow_id} + + } + /> + + + + + + ); + })} + + )} + +
+

WebHooks

+
+ + + {webHooks === undefined || webHooks === null || webHooks.length === 0 ? ( +
+ No webhooks found. +
+ ) : ( + + + + + + + + + {webHooks.map((webhook, index) => { + var bgColor = "#27292d"; + if (index % 2 === 0) { + bgColor = "#1f2023"; + } + + return ( + + + + + {webhook.workflows[0]} + + } + /> + + + { + const elementName = "copy_element_shuffle"; + var copyText = document.getElementById(elementName); + if (copyText !== null && copyText !== undefined) { + const clipboard = navigator.clipboard; + if (clipboard === undefined) { + toast("Can only copy over HTTPS (port 3443)"); + return; + } + + navigator.clipboard.writeText(webhook.info.url); + copyText.select(); + copyText.setSelectionRange( + 0, + 99999, + ); /* For mobile devices */ + + /* Copy the text inside the text field */ + document.execCommand("copy"); + + toast("URL copied to clipboard"); + } + }} + > + + + + ) + } + /> + + + + + + ); + })} + + )} + + {/*
+

Tenzir Pipelines

+ + Controls a pipeline to run things.{" "} + + Learn more + + +
+ + + {pipelines === undefined || + pipelines === null || + pipelines.length === 0 ? ( +
+ No pipelines found. +
+ ) : ( + + + + + + + + {pipelines.map((pipeline, index) => { + var bgColor = "#27292d"; + if (index % 2 === 0) { + bgColor = "#1f2023"; + } + + return ( + + + + + {pipeline.workflow_id} + + } + /> + + + + + ); + })} + + )}*/}
) : null; diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index 76953e68..5832f76f 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -13124,7 +13124,7 @@ const AngularWorkflow = (defaultprops) => { if (trigger.id === undefined) { return; } - + fetch(globalUrl + "/api/v1/hooks/" + trigger.id + "/delete", { method: "DELETE", headers: { @@ -13137,32 +13137,34 @@ const AngularWorkflow = (defaultprops) => { if (response.status !== 200) { console.log("Status not 200 for stream results :O!"); } - + return response.json(); }) .then((responseJson) => { + if (!responseJson.success) { + if (responseJson.reason !== undefined) { + toast("Failed to stop webhook: " + responseJson.reason); + } + } else { + toast("Successfully stopped webhook"); + } if (workflow.triggers[triggerindex] !== undefined) { workflow.triggers[triggerindex].status = "stopped"; } - - if (responseJson.success) { - // Set the status - saveWorkflow(workflow); - } else { - if (responseJson.reason !== undefined) { - toast("Failed stopping webhook: " + responseJson.reason); - } - } - trigger.status = "stopped"; - setWorkflow(workflow); setSelectedTrigger(trigger); + setWorkflow(workflow); + saveWorkflow(workflow); + }) .catch((error) => { //toast(error.toString()); - toast("Delete webhook error. Contact support or check logs if this persists.") + toast( + "Delete webhook error. Contact support or check logs if this persists.", + ); }); }; + // POST to /api/v1/workflows const createWorkflow = (workflow, trigger_index) => {