forked from github/plane
dev: Updating themening worfkflow (#1827)
This commit is contained in:
parent
be062ccd34
commit
005b42cb8d
@ -4,17 +4,13 @@ import { useTheme } from "next-themes";
|
||||
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
// hooks
|
||||
import useUser from "hooks/use-user";
|
||||
// ui
|
||||
import { PrimaryButton } from "components/ui";
|
||||
import { ColorPickerInput } from "components/core";
|
||||
// services
|
||||
import userService from "services/user.service";
|
||||
// helper
|
||||
import { applyTheme } from "helpers/theme.helper";
|
||||
// types
|
||||
import { ICustomTheme } from "types";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
@ -33,11 +29,11 @@ const defaultValues: ICustomTheme = {
|
||||
theme: "custom",
|
||||
};
|
||||
|
||||
export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
||||
export const CustomThemeSelector: React.FC<Props> = observer(({ preLoadedData }) => {
|
||||
const store: any = useMobxStore();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
const [darkPalette, setDarkPalette] = useState(false);
|
||||
|
||||
const {
|
||||
register,
|
||||
formState: { errors, isSubmitting },
|
||||
@ -48,11 +44,14 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
||||
} = useForm<ICustomTheme>({
|
||||
defaultValues,
|
||||
});
|
||||
useEffect(() => {
|
||||
reset({
|
||||
...defaultValues,
|
||||
...preLoadedData,
|
||||
});
|
||||
}, [preLoadedData, reset]);
|
||||
|
||||
const { setTheme } = useTheme();
|
||||
const { mutateUser } = useUser();
|
||||
|
||||
const handleFormSubmit = async (formData: ICustomTheme) => {
|
||||
const handleUpdateTheme = async (formData: any) => {
|
||||
const payload: ICustomTheme = {
|
||||
background: formData.background,
|
||||
text: formData.text,
|
||||
@ -64,28 +63,14 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
||||
theme: "custom",
|
||||
};
|
||||
|
||||
store.user
|
||||
.updateCurrentUserSettings({ theme: payload })
|
||||
.then((response: any) => {
|
||||
setTheme("custom");
|
||||
applyTheme(payload.palette, darkPalette);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
console.log("error", error);
|
||||
});
|
||||
};
|
||||
|
||||
const handleUpdateTheme = async (formData: any) => {
|
||||
await handleFormSubmit({ ...formData, darkPalette });
|
||||
return store.user
|
||||
.updateCurrentUserSettings({ theme: payload })
|
||||
.then((response: any) => response)
|
||||
.catch((error: any) => error);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
reset({
|
||||
...defaultValues,
|
||||
...preLoadedData,
|
||||
});
|
||||
}, [preLoadedData, reset]);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit(handleUpdateTheme)}>
|
||||
<div className="space-y-5">
|
||||
@ -164,4 +149,4 @@ export const CustomThemeSelector: React.FC<Props> = ({ preLoadedData }) => {
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
@ -1,9 +1,5 @@
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
// next-themes
|
||||
import { useTheme } from "next-themes";
|
||||
// services
|
||||
import userService from "services/user.service";
|
||||
// hooks
|
||||
import useUser from "hooks/use-user";
|
||||
// constants
|
||||
@ -13,6 +9,10 @@ import { CustomSelect } from "components/ui";
|
||||
// types
|
||||
import { ICustomTheme } from "types";
|
||||
import { unsetCustomCssVariables } from "helpers/theme.helper";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
type Props = {
|
||||
setPreLoadedData: React.Dispatch<React.SetStateAction<ICustomTheme | null>>;
|
||||
@ -20,48 +20,21 @@ type Props = {
|
||||
setCustomThemeSelectorOptions: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
};
|
||||
|
||||
export const ThemeSwitch: React.FC<Props> = ({
|
||||
setPreLoadedData,
|
||||
customThemeSelectorOptions,
|
||||
setCustomThemeSelectorOptions,
|
||||
}) => {
|
||||
const [mounted, setMounted] = useState(false);
|
||||
|
||||
const { theme, setTheme } = useTheme();
|
||||
export const ThemeSwitch: React.FC<Props> = observer(
|
||||
({ setPreLoadedData, customThemeSelectorOptions, setCustomThemeSelectorOptions }) => {
|
||||
const store: any = useMobxStore();
|
||||
|
||||
const { user, mutateUser } = useUser();
|
||||
const { theme, setTheme } = useTheme();
|
||||
|
||||
const updateUserTheme = (newTheme: string) => {
|
||||
if (!user) return;
|
||||
|
||||
setTheme(newTheme);
|
||||
|
||||
mutateUser((prevData) => {
|
||||
if (!prevData) return prevData;
|
||||
|
||||
return {
|
||||
...prevData,
|
||||
theme: {
|
||||
...prevData.theme,
|
||||
theme: newTheme,
|
||||
},
|
||||
return store.user
|
||||
.updateCurrentUserSettings({ theme: { ...user.theme, theme: newTheme } })
|
||||
.then((response: any) => response)
|
||||
.catch((error: any) => error);
|
||||
};
|
||||
}, false);
|
||||
|
||||
userService.updateUser({
|
||||
theme: {
|
||||
...user.theme,
|
||||
theme: newTheme,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// useEffect only runs on the client, so now we can safely show the UI
|
||||
useEffect(() => {
|
||||
setMounted(true);
|
||||
}, []);
|
||||
|
||||
if (!mounted) return null;
|
||||
|
||||
const currentThemeObj = THEMES_OBJ.find((t) => t.value === theme);
|
||||
|
||||
@ -158,4 +131,5 @@ export const ThemeSwitch: React.FC<Props> = ({
|
||||
))}
|
||||
</CustomSelect>
|
||||
);
|
||||
};
|
||||
}
|
||||
);
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { useEffect } from "react";
|
||||
// next themes
|
||||
import { useTheme } from "next-themes";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// theme helpers
|
||||
import { applyTheme, unsetCustomCssVariables } from "helpers/theme.helper";
|
||||
|
||||
const MobxStoreInit = () => {
|
||||
const store: any = useMobxStore();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
// sidebar collapsed toggle
|
||||
@ -21,11 +26,25 @@ const MobxStoreInit = () => {
|
||||
);
|
||||
|
||||
// theme
|
||||
if (localStorage && localStorage.getItem("theme") && store.theme.theme === null)
|
||||
store.theme.setTheme(
|
||||
localStorage.getItem("theme") ? localStorage.getItem("theme") : "system"
|
||||
);
|
||||
}, [store?.theme]);
|
||||
if (store.theme.theme === null && store?.user?.currentUserSettings) {
|
||||
let currentTheme = localStorage.getItem("theme");
|
||||
currentTheme = currentTheme ? currentTheme : "system";
|
||||
|
||||
// validating the theme and applying for initial state
|
||||
if (currentTheme) {
|
||||
setTheme(currentTheme);
|
||||
store.theme.setTheme({ theme: { theme: currentTheme } });
|
||||
}
|
||||
}
|
||||
}, [store?.theme, store?.user, setTheme]);
|
||||
|
||||
useEffect(() => {
|
||||
// current user
|
||||
if (store?.user?.currentUser === null) store.user.setCurrentUser();
|
||||
|
||||
// current user settings
|
||||
if (store?.user?.currentUserSettings === null) store.user.setCurrentUserSettings();
|
||||
}, [store?.user]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
@ -1,7 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
// next-themes
|
||||
import { useTheme } from "next-themes";
|
||||
// hooks
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
@ -14,37 +11,47 @@ import { Spinner } from "components/ui";
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// types
|
||||
import { ICustomTheme } from "types";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// next themes
|
||||
import { useTheme } from "next-themes";
|
||||
|
||||
const ProfilePreferences = () => {
|
||||
const [customThemeSelectorOptions, setCustomThemeSelectorOptions] = useState(false);
|
||||
const [preLoadedData, setPreLoadedData] = useState<ICustomTheme | null>(null);
|
||||
|
||||
const { theme } = useTheme();
|
||||
|
||||
const ProfilePreferences = observer(() => {
|
||||
const { user: myProfile } = useUserAuth();
|
||||
|
||||
const store: any = useMobxStore();
|
||||
const { theme } = useTheme();
|
||||
|
||||
console.log("store", store?.theme?.theme);
|
||||
console.log("theme", theme);
|
||||
|
||||
const [customThemeSelectorOptions, setCustomThemeSelectorOptions] = useState(false);
|
||||
|
||||
const [preLoadedData, setPreLoadedData] = useState<ICustomTheme | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (theme === "custom") {
|
||||
if (myProfile?.theme.palette)
|
||||
if (store?.user && store?.theme?.theme === "custom") {
|
||||
const currentTheme = store?.user?.currentUserSettings?.theme;
|
||||
if (currentTheme.palette)
|
||||
setPreLoadedData({
|
||||
background: myProfile.theme.background !== "" ? myProfile.theme.background : "#0d101b",
|
||||
text: myProfile.theme.text !== "" ? myProfile.theme.text : "#c5c5c5",
|
||||
primary: myProfile.theme.primary !== "" ? myProfile.theme.primary : "#3f76ff",
|
||||
background: currentTheme.background !== "" ? currentTheme.background : "#0d101b",
|
||||
text: currentTheme.text !== "" ? currentTheme.text : "#c5c5c5",
|
||||
primary: currentTheme.primary !== "" ? currentTheme.primary : "#3f76ff",
|
||||
sidebarBackground:
|
||||
myProfile.theme.sidebarBackground !== ""
|
||||
? myProfile.theme.sidebarBackground
|
||||
: "#0d101b",
|
||||
sidebarText: myProfile.theme.sidebarText !== "" ? myProfile.theme.sidebarText : "#c5c5c5",
|
||||
currentTheme.sidebarBackground !== "" ? currentTheme.sidebarBackground : "#0d101b",
|
||||
sidebarText: currentTheme.sidebarText !== "" ? currentTheme.sidebarText : "#c5c5c5",
|
||||
darkPalette: false,
|
||||
palette:
|
||||
myProfile.theme.palette !== ",,,,"
|
||||
? myProfile.theme.palette
|
||||
currentTheme.palette !== ",,,,"
|
||||
? currentTheme.palette
|
||||
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
|
||||
theme: "custom",
|
||||
});
|
||||
if (!customThemeSelectorOptions) setCustomThemeSelectorOptions(true);
|
||||
setCustomThemeSelectorOptions((prevData) => true);
|
||||
}
|
||||
}, [myProfile, theme, customThemeSelectorOptions]);
|
||||
}, [store, store?.theme?.theme]);
|
||||
|
||||
return (
|
||||
<WorkspaceAuthorizationLayout
|
||||
@ -91,6 +98,6 @@ const ProfilePreferences = () => {
|
||||
)}
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default ProfilePreferences;
|
||||
|
@ -22,8 +22,14 @@ import {
|
||||
import { Spinner } from "components/ui";
|
||||
// images
|
||||
import BluePlaneLogoWithoutText from "public/plane-logos/blue-without-text.png";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// next themes
|
||||
import { useTheme } from "next-themes";
|
||||
import { ICurrentUserResponse, IUser } from "types";
|
||||
import { IUser } from "types";
|
||||
|
||||
// types
|
||||
type EmailPasswordFormValues = {
|
||||
email: string;
|
||||
@ -31,15 +37,18 @@ type EmailPasswordFormValues = {
|
||||
medium?: string;
|
||||
};
|
||||
|
||||
const HomePage: NextPage = () => {
|
||||
const HomePage: NextPage = observer(() => {
|
||||
const store: any = useMobxStore();
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
const { isLoading, mutateUser } = useUserAuth("sign-in");
|
||||
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const { setTheme } = useTheme();
|
||||
|
||||
const changeTheme = (user: IUser) => {
|
||||
setTheme(user.theme.theme ?? "system");
|
||||
const handleTheme = (user: IUser) => {
|
||||
const currentTheme = user.theme.theme ?? "system";
|
||||
setTheme(currentTheme);
|
||||
store?.user?.setCurrentUserSettings();
|
||||
};
|
||||
|
||||
const handleGoogleSignIn = async ({ clientId, credential }: any) => {
|
||||
@ -53,7 +62,7 @@ const HomePage: NextPage = () => {
|
||||
const response = await authenticationService.socialAuth(socialAuthPayload);
|
||||
if (response && response?.user) {
|
||||
mutateUser();
|
||||
changeTheme(response.user);
|
||||
handleTheme(response?.user);
|
||||
}
|
||||
} else {
|
||||
throw Error("Cant find credentials");
|
||||
@ -79,7 +88,7 @@ const HomePage: NextPage = () => {
|
||||
const response = await authenticationService.socialAuth(socialAuthPayload);
|
||||
if (response && response?.user) {
|
||||
mutateUser();
|
||||
changeTheme(response.user);
|
||||
handleTheme(response?.user);
|
||||
}
|
||||
} else {
|
||||
throw Error("Cant find credentials");
|
||||
@ -101,7 +110,7 @@ const HomePage: NextPage = () => {
|
||||
try {
|
||||
if (response) {
|
||||
mutateUser();
|
||||
changeTheme(response.user);
|
||||
handleTheme(response?.user);
|
||||
}
|
||||
} catch (err: any) {
|
||||
setToastAlert({
|
||||
@ -128,7 +137,7 @@ const HomePage: NextPage = () => {
|
||||
try {
|
||||
if (response) {
|
||||
mutateUser();
|
||||
changeTheme(response.user);
|
||||
handleTheme(response?.user);
|
||||
}
|
||||
} catch (err: any) {
|
||||
setToastAlert({
|
||||
@ -140,10 +149,6 @@ const HomePage: NextPage = () => {
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTheme("system");
|
||||
}, [setTheme]);
|
||||
|
||||
return (
|
||||
<DefaultLayout>
|
||||
{isLoading ? (
|
||||
@ -202,6 +207,6 @@ const HomePage: NextPage = () => {
|
||||
)}
|
||||
</DefaultLayout>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default HomePage;
|
||||
|
@ -38,21 +38,24 @@ class ThemeStore {
|
||||
}
|
||||
}
|
||||
|
||||
setTheme = async (_theme: ICurrentUserSettings) => {
|
||||
setTheme = async (_theme: { theme: ICurrentUserSettings }) => {
|
||||
try {
|
||||
localStorage.setItem("theme", _theme.theme.toString());
|
||||
this.theme = _theme.theme.toString();
|
||||
const currentTheme: string = _theme.theme.theme.toString();
|
||||
|
||||
if (this.theme === "custom") {
|
||||
let themeSettings = this.rootStore.user.currentUserSettings || null;
|
||||
if (themeSettings && themeSettings.theme.palette) {
|
||||
// updating the local storage theme value
|
||||
localStorage.setItem("theme", currentTheme);
|
||||
// updating the mobx theme value
|
||||
this.theme = currentTheme;
|
||||
|
||||
// applying the theme to platform if the selected theme is custom
|
||||
if (currentTheme === "custom") {
|
||||
const themeSettings = this.rootStore.user.currentUserSettings || null;
|
||||
applyTheme(
|
||||
themeSettings.theme.palette !== ",,,,"
|
||||
? themeSettings.theme.palette
|
||||
themeSettings?.theme?.palette !== ",,,,"
|
||||
? themeSettings?.theme?.palette
|
||||
: "#0d101b,#c5c5c5,#3f76ff,#0d101b,#c5c5c5",
|
||||
themeSettings.theme.darkPalette
|
||||
themeSettings?.theme?.darkPalette
|
||||
);
|
||||
}
|
||||
} else unsetCustomCssVariables();
|
||||
} catch (error) {
|
||||
console.error("setting user theme error", error);
|
||||
|
@ -1,5 +1,5 @@
|
||||
// mobx
|
||||
import { action, observable, computed, makeObservable } from "mobx";
|
||||
import { action, observable, computed, runInAction, makeObservable } from "mobx";
|
||||
// services
|
||||
import UserService from "services/user.service";
|
||||
// interfaces
|
||||
@ -31,8 +31,9 @@ class UserStore {
|
||||
try {
|
||||
let userResponse: ICurrentUser | null = await UserService.currentUser();
|
||||
userResponse = userResponse || null;
|
||||
|
||||
if (userResponse) {
|
||||
this.currentUser = {
|
||||
const userPayload: ICurrentUser = {
|
||||
id: userResponse?.id,
|
||||
avatar: userResponse?.avatar,
|
||||
first_name: userResponse?.first_name,
|
||||
@ -46,6 +47,9 @@ class UserStore {
|
||||
is_onboarded: userResponse?.is_onboarded,
|
||||
role: userResponse?.role,
|
||||
};
|
||||
runInAction(() => {
|
||||
this.currentUser = userPayload;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fetching current user error", error);
|
||||
@ -56,11 +60,15 @@ class UserStore {
|
||||
try {
|
||||
let userSettingsResponse: ICurrentUserSettings | null = await UserService.currentUser();
|
||||
userSettingsResponse = userSettingsResponse || null;
|
||||
|
||||
if (userSettingsResponse) {
|
||||
this.currentUserSettings = {
|
||||
theme: userSettingsResponse?.theme,
|
||||
const themePayload = {
|
||||
theme: { ...userSettingsResponse?.theme },
|
||||
};
|
||||
this.rootStore.theme.setTheme();
|
||||
runInAction(() => {
|
||||
this.currentUserSettings = themePayload;
|
||||
this.rootStore.theme.setTheme(themePayload);
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Fetching current user error", error);
|
||||
@ -71,9 +79,26 @@ class UserStore {
|
||||
try {
|
||||
let userResponse: ICurrentUser = await UserService.updateUser(user);
|
||||
userResponse = userResponse || null;
|
||||
|
||||
if (userResponse) {
|
||||
this.currentUser = userResponse;
|
||||
return userResponse;
|
||||
const userPayload: ICurrentUser = {
|
||||
id: userResponse?.id,
|
||||
avatar: userResponse?.avatar,
|
||||
first_name: userResponse?.first_name,
|
||||
last_name: userResponse?.last_name,
|
||||
username: userResponse?.username,
|
||||
email: userResponse?.email,
|
||||
mobile_number: userResponse?.mobile_number,
|
||||
is_email_verified: userResponse?.is_email_verified,
|
||||
is_tour_completed: userResponse?.is_tour_completed,
|
||||
onboarding_step: userResponse?.onboarding_step,
|
||||
is_onboarded: userResponse?.is_onboarded,
|
||||
role: userResponse?.role,
|
||||
};
|
||||
runInAction(() => {
|
||||
this.currentUser = userPayload;
|
||||
});
|
||||
return userPayload;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Updating user error", error);
|
||||
@ -86,9 +111,14 @@ class UserStore {
|
||||
let userSettingsResponse: ICurrentUserSettings = await UserService.updateUser(userTheme);
|
||||
userSettingsResponse = userSettingsResponse || null;
|
||||
if (userSettingsResponse) {
|
||||
this.currentUserSettings = userSettingsResponse;
|
||||
this.rootStore.theme.setTheme(userTheme);
|
||||
return userSettingsResponse;
|
||||
const themePayload = {
|
||||
theme: { ...userSettingsResponse?.theme },
|
||||
};
|
||||
runInAction(() => {
|
||||
this.currentUserSettings = themePayload;
|
||||
this.rootStore.theme.setTheme(themePayload);
|
||||
});
|
||||
return themePayload;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Updating user settings error", error);
|
||||
@ -97,10 +127,7 @@ class UserStore {
|
||||
};
|
||||
|
||||
// init load
|
||||
initialLoad() {
|
||||
this.setCurrentUser();
|
||||
this.setCurrentUserSettings();
|
||||
}
|
||||
initialLoad() {}
|
||||
}
|
||||
|
||||
export default UserStore;
|
||||
|
Loading…
Reference in New Issue
Block a user