chore: updating the theme using MobX from command k (#1879)

* chore: updating the theme using mobx from command k

* feat: Showing the project published status in the app header

* dev: updated validation and redirection the project publish modal and added redirection on the app header
This commit is contained in:
guru_sainath 2023-08-16 18:26:36 +05:30 committed by GitHub
parent 5b6b43fb83
commit 65295f6c6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 135 additions and 79 deletions

View File

@ -9,12 +9,18 @@ import userService from "services/user.service";
import useUser from "hooks/use-user"; import useUser from "hooks/use-user";
// helper // helper
import { unsetCustomCssVariables } from "helpers/theme.helper"; 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 = { type Props = {
setIsPaletteOpen: Dispatch<SetStateAction<boolean>>; setIsPaletteOpen: Dispatch<SetStateAction<boolean>>;
}; };
export const ChangeInterfaceTheme: React.FC<Props> = ({ setIsPaletteOpen }) => { export const ChangeInterfaceTheme: React.FC<Props> = observer(({ setIsPaletteOpen }) => {
const store: any = useMobxStore();
const [mounted, setMounted] = useState(false); const [mounted, setMounted] = useState(false);
const { setTheme } = useTheme(); const { setTheme } = useTheme();
@ -23,29 +29,11 @@ export const ChangeInterfaceTheme: React.FC<Props> = ({ setIsPaletteOpen }) => {
const updateUserTheme = (newTheme: string) => { const updateUserTheme = (newTheme: string) => {
if (!user) return; if (!user) return;
unsetCustomCssVariables();
setTheme(newTheme); setTheme(newTheme);
return store.user
mutateUser((prevData: any) => { .updateCurrentUserSettings({ theme: { ...user.theme, theme: newTheme } })
if (!prevData) return prevData; .then((response: any) => response)
.catch((error: any) => error);
return {
...prevData,
theme: {
...prevData?.theme,
theme: newTheme,
},
};
}, false);
userService.updateUser({
theme: {
...user.theme,
theme: newTheme,
},
});
}; };
// useEffect only runs on the client, so now we can safely show the UI // useEffect only runs on the client, so now we can safely show the UI
@ -74,4 +62,4 @@ export const ChangeInterfaceTheme: React.FC<Props> = ({ setIsPaletteOpen }) => {
))} ))}
</> </>
); );
}; });

View File

