From 45c7c60674a810de0bdf6c24da5e0bab760a212f Mon Sep 17 00:00:00 2001 From: Shaurya Sharma Date: Tue, 4 Mar 2025 02:00:19 +0530 Subject: [PATCH] Main setup for Custom theme --- .../AppBuilder/CodeBuilder/Elements/Color.jsx | 3 +- .../CodeBuilder/Elements/ColorSwatches.jsx | 38 +++++-- .../GlobalSettings/ThemeSelect.jsx | 99 ++++++++++++++++--- frontend/src/AppBuilder/_hooks/useAppData.js | 13 +++ .../src/AppBuilder/_hooks/useThemeAccess.js | 10 ++ frontend/src/_styles/tabler.scss | 13 ++- frontend/src/_styles/theme.scss | 78 ++++++++++++--- 7 files changed, 216 insertions(+), 38 deletions(-) create mode 100644 frontend/src/AppBuilder/_hooks/useThemeAccess.js diff --git a/frontend/src/AppBuilder/CodeBuilder/Elements/Color.jsx b/frontend/src/AppBuilder/CodeBuilder/Elements/Color.jsx index 691e299d45..918abe370e 100644 --- a/frontend/src/AppBuilder/CodeBuilder/Elements/Color.jsx +++ b/frontend/src/AppBuilder/CodeBuilder/Elements/Color.jsx @@ -9,6 +9,7 @@ export const Color = ({ value, onChange, pickerStyle = {}, + colorMap = {}, cyLabel, asBoxShadowPopover = true, meta, @@ -112,7 +113,7 @@ export const Color = ({ >
- {value} + {colorMap?.[value] ? colorMap?.[value]?.charAt(0).toUpperCase() + colorMap?.[value]?.slice(1) : value}
); diff --git a/frontend/src/AppBuilder/CodeBuilder/Elements/ColorSwatches.jsx b/frontend/src/AppBuilder/CodeBuilder/Elements/ColorSwatches.jsx index 17bc178862..465ca744ac 100644 --- a/frontend/src/AppBuilder/CodeBuilder/Elements/ColorSwatches.jsx +++ b/frontend/src/AppBuilder/CodeBuilder/Elements/ColorSwatches.jsx @@ -4,6 +4,8 @@ import ToggleGroupItem from '@/ToolJetUI/SwitchGroup/ToggleGroupItem'; import cx from 'classnames'; import { Color } from './Color'; import CheckIcon from '@/components/ui/Checkbox/CheckboxUtils/CheckIcon'; +import useStore from '@/AppBuilder/_stores/store'; +import { shallow } from 'zustand/shallow'; export const ColorSwatches = ({ value, @@ -17,10 +19,17 @@ export const ColorSwatches = ({ styleDefinition, }) => { const [componentType, setComponentType] = useState('color'); + const selectedTheme = useStore((state) => state.globalSettings.theme, shallow); + const darkMode = localStorage.getItem('darkMode') === 'true'; + const brandColors = selectedTheme?.definition?.brand?.colors || {}; return ( { + acc[`var(--${colorType}-brand)`] = colorType; + return acc; + }, {})} onChange={onChange} pickerStyle={pickerStyle} cyLabel={cyLabel} @@ -37,10 +46,15 @@ export const ColorSwatches = ({ )} CustomOptionList={() => (
- - - - + {Object.keys(brandColors)?.map((colorType, index) => ( + + ))}
)} /> @@ -69,13 +83,19 @@ const SwatchesToggle = ({ value, onChange }) => { ); }; -const CustomOption = () => { +const CustomOption = ({ onChange, colorType, color, value }) => { + const isSelected = `var(--${colorType}-brand)` === value; return ( -
+
{ + onChange(`var(--${colorType}-brand)`); + }} + >
- -
- Test + {isSelected && } +
+ {colorType.charAt(0).toUpperCase() + colorType.slice(1)}
); diff --git a/frontend/src/AppBuilder/LeftSidebar/GlobalSettings/ThemeSelect.jsx b/frontend/src/AppBuilder/LeftSidebar/GlobalSettings/ThemeSelect.jsx index 74817c21c6..c0bc2079c3 100644 --- a/frontend/src/AppBuilder/LeftSidebar/GlobalSettings/ThemeSelect.jsx +++ b/frontend/src/AppBuilder/LeftSidebar/GlobalSettings/ThemeSelect.jsx @@ -1,16 +1,56 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import Select from '@/_ui/Select'; import CheckMark from '@/_ui/Icon/bulkIcons/CheckMark'; import { components } from 'react-select'; import { ButtonSolid } from '@/_ui/AppButton/AppButton'; +import useStore from '@/AppBuilder/_stores/store'; +import { shallow } from 'zustand/shallow'; +import { useNavigate } from 'react-router-dom'; +import { getWorkspaceId } from '@/_helpers/utils'; +import { appThemesService } from '../../../../ee/modules/WorkspaceSettings/pages/ManageThemes/service/app_themes.service'; const ThemeSelect = ({ darkMode }) => { + const [themesList, setThemesList] = useState([]); + const selectedTheme = useStore((state) => state.globalSettings.theme, shallow); + const featureAccess = useStore((state) => state?.license?.featureAccess, shallow); + const licenseValid = !featureAccess?.licenseStatus?.isExpired && featureAccess?.licenseStatus?.isLicenseValid; + const globalSettingsChanged = useStore((state) => state.globalSettingsChanged, shallow); + const workspaceId = getWorkspaceId(); + const appId = useStore((state) => state.app.appId, shallow); + const versionId = useStore((state) => state.currentVersionId, shallow); + const navigate = useNavigate(); + + const fetchAllThemes = async () => { + const themes = await appThemesService.fetchAllThemes(); + + const options = themes.map((theme) => ({ + value: theme.id, + name: theme.name, + label: theme.name, + color: theme?.definition?.brand?.colors?.primary?.[darkMode ? 'dark' : 'light'], + isDefault: theme?.isDefault, + theme: theme, + })); + + setThemesList(options); + }; + + const setTheme = async (themeId) => { + await appThemesService.updateAppTheme(appId, versionId, themeId); + }; + + useEffect(() => { + fetchAllThemes(); + }, []); + const customSelectStyles = { control: (provided) => ({ ...provided, width: '158px', height: '32px', minHeight: '32px', + flexWrap: 'nowrap', + overflow: 'hidden', }), input: (provided) => ({ ...provided, @@ -37,6 +77,10 @@ const ThemeSelect = ({ darkMode }) => { scrollbarWidth: 'none', // Hide scrollbar for Firefox borderRadius: '8px', }), + menuPortal: (base) => ({ + ...base, + top: base.top + 2, // Adjust the top position + }), option: (provided, state) => ({ ...provided, backgroundColor: state.isFocused @@ -54,22 +98,44 @@ const ThemeSelect = ({ darkMode }) => { const CustomOption = (props) => { const { data, isSelected } = props; - return (
{isSelected && ( - + + )} +
+ {data.label} + {data?.isDefault && ( + + Default + )} -
- {data.label}
); @@ -92,10 +158,12 @@ const ThemeSelect = ({ darkMode }) => { }} > {}} + onClick={() => { + navigate(`/${workspaceId}/workspace-settings/themes`); + }} variant="tertiary" leftIcon="addrectangle" - fill="var(--primary-brand)" + fill="#3e63dd" iconWidth="16" className="tj-text-xsm theme-create-btn" > @@ -112,13 +180,14 @@ const ThemeSelect = ({ darkMode }) => {

Theme