chore: handled ui and preloading in init page (#4491)

This commit is contained in:
guru_sainath 2024-05-16 19:28:37 +05:30 committed by GitHub
parent 7569c03cec
commit 9b92fd4a16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 84 additions and 64 deletions

View File

@ -118,7 +118,9 @@ export const NavbarControls: FC<NavbarControlsProps> = observer((props) => {
{user?.id ? ( {user?.id ? (
<div className="flex items-center gap-2 rounded border border-custom-border-200 p-2"> <div className="flex items-center gap-2 rounded border border-custom-border-200 p-2">
<Avatar name={user?.display_name} src={user?.avatar ?? undefined} shape="square" size="sm" /> <Avatar name={user?.display_name} src={user?.avatar ?? undefined} shape="square" size="sm" />
<h6 className="text-xs font-medium">{user.display_name}</h6> <h6 className="text-xs font-medium">
{user?.display_name || `${user?.first_name} ${user?.first_name}` || user?.email || "User"}
</h6>
</div> </div>
) : ( ) : (
<div className="flex-shrink-0"> <div className="flex-shrink-0">

View File

@ -36,8 +36,7 @@ export const ProjectDetailsView: FC<ProjectDetailsViewProps> = observer((props)
// hooks // hooks
const { fetchProjectSettings } = useProject(); const { fetchProjectSettings } = useProject();
const { issueFilters } = useIssueFilter(); const { issueFilters } = useIssueFilter();
const { loader, issues, error } = useIssue(); const { loader, issues, error, fetchPublicIssues } = useIssue();
const { fetchPublicIssues } = useIssue();
const issueDetailStore = useIssueDetails(); const issueDetailStore = useIssueDetails();
const { data: currentUser, fetchCurrentUser } = useUser(); const { data: currentUser, fetchCurrentUser } = useUser();
@ -51,12 +50,10 @@ export const ProjectDetailsView: FC<ProjectDetailsViewProps> = observer((props)
? () => fetchPublicIssues(workspaceSlug, projectId, { states, priority, labels }) ? () => fetchPublicIssues(workspaceSlug, projectId, { states, priority, labels })
: null : null
); );
useSWR(
useEffect(() => { workspaceSlug && projectId && !currentUser ? "WORKSPACE_PROJECT_CURRENT_USER" : null,
if (!currentUser) { workspaceSlug && projectId && !currentUser ? () => fetchCurrentUser() : null
fetchCurrentUser(); );
}
}, [currentUser, fetchCurrentUser]);
useEffect(() => { useEffect(() => {
if (peekId && workspaceSlug && projectId) { if (peekId && workspaceSlug && projectId) {

View File

@ -1,19 +1,19 @@
// mobx // mobx
import { observable, action, makeObservable, runInAction } from "mobx"; import { observable, action, makeObservable, runInAction, computed } from "mobx";
// service // service
import ProjectService from "@/services/project.service"; import ProjectService from "@/services/project.service";
// store types // store types
import { RootStore } from "@/store/root.store"; import { RootStore } from "@/store/root.store";
// types // types
import { IWorkspace, IProject, IProjectSettings } from "@/types/project"; import { TWorkspaceDetails, TProjectDetails, TProjectSettings } from "@/types/project";
export interface IProjectStore { export interface IProjectStore {
// observables // observables
loader: boolean; loader: boolean;
error: any | null; error: any | undefined;
workspace: IWorkspace | null; settings: TProjectSettings | undefined;
project: IProject | null; workspace: TWorkspaceDetails | undefined;
settings: IProjectSettings | null; project: TProjectDetails | undefined;
canReact: boolean; canReact: boolean;
canComment: boolean; canComment: boolean;
canVote: boolean; canVote: boolean;
@ -25,13 +25,10 @@ export interface IProjectStore {
export class ProjectStore implements IProjectStore { export class ProjectStore implements IProjectStore {
// observables // observables
loader: boolean = false; loader: boolean = false;
error: any | null = null; error: any | undefined = undefined;
workspace: IWorkspace | null = null; settings: TProjectSettings | undefined = undefined;
project: IProject | null = null; workspace: TWorkspaceDetails | undefined = undefined;
settings: IProjectSettings | null = null; project: TProjectDetails | undefined = undefined;
canReact: boolean = false;
canComment: boolean = false;
canVote: boolean = false;
// service // service
projectService; projectService;
@ -44,28 +41,28 @@ export class ProjectStore implements IProjectStore {
workspace: observable, workspace: observable,
project: observable, project: observable,
settings: observable, settings: observable,
canReact: observable.ref, // computed
canComment: observable.ref, canReact: computed,
canVote: observable.ref, canComment: computed,
canVote: computed,
// actions // actions
fetchProjectSettings: action, fetchProjectSettings: action,
hydrate: action, hydrate: action,
// computed
}); });
// services // services
this.projectService = new ProjectService(); this.projectService = new ProjectService();
} }
hydrate = (projectSettings: any) => { // computed
const { workspace_detail, project_details, votes, comments, reactions } = projectSettings; get canReact() {
this.workspace = workspace_detail; return this.settings?.reactions ?? false;
this.project = project_details; }
this.canComment = comments; get canComment() {
this.canVote = votes; return this.settings?.comments ?? false;
this.canReact = reactions; }
}; get canVote() {
return this.settings?.votes ?? false;
}
fetchProjectSettings = async (workspace_slug: string, project_slug: string) => { fetchProjectSettings = async (workspace_slug: string, project_slug: string) => {
try { try {
@ -75,14 +72,11 @@ export class ProjectStore implements IProjectStore {
const response = await this.projectService.getProjectSettings(workspace_slug, project_slug); const response = await this.projectService.getProjectSettings(workspace_slug, project_slug);
if (response) { if (response) {
const currentProject: IProject = { ...response?.project_details };
const currentWorkspace: IWorkspace = { ...response?.workspace_detail };
const currentDeploySettings = { ...response };
this.store.issueFilter.updateLayoutOptions(response?.views); this.store.issueFilter.updateLayoutOptions(response?.views);
runInAction(() => { runInAction(() => {
this.project = currentProject; this.project = response?.project_details;
this.workspace = currentWorkspace; this.workspace = response?.workspace_detail;
this.settings = currentDeploySettings; this.settings = response;
this.loader = false; this.loader = false;
}); });
} }
@ -93,4 +87,10 @@ export class ProjectStore implements IProjectStore {
return error; return error;
} }
}; };
hydrate = (projectSettings: TProjectSettings) => {
const { workspace_detail, project_details } = projectSettings;
this.workspace = workspace_detail;
this.project = project_details;
};
} }

View File

@ -32,8 +32,8 @@ export class RootStore {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
hydrate = (data: any) => { hydrate = (data: any) => {
if (!data) return; if (!data) return;
this.instance.hydrate(data?.instance || {}); this.instance.hydrate(data?.instance || undefined);
this.user.hydrate(data?.user || {}); this.user.hydrate(data?.user || undefined);
}; };
reset = () => { reset = () => {

View File

@ -29,7 +29,7 @@ export interface IUserStore {
// actions // actions
fetchCurrentUser: () => Promise<IUser | undefined>; fetchCurrentUser: () => Promise<IUser | undefined>;
updateCurrentUser: (data: Partial<IUser>) => Promise<IUser | undefined>; updateCurrentUser: (data: Partial<IUser>) => Promise<IUser | undefined>;
hydrate: (data: IUser) => void; hydrate: (data: IUser | undefined) => void;
reset: () => void; reset: () => void;
signOut: () => Promise<void>; signOut: () => Promise<void>;
} }
@ -91,7 +91,7 @@ export class UserStore implements IUserStore {
fetchCurrentUser = async (): Promise<IUser> => { fetchCurrentUser = async (): Promise<IUser> => {
try { try {
runInAction(() => { runInAction(() => {
this.isLoading = true; if (this.data === undefined) this.isLoading = true;
this.error = undefined; this.error = undefined;
}); });
const user = await this.userService.currentUser(); const user = await this.userService.currentUser();
@ -155,7 +155,8 @@ export class UserStore implements IUserStore {
} }
}; };
hydrate = (data: IUser): void => { hydrate = (data: IUser | undefined): void => {
if (!data) return;
this.data = { ...this.data, ...data }; this.data = { ...this.data, ...data };
}; };

View File

@ -329,3 +329,11 @@
height: 0 !important; height: 0 !important;
width: 0 !important; width: 0 !important;
} }
/* By applying below class, the autofilled text in form fields will not have the default autofill background color and styles applied by WebKit browsers */
.disable-autofill-style:-webkit-autofill,
.disable-autofill-style:-webkit-autofill:hover,
.disable-autofill-style:-webkit-autofill:focus,
.disable-autofill-style:-webkit-autofill:active {
-webkit-background-clip: text;
}

View File

@ -1,29 +1,42 @@
import { TProjectLogoProps } from "@plane/types"; import { TProjectLogoProps } from "@plane/types";
export interface IWorkspace { export type TWorkspaceDetails = {
id: string;
name: string; name: string;
slug: string; slug: string;
}
export interface IProject {
id: string; id: string;
identifier: string; };
name: string;
description: string;
cover_image: string | null;
logo_props: TProjectLogoProps;
}
export interface IProjectSettings { export type TViewDetails = {
comments: boolean;
reactions: boolean;
votes: boolean;
views: {
list: boolean; list: boolean;
gantt: boolean; gantt: boolean;
kanban: boolean; kanban: boolean;
calendar: boolean; calendar: boolean;
spreadsheet: boolean; spreadsheet: boolean;
}; };
}
export type TProjectDetails = {
id: string;
identifier: string;
name: string;
cover_image: string | undefined;
logo_props: TProjectLogoProps;
description: string;
};
export type TProjectSettings = {
id: string;
anchor: string;
comments: boolean;
reactions: boolean;
votes: boolean;
inbox: unknown;
workspace: string;
workspace_detail: TWorkspaceDetails;
project: string;
project_details: TProjectDetails;
views: TViewDetails;
created_by: string;
updated_by: string;
created_at: string;
updated_at: string;
};

View File

@ -668,7 +668,6 @@ div.web-view-spinner div.bar12 {
} }
/* By applying below class, the autofilled text in form fields will not have the default autofill background color and styles applied by WebKit browsers */ /* By applying below class, the autofilled text in form fields will not have the default autofill background color and styles applied by WebKit browsers */
.disable-autofill-style:-webkit-autofill, .disable-autofill-style:-webkit-autofill,
.disable-autofill-style:-webkit-autofill:hover, .disable-autofill-style:-webkit-autofill:hover,
.disable-autofill-style:-webkit-autofill:focus, .disable-autofill-style:-webkit-autofill:focus,