forked from github/plane
fix: project loaders for mobx store (#3356)
* add loaders to all the dropdowns outside project wrpper * fix build errors * minor refactor for project states color --------- Co-authored-by: Rahul R <rahulr@Rahuls-MacBook-Pro.local>
This commit is contained in:
parent
151c355177
commit
9789068880
@ -464,7 +464,7 @@ export const ActiveCycleDetails: React.FC<IActiveCycleDetails> = observer((props
|
|||||||
{
|
{
|
||||||
issueIds?.filter(
|
issueIds?.filter(
|
||||||
(issueId) =>
|
(issueId) =>
|
||||||
getProjectStates(issueMap[issueId]?.project_id).find(
|
getProjectStates(issueMap[issueId]?.project_id)?.find(
|
||||||
(issue) => issue.id === issueMap[issueId]?.state_id
|
(issue) => issue.id === issueMap[issueId]?.state_id
|
||||||
)?.group === "completed"
|
)?.group === "completed"
|
||||||
)?.length
|
)?.length
|
||||||
|
@ -129,34 +129,37 @@ export const SelectDuplicateInboxIssueModal: React.FC<Props> = (props) => {
|
|||||||
<h2 className="mb-2 mt-4 px-3 text-xs font-semibold text-custom-text-100">Select issue</h2>
|
<h2 className="mb-2 mt-4 px-3 text-xs font-semibold text-custom-text-100">Select issue</h2>
|
||||||
)}
|
)}
|
||||||
<ul className="text-sm text-custom-text-100">
|
<ul className="text-sm text-custom-text-100">
|
||||||
{filteredIssues.map((issue) => (
|
{filteredIssues.map((issue) => {
|
||||||
<Combobox.Option
|
const stateColor =
|
||||||
key={issue.id}
|
getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)
|
||||||
as="div"
|
?.color || "";
|
||||||
value={issue.id}
|
|
||||||
className={({ active, selected }) =>
|
return (
|
||||||
`flex w-full cursor-pointer select-none items-center gap-2 rounded-md px-3 py-2 text-custom-text-200 ${
|
<Combobox.Option
|
||||||
active || selected ? "bg-custom-background-80 text-custom-text-100" : ""
|
key={issue.id}
|
||||||
} `
|
as="div"
|
||||||
}
|
value={issue.id}
|
||||||
>
|
className={({ active, selected }) =>
|
||||||
<div className="flex items-center gap-2">
|
`flex w-full cursor-pointer select-none items-center gap-2 rounded-md px-3 py-2 text-custom-text-200 ${
|
||||||
<span
|
active || selected ? "bg-custom-background-80 text-custom-text-100" : ""
|
||||||
className="block h-1.5 w-1.5 flex-shrink-0 rounded-full"
|
} `
|
||||||
style={{
|
}
|
||||||
backgroundColor:
|
>
|
||||||
getProjectStates(issue?.project_id)?.find(
|
<div className="flex items-center gap-2">
|
||||||
(state) => state?.id == issue?.state_id
|
<span
|
||||||
)?.color || "",
|
className="block h-1.5 w-1.5 flex-shrink-0 rounded-full"
|
||||||
}}
|
style={{
|
||||||
/>
|
backgroundColor: stateColor,
|
||||||
<span className="flex-shrink-0 text-xs text-custom-text-200">
|
}}
|
||||||
{getProjectById(issue?.project_id)?.identifier}-{issue.sequence_id}
|
/>
|
||||||
</span>
|
<span className="flex-shrink-0 text-xs text-custom-text-200">
|
||||||
<span className="text-custom-text-200">{issue.name}</span>
|
{getProjectById(issue?.project_id)?.identifier}-{issue.sequence_id}
|
||||||
</div>
|
</span>
|
||||||
</Combobox.Option>
|
<span className="text-custom-text-200">{issue.name}</span>
|
||||||
))}
|
</div>
|
||||||
|
</Combobox.Option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
) : (
|
) : (
|
||||||
|
@ -59,6 +59,10 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
if (!issues?.[issueId]) return null;
|
if (!issues?.[issueId]) return null;
|
||||||
|
|
||||||
const issue = issues?.[issueId];
|
const issue = issues?.[issueId];
|
||||||
|
|
||||||
|
const stateColor =
|
||||||
|
getProjectStates(issue?.project_id)?.find((state) => state?.id == issue?.state_id)?.color || "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Draggable key={issue.id} draggableId={issue.id} index={index}>
|
<Draggable key={issue.id} draggableId={issue.id} index={index}>
|
||||||
{(provided, snapshot) => (
|
{(provided, snapshot) => (
|
||||||
@ -90,9 +94,7 @@ export const CalendarIssueBlocks: React.FC<Props> = observer((props) => {
|
|||||||
<span
|
<span
|
||||||
className="h-full w-0.5 flex-shrink-0 rounded"
|
className="h-full w-0.5 flex-shrink-0 rounded"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: getProjectStates(issue?.project_id).find(
|
backgroundColor: stateColor,
|
||||||
(state) => state?.id == issue?.state_id
|
|
||||||
)?.color,
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<div className="flex-shrink-0 text-xs text-custom-text-300">
|
<div className="flex-shrink-0 text-xs text-custom-text-300">
|
||||||
|
@ -22,11 +22,13 @@ export const IssueGanttBlock = ({ data }: { data: TIssue }) => {
|
|||||||
data.id &&
|
data.id &&
|
||||||
setPeekIssue({ workspaceSlug, projectId: data.project_id, issueId: data.id });
|
setPeekIssue({ workspaceSlug, projectId: data.project_id, issueId: data.id });
|
||||||
|
|
||||||
|
const stateColor = getProjectStates(data?.project_id)?.find((state) => state?.id == data?.state_id)?.color || "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative flex h-full w-full cursor-pointer items-center rounded"
|
className="relative flex h-full w-full cursor-pointer items-center rounded"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: getProjectStates(data?.project_id)?.find((state) => state?.id == data?.state_id)?.color,
|
backgroundColor: stateColor,
|
||||||
}}
|
}}
|
||||||
onClick={handleIssuePeekOverview}
|
onClick={handleIssuePeekOverview}
|
||||||
>
|
>
|
||||||
|
@ -30,7 +30,7 @@ export const IssueLabelSelect: React.FC<Props> = observer((props) => {
|
|||||||
const { workspaceSlug } = router.query;
|
const { workspaceSlug } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const {
|
const {
|
||||||
project: { projectLabels, fetchProjectLabels },
|
project: { getProjectLabels, fetchProjectLabels },
|
||||||
} = useLabel();
|
} = useLabel();
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -43,6 +43,9 @@ export const IssueLabelSelect: React.FC<Props> = observer((props) => {
|
|||||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||||
placement: "bottom-start",
|
placement: "bottom-start",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const projectLabels = getProjectLabels(projectId);
|
||||||
|
|
||||||
// derived values
|
// derived values
|
||||||
const filteredOptions =
|
const filteredOptions =
|
||||||
query === "" ? projectLabels : projectLabels?.filter((l) => l.name.toLowerCase().includes(query.toLowerCase()));
|
query === "" ? projectLabels : projectLabels?.filter((l) => l.name.toLowerCase().includes(query.toLowerCase()));
|
||||||
|
@ -12,6 +12,8 @@ import { IssueService } from "services/issue";
|
|||||||
import { CycleService } from "services/cycle.service";
|
import { CycleService } from "services/cycle.service";
|
||||||
|
|
||||||
export interface ICycleStore {
|
export interface ICycleStore {
|
||||||
|
//Loaders
|
||||||
|
fetchedMap: Record<string, boolean>;
|
||||||
// observables
|
// observables
|
||||||
cycleMap: Record<string, ICycle>;
|
cycleMap: Record<string, ICycle>;
|
||||||
activeCycleIdMap: Record<string, boolean>;
|
activeCycleIdMap: Record<string, boolean>;
|
||||||
@ -50,6 +52,8 @@ export class CycleStore implements ICycleStore {
|
|||||||
// observables
|
// observables
|
||||||
cycleMap: Record<string, ICycle> = {};
|
cycleMap: Record<string, ICycle> = {};
|
||||||
activeCycleIdMap: Record<string, boolean> = {};
|
activeCycleIdMap: Record<string, boolean> = {};
|
||||||
|
//loaders
|
||||||
|
fetchedMap: Record<string, boolean> = {};
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
// services
|
// services
|
||||||
@ -62,6 +66,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
// observables
|
// observables
|
||||||
cycleMap: observable,
|
cycleMap: observable,
|
||||||
activeCycleIdMap: observable,
|
activeCycleIdMap: observable,
|
||||||
|
fetchedMap: observable,
|
||||||
// computed
|
// computed
|
||||||
currentProjectCycleIds: computed,
|
currentProjectCycleIds: computed,
|
||||||
currentProjectCompletedCycleIds: computed,
|
currentProjectCompletedCycleIds: computed,
|
||||||
@ -96,11 +101,11 @@ export class CycleStore implements ICycleStore {
|
|||||||
*/
|
*/
|
||||||
get currentProjectCycleIds() {
|
get currentProjectCycleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let allCycles = Object.values(this.cycleMap ?? {}).filter((c) => c?.project === projectId);
|
let allCycles = Object.values(this.cycleMap ?? {}).filter((c) => c?.project === projectId);
|
||||||
allCycles = sortBy(allCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
allCycles = sortBy(allCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const allCycleIds = allCycles.map((c) => c.id);
|
const allCycleIds = allCycles.map((c) => c.id);
|
||||||
return allCycleIds || null;
|
return allCycleIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,14 +113,14 @@ export class CycleStore implements ICycleStore {
|
|||||||
*/
|
*/
|
||||||
get currentProjectCompletedCycleIds() {
|
get currentProjectCompletedCycleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let completedCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
let completedCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
||||||
const hasEndDatePassed = isPast(new Date(c.end_date ?? ""));
|
const hasEndDatePassed = isPast(new Date(c.end_date ?? ""));
|
||||||
return c.project === projectId && hasEndDatePassed;
|
return c.project === projectId && hasEndDatePassed;
|
||||||
});
|
});
|
||||||
completedCycles = sortBy(completedCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
completedCycles = sortBy(completedCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const completedCycleIds = completedCycles.map((c) => c.id);
|
const completedCycleIds = completedCycles.map((c) => c.id);
|
||||||
return completedCycleIds || null;
|
return completedCycleIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,14 +128,14 @@ export class CycleStore implements ICycleStore {
|
|||||||
*/
|
*/
|
||||||
get currentProjectUpcomingCycleIds() {
|
get currentProjectUpcomingCycleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let upcomingCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
let upcomingCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
||||||
const isStartDateUpcoming = isFuture(new Date(c.start_date ?? ""));
|
const isStartDateUpcoming = isFuture(new Date(c.start_date ?? ""));
|
||||||
return c.project === projectId && isStartDateUpcoming;
|
return c.project === projectId && isStartDateUpcoming;
|
||||||
});
|
});
|
||||||
upcomingCycles = sortBy(upcomingCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
upcomingCycles = sortBy(upcomingCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const upcomingCycleIds = upcomingCycles.map((c) => c.id);
|
const upcomingCycleIds = upcomingCycles.map((c) => c.id);
|
||||||
return upcomingCycleIds || null;
|
return upcomingCycleIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,14 +143,14 @@ export class CycleStore implements ICycleStore {
|
|||||||
*/
|
*/
|
||||||
get currentProjectIncompleteCycleIds() {
|
get currentProjectIncompleteCycleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let incompleteCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
let incompleteCycles = Object.values(this.cycleMap ?? {}).filter((c) => {
|
||||||
const hasEndDatePassed = isPast(new Date(c.end_date ?? ""));
|
const hasEndDatePassed = isPast(new Date(c.end_date ?? ""));
|
||||||
return c.project === projectId && !hasEndDatePassed;
|
return c.project === projectId && !hasEndDatePassed;
|
||||||
});
|
});
|
||||||
incompleteCycles = sortBy(incompleteCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
incompleteCycles = sortBy(incompleteCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const incompleteCycleIds = incompleteCycles.map((c) => c.id);
|
const incompleteCycleIds = incompleteCycles.map((c) => c.id);
|
||||||
return incompleteCycleIds || null;
|
return incompleteCycleIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -153,13 +158,13 @@ export class CycleStore implements ICycleStore {
|
|||||||
*/
|
*/
|
||||||
get currentProjectDraftCycleIds() {
|
get currentProjectDraftCycleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let draftCycles = Object.values(this.cycleMap ?? {}).filter(
|
let draftCycles = Object.values(this.cycleMap ?? {}).filter(
|
||||||
(c) => c.project === projectId && !c.start_date && !c.end_date
|
(c) => c.project === projectId && !c.start_date && !c.end_date
|
||||||
);
|
);
|
||||||
draftCycles = sortBy(draftCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
draftCycles = sortBy(draftCycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const draftCycleIds = draftCycles.map((c) => c.id);
|
const draftCycleIds = draftCycles.map((c) => c.id);
|
||||||
return draftCycleIds || null;
|
return draftCycleIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -194,6 +199,8 @@ export class CycleStore implements ICycleStore {
|
|||||||
* @param projectId
|
* @param projectId
|
||||||
*/
|
*/
|
||||||
getProjectCycleIds = (projectId: string): string[] | null => {
|
getProjectCycleIds = (projectId: string): string[] | null => {
|
||||||
|
if (!this.fetchedMap[projectId]) return null;
|
||||||
|
|
||||||
let cycles = Object.values(this.cycleMap ?? {}).filter((c) => c.project === projectId);
|
let cycles = Object.values(this.cycleMap ?? {}).filter((c) => c.project === projectId);
|
||||||
cycles = sortBy(cycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
cycles = sortBy(cycles, [(c) => !c.is_favorite, (c) => c.name.toLowerCase()]);
|
||||||
const cycleIds = cycles.map((c) => c.id);
|
const cycleIds = cycles.map((c) => c.id);
|
||||||
@ -222,6 +229,7 @@ export class CycleStore implements ICycleStore {
|
|||||||
response.forEach((cycle) => {
|
response.forEach((cycle) => {
|
||||||
set(this.cycleMap, [cycle.id], cycle);
|
set(this.cycleMap, [cycle.id], cycle);
|
||||||
});
|
});
|
||||||
|
set(this.fetchedMap, projectId, true);
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { action, computed, makeObservable, runInAction } from "mobx";
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
import set from "lodash/set";
|
import set from "lodash/set";
|
||||||
// services
|
// services
|
||||||
import { IssueLabelService } from "services/issue";
|
import { IssueLabelService } from "services/issue";
|
||||||
@ -10,9 +10,13 @@ import { IIssueLabel, IIssueLabelTree } from "@plane/types";
|
|||||||
import { ILabelRootStore } from "store/label";
|
import { ILabelRootStore } from "store/label";
|
||||||
|
|
||||||
export interface IProjectLabelStore {
|
export interface IProjectLabelStore {
|
||||||
|
//Loaders
|
||||||
|
fetchedMap: Record<string, boolean>;
|
||||||
// computed
|
// computed
|
||||||
projectLabels: IIssueLabel[] | undefined;
|
projectLabels: IIssueLabel[] | undefined;
|
||||||
projectLabelsTree: IIssueLabelTree[] | undefined;
|
projectLabelsTree: IIssueLabelTree[] | undefined;
|
||||||
|
//computed actions
|
||||||
|
getProjectLabels: (projectId: string) => IIssueLabel[] | undefined;
|
||||||
// fetch actions
|
// fetch actions
|
||||||
fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise<IIssueLabel[]>;
|
fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise<IIssueLabel[]>;
|
||||||
// crud actions
|
// crud actions
|
||||||
@ -40,15 +44,21 @@ export class ProjectLabelStore implements IProjectLabelStore {
|
|||||||
rootStore;
|
rootStore;
|
||||||
// root store labelMap
|
// root store labelMap
|
||||||
labelMap: Record<string, IIssueLabel> = {};
|
labelMap: Record<string, IIssueLabel> = {};
|
||||||
|
//loaders
|
||||||
|
fetchedMap: Record<string, boolean> = {};
|
||||||
// services
|
// services
|
||||||
issueLabelService;
|
issueLabelService;
|
||||||
|
|
||||||
constructor(_labelRoot: ILabelRootStore, _rootStore: RootStore) {
|
constructor(_labelRoot: ILabelRootStore, _rootStore: RootStore) {
|
||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
|
labelMap: observable,
|
||||||
|
fetchedMap: observable,
|
||||||
// computed
|
// computed
|
||||||
projectLabels: computed,
|
projectLabels: computed,
|
||||||
projectLabelsTree: computed,
|
projectLabelsTree: computed,
|
||||||
// actions
|
// actions
|
||||||
|
getProjectLabels: action,
|
||||||
|
|
||||||
fetchProjectLabels: action,
|
fetchProjectLabels: action,
|
||||||
createLabel: action,
|
createLabel: action,
|
||||||
updateLabel: action,
|
updateLabel: action,
|
||||||
@ -68,7 +78,7 @@ export class ProjectLabelStore implements IProjectLabelStore {
|
|||||||
*/
|
*/
|
||||||
get projectLabels() {
|
get projectLabels() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId || !this.labelMap) return;
|
if (!projectId || !this.fetchedMap[projectId] || !this.labelMap) return;
|
||||||
return Object.values(this.labelMap ?? {}).filter((label) => label.project === projectId);
|
return Object.values(this.labelMap ?? {}).filter((label) => label.project === projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,6 +90,11 @@ export class ProjectLabelStore implements IProjectLabelStore {
|
|||||||
return buildTree(this.projectLabels);
|
return buildTree(this.projectLabels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProjectLabels = (projectId: string) => {
|
||||||
|
if (!this.fetchedMap[projectId] || !this.labelMap) return;
|
||||||
|
return Object.values(this.labelMap ?? {}).filter((label) => label.project === projectId);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches all the labelMap belongs to a specific project
|
* Fetches all the labelMap belongs to a specific project
|
||||||
* @param workspaceSlug
|
* @param workspaceSlug
|
||||||
@ -92,6 +107,7 @@ export class ProjectLabelStore implements IProjectLabelStore {
|
|||||||
response.forEach((label) => {
|
response.forEach((label) => {
|
||||||
set(this.labelMap, [label.id], label);
|
set(this.labelMap, [label.id], label);
|
||||||
});
|
});
|
||||||
|
set(this.fetchedMap, projectId, true);
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
@ -120,7 +120,8 @@ export class ProjectMemberStore implements IProjectMemberStore {
|
|||||||
* @param projectId
|
* @param projectId
|
||||||
*/
|
*/
|
||||||
getProjectMemberIds = (projectId: string): string[] | null => {
|
getProjectMemberIds = (projectId: string): string[] | null => {
|
||||||
let members = Object.values(this.projectMemberMap?.[projectId] ?? {});
|
if (!this.projectMemberMap?.[projectId]) return null;
|
||||||
|
let members = Object.values(this.projectMemberMap?.[projectId]);
|
||||||
members = sortBy(members, [
|
members = sortBy(members, [
|
||||||
(m) => m.member !== this.userStore.currentUser?.id,
|
(m) => m.member !== this.userStore.currentUser?.id,
|
||||||
(m) => this.memberRoot?.memberMap?.[m.member]?.display_name?.toLowerCase(),
|
(m) => this.memberRoot?.memberMap?.[m.member]?.display_name?.toLowerCase(),
|
||||||
|
@ -9,6 +9,8 @@ import { IModule, ILinkDetails } from "@plane/types";
|
|||||||
import { RootStore } from "store/root.store";
|
import { RootStore } from "store/root.store";
|
||||||
|
|
||||||
export interface IModuleStore {
|
export interface IModuleStore {
|
||||||
|
//Loaders
|
||||||
|
fetchedMap: Record<string, boolean>;
|
||||||
// observables
|
// observables
|
||||||
moduleMap: Record<string, IModule>;
|
moduleMap: Record<string, IModule>;
|
||||||
// computed
|
// computed
|
||||||
@ -51,6 +53,8 @@ export interface IModuleStore {
|
|||||||
export class ModulesStore implements IModuleStore {
|
export class ModulesStore implements IModuleStore {
|
||||||
// observables
|
// observables
|
||||||
moduleMap: Record<string, IModule> = {};
|
moduleMap: Record<string, IModule> = {};
|
||||||
|
//loaders
|
||||||
|
fetchedMap: Record<string, boolean> = {};
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
// services
|
// services
|
||||||
@ -61,6 +65,7 @@ export class ModulesStore implements IModuleStore {
|
|||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
// observables
|
// observables
|
||||||
moduleMap: observable,
|
moduleMap: observable,
|
||||||
|
fetchedMap: observable,
|
||||||
// computed
|
// computed
|
||||||
projectModuleIds: computed,
|
projectModuleIds: computed,
|
||||||
// computed actions
|
// computed actions
|
||||||
@ -92,7 +97,7 @@ export class ModulesStore implements IModuleStore {
|
|||||||
*/
|
*/
|
||||||
get projectModuleIds() {
|
get projectModuleIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
let projectModules = Object.values(this.moduleMap).filter((m) => m.project === projectId);
|
let projectModules = Object.values(this.moduleMap).filter((m) => m.project === projectId);
|
||||||
projectModules = sortBy(projectModules, [(m) => !m.is_favorite, (m) => m.name.toLowerCase()]);
|
projectModules = sortBy(projectModules, [(m) => !m.is_favorite, (m) => m.name.toLowerCase()]);
|
||||||
const projectModuleIds = projectModules.map((m) => m.id);
|
const projectModuleIds = projectModules.map((m) => m.id);
|
||||||
@ -111,10 +116,12 @@ export class ModulesStore implements IModuleStore {
|
|||||||
* @param projectId
|
* @param projectId
|
||||||
*/
|
*/
|
||||||
getProjectModuleIds = (projectId: string) => {
|
getProjectModuleIds = (projectId: string) => {
|
||||||
|
if (!this.fetchedMap[projectId]) return null;
|
||||||
|
|
||||||
let projectModules = Object.values(this.moduleMap).filter((m) => m.project === projectId);
|
let projectModules = Object.values(this.moduleMap).filter((m) => m.project === projectId);
|
||||||
projectModules = sortBy(projectModules, [(m) => !m.is_favorite, (m) => m.name.toLowerCase()]);
|
projectModules = sortBy(projectModules, [(m) => !m.is_favorite, (m) => m.name.toLowerCase()]);
|
||||||
const projectModuleIds = projectModules.map((m) => m.id);
|
const projectModuleIds = projectModules.map((m) => m.id);
|
||||||
return projectModuleIds || null;
|
return projectModuleIds;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,6 +136,7 @@ export class ModulesStore implements IModuleStore {
|
|||||||
response.forEach((module) => {
|
response.forEach((module) => {
|
||||||
set(this.moduleMap, [module.id], { ...this.moduleMap[module.id], ...module });
|
set(this.moduleMap, [module.id], { ...this.moduleMap[module.id], ...module });
|
||||||
});
|
});
|
||||||
|
set(this.fetchedMap, projectId, true);
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
@ -7,6 +7,8 @@ import { RootStore } from "store/root.store";
|
|||||||
import { IProjectView } from "@plane/types";
|
import { IProjectView } from "@plane/types";
|
||||||
|
|
||||||
export interface IProjectViewStore {
|
export interface IProjectViewStore {
|
||||||
|
//Loaders
|
||||||
|
fetchedMap: Record<string, boolean>;
|
||||||
// observables
|
// observables
|
||||||
viewMap: Record<string, IProjectView>;
|
viewMap: Record<string, IProjectView>;
|
||||||
// computed
|
// computed
|
||||||
@ -33,6 +35,8 @@ export interface IProjectViewStore {
|
|||||||
export class ProjectViewStore implements IProjectViewStore {
|
export class ProjectViewStore implements IProjectViewStore {
|
||||||
// observables
|
// observables
|
||||||
viewMap: Record<string, IProjectView> = {};
|
viewMap: Record<string, IProjectView> = {};
|
||||||
|
//loaders
|
||||||
|
fetchedMap: Record<string, boolean> = {};
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
// services
|
// services
|
||||||
@ -42,6 +46,7 @@ export class ProjectViewStore implements IProjectViewStore {
|
|||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
// observables
|
// observables
|
||||||
viewMap: observable,
|
viewMap: observable,
|
||||||
|
fetchedMap: observable,
|
||||||
// computed
|
// computed
|
||||||
projectViewIds: computed,
|
projectViewIds: computed,
|
||||||
// computed actions
|
// computed actions
|
||||||
@ -68,7 +73,7 @@ export class ProjectViewStore implements IProjectViewStore {
|
|||||||
*/
|
*/
|
||||||
get projectViewIds() {
|
get projectViewIds() {
|
||||||
const projectId = this.rootStore.app.router.projectId;
|
const projectId = this.rootStore.app.router.projectId;
|
||||||
if (!projectId) return null;
|
if (!projectId || !this.fetchedMap[projectId]) return null;
|
||||||
const viewIds = Object.keys(this.viewMap ?? {})?.filter((viewId) => this.viewMap?.[viewId]?.project === projectId);
|
const viewIds = Object.keys(this.viewMap ?? {})?.filter((viewId) => this.viewMap?.[viewId]?.project === projectId);
|
||||||
return viewIds;
|
return viewIds;
|
||||||
}
|
}
|
||||||
@ -90,6 +95,7 @@ export class ProjectViewStore implements IProjectViewStore {
|
|||||||
response.forEach((view) => {
|
response.forEach((view) => {
|
||||||
set(this.viewMap, [view.id], view);
|
set(this.viewMap, [view.id], view);
|
||||||
});
|
});
|
||||||
|
set(this.fetchedMap, projectId, true);
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,8 @@ import { IState } from "@plane/types";
|
|||||||
import { ProjectStateService } from "services/project";
|
import { ProjectStateService } from "services/project";
|
||||||
|
|
||||||
export interface IStateStore {
|
export interface IStateStore {
|
||||||
|
//Loaders
|
||||||
|
fetchedMap: Record<string, boolean>;
|
||||||
// observables
|
// observables
|
||||||
stateMap: Record<string, IState>;
|
stateMap: Record<string, IState>;
|
||||||
// computed
|
// computed
|
||||||
@ -16,7 +18,7 @@ export interface IStateStore {
|
|||||||
groupedProjectStates: Record<string, IState[]> | undefined;
|
groupedProjectStates: Record<string, IState[]> | undefined;
|
||||||
// computed actions
|
// computed actions
|
||||||
getStateById: (stateId: string) => IState | undefined;
|
getStateById: (stateId: string) => IState | undefined;
|
||||||
getProjectStates: (projectId: string) => IState[];
|
getProjectStates: (projectId: string) => IState[] | undefined;
|
||||||
// fetch actions
|
// fetch actions
|
||||||
fetchProjectStates: (workspaceSlug: string, projectId: string) => Promise<IState[]>;
|
fetchProjectStates: (workspaceSlug: string, projectId: string) => Promise<IState[]>;
|
||||||
// crud actions
|
// crud actions
|
||||||
@ -40,6 +42,8 @@ export interface IStateStore {
|
|||||||
|
|
||||||
export class StateStore implements IStateStore {
|
export class StateStore implements IStateStore {
|
||||||
stateMap: Record<string, IState> = {};
|
stateMap: Record<string, IState> = {};
|
||||||
|
//loaders
|
||||||
|
fetchedMap: Record<string, boolean> = {};
|
||||||
router;
|
router;
|
||||||
stateService;
|
stateService;
|
||||||
|
|
||||||
@ -47,6 +51,7 @@ export class StateStore implements IStateStore {
|
|||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
// observables
|
// observables
|
||||||
stateMap: observable,
|
stateMap: observable,
|
||||||
|
fetchedMap: observable,
|
||||||
// computed
|
// computed
|
||||||
projectStates: computed,
|
projectStates: computed,
|
||||||
groupedProjectStates: computed,
|
groupedProjectStates: computed,
|
||||||
@ -71,7 +76,8 @@ export class StateStore implements IStateStore {
|
|||||||
* Returns the stateMap belongs to a specific project
|
* Returns the stateMap belongs to a specific project
|
||||||
*/
|
*/
|
||||||
get projectStates() {
|
get projectStates() {
|
||||||
if (!this.router.query?.projectId) return;
|
const projectId = this.router.query?.projectId?.toString();
|
||||||
|
if (!projectId || !this.fetchedMap[projectId]) return;
|
||||||
return Object.values(this.stateMap).filter((state) => state.project === this.router.query.projectId);
|
return Object.values(this.stateMap).filter((state) => state.project === this.router.query.projectId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +103,10 @@ export class StateStore implements IStateStore {
|
|||||||
* @param projectId
|
* @param projectId
|
||||||
* @returns IState[]
|
* @returns IState[]
|
||||||
*/
|
*/
|
||||||
getProjectStates = (projectId: string) => Object.values(this.stateMap).filter((state) => state.project === projectId);
|
getProjectStates = (projectId: string) => {
|
||||||
|
if (!projectId || !this.fetchedMap[projectId]) return;
|
||||||
|
return Object.values(this.stateMap).filter((state) => state.project === projectId);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetches the stateMap of a project
|
* fetches the stateMap of a project
|
||||||
@ -111,6 +120,7 @@ export class StateStore implements IStateStore {
|
|||||||
statesResponse.forEach((state) => {
|
statesResponse.forEach((state) => {
|
||||||
set(this.stateMap, [state.id], state);
|
set(this.stateMap, [state.id], state);
|
||||||
});
|
});
|
||||||
|
set(this.fetchedMap, projectId, true);
|
||||||
});
|
});
|
||||||
return statesResponse;
|
return statesResponse;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user