@ -14,6 +14,9 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root"; import { RootStore } from "store/root";
import { IProjectPublishSettingsViews } from "store/project-publish"; import { IProjectPublishSettingsViews } from "store/project-publish";
// hooks
import useToast from "hooks/use-toast";
import useProjectDetails from "hooks/use-project-details";
type Props = { type Props = {
// user: ICurrentUserResponse | undefined; // user: ICurrentUserResponse | undefined;
@ -25,7 +28,7 @@ const defaultValues: Partial<any> = {
reactions: false, reactions: false,
votes: false, votes: false,
inbox: null, inbox: null,
views: [], views: ["list", "kanban"],
}; };
const viewOptions = [ const viewOptions = [
@ -40,6 +43,17 @@ export const PublishProjectModal: React.FC<Props> = observer(() => {
const store: RootStore = useMobxStore(); const store: RootStore = useMobxStore();
const { projectPublish } = store; const { projectPublish } = store;
const { projectDetails, mutateProjectDetails } = useProjectDetails();
const { setToastAlert } = useToast();
const handleToastAlert = (title: string, type: string, message: string) => {
setToastAlert({
title: title || "Title",
type: "error" || "warning",
message: message || "Message",
});
};
const { NEXT_PUBLIC_DEPLOY_URL } = process.env; const { NEXT_PUBLIC_DEPLOY_URL } = process.env;
const plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL const plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL
? NEXT_PUBLIC_DEPLOY_URL ? NEXT_PUBLIC_DEPLOY_URL
@ -111,32 +125,41 @@ export const PublishProjectModal: React.FC<Props> = observer(() => {
}, [workspaceSlug, projectPublish, projectPublish.projectPublishModal]); }, [workspaceSlug, projectPublish, projectPublish.projectPublishModal]);
const onSettingsPublish = async (formData: any) => { const onSettingsPublish = async (formData: any) => {
const payload = { if (formData.views && formData.views.length > 0) {
comments: formData.comments || false, const payload = {
reactions: formData.reactions || false, comments: formData.comments || false,
votes: formData.votes || false, reactions: formData.reactions || false,
inbox: formData.inbox || null, votes: formData.votes || false,
views: { inbox: formData.inbox || null,
list: formData.views.includes("list") || false, views: {
kanban: formData.views.includes("kanban") || false, list: formData.views.includes("list") || false,
calendar: formData.views.includes("calendar") || false, kanban: formData.views.includes("kanban") || false,
gantt: formData.views.includes("gantt") || false, calendar: formData.views.includes("calendar") || false,
spreadsheet: formData.views.includes("spreadsheet") || false, gantt: formData.views.includes("gantt") || false,
}, spreadsheet: formData.views.includes("spreadsheet") || false,
}; },
};
return projectPublish const _workspaceSlug = workspaceSlug;
.createProjectSettingsAsync( const _projectId = projectPublish.project_id;
workspaceSlug as string,
projectPublish.project_id as string, return projectPublish
payload, .createProjectSettingsAsync(_workspaceSlug as string, _projectId as string, payload, null)
null .then((response) => {
) mutateProjectDetails();
.then((response) => response) handleClose();
.catch((error) => { console.log("_projectId", _projectId);
console.error("error", error); if (_projectId)
return error; window.open(`${plane_deploy_url}/${_workspaceSlug}/${_projectId}`, "_blank");
}); return response;
})
.catch((error) => {
console.error("error", error);
return error;
});
} else {
handleToastAlert("Missing fields", "warning", "Please select at least one view to publish");
}
}; };
const onSettingsUpdate = async (key: string, value: any) => { const onSettingsUpdate = async (key: string, value: any) => {
@ -171,7 +194,10 @@ export const PublishProjectModal: React.FC<Props> = observer(() => {
payload, payload,
null null
) )
.then((response) => response) .then((response) => {
mutateProjectDetails();
return response;
})
.catch((error) => { .catch((error) => {
console.log("error", error); console.log("error", error);
return error; return error;
@ -187,7 +213,9 @@ export const PublishProjectModal: React.FC<Props> = observer(() => {
null null
) )
.then((response) => { .then((response) => {
mutateProjectDetails();
reset({ ...defaultValues }); reset({ ...defaultValues });
handleClose();
return response; return response;
}) })
.catch((error) => { .catch((error) => {

View File

@ -1,5 +1,12 @@
// next imports
import { useRouter } from "next/router";
import Link from "next/link";
// icons // icons
import { Bars3Icon } from "@heroicons/react/24/outline"; import { Bars3Icon } from "@heroicons/react/24/outline";
// ui components
import { Tooltip } from "components/ui";
// hooks
import useProjectDetails from "hooks/use-project-details";
type Props = { type Props = {
breadcrumbs?: JSX.Element; breadcrumbs?: JSX.Element;
@ -9,27 +16,61 @@ type Props = {
noHeader: boolean; noHeader: boolean;
}; };
const Header: React.FC<Props> = ({ breadcrumbs, left, right, setToggleSidebar, noHeader }) => ( const { NEXT_PUBLIC_DEPLOY_URL } = process.env;
<div const plane_deploy_url = NEXT_PUBLIC_DEPLOY_URL ? NEXT_PUBLIC_DEPLOY_URL : "http://localhost:3001";
className={`relative flex w-full flex-shrink-0 flex-row z-10 items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 px-5 py-4 ${
noHeader ? "md:hidden" : "" const Header: React.FC<Props> = ({ breadcrumbs, left, right, setToggleSidebar, noHeader }) => {
}`} const { projectDetails } = useProjectDetails();
>
<div className="flex items-center gap-2 flex-grow w-full whitespace-nowrap overflow-ellipsis"> const router = useRouter();
<div className="block md:hidden"> const { workspaceSlug, projectId } = router.query;
<button
type="button" return (
className="grid h-8 w-8 place-items-center rounded border border-custom-border-200" <div
onClick={() => setToggleSidebar((prevData) => !prevData)} className={`relative flex w-full flex-shrink-0 flex-row z-10 items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 px-5 py-4 ${
> noHeader ? "md:hidden" : ""
<Bars3Icon className="h-5 w-5" /> }`}
</button> >
<div className="flex items-center gap-2 flex-grow w-full whitespace-nowrap overflow-ellipsis">
<div className="block md:hidden">
<button
type="button"
className="grid h-8 w-8 place-items-center rounded border border-custom-border-200"
onClick={() => setToggleSidebar((prevData) => !prevData)}
>
<Bars3Icon className="h-5 w-5" />
</button>
</div>
<div>{breadcrumbs}</div>
{projectDetails && projectDetails?.is_deployed && (
<Link href={`${plane_deploy_url}/${workspaceSlug}/${projectId}`}>
<a target="_blank" rel="noreferrer">
<Tooltip
tooltipContent="This project is public, and live on web."
position="bottom-left"
>
<div className="transition-all flex-shrink-0 bg-custom-primary-100/20 text-custom-primary-100 p-1 rounded overflow-hidden relative flex items-center gap-1 cursor-pointer group">
<div className="w-[14px] h-[14px] flex justify-center items-center">
<span className="material-symbols-rounded text-[14px]">
radio_button_checked
</span>
</div>
<div className="text-xs font-medium">Public</div>
<div className="w-[14px] h-[14px] hidden group-hover:flex justify-center items-center">
<span className="material-symbols-rounded text-[14px]">open_in_new</span>
</div>
</div>
</Tooltip>
</a>
</Link>
)}
<div className="flex-shrink-0">{left}</div>
</div> </div>
{breadcrumbs} <div className="flex-shrink-0">{right}</div>
<div className="flex-shrink-0">{left}</div>
</div> </div>
<div className="flex-shrink-0">{right}</div> );
</div> };
);
export default Header; export default Header;

View File

@ -259,15 +259,13 @@ class ProjectPublishStore implements IProjectPublishStore {
user user
); );
if (response) { runInAction(() => {
runInAction(() => { this.projectPublishSettings = "not-initialized";
this.projectPublishSettings = "not-initialized"; this.loader = false;
this.loader = false; this.error = null;
this.error = null; });
});
return response; return response;
}
} catch (error) { } catch (error) {
this.loader = false; this.loader = false;
this.error = error; this.error = error;

View File

@ -57,6 +57,7 @@ export interface IProject {
updated_by: string; updated_by: string;
workspace: IWorkspace | string; workspace: IWorkspace | string;
workspace_detail: IWorkspaceLite; workspace_detail: IWorkspaceLite;
is_deployed: boolean;
} }
export interface IProjectLite { export interface IProjectLite {