From c0aaebaff603a65acb5b0d676892649f94d13a3e Mon Sep 17 00:00:00 2001 From: Frikky Date: Fri, 23 May 2025 12:10:38 +0200 Subject: [PATCH] Synced over bugfixes and theme control --- frontend/src/components/Branding.jsx | 7 +- frontend/src/components/LeftSideBar.jsx | 46 +- frontend/src/components/Priorities.jsx | 2441 ++++++++++++----- .../src/components/ShuffleCodeEditor1.jsx | 10 +- frontend/src/views/AngularWorkflow.jsx | 18 +- frontend/src/views/LoginPage.jsx | 61 +- frontend/src/views/SettingsPage.jsx | 7 +- frontend/src/views/Workflows2.jsx | 6 +- 8 files changed, 1898 insertions(+), 698 deletions(-) diff --git a/frontend/src/components/Branding.jsx b/frontend/src/components/Branding.jsx index 649c509a..40a76846 100644 --- a/frontend/src/components/Branding.jsx +++ b/frontend/src/components/Branding.jsx @@ -39,7 +39,7 @@ const Branding = (props) => { const theme = getTheme(themeMode, brandColor) const [selectedBrandColor, setSelectedBrandColor] = useState(theme?.palette?.main || "#FF8544") const [selectedBrandName, setSelectedBrandName] = useState(selectedOrganization?.branding?.brand_name || "") - const isCloud = window.location.host === "localhost:3002" || window.location.host === "shuffler.io"; + const [isLoading,setIsLoading] = useState(false); const handleEditOrg = (joinStatus) => { @@ -391,7 +391,7 @@ const Branding = (props) => { - { integrationPartner ? ( + {integrationPartner ? ( <> @@ -414,9 +414,6 @@ const Branding = (props) => { if (changingTheme === true) { return } - - - toast.info("Changing theme to " + newTheme + ". Please wait a moment.") setChangingTheme(true) handleEditOrg(newTheme); }} diff --git a/frontend/src/components/LeftSideBar.jsx b/frontend/src/components/LeftSideBar.jsx index 2d9bad44..69a9b29e 100644 --- a/frontend/src/components/LeftSideBar.jsx +++ b/frontend/src/components/LeftSideBar.jsx @@ -403,7 +403,6 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { const handleChangeTheme = (newTheme) => { - toast.info("Changing theme to " + newTheme + " - please wait!"); const data = { "org_id": userdata?.active_org?.id, @@ -449,6 +448,38 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { }); }; + + const handleUpdateTheme = (newTheme) => { + + const data = { + "user_id": userdata?.id, + "theme": newTheme, + } + + const url = globalUrl + `/api/v1/users/updateuser`; + fetch(url, { + mode: "cors", + method: "PUT", + 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 theme: ", responseJson.reason); + } else { + handleThemeChange(newTheme); + setCurrentSelectedTheme(newTheme); + } + }) + ).catch((error) => { + console.log("Error changing theme: ", error); + }); + }; const removeCookie = (name, path = "/") => { @@ -487,6 +518,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { console.error("Logout error:", error); }); }; + console.log("userdata: ", userdata); const avatarMenu = ( { }, }} > - {userdata && ( + {userdata && (userdata?.org_status?.includes("integration_partner") && userdata?.org_status?.includes("sub_org")) ? null : ( <> { if (newTheme === currentSelectedTheme) { return; } - handleChangeTheme(newTheme); + if (userdata?.org_status?.includes("integration_partner")){ + handleChangeTheme(newTheme); + }else { + handleUpdateTheme(newTheme); + } }} aria-label="theme" style={{display: 'flex', justifyContent: "center", marginBottom: 10, }} @@ -1648,7 +1684,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { + + + + ) : null + + const modalView = notificationWorkflowModal ? ( + { + setNotificationWorkflowModal(false); + }} + > + + +
+ {`Configure ${selectedAppDetails.name} workflow`} +
+
+ + + {console.log("len Selected app details: ", selectedAppDetails)} + {(selectedAppDetails.authentication_data || (selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false) || (selectedAppDetails.authentication && selectedAppDetails.authentication.required == false)) ? + <> + + {true || (selectedAppDetails.auth_config && selectedAppDetails.auth_config.required == false || (selectedAppDetails.authentication && selectedAppDetails.authentication.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 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 = useCallback(() => { + const appList = Object.values(notificationAppsDetails); + return ( + + + {appList.map((app) => ( + { + 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={{app.name}} + /> + ))} + + + + + + Want access to more templates? + + Set up app authentication + + to unlock additional workflow options. + + + + ); + }, [notificationAppsDetails]) + useEffect(() => { getFramework() @@ -83,7 +1224,7 @@ const Priorities = memo((props) => { setSelectedExecutionId(execution_id) //toast.info("Execution-related notifications are highlighted.") - } + } if (workflow !== null) { setSelectedWorkflow(workflow) @@ -97,7 +1238,7 @@ const Priorities = memo((props) => { return } - if(workflows?.length === 0) { + if (workflows?.length === 0) { getAvailableWorkflows() } @@ -107,7 +1248,7 @@ const Priorities = memo((props) => { }, [selectedOrganization]) if (userdata === undefined || userdata === null) { - return + return } const getFramework = () => { @@ -119,67 +1260,67 @@ const Priorities = memo((props) => { }, credentials: "include", }) - .then((response) => { - if (response.status !== 200) { - console.log("Status not 200 for framework!"); - } - - return response.json(); - }) - .then((responseJson) => { - if (responseJson.success === false) { - setAppFramework({}) - if (responseJson.reason !== undefined) { - //toast("Failed loading: " + responseJson.reason) - } else { - //toast("Failed to load framework for your org.") + .then((response) => { + if (response.status !== 200) { + console.log("Status not 200 for framework!"); } - } else { - setAppFramework(responseJson) - } - }) - .catch((error) => { - console.log("err in framework: ", error.toString()); - }) + + return response.json(); + }) + .then((responseJson) => { + if (responseJson.success === false) { + setAppFramework({}) + if (responseJson.reason !== undefined) { + //toast("Failed loading: " + responseJson.reason) + } else { + //toast("Failed to load framework for your org.") + } + } else { + setAppFramework(responseJson) + } + }) + .catch((error) => { + console.log("err in framework: ", error.toString()); + }) } - const clearNotifications = () => { - // Don't really care about the logout + const clearNotifications = () => { + // Don't really care about the logout - toast("Clearing notifications") - fetch(`${globalUrl}/api/v1/notifications/clear`, { - credentials: "include", - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }) - .then(function (response) { - if (response.status !== 200) { - console.log("Error in response"); - } + toast("Clearing notifications") + fetch(`${globalUrl}/api/v1/notifications/clear`, { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }) + .then(function (response) { + if (response.status !== 200) { + console.log("Error in response"); + } - return response.json(); - }) - .then(function (responseJson) { - if (responseJson.success === true) { - // Reload the UI - const newNotifications = notifications.map((notification) => { - notification.read = true - return notification - }) + return response.json(); + }) + .then(function (responseJson) { + if (responseJson.success === true) { + // Reload the UI + const newNotifications = notifications.map((notification) => { + notification.read = true + return notification + }) - setNotifications(newNotifications) - setShowRead(true) - } else { - toast("Failed dismissing notifications. Please try again later."); - } - }) - .catch((error) => { - console.log("error in notification dismissal: ", error); - //removeCookie("session_token", {path: "/"}) - }); - }; + setNotifications(newNotifications) + setShowRead(true) + } else { + toast("Failed dismissing notifications. Please try again later."); + } + }) + .catch((error) => { + console.log("error in notification dismissal: ", error); + //removeCookie("session_token", {path: "/"}) + }); + }; const dismissNotification = (alert_id, disabled) => { var notificationurl = `${globalUrl}/api/v1/notifications/${alert_id}/markasread` @@ -189,82 +1330,82 @@ const Priorities = memo((props) => { notificationurl += "?disabled=false" } - fetch(notificationurl , { - credentials: "include", - method: "GET", - headers: { - "Content-Type": "application/json", - }, - }) - .then(function (response) { - if (response.status !== 200) { - console.log("Error in response"); - } - - return response.json(); - }) - .then(function (responseJson) { - if (responseJson.success === true) { - // Mark current one as read - var newNotifications = notifications.map((notification) => { - if (notification.id === alert_id) { - notification.read = true + fetch(notificationurl, { + credentials: "include", + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }) + .then(function (response) { + if (response.status !== 200) { + console.log("Error in response"); } - return notification + return response.json(); }) + .then(function (responseJson) { + if (responseJson.success === true) { + // Mark current one as read + var newNotifications = notifications.map((notification) => { + if (notification.id === alert_id) { + notification.read = true + } + + return notification + }) - if (disabled === true) { - toast("Notification disabled, and will not be shown again.") + if (disabled === true) { + toast("Notification disabled, and will not be shown again.") - newNotifications = newNotifications.map((notification) => { - if (notification.id === alert_id) { - notification.ignored = true + newNotifications = newNotifications.map((notification) => { + if (notification.id === alert_id) { + notification.ignored = true + } + + return notification + }) + + console.log("NEW NOTIFICATIONS: ", newNotifications); + } else if (disabled === false) { + toast("Notification re-enabled successfully") + + newNotifications = newNotifications.map((notification) => { + if (notification.id === alert_id) { + notification.ignored = false + } + + return notification + }) + + } else { + toast("Notification dismissed successfully") } - return notification - }) + //const newNotifications = notifications.filter( + // (data) => data.id !== alert_id + //) - console.log("NEW NOTIFICATIONS: ", newNotifications); - } else if (disabled === false) { - toast("Notification re-enabled successfully") + //console.log("NEW NOTIFICATIONS: ", newNotifications); - newNotifications = newNotifications.map((notification) => { - if (notification.id === alert_id) { - notification.ignored = false + if (setNotifications !== undefined && newNotifications !== undefined) { + setNotifications(newNotifications) } - - return notification - }) - - } else { - toast("Notification dismissed successfully") - } - - //const newNotifications = notifications.filter( - // (data) => data.id !== alert_id - //) - - //console.log("NEW NOTIFICATIONS: ", newNotifications); - - if (setNotifications !== undefined && newNotifications !== undefined) { - setNotifications(newNotifications) - } - } else { - toast("Failed dismissing notification. Please try again later."); - } - }) - .catch((error) => { - console.log("error in notification dismissal: ", error); - //removeCookie("session_token", {path: "/"}) - }) + } else { + toast("Failed dismissing notification. Please try again later."); + } + }) + .catch((error) => { + console.log("error in notification dismissal: ", error); + //removeCookie("session_token", {path: "/"}) + }) } - - const notificationWidth = "100%" + + const notificationWidth = "100%" const imagesize = 22 - const boxColor = "#86c142" + const boxColor = "#86c142" const getAvailableWorkflows = () => { @@ -354,134 +1495,168 @@ const Priorities = memo((props) => { } return ( -
-
-
- - Notification Workflow - - - The notification workflow triggers when an error occurs in one of your workflows. Each individual one will only start a workflow once every 2 minutes. You can point child org notifications into the parent org notification by choosing it in the list. - - -
+
+
+
+ + Notification Workflow + + + The notification workflow triggers when an error occurs in one of your workflows. Each individual one will only start a workflow once every 2 minutes. You can point child org notifications into the parent org notification by choosing it in the list. + - {workflows !== undefined && workflows !== null && workflows.length > 0 ? - { - setOpenNotification(true); - }} - onClose={() => { - setOpenNotification(false); - }} - freeSolo - //autoSelect - value={workflows?.find(w => w.id === notificationWorkflow) || null} - classes={{ inputRoot: classes.inputRoot }} - ListboxProps={{ - style: { - backgroundColor: theme.palette.surfaceColor, - color: theme.palette.text.primary, - borderRadius: theme.palette.borderRadius, - }, - }} - getOptionLabel={(option) => { - if ( - option === undefined || - option === null || - option.name === undefined || - option.name === null - ) { - return "No Workflow Selected"; - } + {modalView} + {/*{testWorkflowModal} */} +
+ {renderChips()} +
- const newname = ( - option.name.charAt(0).toUpperCase() + option.name.substring(1) - ).replaceAll("_", " "); - return newname; - }} - options={workflows} - fullWidth - style={{ - backgroundColor: theme.palette.textFieldStyle.backgroundColor, - borderRadius: theme.palette.textFieldStyle.borderRadius, - color: theme.palette.textFieldStyle.color, - height: 35, - marginBottom: 40, - }} - 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"> - 0 ? + { + setOpenNotification(true); + }} + onClose={() => { + setOpenNotification(false); + }} + freeSolo + //autoSelect + value={workflows?.find(w => w.id === notificationWorkflow) || null} + classes={{ inputRoot: classes.inputRoot }} + ListboxProps={{ + style: { backgroundColor: theme.palette.surfaceColor, - color: data.id === workflow.id ? "red" : theme.palette.text.primary, - borderBottom: data.id === "parent" ? "2px solid rgba(255,255,255,0.5)" : null - }} - value={data} - onClick={(e) => { - props.onMouseDown?.(null); - var parsedinput = { target: { value: data } } - handleWorkflowSelectionUpdate(parsedinput) - }} - > - {data.name} - - - ) - }} - renderInput={(params) => { - return ( - { + 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.textFieldStyle.backgroundColor, - color: theme.palette.textFieldStyle.color, borderRadius: theme.palette.textFieldStyle.borderRadius, + color: theme.palette.textFieldStyle.color, height: 35, - fontSize: 16, - marginTop: "16px" + marginBottom: 40, }} + 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"> + { + props.onMouseDown?.(null); + var parsedinput = { target: { value: data } } + handleWorkflowSelectionUpdate(parsedinput) + }} + > + {data.name} + + + ) + }} + renderInput={(params) => { + return ( + + ); + }} + /> + : + { borderRadius: 4, }, inputProps: { - ...params.inputProps, style: { height: "100%", boxSizing: "border-box", @@ -499,198 +1673,171 @@ const Priorities = memo((props) => { } }} - // label="Find a notification workflow" - variant="outlined" - placeholder="Select a notification workflow" + style={{ + backgroundColor: theme.palette.textFieldStyle.backgroundColor, + color: theme.palette.textFieldStyle.color, + borderRadius: 4, + height: 35, + fontSize: 16, + marginBottom: 30 + }} + fullWidth={true} + type="name" + id="outlined-with-placeholder" + margin="normal" + variant="outlined" + placeholder="ID of the workflow to receive notifications" + value={notificationWorkflow} + onChange={(e) => { + setNotificationWorkflow(e.target.value); + }} /> - ); - }} - /> - : - { - setNotificationWorkflow(e.target.value); - }} - /> - } - {/*
+ {/*
{orgSaveButton}
*/} -
+
- {notificationWorkflow === undefined || notificationWorkflow === null || notificationWorkflow.length === 0 ? null : -
- + { + if (notificationWorkflow === "parent") { + toast.error("Can't open parent org's notification workflow from here.") + return + } + + window.open(`/workflows/${notificationWorkflow}?view=executions`, "_blank") + }} + > + + +
} - fetch(`${globalUrl}/api/v1/workflows/${notificationWorkflow}/execute`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "Accept": "application/json", - }, - credentials: "include", - body: JSON.stringify({ - "title": "Test Notification", - "description": "This is a test notification to check if the notification workflow is working correctly.", - "org_id": selectedOrganization.id, - "id": uuidv4(), - "reference_url": "/admin?type=test&admin_tab=notifications", - "created_at": Math.floor(new Date().getTime() / 1000), - "updated_at": Math.floor(new Date().getTime() / 1000), + Notifications ({ + notifications?.filter((notification) => showRead === true || notification.read === false).length + }) + + + Notifications help you find potential problems with your workflows and apps.  + + Learn more + + +
+
+ { + setShowRead(!showRead); + }} + />  Show read + {notifications !== undefined && notifications !== null && notifications.length > 1 ? ( + + ) : null} +
+ + + + {clickedFromOrgTab ? null : } + + Suggestions + + Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company.
These range from simple configurations in Shuffle to Usecases you may have missed.  + + Learn more + +
+
+ { + setShowDismissed(!showDismissed); + }} + />  Show dismissed + {userdata.priorities === null || userdata.priorities === undefined || userdata.priorities.length === 0 ? + + No Suggestions found + + : + userdata.priorities.map((priority, index) => { + if (showDismissed === false && priority.active === false) { + return null + } + + return ( + + ) }) - }) - .then((response) => { - if (response.status === 200) { - toast.success("Test notification sent successfully.") - } else { - toast.error("Failed to send test notification. Please contact support if this persists") - } - }).catch((error) => { - toast.error("Failed to send test notification (2). Please contact support if this persists") - }) - }}> - Send test notification - - { - if (notificationWorkflow === "parent") { - toast.error("Can't open parent org's notification workflow from here.") - return - } - - window.open(`/workflows/${notificationWorkflow}?view=executions`, "_blank") - }} - > - - -
- } - - Notifications ({ - notifications?.filter((notification) => showRead === true || notification.read === false).length - }) - - - Notifications help you find potential problems with your workflows and apps.  - - Learn more - - -
-
- { - setShowRead(!showRead); - }} - />  Show read - {notifications !== undefined && notifications !== null && notifications.length > 1 ? ( - - ) : null} -
- - - - {clickedFromOrgTab? null : } - - Suggestions - - Suggestions are tasks identified by Shuffle to help you discover ways to protect your and customers' company.
These range from simple configurations in Shuffle to Usecases you may have missed.  - - Learn more - -
-
- { - setShowDismissed(!showDismissed); - }} - />  Show dismissed - {userdata.priorities === null || userdata.priorities === undefined || userdata.priorities.length === 0 ? - - No Suggestions found - - : - userdata.priorities.map((priority, index) => { - if (showDismissed === false && priority.active === false) { - return null } - - return ( - - ) - }) - } -
-
+
+
) }) @@ -699,15 +1846,15 @@ export default Priorities; const NotificationItem = memo((props) => { - const {data, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification} = props + const { data, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification } = props var image = ""; var orgName = ""; var orgId = ""; const { themeMode, brandColor } = useContext(Context); - const theme = getTheme(themeMode, brandColor); - - var highlighted = selectedExecutionId === "" && selectedWorkflow === "" ? false : data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0 ? false : data.reference_url.includes(selectedExecutionId) || data.reference_url.includes(selectedWorkflow) + const theme = getTheme(themeMode, brandColor); + + var highlighted = selectedExecutionId === "" && selectedWorkflow === "" ? false : data.reference_url === undefined || data.reference_url === null || data.reference_url.length === 0 ? false : data.reference_url.includes(selectedExecutionId) || data.reference_url.includes(selectedWorkflow) if (!highlighted && highlightKMS) { if (data.title !== undefined && data.title !== null && data.title.toLowerCase().includes("kms")) { @@ -719,45 +1866,45 @@ const NotificationItem = memo((props) => { } if (userdata.orgs !== undefined) { - const foundOrg = userdata.orgs.find((org) => org.id === data["org_id"]); - if (foundOrg !== undefined && foundOrg !== null) { - //position: "absolute", bottom: 5, right: -5, - const imageStyle = { - width: imagesize, - height: imagesize, - pointerEvents: "none", - marginLeft: - data.creator_org !== undefined && data.creator_org.length > 0 - ? 20 - : 0, - borderRadius: 10, - border: - foundOrg.id === userdata.active_org.id - ? `3px solid ${boxColor}` - : null, - cursor: "pointer", - marginRight: 10, - }; + const foundOrg = userdata.orgs.find((org) => org.id === data["org_id"]); + if (foundOrg !== undefined && foundOrg !== null) { + //position: "absolute", bottom: 5, right: -5, + const imageStyle = { + width: imagesize, + height: imagesize, + pointerEvents: "none", + marginLeft: + data.creator_org !== undefined && data.creator_org.length > 0 + ? 20 + : 0, + borderRadius: 10, + border: + foundOrg.id === userdata.active_org.id + ? `3px solid ${boxColor}` + : null, + cursor: "pointer", + marginRight: 10, + }; - image = - foundOrg.image === "" ? ( - {foundOrg.name} - ) : ( - {foundOrg.name} {}} - /> - ); + image = + foundOrg.image === "" ? ( + {foundOrg.name} + ) : ( + {foundOrg.name} { }} + /> + ); - orgName = foundOrg.name; - orgId = foundOrg.id; - } + orgName = foundOrg.name; + orgId = foundOrg.id; + } } return ( @@ -776,185 +1923,185 @@ const NotificationItem = memo((props) => { backgroundColor: theme.palette.cardHoverColor, }, }} - > -
- {data.amount === 1 && data.read === false ? - - : null} - {data.ignored === true ? - - : null} - {data.read === false ? - - : - - } - - {data.title} - -
- - {data.image !== undefined && data.image !== null && data.image.length > 0 ? - {data.title} - : - null - } - - {data.description} - -
- - - - {data.read === false ? ( - - ) : null} - - - - - +
+ {data.amount === 1 && data.read === false ? + + : null} + {data.ignored === true ? + + : null} + {data.read === false ? + + : + + } + + {data.title} + +
- 0 ? + {data.title} + : + null + } + + {data.description} + +
+ + - }} - > - First seen:{" "} - {new Date(data.created_at * 1000).toISOString().slice(0, 19)} - + {data.read === false ? ( + + ) : null} - - Last seen:{" "} - {new Date(data.updated_at * 1000).toISOString().slice(0, 19)} - + + + + - - Times seen: {data.amount} - -
+ + }} + > + First seen:{" "} + {new Date(data.created_at * 1000).toISOString().slice(0, 19)} + + + + Last seen:{" "} + {new Date(data.updated_at * 1000).toISOString().slice(0, 19)} + + + + Times seen: {data.amount} + +
+ + ); }) -const NotificationComponent = memo(({notifications, showRead, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification}) => { +const NotificationComponent = memo(({ notifications, showRead, selectedExecutionId, selectedWorkflow, highlightKMS, userdata, imagesize, boxColor, clickedFromOrgTab, notificationWidth, dismissNotification }) => { - return( + return (
{notifications === null || notifications === undefined || notifications?.length === 0 ? ( - null - ) : -
- {notifications?.map((notification, index) => { - if (showRead === false && notification.read === true) { - return null - } + null + ) : +
+ {notifications?.map((notification, index) => { + if (showRead === false && notification.read === true) { + return null + } - return ( - - ) - })} -
- } + return ( + + ) + })} +
+ }
) }) diff --git a/frontend/src/components/ShuffleCodeEditor1.jsx b/frontend/src/components/ShuffleCodeEditor1.jsx index 33b37483..3132034f 100644 --- a/frontend/src/components/ShuffleCodeEditor1.jsx +++ b/frontend/src/components/ShuffleCodeEditor1.jsx @@ -132,7 +132,7 @@ const CodeEditor = (props) => { fieldname, contentLoading, editorData, - handleSubflowParamChange, + handleTriggerParamChange, setAiQueryModalOpen, fullScreenMode, environment, @@ -212,7 +212,7 @@ const CodeEditor = (props) => { const triggerField = searchParams.get('trigger_field'); const triggerName = searchParams.get('trigger_name'); const conditionId = searchParams.get('condition_id'); - const conditionField = searchParams.get('field'); + const conditionField = searchParams.get('condition_field'); useEffect(() => { if (actionId === undefined || actionId === null) { @@ -251,7 +251,7 @@ const CodeEditor = (props) => { setSelectedCondition(condition); // Update available variables when condition changes updateAvailableVariables(actionlist); - }, [conditionId, fieldName]) + }, [conditionId, conditionField]) // Extract variable updating logic into a separate function const updateAvailableVariables = (actionlist) => { @@ -2588,7 +2588,7 @@ const CodeEditor = (props) => { // Handle condition fields if (conditionField !== null && handleConditionFieldChange !== undefined) { - handleConditionFieldChange(conditionField, fieldName, fixedcodedata); + handleConditionFieldChange(conditionField, fixedcodedata); } // Handle action fields else if (actionId !== undefined && actionId !== null && actionId.length > 0) { @@ -2596,7 +2596,7 @@ const CodeEditor = (props) => { } // Handle trigger fields else if (triggerId !== undefined && triggerId !== null && triggerId.length > 0) { - handleSubflowParamChange(triggerId, triggerField, fixedcodedata) + handleTriggerParamChange(triggerId, triggerField, fixedcodedata) } setExpansionModalOpen(false) diff --git a/frontend/src/views/AngularWorkflow.jsx b/frontend/src/views/AngularWorkflow.jsx index db5111bd..95b3e462 100755 --- a/frontend/src/views/AngularWorkflow.jsx +++ b/frontend/src/views/AngularWorkflow.jsx @@ -13032,7 +13032,7 @@ const AngularWorkflow = (defaultprops) => { event.preventDefault() setExpansionModalOpen(true) setActiveDialog("codeeditor") - navigate(`?condition_id=${data.id}&field=${data.name}`) + navigate(`?condition_id=${data.id}&condition_field=${data.name}`) setEditorData({ "name": data.name, "value": data.value || "", @@ -13117,9 +13117,9 @@ const AngularWorkflow = (defaultprops) => { // Update the field value based on type if (type === "source") { - handleConditionFieldChange("source", "value", toComplete); + handleConditionFieldChange("source", toComplete); } else if (type === "destination") { - handleConditionFieldChange("destination", "value", toComplete); + handleConditionFieldChange("destination", toComplete); } handleMenuClose(); @@ -13996,7 +13996,7 @@ const AngularWorkflow = (defaultprops) => { /> - const handleConditionFieldChange = (fieldType, fieldName, value) => { + const handleConditionFieldChange = (fieldType, value) => { if (fieldType === "source") { setSourceValue({ ...sourceValue, @@ -15197,7 +15197,7 @@ const AngularWorkflow = (defaultprops) => { } ] - const handleSubflowParamChange = (triggerId, triggerField, newData) => { + const handleTriggerParamChange = (triggerId, triggerField, newData) => { var updateFail = "" if (workflow !== undefined && workflow !== null) { @@ -17336,9 +17336,13 @@ const AngularWorkflow = (defaultprops) => { fullWidth rows="4" multiline - defaultValue={selectedTrigger.parameters[0]?.value} + value={selectedTriggerValue || ""} color="primary" placeholder="" + onChange={(e) => { + setLastSaved(false) + setSelectedTriggerValue(e.target.value) + }} onBlur={(e) => { setLastSaved(false) setTriggerTextInformationWrapper(e.target.value); @@ -25472,7 +25476,7 @@ const AngularWorkflow = (defaultprops) => { // selectedTrigger={selectedTrigger} aiSubmit={aiSubmit} toolsAppId={toolsApp.id} - handleSubflowParamChange={handleSubflowParamChange} + handleTriggerParamChange={handleTriggerParamChange} codedata={editorData.value} setcodedata={setcodedata} selectedEdge={selectedEdge} diff --git a/frontend/src/views/LoginPage.jsx b/frontend/src/views/LoginPage.jsx index 26bf6782..b2cb9426 100755 --- a/frontend/src/views/LoginPage.jsx +++ b/frontend/src/views/LoginPage.jsx @@ -314,12 +314,15 @@ const LoginPage = props => { }, }) - if (serverside !== true) { - const tmpMessage = new URLSearchParams(window.location.search).get("message") - if (tmpMessage !== undefined && tmpMessage !== null && message !== tmpMessage) { - setMessage(tmpMessage) + useEffect(() => { + if (serverside !== true) { + const tmpMessage = new URLSearchParams(window.location.search).get("message") + if (tmpMessage !== undefined && tmpMessage !== null && message !== tmpMessage) { + setMessage(tmpMessage) + toast(tmpMessage) + } } - } + }, []) if (document !== undefined) { if (register) { @@ -444,13 +447,17 @@ const LoginPage = props => { } if (isLoggedIn === true && serverside !== true) { - const tmpView = new URLSearchParams(window.location.search).get("view") - if (tmpView !== undefined && tmpView !== null && tmpView === "pricing") { - window.location.pathname = "/pricing" - return - } else if (tmpView !== undefined && tmpView !== null) { - window.location.pathname = tmpView - return + const tmpView = new URLSearchParams(window.location.search).get("view"); + if (tmpView !== undefined && tmpView !== null) { + let pathOnly = tmpView.split("?")[0]; + if (!pathOnly.startsWith("/")) pathOnly = "/" + pathOnly; + + if (pathOnly === "/pricing" || pathOnly === "admin") { + window.location.replace(pathOnly + window.location.search); + } else { + window.location.replace(pathOnly); + } + return; } window.location.pathname = "/workflows" @@ -575,20 +582,17 @@ const LoginPage = props => { setCookie(responseJson["cookies"][key].key, responseJson["cookies"][key].value, { path: "/" }) } - const tmpView = new URLSearchParams(window.location.search).get("view") + const tmpView = new URLSearchParams(window.location.search).get("view"); if (tmpView !== undefined && tmpView !== null) { - //const newUrl = `/${tmpView}${decodeURIComponent(window.location.search)}` - // Check if slash in the url + let pathOnly = tmpView.split("?")[0]; + if (!pathOnly.startsWith("/")) pathOnly = "/" + pathOnly; - var newUrl = `/${tmpView}` - if (tmpView.startsWith("/")) { - newUrl = `${tmpView}` + if (pathOnly === "/pricing" || pathOnly === "admin") { + window.location.replace(pathOnly + window.location.search); + } else { + window.location.replace(pathOnly); } - - console.log("Found url: ", newUrl) - - window.location.pathname = newUrl - return + return; } console.log("LOGIN DATA: ", responseJson) @@ -647,9 +651,14 @@ const LoginPage = props => { const tmpView = new URLSearchParams(window.location.search).get("view") if (tmpView !== undefined && tmpView !== null) { - //const newUrl = `/${tmpView}${decodeURIComponent(window.location.search)}` - const newUrl = `/${tmpView}` - window.location.pathname = newUrl + let pathOnly = tmpView.split("?")[0]; + if (!pathOnly.startsWith("/")) pathOnly = "/" + pathOnly; + + if (pathOnly === "/pricing" || pathOnly === "admin") { + window.location.replace(pathOnly + window.location.search); + } else { + window.location.replace(pathOnly); + } return } diff --git a/frontend/src/views/SettingsPage.jsx b/frontend/src/views/SettingsPage.jsx index f10dbfb7..ec5ba658 100755 --- a/frontend/src/views/SettingsPage.jsx +++ b/frontend/src/views/SettingsPage.jsx @@ -458,7 +458,12 @@ const Settings = (props) => { if (responseJson["success"] === false) { setPasswordFormMessage(responseJson["reason"]); } else { - toast("Changed password!"); + var reason = "" + if (responseJson.reason !== undefined && responseJson.reason !== null && responseJson.reason.length > 0) { + reason += responseJson.reason + } + + toast.success("Changed password! " + reason); setPasswordFormMessage(""); } }) diff --git a/frontend/src/views/Workflows2.jsx b/frontend/src/views/Workflows2.jsx index 1655c901..c059f991 100644 --- a/frontend/src/views/Workflows2.jsx +++ b/frontend/src/views/Workflows2.jsx @@ -5071,7 +5071,7 @@ const Workflows2 = (props) => { //isLoaded && isLoggedIn && workflowDone ? ( const loadedCheck = - workflowDone ? ( + workflowDone && isLoaded ? (
{/* @@ -5134,7 +5134,9 @@ const Workflows2 = (props) => { }} > - Loading Workflows + + Loading Workflows and Apps +
);