fix(web): resolve issues board blank rendering due to MobX strict mode in IssueRootStore
All checks were successful
Deploy Plane Project Tracker / Deploy to cisystem (push) Successful in 5m26s
All checks were successful
Deploy Plane Project Tracker / Deploy to cisystem (push) Successful in 5m26s
This commit is contained in:
parent
a4687eaf39
commit
d27b7fdbea
7 changed files with 115 additions and 69 deletions
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import type { MutableRefObject } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import type {
|
||||
GroupByColumnTypes,
|
||||
IGroupByColumn,
|
||||
|
|
@ -106,11 +107,13 @@ export const KanBan = observer(function KanBan(props: IKanBan) {
|
|||
|
||||
const { getIsWorkflowWorkItemCreationDisabled } = useWorkFlowFDragNDrop(group_by, sub_group_by);
|
||||
|
||||
const { projectId } = useParams();
|
||||
const list = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
isEpic: isEpic,
|
||||
projectId: projectId?.toString(),
|
||||
});
|
||||
|
||||
if (!list) return null;
|
||||
|
|
@ -165,7 +168,7 @@ export const KanBan = observer(function KanBan(props: IKanBan) {
|
|||
groupByVisibilityToggle.showIssues ? `w-[350px]` : ``
|
||||
} `}
|
||||
>
|
||||
{sub_group_by === null && (
|
||||
{!sub_group_by && (
|
||||
<div className="sticky top-0 z-[2] w-full flex-shrink-0 bg-surface-2 py-1">
|
||||
<HeaderGroupByCard
|
||||
sub_group_by={sub_group_by}
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ export const HeaderGroupByCard = observer(function HeaderGroupByCard(props: IHea
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{sub_group_by === null && (
|
||||
{!sub_group_by && (
|
||||
<button
|
||||
className="flex h-[20px] w-[20px] flex-shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-sm bg-layer-transparent transition-all hover:bg-layer-transparent-hover"
|
||||
onClick={() => handleCollapsedGroups("group_by", column_id)}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import type { MutableRefObject } from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
// plane imports
|
||||
import type {
|
||||
GroupByColumnTypes,
|
||||
|
|
@ -290,17 +291,20 @@ export const KanBanSwimLanes = observer(function KanBanSwimLanes(props: IKanBanS
|
|||
// store hooks
|
||||
const storeType = useIssueStoreType();
|
||||
// derived values
|
||||
const { projectId } = useParams();
|
||||
const groupByList = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
isEpic: isEpic,
|
||||
projectId: projectId?.toString(),
|
||||
});
|
||||
const subGroupByList = getGroupByColumns({
|
||||
groupBy: sub_group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
isEpic: isEpic,
|
||||
projectId: projectId?.toString(),
|
||||
});
|
||||
|
||||
if (!groupByList || !subGroupByList) return null;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
||||
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
|
||||
import { observer } from "mobx-react";
|
||||
|
|
@ -87,11 +88,13 @@ export const List = observer(function List(props: IList) {
|
|||
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const { projectId } = useParams();
|
||||
const groups = getGroupByColumns({
|
||||
groupBy: group_by as GroupByColumnTypes,
|
||||
includeNone: true,
|
||||
isWorkspaceLevel: isWorkspaceLevel(storeType),
|
||||
isEpic: isEpic,
|
||||
projectId: projectId?.toString(),
|
||||
});
|
||||
|
||||
// Enable Auto Scroll for Main Kanban
|
||||
|
|
|
|||
|
|
@ -240,9 +240,15 @@ const getModuleColumns = (): IGroupByColumn[] | undefined => {
|
|||
};
|
||||
|
||||
const getStateColumns = ({ projectId }: TGetColumns): IGroupByColumn[] | undefined => {
|
||||
const { getProjectStates, projectStates } = store.state;
|
||||
const _states = projectId ? getProjectStates(projectId) : projectStates;
|
||||
if (!_states) return;
|
||||
const { getProjectStates, projectStates, stateMap } = store.state;
|
||||
let _states = projectId ? getProjectStates(projectId) : projectStates;
|
||||
if (!_states || _states.length === 0) {
|
||||
const targetProjectId = projectId || store.router.projectId;
|
||||
if (targetProjectId && stateMap) {
|
||||
_states = Object.values(stateMap).filter((state) => state.project_id === targetProjectId);
|
||||
}
|
||||
}
|
||||
if (!_states || _states.length === 0) return;
|
||||
// map project states to group by columns
|
||||
return _states.map((state) => ({
|
||||
id: state.id,
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
import { isEmpty } from "lodash-es";
|
||||
import { autorun, makeObservable, observable, runInAction } from "mobx";
|
||||
import { makeObservable, computed } from "mobx";
|
||||
// types
|
||||
import type { ICycle, IIssueLabel, IModule, IProject, IState, IUserLite, TIssueServiceType } from "@plane/types";
|
||||
import { EIssueServiceType } from "@plane/types";
|
||||
|
|
@ -109,25 +108,6 @@ export interface IIssueRootStore {
|
|||
}
|
||||
|
||||
export class IssueRootStore implements IIssueRootStore {
|
||||
currentUserId: string | undefined = undefined;
|
||||
workspaceSlug: string | undefined = undefined;
|
||||
teamspaceId: string | undefined = undefined;
|
||||
projectId: string | undefined = undefined;
|
||||
cycleId: string | undefined = undefined;
|
||||
moduleId: string | undefined = undefined;
|
||||
viewId: string | undefined = undefined;
|
||||
globalViewId: string | undefined = undefined;
|
||||
userId: string | undefined = undefined;
|
||||
stateMap: Record<string, IState> | undefined = undefined;
|
||||
stateDetails: IState[] | undefined = undefined;
|
||||
workspaceStateDetails: IState[] | undefined = undefined;
|
||||
labelMap: Record<string, IIssueLabel> | undefined = undefined;
|
||||
workSpaceMemberRolesMap: Record<string, IWorkspaceMembership> | undefined = undefined;
|
||||
memberMap: Record<string, IUserLite> | undefined = undefined;
|
||||
projectMap: Record<string, IProject> | undefined = undefined;
|
||||
moduleMap: Record<string, IModule> | undefined = undefined;
|
||||
cycleMap: Record<string, ICycle> | undefined = undefined;
|
||||
|
||||
rootStore: RootStore;
|
||||
serviceType: TIssueServiceType;
|
||||
|
||||
|
|
@ -175,55 +155,103 @@ export class IssueRootStore implements IIssueRootStore {
|
|||
projectEpicsFilter: IProjectIssuesFilter;
|
||||
projectEpics: IProjectIssues;
|
||||
|
||||
get currentUserId(): string | undefined {
|
||||
return this.rootStore?.user?.data?.id;
|
||||
}
|
||||
|
||||
get workspaceSlug(): string | undefined {
|
||||
return this.rootStore?.router?.workspaceSlug;
|
||||
}
|
||||
|
||||
get teamspaceId(): string | undefined {
|
||||
return this.rootStore?.router?.teamspaceId;
|
||||
}
|
||||
|
||||
get projectId(): string | undefined {
|
||||
return this.rootStore?.router?.projectId;
|
||||
}
|
||||
|
||||
get cycleId(): string | undefined {
|
||||
return this.rootStore?.router?.cycleId;
|
||||
}
|
||||
|
||||
get moduleId(): string | undefined {
|
||||
return this.rootStore?.router?.moduleId;
|
||||
}
|
||||
|
||||
get viewId(): string | undefined {
|
||||
return this.rootStore?.router?.viewId;
|
||||
}
|
||||
|
||||
get globalViewId(): string | undefined {
|
||||
return this.rootStore?.router?.globalViewId;
|
||||
}
|
||||
|
||||
get userId(): string | undefined {
|
||||
return this.rootStore?.router?.userId;
|
||||
}
|
||||
|
||||
get stateMap(): Record<string, IState> | undefined {
|
||||
return this.rootStore?.state?.stateMap;
|
||||
}
|
||||
|
||||
get stateDetails(): IState[] | undefined {
|
||||
return this.rootStore?.state?.projectStates;
|
||||
}
|
||||
|
||||
get workspaceStateDetails(): IState[] | undefined {
|
||||
return this.rootStore?.state?.workspaceStates;
|
||||
}
|
||||
|
||||
get labelMap(): Record<string, IIssueLabel> | undefined {
|
||||
return this.rootStore?.label?.labelMap;
|
||||
}
|
||||
|
||||
get workSpaceMemberRolesMap(): Record<string, IWorkspaceMembership> | undefined {
|
||||
return this.rootStore?.memberRoot?.workspace?.memberMap || undefined;
|
||||
}
|
||||
|
||||
get memberMap(): Record<string, IUserLite> | undefined {
|
||||
return this.rootStore?.memberRoot?.memberMap || undefined;
|
||||
}
|
||||
|
||||
get projectMap(): Record<string, IProject> | undefined {
|
||||
return this.rootStore?.projectRoot?.project?.projectMap;
|
||||
}
|
||||
|
||||
get moduleMap(): Record<string, IModule> | undefined {
|
||||
return this.rootStore?.module?.moduleMap;
|
||||
}
|
||||
|
||||
get cycleMap(): Record<string, ICycle> | undefined {
|
||||
return this.rootStore?.cycle?.cycleMap;
|
||||
}
|
||||
|
||||
constructor(rootStore: RootStore, serviceType: TIssueServiceType = EIssueServiceType.ISSUES) {
|
||||
makeObservable(this, {
|
||||
workspaceSlug: observable.ref,
|
||||
teamspaceId: observable.ref,
|
||||
projectId: observable.ref,
|
||||
cycleId: observable.ref,
|
||||
moduleId: observable.ref,
|
||||
viewId: observable.ref,
|
||||
userId: observable.ref,
|
||||
globalViewId: observable.ref,
|
||||
stateMap: observable,
|
||||
stateDetails: observable,
|
||||
workspaceStateDetails: observable,
|
||||
labelMap: observable,
|
||||
memberMap: observable,
|
||||
workSpaceMemberRolesMap: observable,
|
||||
projectMap: observable,
|
||||
moduleMap: observable,
|
||||
cycleMap: observable,
|
||||
currentUserId: computed,
|
||||
workspaceSlug: computed,
|
||||
teamspaceId: computed,
|
||||
projectId: computed,
|
||||
cycleId: computed,
|
||||
moduleId: computed,
|
||||
viewId: computed,
|
||||
userId: computed,
|
||||
globalViewId: computed,
|
||||
stateMap: computed,
|
||||
stateDetails: computed,
|
||||
workspaceStateDetails: computed,
|
||||
labelMap: computed,
|
||||
memberMap: computed,
|
||||
workSpaceMemberRolesMap: computed,
|
||||
projectMap: computed,
|
||||
moduleMap: computed,
|
||||
cycleMap: computed,
|
||||
});
|
||||
|
||||
this.serviceType = serviceType;
|
||||
this.rootStore = rootStore;
|
||||
|
||||
autorun(() => {
|
||||
runInAction(() => {
|
||||
if (rootStore?.user?.data?.id) this.currentUserId = rootStore?.user?.data?.id;
|
||||
if (this.workspaceSlug !== rootStore.router.workspaceSlug) this.workspaceSlug = rootStore.router.workspaceSlug;
|
||||
if (this.teamspaceId !== rootStore.router.teamspaceId) this.teamspaceId = rootStore.router.teamspaceId;
|
||||
if (this.projectId !== rootStore.router.projectId) this.projectId = rootStore.router.projectId;
|
||||
if (this.cycleId !== rootStore.router.cycleId) this.cycleId = rootStore.router.cycleId;
|
||||
if (this.moduleId !== rootStore.router.moduleId) this.moduleId = rootStore.router.moduleId;
|
||||
if (this.viewId !== rootStore.router.viewId) this.viewId = rootStore.router.viewId;
|
||||
if (this.globalViewId !== rootStore.router.globalViewId) this.globalViewId = rootStore.router.globalViewId;
|
||||
if (this.userId !== rootStore.router.userId) this.userId = rootStore.router.userId;
|
||||
if (!isEmpty(rootStore?.state?.stateMap)) this.stateMap = rootStore?.state?.stateMap;
|
||||
if (!isEmpty(rootStore?.state?.projectStates)) this.stateDetails = rootStore?.state?.projectStates;
|
||||
if (!isEmpty(rootStore?.state?.workspaceStates)) this.workspaceStateDetails = rootStore?.state?.workspaceStates;
|
||||
if (!isEmpty(rootStore?.label?.labelMap)) this.labelMap = rootStore?.label?.labelMap;
|
||||
if (!isEmpty(rootStore?.memberRoot?.workspace?.workspaceMemberMap))
|
||||
this.workSpaceMemberRolesMap = rootStore?.memberRoot?.workspace?.memberMap || undefined;
|
||||
if (!isEmpty(rootStore?.memberRoot?.memberMap)) this.memberMap = rootStore?.memberRoot?.memberMap || undefined;
|
||||
if (!isEmpty(rootStore?.projectRoot?.project?.projectMap))
|
||||
this.projectMap = rootStore?.projectRoot?.project?.projectMap;
|
||||
if (!isEmpty(rootStore?.module?.moduleMap)) this.moduleMap = rootStore?.module?.moduleMap;
|
||||
if (!isEmpty(rootStore?.cycle?.cycleMap)) this.cycleMap = rootStore?.cycle?.cycleMap;
|
||||
});
|
||||
});
|
||||
|
||||
this.issues = new IssueStore();
|
||||
|
||||
this.issueDetail = new IssueDetail(this, EIssueServiceType.ISSUES);
|
||||
|
|
|
|||
|
|
@ -180,7 +180,9 @@ export class BaseWorkspaceRootStore implements IWorkspaceRootStore {
|
|||
* fetch user workspaces from API
|
||||
*/
|
||||
fetchWorkspaces = async () => {
|
||||
this.loader = true;
|
||||
runInAction(() => {
|
||||
this.loader = true;
|
||||
});
|
||||
try {
|
||||
const workspaceResponse = await this.workspaceService.userWorkspaces();
|
||||
runInAction(() => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue