From e92c2817b26fd951544e1dda767b71a61acaa4a7 Mon Sep 17 00:00:00 2001 From: "lalitdeore12@gmail.com" Date: Tue, 20 May 2025 01:02:16 +0530 Subject: [PATCH] Fix - light theme ui break due to theme --- backend/go-app/main.go | 1 + frontend/src/App.jsx | 35 +- frontend/src/components/Branding.jsx | 467 +++++++++++++++++- frontend/src/components/CacheView.jsx | 6 +- frontend/src/components/CloudSyncTab.jsx | 5 +- frontend/src/components/LeftSideBar.jsx | 58 ++- .../src/components/OrgHeaderexpandedNew.jsx | 19 +- frontend/src/components/UserManagmentTab.jsx | 12 +- 8 files changed, 542 insertions(+), 61 deletions(-) diff --git a/backend/go-app/main.go b/backend/go-app/main.go index fbd2a251..60f162b4 100755 --- a/backend/go-app/main.go +++ b/backend/go-app/main.go @@ -1069,6 +1069,7 @@ func handleInfo(resp http.ResponseWriter, request *http.Request) { activatedAppIds = append(activatedAppIds, app.ID) } + userInfo.ActiveOrg.Branding = org.Branding returnValue := shuffle.HandleInfo{ Success: true, diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index cd092d98..fa3ac7ea 100755 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -92,8 +92,8 @@ const App = (message, props) => { const [dataset, setDataset] = useState(false) const [isLoaded, setIsLoaded] = useState(false) const [curpath, setCurpath] = useState(typeof window === "undefined" || window.location === undefined ? "" : window.location.pathname) - const { themeMode, handleThemeChange } = useContext(Context); - const currentTheme = getTheme(themeMode); + const { themeMode, handleThemeChange, setBrandColor, brandColor} = useContext(Context); + const currentTheme = getTheme(themeMode, brandColor); const mainColor = currentTheme?.palette?.backgroundColor const [isPreviousThemeLight, setIsPreviousThemeLight] = useState(false) @@ -106,18 +106,27 @@ const App = (message, props) => { }, []); useEffect(() => { - const isDarkPath = curpath === "/" || curpath === "/pricing" || curpath === "/partners" || curpath === "/faq" || curpath === "/professional-services" || curpath === "/contact" || curpath === "/training"; - if (curpath && isDarkPath) { - if (themeMode === "light") { - setIsPreviousThemeLight(true) + const isDarkPath = curpath === "/" || curpath === "/pricing" || curpath === "/partners" || curpath === "/faq" || curpath === "/professional-services" || curpath === "/contact" || curpath === "/training"; + if (curpath && isDarkPath) { + if (themeMode === "light") { + setIsPreviousThemeLight(true) + } + handleThemeChange("dark") + }else if ( !isDarkPath && isPreviousThemeLight && userdata?.active_org?.branding?.theme === "light") { + handleThemeChange("light") + setIsPreviousThemeLight(false) } - handleThemeChange("dark") - }else if ( !isDarkPath && isPreviousThemeLight && userdata?.active_org?.branding?.theme === "light") { - handleThemeChange("light") - setIsPreviousThemeLight(false) - } -}, [themeMode, curpath, userdata]) + if (isDarkPath && userdata && userdata?.active_org?.branding?.brand_color !== "#ff8544") { + setBrandColor("#ff8544") + }else if(!isDarkPath && userdata && userdata?.active_org?.branding?.brand_color !== "#ff8544" && userdata?.active_org?.branding?.brand_color?.length > 0) { + const brandColor = localStorage.getItem("brandColor") + if (brandColor !== null && brandColor !== undefined && brandColor.length > 0) { + setBrandColor(brandColor) + } + } + + }, [themeMode, curpath, userdata]) if ( isLoaded && @@ -936,7 +945,7 @@ const App = (message, props) => { pauseOnFocusLoss draggable pauseOnHover - theme="dark" + theme={themeMode} /> diff --git a/frontend/src/components/Branding.jsx b/frontend/src/components/Branding.jsx index e549d12e..649c509a 100644 --- a/frontend/src/components/Branding.jsx +++ b/frontend/src/components/Branding.jsx @@ -1,8 +1,7 @@ import React, { useState, useEffect, useContext } from "react"; import ReactGA from 'react-ga4'; -import theme from "../theme.jsx"; +import {getTheme} from "../theme.jsx"; import { ToastContainer, toast } from "react-toastify" - import { CheckCircle as CheckCircleIcon, } from "@mui/icons-material"; @@ -13,8 +12,11 @@ import { Divider, Button, Tooltip, - Grid, - Card, + ToggleButtonGroup, + ToggleButton, + useMediaQuery, + TextField, + Box, } from "@mui/material"; import { @@ -27,18 +29,98 @@ import { Context } from "../context/ContextApi.jsx"; const Branding = (props) => { const { globalUrl, userdata, serverside, billingInfo,clickedFromOrgTab, stripeKey, selectedOrganization, handleGetOrg, } = props; + const { themeMode, handleThemeChange, supportEmail, setSupportEmail, logoutUrl, setLogoutUrl, brandColor, setBrandColor, setBrandName } = useContext(Context) //const alert = useAlert(); const [publishingInfo, setPublishingInfo] = useState(""); const [publishRequirements, setPublishRequirements] = useState([]) + const [currentSelectedTheme, setCurrentSelectedTheme] = useState("dark"); + const [integrationPartner, setIntegrationPartner] = useState(false); + const [changingTheme, setChangingTheme] = useState(false); + 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 { leftSideBarOpenByClick } = useContext(Context) - - const handleEditOrg = (joinStatus) => { + const handleEditOrg = (joinStatus) => { + setIsLoading(true) const data = { "org_id": selectedOrganization.id, - "creator_config": joinStatus, }; + if (joinStatus === "join" || joinStatus === "leave") { + data["creator_config"] = joinStatus + } + + if (joinStatus === "light" || joinStatus === "dark" || joinStatus === "system") { + data["branding"] = { + "theme": joinStatus, + "enable_chat": selectedOrganization?.branding?.enable_chat || false, + "home_url": selectedOrganization?.branding?.home_url || "", + "brand_color": selectedOrganization?.branding?.brand_color || theme.palette.primary.main, + "brand_name": selectedOrganization?.branding?.brand_name || "", + "logout_url": selectedOrganization?.branding?.logout_url || "", + "support_email": selectedOrganization?.branding?.support_email || "", + } + + data["editing_branding"] = true; + } + + if (joinStatus === "brand_color") { + data["branding"] = { + "theme": selectedOrganization?.branding?.theme || "dark", + "enable_chat": selectedOrganization?.branding?.enable_chat || false, + "home_url": selectedOrganization?.branding?.home_url || "", + "brand_color": selectedBrandColor, + "brand_name": selectedOrganization?.branding?.brand_name || "", + "logout_url": selectedOrganization?.branding?.logout_url || "", + "support_email": selectedOrganization?.branding?.support_email || "", + } + + data["editing_branding"] = true; + } + + if (joinStatus === "brand_name") { + data["branding"] = { + "theme": selectedOrganization?.branding?.theme || "dark", + "enable_chat": selectedOrganization?.branding?.enable_chat || false, + "home_url": selectedOrganization?.branding?.home_url || "", + "brand_color": selectedOrganization?.branding?.brand_color || theme.palette.primary.main, + "brand_name": selectedBrandName, + "logout_url": selectedOrganization?.branding?.logout_url || "", + "support_email": selectedOrganization?.branding?.support_email || "", + } + toast.info("Updating brand name to " + selectedBrandName + ". Please wait a moment.") + data["editing_branding"] = true; + } + + if (joinStatus === "support_email") { + data["branding"] = { + "theme": selectedOrganization?.branding?.theme || "dark", + "enable_chat": selectedOrganization?.branding?.enable_chat || false, + "home_url": selectedOrganization?.branding?.home_url || "", + "brand_color": selectedOrganization?.branding?.brand_color || theme.palette.primary.main, + "brand_name": selectedOrganization?.branding?.brand_name || "", + "support_email": supportEmail, + "logout_url": selectedOrganization?.branding?.logout_url || "", + } + data["editing_branding"] = true; + } + + if (joinStatus === "logout_url") { + data["branding"] = { + "theme": selectedOrganization?.branding?.theme || "dark", + "enable_chat": selectedOrganization?.branding?.enable_chat || false, + "home_url": selectedOrganization?.branding?.home_url || "", + "brand_color": selectedOrganization?.branding?.brand_color || theme.palette.primary.main, + "brand_name": selectedOrganization?.branding?.brand_name || "", + "support_email": selectedOrganization?.branding?.support_email || "", + "logout_url": logoutUrl, + } + data["editing_branding"] = true; + } + + const url = globalUrl + `/api/v1/orgs/${selectedOrganization.id}`; fetch(url, { mode: "cors", @@ -56,18 +138,56 @@ const Branding = (props) => { if (responseJson["success"] === false) { toast("Failed updating org: ", responseJson.reason); } else { - if (joinStatus == "join") { - setPublishingInfo("Your organization is now part of the Partner Program. You can now create, publish and manage content for your organization's public page.") - } else { - setPublishingInfo("Your organization is no longer part of the Creator Incentive Program. You can still create a creator account to manage your organization's content.") + if (joinStatus === "join" || joinStatus === "leave") { + if (joinStatus === "join") { + setPublishingInfo("Your organization is now part of the Partner Program. You can now create, publish and manage content for your organization's public page.") + } else { + setPublishingInfo("Your organization is no longer part of the Creator Incentive Program. You can still create a creator account to manage your organization's content.") + } } + + if (joinStatus === "light" || joinStatus === "dark" || joinStatus === "system") { + handleThemeChange(joinStatus) + setChangingTheme(false) + setCurrentSelectedTheme(joinStatus) + } + + if (joinStatus === "support_email") { + toast.info("Support email updated successfully.") + if (supportEmail?.length > 0) { + setSupportEmail(supportEmail) + }else { + setSupportEmail("support@shuffler.io") + } + } + + if (joinStatus === "logout_url") { + toast.info("Logout URL updated successfully.") + setLogoutUrl(logoutUrl) + } + + if (joinStatus === "brand_color") { + toast.info("Brand color updated successfully.") + setBrandColor(selectedBrandColor) + localStorage.setItem("brandColor", selectedBrandColor) + } + + if (joinStatus === "brand_name") { + toast.info("Brand name updated successfully.") + setBrandName(selectedBrandName) + localStorage.setItem("brandName", selectedBrandName) + } + handleGetOrg(selectedOrganization.id); - } + + setIsLoading(false) + } }) ) .catch((error) => { toast("Err: " + error.toString()); - }); + setIsLoading(false) + }) }; // Should enable / disable org branding @@ -117,16 +237,60 @@ const Branding = (props) => { const leadinfo = selectedOrganization.lead_info === undefined || selectedOrganization.lead_info === null || selectedOrganization.lead_info === "" ? "" : JSON.stringify(selectedOrganization.lead_info) const isPartner = leadinfo.includes("partner") + + useEffect(() => { + if (selectedOrganization?.branding?.theme && selectedOrganization?.creator_org?.length === 0) { + setCurrentSelectedTheme(selectedOrganization.branding.theme); + } + + if (selectedOrganization?.creator_org?.length > 0 && userdata?.active_org?.branding.theme) { + setCurrentSelectedTheme(userdata?.active_org?.branding.theme); + } + + if (userdata.support) { + setCurrentSelectedTheme(localStorage.getItem("theme") || "dark"); + } + + if ( + selectedOrganization && + selectedOrganization?.branding?.brand_color && + selectedOrganization?.branding?.brand_color !== selectedBrandColor + ) { + setSelectedBrandColor(selectedOrganization.branding.brand_color); + } + + if (selectedOrganization?.branding?.brand_name && selectedOrganization?.branding?.brand_name !== selectedBrandName) { + setSelectedBrandName(selectedOrganization.branding.brand_name); + } + + }, [selectedOrganization, userdata]); + + useEffect(() => { + if ((userdata && userdata?.org_status?.includes("integration_partner") && !integrationPartner && !userdata?.org_status?.includes("sub_org")) || userdata?.support) { + setIntegrationPartner(true) + } + + },[userdata, integrationPartner]); + + const handleColorChange = (e) => { + setSelectedBrandColor(e.target.value); + }; + + const saveColorChanges = () => { + toast.info("Updating brand color to " + selectedBrandColor + ". Please wait a moment.") + handleEditOrg("brand_color"); + }; + return ( -
-
+
+
Partner Status & Branding - You can customize your organization's branding by uploading a logo, changing the color scheme and a lot more. + Please note that same theme settings are applied to all sub organizations for partners. @@ -150,7 +314,8 @@ const Branding = (props) => { style={{ textDecoration: "none" }} // Optional: remove underline > )} - + - Partner Program + Public Partner Program
- - By changing publishing settings, you agree to our Terms of Service, and acknowledge that your organization's non-sensitive data will be added as a creator account. None of your existing workflows, apps, or other stored data will be published. Any admin in your organization can manage the creator configuration. Becoming a creator organization IS reversible.
Support: support@shuffler.io + + By changing publishing settings, you agree to our Terms of Service, and acknowledge that your organization's non-sensitive data will be added as a creator account. None of your existing workflows, apps, or other stored data will be published. Any admin in your organization can manage the creator configuration. Becoming a creator organization IS reversible.
Support: {supportEmail} {selectedOrganization.creator_id == "" ? @@ -195,7 +360,9 @@ const Branding = (props) => { }
+ + + { integrationPartner ? ( + <> + + + Parent & Sub Organization Branding + + + Sub organizations are not allowed to change their branding. The branding is inherited from the parent organization. + + { + if (newTheme === null) { + return; + } + if (newTheme === currentSelectedTheme) { + return; + } + if (changingTheme === true) { + return + } + + + toast.info("Changing theme to " + newTheme + ". Please wait a moment.") + setChangingTheme(true) + handleEditOrg(newTheme); + }} + aria-label="theme" + style={{ justifyContent: "flex-start", marginBottom: 10, marginTop: 20 }} + > + + Light + + + Dark + + + System + + + + ): null} + + {integrationPartner ? <> + + Brand Name +
+ { + const value = e.target.value; + setSelectedBrandName(value); + }} + size="small" + PaperProps={{ style: { backgroundColor: theme.palette.backgroundColor, borderRadius: 4, border: `1px solid ${theme.palette.defaultBorder}` } }} + style={{ + height: 36, + borderRadius: 4, + border: `1px solid ${theme.palette.defaultBorder}`, + width: 300 + }} + /> + +
+ : null} + + {integrationPartner ? <> + Brand Color +
+ + + +
+ : null} + + + {integrationPartner ? ( +
+ Support Email + + { + setSupportEmail(e.target.value) + }} + color="primary" + InputProps={{ + style: { + color: theme.palette.textFieldStyle.color, + height: "35px", + fontSize: "1em", + borderRadius: 4, + backgroundColor: theme.palette.textFieldStyle.backgroundColor, + }, + }} + /> + + +
+ ) : null} + + {integrationPartner ? ( +
+ Logout URL + + { + setLogoutUrl(e.target.value) + }} + color="primary" + InputProps={{ + style: { + color: theme.palette.textFieldStyle.color, + height: "35px", + fontSize: "1em", + borderRadius: 4, + backgroundColor: theme.palette.textFieldStyle.backgroundColor, + }, + }} + /> + + +
+ ) : null}
) diff --git a/frontend/src/components/CacheView.jsx b/frontend/src/components/CacheView.jsx index e28b73f5..9cff6231 100644 --- a/frontend/src/components/CacheView.jsx +++ b/frontend/src/components/CacheView.jsx @@ -680,7 +680,7 @@ const CacheView = memo((props) => { labelId="input-namespace-select-label" id="input-namespace-select-id" style={{ - color: "white", + color: theme.palette.textFieldStyle.color, minWidth: 122, maxWidth: 122, height: 35, @@ -719,7 +719,7 @@ const CacheView = memo((props) => { {data.replaceAll("_", " ")} @@ -826,7 +826,7 @@ const CacheView = memo((props) => { }} InputProps={{ style: { - color: "white", + color: theme.palette.textFieldStyle.color, height: 35, fontSize: 16, borderRadius: 4, diff --git a/frontend/src/components/CloudSyncTab.jsx b/frontend/src/components/CloudSyncTab.jsx index 24a043fa..d4aaa072 100644 --- a/frontend/src/components/CloudSyncTab.jsx +++ b/frontend/src/components/CloudSyncTab.jsx @@ -644,14 +644,15 @@ const CloudSyncTab = (props) => { { } }, [usersWorkFlows]); + const handleChangeTheme = (newTheme) => { + + toast.info("Changing theme to " + newTheme + " - please wait!"); + + const data = { + "org_id": userdata?.active_org?.id, + }; + + data["branding"] = { + "theme": newTheme, + "enable_chat": userdata?.active_org?.branding?.enable_chat || false, + "home_url": userdata.active_org?.branding?.home_url || "", + "brand_color": userdata?.active_org?.branding?.brand_color || theme.palette.primary.main, + "brand_name": userdata?.active_org?.branding?.brand_name || "", + "logout_url": userdata?.active_org?.branding?.logout_url || "", + "support_email": userdata?.active_org?.branding?.support_email || "", + } + + data["editing_branding"] = true; + + const url = globalUrl + `/api/v1/orgs/${userdata?.active_org?.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 { + handleThemeChange(newTheme) + setCurrentSelectedTheme(newTheme); + } + + }) + ) + .catch((error) => { + console.log("Error changing theme: ", error); + }); + }; + + + const removeCookie = (name, path = "/") => { document.cookie = `${name}=; path=${path}; expires=Thu, 01 Jan 1970 00:00:00 GMT;`; }; @@ -505,9 +555,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { if (newTheme === currentSelectedTheme) { return; } - console.log("Selected theme:", newTheme); - setCurrentSelectedTheme(newTheme) - handleThemeChange(newTheme) + handleChangeTheme(newTheme); }} aria-label="theme" style={{display: 'flex', justifyContent: "center", marginBottom: 10, }} @@ -587,7 +635,7 @@ const LeftSideBar = ({ userdata, serverside, globalUrl, notifications, }) => { - Version: 2.1.0-beta + Version: 2.0.2 @@ -2022,4 +2070,4 @@ const ModalView = memo(({searchBarModalOpen, setSearchBarModalOpen, globalUrl, s ) ) -}); +}); \ No newline at end of file diff --git a/frontend/src/components/OrgHeaderexpandedNew.jsx b/frontend/src/components/OrgHeaderexpandedNew.jsx index 4f708800..525491e6 100644 --- a/frontend/src/components/OrgHeaderexpandedNew.jsx +++ b/frontend/src/components/OrgHeaderexpandedNew.jsx @@ -448,7 +448,7 @@ const OrgHeaderexpandedNew = (props) => {
-
+
@@ -931,7 +931,7 @@ const OrgHeaderexpandedNew = (props) => { marginTop: "8px", marginRight: "16px", height: 35, - backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor, + backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor, }} fullWidth={true} type="name" @@ -948,7 +948,8 @@ const OrgHeaderexpandedNew = (props) => { notchedOutline: isEditOrgTab ? null : classes.notchedOutline, }, style: { - color: "white", + color: theme.palette.textFieldStyle.color, + backgroundColor: theme.palette.textFieldStyle.backgroundColor, fontWeight: 400, fontSize: 16, @@ -970,7 +971,7 @@ const OrgHeaderexpandedNew = (props) => { flex: "1", marginTop: "8px", marginRight: "15px", - backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor, + backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor, height: 35, }} fullWidth={true} @@ -988,7 +989,7 @@ const OrgHeaderexpandedNew = (props) => { notchedOutline: isEditOrgTab ? null : classes.notchedOutline, }, style: { - color: "white", + color: theme.palette.textFieldStyle.color, fontWeight: 400, fontSize: 16, @@ -1010,7 +1011,7 @@ const OrgHeaderexpandedNew = (props) => { flex: "1", marginTop: "5px", marginRight: "15px", - backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor, + backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor, height: 35, }} fullWidth={true} @@ -1028,7 +1029,7 @@ const OrgHeaderexpandedNew = (props) => { notchedOutline: isEditOrgTab ? null : classes.notchedOutline, }, style: { - color: "white", + color: theme.palette.textFieldStyle.color, fontWeight: 400, fontSize: 16, @@ -1050,7 +1051,7 @@ const OrgHeaderexpandedNew = (props) => { flex: "1", marginTop: "5px", marginRight: "15px", - backgroundColor: isEditOrgTab ? "rgba(33, 33, 33, 1)" : theme.palette.inputColor, + backgroundColor: isEditOrgTab ? theme.palette.textFieldStyle.backgroundColor : theme.palette.inputColor, height: 35, }} fullWidth={true} @@ -1068,7 +1069,7 @@ const OrgHeaderexpandedNew = (props) => { notchedOutline: isEditOrgTab ? null : classes.notchedOutline, }, style: { - color: "white", + color: theme.palette.textFieldStyle.color, fontWeight: 400, fontSize: 16, diff --git a/frontend/src/components/UserManagmentTab.jsx b/frontend/src/components/UserManagmentTab.jsx index ec7036cc..2346a5a4 100644 --- a/frontend/src/components/UserManagmentTab.jsx +++ b/frontend/src/components/UserManagmentTab.jsx @@ -657,7 +657,7 @@ const UserManagmentTab = memo((props) => { InputProps={{ style: { height: "50px", - color: "white", + color: theme.palette.textFieldStyle.color, fontSize: "1em", }, }} @@ -772,7 +772,7 @@ const UserManagmentTab = memo((props) => { InputProps={{ style: { height: 50, - color: "white", + color: theme.palette.textFieldStyle.color, }, }} color="primary" @@ -815,7 +815,7 @@ const UserManagmentTab = memo((props) => { InputProps={{ style: { height: 50, - color: "white", + color: theme.palette.textFieldStyle.color, }, }} color="primary" @@ -956,7 +956,7 @@ const UserManagmentTab = memo((props) => { InputProps={{ style: { height: 50, - color: "white", + color: theme.palette.textFieldStyle.color, }, }} color="primary" @@ -1027,7 +1027,7 @@ const UserManagmentTab = memo((props) => { InputProps={{ style: { height: 50, - color: "white", + color: theme.palette.textFieldStyle.color, fontSize: "1em", }, maxLength: 6, @@ -1135,7 +1135,7 @@ const UserManagmentTab = memo((props) => { }} > - User Logs + User Logs {/* ask user for which IP they want to see logs for by iterating of user.login_info */}