mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
Merge branch 'refactor/mobx-store' of gurusainath:makeplane/plane into refactor/mobx-store
This commit is contained in:
commit
1ccd0a683b
@ -2,7 +2,7 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
# Module imports
|
||||
from .base import BaseSerializer
|
||||
from .base import BaseSerializer, DynamicBaseSerializer
|
||||
from .user import UserLiteSerializer
|
||||
from .project import ProjectLiteSerializer
|
||||
from .workspace import WorkspaceLiteSerializer
|
||||
@ -159,7 +159,7 @@ class ModuleLinkSerializer(BaseSerializer):
|
||||
return ModuleLink.objects.create(**validated_data)
|
||||
|
||||
|
||||
class ModuleSerializer(BaseSerializer):
|
||||
class ModuleSerializer(DynamicBaseSerializer):
|
||||
project_detail = ProjectLiteSerializer(read_only=True, source="project")
|
||||
lead_detail = UserLiteSerializer(read_only=True, source="lead")
|
||||
members_detail = UserLiteSerializer(read_only=True, many=True, source="members")
|
||||
|
@ -176,6 +176,7 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
|
||||
def list(self, request, slug, project_id):
|
||||
queryset = self.get_queryset()
|
||||
cycle_view = request.GET.get("cycle_view", "all")
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
||||
queryset = queryset.order_by("-is_favorite","-created_at")
|
||||
|
||||
@ -280,45 +281,10 @@ class CycleViewSet(WebhookMixin, BaseViewSet):
|
||||
)
|
||||
|
||||
return Response(data, status=status.HTTP_200_OK)
|
||||
|
||||
# Upcoming Cycles
|
||||
if cycle_view == "upcoming":
|
||||
queryset = queryset.filter(start_date__gt=timezone.now())
|
||||
return Response(
|
||||
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# Completed Cycles
|
||||
if cycle_view == "completed":
|
||||
queryset = queryset.filter(end_date__lt=timezone.now())
|
||||
return Response(
|
||||
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# Draft Cycles
|
||||
if cycle_view == "draft":
|
||||
queryset = queryset.filter(
|
||||
end_date=None,
|
||||
start_date=None,
|
||||
)
|
||||
|
||||
return Response(
|
||||
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# Incomplete Cycles
|
||||
if cycle_view == "incomplete":
|
||||
queryset = queryset.filter(
|
||||
Q(end_date__gte=timezone.now().date()) | Q(end_date__isnull=True),
|
||||
)
|
||||
return Response(
|
||||
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# If no matching view is found return all cycles
|
||||
return Response(
|
||||
CycleSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
cycles = CycleSerializer(queryset, many=True, fields=fields if fields else None).data
|
||||
cycle_dict = {str(cycle["id"]): cycle for cycle in cycles}
|
||||
return Response(cycle_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def create(self, request, slug, project_id):
|
||||
if (
|
||||
|
@ -152,6 +152,13 @@ class ModuleViewSet(WebhookMixin, BaseViewSet):
|
||||
serializer = ModuleSerializer(module)
|
||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
def list(self, request, slug, project_id):
|
||||
queryset = self.get_queryset()
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
modules = ModuleSerializer(queryset, many=True, fields=fields if fields else None).data
|
||||
modules_dict = {str(module["id"]): module for module in modules}
|
||||
return Response(modules_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def retrieve(self, request, slug, project_id, pk):
|
||||
queryset = self.get_queryset().get(pk=pk)
|
||||
|
@ -157,9 +157,10 @@ class PageViewSet(BaseViewSet):
|
||||
|
||||
def list(self, request, slug, project_id):
|
||||
queryset = self.get_queryset().filter(archived_at__isnull=True)
|
||||
return Response(
|
||||
PageSerializer(queryset, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
pages = PageSerializer(queryset, many=True, fields=fields if fields else None).data
|
||||
pages_dict = {str(page["id"]): page for page in pages}
|
||||
return Response(pages_dict, status=status.HTTP_200_OK)
|
||||
|
||||
def archive(self, request, slug, project_id, page_id):
|
||||
page = Page.objects.get(pk=page_id, workspace__slug=slug, project_id=project_id)
|
||||
@ -205,14 +206,16 @@ class PageViewSet(BaseViewSet):
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
def archive_list(self, request, slug, project_id):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
pages = Page.objects.filter(
|
||||
project_id=project_id,
|
||||
workspace__slug=slug,
|
||||
).filter(archived_at__isnull=False)
|
||||
|
||||
return Response(
|
||||
PageSerializer(pages, many=True).data, status=status.HTTP_200_OK
|
||||
)
|
||||
pages = PageSerializer(pages, many=True, fields=fields if fields else None).data
|
||||
pages_dict = {str(page["id"]): page for page in pages}
|
||||
return Response(pages_dict, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
def destroy(self, request, slug, project_id, pk):
|
||||
page = Page.objects.get(pk=pk, workspace__slug=slug, project_id=project_id)
|
||||
|
@ -179,12 +179,10 @@ class ProjectViewSet(WebhookMixin, BaseViewSet):
|
||||
projects, many=True
|
||||
).data,
|
||||
)
|
||||
projects = ProjectListSerializer(projects, many=True, fields=fields if fields else None).data
|
||||
project_dict = {str(project["id"]): project for project in projects}
|
||||
return Response(project_dict, status=status.HTTP_200_OK)
|
||||
|
||||
return Response(
|
||||
ProjectListSerializer(
|
||||
projects, many=True, fields=fields if fields else None
|
||||
).data
|
||||
)
|
||||
|
||||
def create(self, request, slug):
|
||||
try:
|
||||
|
@ -75,6 +75,7 @@ from plane.bgtasks.workspace_invitation_task import workspace_invitation
|
||||
from plane.utils.issue_filters import issue_filters
|
||||
from plane.bgtasks.event_tracking_task import workspace_invite_event
|
||||
|
||||
|
||||
class WorkSpaceViewSet(BaseViewSet):
|
||||
model = Workspace
|
||||
serializer_class = WorkSpaceSerializer
|
||||
@ -172,6 +173,7 @@ class UserWorkSpacesEndpoint(BaseAPIView):
|
||||
]
|
||||
|
||||
def get(self, request):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
member_count = (
|
||||
WorkspaceMember.objects.filter(
|
||||
workspace=OuterRef("id"),
|
||||
@ -207,9 +209,13 @@ class UserWorkSpacesEndpoint(BaseAPIView):
|
||||
)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
serializer = WorkSpaceSerializer(self.filter_queryset(workspace), many=True)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
workspaces = WorkSpaceSerializer(
|
||||
self.filter_queryset(workspace),
|
||||
fields=fields if fields else None,
|
||||
many=True,
|
||||
).data
|
||||
workspace_dict = {str(workspaces["id"]): workspaces for workspace in workspaces}
|
||||
return Response(workspace_dict, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
class WorkSpaceAvailabilityCheckEndpoint(BaseAPIView):
|
||||
@ -406,7 +412,7 @@ class WorkspaceJoinEndpoint(BaseAPIView):
|
||||
|
||||
# Delete the invitation
|
||||
workspace_invite.delete()
|
||||
|
||||
|
||||
# Send event
|
||||
workspace_invite_event.delay(
|
||||
user=user.id if user is not None else None,
|
||||
|
@ -132,7 +132,7 @@ export class ModuleService extends APIService {
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
data: ModuleLink
|
||||
data: Partial<ModuleLink>
|
||||
): Promise<ILinkDetails> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/`, data)
|
||||
.then((response) => response?.data)
|
||||
@ -146,7 +146,7 @@ export class ModuleService extends APIService {
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
linkId: string,
|
||||
data: ModuleLink
|
||||
data: Partial<ModuleLink>
|
||||
): Promise<ILinkDetails> {
|
||||
return this.patch(
|
||||
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`,
|
||||
|
@ -50,6 +50,14 @@ export class PageService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getProjectPages(workspaceSlug: string, projectId: string) {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/pages/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getPagesWithParams(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { action, computed, makeObservable, observable } from "mobx";
|
||||
import { ParsedUrlQuery } from "querystring";
|
||||
import { action, makeObservable, observable, computed } from "mobx";
|
||||
import { ParsedUrlQuery } from "node:querystring";
|
||||
|
||||
export interface IRouterStore {
|
||||
query: ParsedUrlQuery;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { action, computed, observable, makeObservable, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
// types
|
||||
import { ICycle, TCycleView, CycleDateCheckData } from "types";
|
||||
// mobx
|
||||
@ -87,8 +88,8 @@ export class CycleStore implements ICycleStore {
|
||||
error: observable.ref,
|
||||
|
||||
cycleId: observable.ref,
|
||||
cycleMap: observable.ref,
|
||||
cycles: observable.ref,
|
||||
cycleMap: observable,
|
||||
cycles: observable,
|
||||
|
||||
// computed
|
||||
projectCycles: computed,
|
||||
@ -118,14 +119,14 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
// computed
|
||||
get projectCycles() {
|
||||
const projectId = this.rootStore.project.projectId;
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return null;
|
||||
return this.cycles[projectId]?.all || null;
|
||||
}
|
||||
|
||||
get projectCompletedCycles() {
|
||||
const projectId = this.rootStore.project.projectId;
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return null;
|
||||
|
||||
@ -133,7 +134,7 @@ export class CycleStore implements ICycleStore {
|
||||
}
|
||||
|
||||
get projectUpcomingCycles() {
|
||||
const projectId = this.rootStore.project.projectId;
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return null;
|
||||
|
||||
@ -141,18 +142,22 @@ export class CycleStore implements ICycleStore {
|
||||
}
|
||||
|
||||
get projectDraftCycles() {
|
||||
const projectId = this.rootStore.project.projectId;
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return null;
|
||||
|
||||
return this.cycles[projectId]?.draft || null;
|
||||
}
|
||||
|
||||
getCycleById = (cycleId: string) => this.cycleMap[this.rootStore.project][cycleId] || null;
|
||||
getCycleById = (cycleId: string) => {
|
||||
const projectId = this.rootStore.app.router.projectId;
|
||||
|
||||
if (!projectId) return null;
|
||||
|
||||
return this.cycleMap?.[projectId]?.[cycleId] || null;
|
||||
};
|
||||
|
||||
// actions
|
||||
setCycleView = (_cycleView: TCycleView) => (this.cycleView = _cycleView);
|
||||
|
||||
validateDate = async (workspaceSlug: string, projectId: string, payload: CycleDateCheckData) => {
|
||||
try {
|
||||
const response = await this.cycleService.cycleDateCheck(workspaceSlug, projectId, payload);
|
||||
@ -174,18 +179,12 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectId, params);
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId], cyclesResponse);
|
||||
const _cycles = set(this.cycles, [projectId, params], Object.keys(cyclesResponse));
|
||||
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
...cyclesResponse,
|
||||
},
|
||||
};
|
||||
this.cycles = {
|
||||
...this.cycles,
|
||||
[projectId]: { ...this.cycles[projectId], [params]: Object.keys(cyclesResponse) },
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
this.cycles = _cycles;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -200,14 +199,9 @@ export class CycleStore implements ICycleStore {
|
||||
try {
|
||||
const response = await this.cycleService.getCycleDetails(workspaceSlug, projectId, cycleId);
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, response?.id], response);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[response?.id]: response,
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -221,14 +215,9 @@ export class CycleStore implements ICycleStore {
|
||||
try {
|
||||
const response = await this.cycleService.createCycle(workspaceSlug, projectId, data);
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, response?.id], response);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[response?.id]: response,
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
const _currentView = this.cycleView === "active" ? "current" : this.cycleView;
|
||||
@ -247,14 +236,9 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
const currentCycle = this.cycleMap[projectId][cycleId];
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, cycleId], { ...currentCycle, ...data });
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[cycleId]: { ...currentCycle, ...data },
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
const _currentView = this.cycleView === "active" ? "current" : this.cycleView;
|
||||
@ -272,11 +256,9 @@ export class CycleStore implements ICycleStore {
|
||||
const currentProjectCycles = this.cycleMap[projectId];
|
||||
delete currentProjectCycles[cycleId];
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId], currentProjectCycles);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: currentProjectCycles,
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
const _response = await this.cycleService.deleteCycle(workspaceSlug, projectId, cycleId);
|
||||
@ -294,17 +276,11 @@ export class CycleStore implements ICycleStore {
|
||||
addCycleToFavorites = async (workspaceSlug: string, projectId: string, cycleId: string) => {
|
||||
try {
|
||||
const currentCycle = this.cycleMap[projectId][cycleId];
|
||||
|
||||
if (currentCycle.is_favorite) return;
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, cycleId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[cycleId]: { ...currentCycle, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
// updating through api.
|
||||
@ -315,16 +291,9 @@ export class CycleStore implements ICycleStore {
|
||||
console.log("Failed to add cycle to favorites in the cycles store", error);
|
||||
|
||||
// reset on error
|
||||
const currentCycle = this.cycleMap[projectId][cycleId];
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, cycleId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[cycleId]: { ...currentCycle, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
throw error;
|
||||
@ -337,14 +306,9 @@ export class CycleStore implements ICycleStore {
|
||||
|
||||
if (!currentCycle.is_favorite) return;
|
||||
|
||||
const _cycleMap = set(this.cycleMap, [projectId, cycleId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[cycleId]: { ...currentCycle, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
const response = await this.cycleService.removeCycleFromFavorites(workspaceSlug, projectId, cycleId);
|
||||
@ -354,16 +318,11 @@ export class CycleStore implements ICycleStore {
|
||||
console.log("Failed to remove cycle from favorites - Cycle Store", error);
|
||||
|
||||
// reset on error
|
||||
const currentCycle = this.cycleMap[projectId][cycleId];
|
||||
const _cycleMap = set(this.cycleMap, [projectId, cycleId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.cycleMap = {
|
||||
...this.cycleMap,
|
||||
[projectId]: {
|
||||
...this.cycleMap[projectId],
|
||||
[cycleId]: { ...currentCycle, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.cycleMap = _cycleMap;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { makeObservable, observable, action, runInAction, computed } from "mobx";
|
||||
import keyBy from "lodash/keyBy";
|
||||
import omit from "lodash/omit";
|
||||
import set from "lodash/set";
|
||||
// services
|
||||
import { IssueLabelService } from "services/issue";
|
||||
// types
|
||||
@ -11,7 +11,7 @@ import { buildTree } from "helpers/array.helper";
|
||||
import { RootStore } from "./root.store";
|
||||
|
||||
export interface ILabelStore {
|
||||
labels: Record<string, IIssueLabel>;
|
||||
labelMap: Record<string, IIssueLabel>;
|
||||
projectLabels: IIssueLabel[] | undefined;
|
||||
projectLabelsTree: IIssueLabelTree[] | undefined;
|
||||
fetchProjectLabels: (workspaceSlug: string, projectId: string) => Promise<IIssueLabel[]>;
|
||||
@ -35,14 +35,14 @@ export interface ILabelStore {
|
||||
}
|
||||
|
||||
export class LabelStore {
|
||||
labels: Record<string, IIssueLabel> = {};
|
||||
labelMap: Record<string, IIssueLabel> = {};
|
||||
issueLabelService;
|
||||
router;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observables
|
||||
labels: observable.ref,
|
||||
labelMap: observable,
|
||||
// computed
|
||||
projectLabels: computed,
|
||||
projectLabelsTree: computed,
|
||||
@ -57,15 +57,15 @@ export class LabelStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the labels belongs to a specific project
|
||||
* Returns the labelMap belongs to a specific project
|
||||
*/
|
||||
get projectLabels() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
return Object.values(this.labels).filter((label) => label.project === this.router.query.projectId);
|
||||
return Object.values(this.labelMap).filter((label) => label.project === this.router.query.projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the labels in a tree format
|
||||
* Returns the labelMap in a tree format
|
||||
*/
|
||||
get projectLabelsTree() {
|
||||
if (!this.projectLabels) return;
|
||||
@ -73,7 +73,7 @@ export class LabelStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all the labels belongs to a specific project
|
||||
* Fetches all the labelMap belongs to a specific project
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @returns Promise<IIssueLabel[]>
|
||||
@ -81,8 +81,9 @@ export class LabelStore {
|
||||
fetchProjectLabels = async (workspaceSlug: string, projectId: string) => {
|
||||
const response = await this.issueLabelService.getProjectIssueLabels(workspaceSlug, projectId);
|
||||
runInAction(() => {
|
||||
this.labels = {
|
||||
...this.labels,
|
||||
//todo add iteratively without modifying original reference
|
||||
this.labelMap = {
|
||||
...this.labelMap,
|
||||
...keyBy(response, "id"),
|
||||
};
|
||||
});
|
||||
@ -98,11 +99,10 @@ export class LabelStore {
|
||||
*/
|
||||
createLabel = async (workspaceSlug: string, projectId: string, data: Partial<IIssueLabel>) => {
|
||||
const response = await this.issueLabelService.createIssueLabel(workspaceSlug, projectId, data);
|
||||
|
||||
const _labelMap = set(this.labelMap, [response.id], response);
|
||||
runInAction(() => {
|
||||
this.labels = {
|
||||
...this.labels,
|
||||
[response.id]: response,
|
||||
};
|
||||
this.labelMap = _labelMap;
|
||||
});
|
||||
return response;
|
||||
};
|
||||
@ -116,22 +116,22 @@ export class LabelStore {
|
||||
* @returns Promise<IIssueLabel>
|
||||
*/
|
||||
updateLabel = async (workspaceSlug: string, projectId: string, labelId: string, data: Partial<IIssueLabel>) => {
|
||||
const originalLabel = this.labels[labelId];
|
||||
const originalLabel = this.labelMap[labelId];
|
||||
try {
|
||||
const _labelMap = set(this.labelMap, [labelId], { ...this.labelMap[labelId], ...data });
|
||||
runInAction(() => {
|
||||
this.labels = {
|
||||
...this.labels,
|
||||
[labelId]: { ...this.labels[labelId], ...data },
|
||||
};
|
||||
this.labelMap = _labelMap;
|
||||
});
|
||||
|
||||
const response = await this.issueLabelService.patchIssueLabel(workspaceSlug, projectId, labelId, data);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to update label from project store");
|
||||
const _labelMap = set(this.labelMap, [labelId], { ...this.labelMap[labelId], ...data });
|
||||
runInAction(() => {
|
||||
this.labels = {
|
||||
...this.labels,
|
||||
[labelId]: { ...this.labels[labelId], ...originalLabel },
|
||||
this.labelMap = {
|
||||
...this.labelMap,
|
||||
[labelId]: { ...this.labelMap[labelId], ...originalLabel },
|
||||
};
|
||||
});
|
||||
throw error;
|
||||
@ -158,7 +158,7 @@ export class LabelStore {
|
||||
isSameParent: boolean,
|
||||
prevIndex: number | undefined
|
||||
) => {
|
||||
const currLabel = this.labels?.[labelId];
|
||||
const currLabel = this.labelMap?.[labelId];
|
||||
const labelTree = this.projectLabelsTree;
|
||||
|
||||
let currentArray: IIssueLabel[];
|
||||
@ -189,7 +189,7 @@ export class LabelStore {
|
||||
|
||||
let sortOrder: number;
|
||||
|
||||
//based on the next and previous labels calculate current sort order
|
||||
//based on the next and previous labelMap calculate current sort order
|
||||
if (prevSortOrder && nextSortOrder) {
|
||||
sortOrder = (prevSortOrder + nextSortOrder) / 2;
|
||||
} else if (nextSortOrder) {
|
||||
@ -205,27 +205,29 @@ export class LabelStore {
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the label from the project and remove it from the labels object
|
||||
* Delete the label from the project and remove it from the labelMap object
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param labelId
|
||||
*/
|
||||
deleteLabel = async (workspaceSlug: string, projectId: string, labelId: string) => {
|
||||
const originalLabel = this.labels[labelId];
|
||||
runInAction(() => {
|
||||
this.labels = omit(this.labels, labelId);
|
||||
});
|
||||
const originalLabel = this.labelMap[labelId];
|
||||
|
||||
try {
|
||||
const _labelMap = this.labelMap;
|
||||
delete _labelMap[labelId];
|
||||
runInAction(() => {
|
||||
this.labelMap = _labelMap;
|
||||
});
|
||||
|
||||
// deleting using api
|
||||
await this.issueLabelService.deleteIssueLabel(workspaceSlug, projectId, labelId);
|
||||
} catch (error) {
|
||||
console.log("Failed to delete label from project store");
|
||||
// reverting back to original label list
|
||||
const labelMap = set(this.labelMap, [labelId], originalLabel);
|
||||
runInAction(() => {
|
||||
this.labels = {
|
||||
...this.labels,
|
||||
[labelId]: originalLabel,
|
||||
};
|
||||
this.labelMap = labelMap;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { action, computed, observable, makeObservable, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
// services
|
||||
import { ProjectService } from "services/project";
|
||||
import { ModuleService } from "services/module.service";
|
||||
@ -79,12 +80,12 @@ export class ModulesStore implements IModuleStore {
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// states
|
||||
loader: observable,
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
|
||||
// observables
|
||||
moduleId: observable.ref,
|
||||
moduleMap: observable.ref,
|
||||
moduleMap: observable,
|
||||
|
||||
// actions
|
||||
getModuleById: action,
|
||||
@ -116,12 +117,16 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
// computed
|
||||
get projectModules() {
|
||||
if (!this.rootStore.project.projectId) return null;
|
||||
if (!this.rootStore.app.router.projectId) return null;
|
||||
|
||||
return Object.keys(this.moduleMap[this.rootStore.project.projectId]) || null;
|
||||
return Object.keys(this.moduleMap[this.rootStore.app.router.projectId]) || null;
|
||||
}
|
||||
|
||||
getModuleById = (moduleId: string) => this.moduleMap[this.rootStore.project.projectId][moduleId] || null;
|
||||
getModuleById = (moduleId: string) => {
|
||||
if (!this.rootStore.app.router.projectId) return null;
|
||||
|
||||
return this.moduleMap?.[this.rootStore.app.router.projectId]?.[moduleId] || null;
|
||||
};
|
||||
|
||||
// actions
|
||||
|
||||
@ -134,11 +139,9 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectId);
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId], modulesResponse);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: modulesResponse,
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -161,14 +164,9 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
const response = await this.moduleService.getModuleDetails(workspaceSlug, projectId, moduleId);
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId], response);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: response,
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -190,14 +188,9 @@ export class ModulesStore implements IModuleStore {
|
||||
try {
|
||||
const response = await this.moduleService.createModule(workspaceSlug, projectId, data);
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, response?.id], response);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[response.id]: response,
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -219,14 +212,9 @@ export class ModulesStore implements IModuleStore {
|
||||
try {
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId], { ...currentModule, ...data });
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, ...data },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
const response = await this.moduleService.patchModule(workspaceSlug, projectId, moduleId, data);
|
||||
@ -251,11 +239,9 @@ export class ModulesStore implements IModuleStore {
|
||||
const currentProjectModules = this.moduleMap[projectId];
|
||||
delete currentProjectModules[moduleId];
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId], currentProjectModules);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: currentProjectModules,
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
await this.moduleService.deleteModule(workspaceSlug, projectId, moduleId);
|
||||
@ -281,14 +267,13 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
|
||||
const _moduleMap = set(
|
||||
this.moduleMap,
|
||||
[projectId, moduleId, "link_module"],
|
||||
[response, ...currentModule.link_module]
|
||||
);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, link_module: [response, ...currentModule.link_module] },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -319,14 +304,9 @@ export class ModulesStore implements IModuleStore {
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
const linkModules = currentModule.link_module.map((link) => (link.id === linkId ? response : link));
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "link_module"], linkModules);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, link_module: linkModules },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -349,14 +329,9 @@ export class ModulesStore implements IModuleStore {
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
const linkModules = currentModule.link_module.filter((link) => link.id !== linkId);
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "link_module"], linkModules);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, link_module: linkModules },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
await this.moduleService.deleteModuleLink(workspaceSlug, projectId, moduleId, linkId);
|
||||
@ -380,14 +355,9 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
if (currentModule.is_favorite) return;
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
await this.moduleService.addModuleToFavorites(workspaceSlug, projectId, {
|
||||
@ -396,16 +366,9 @@ export class ModulesStore implements IModuleStore {
|
||||
} catch (error) {
|
||||
console.error("Failed to add module to favorites in module store", error);
|
||||
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -416,30 +379,18 @@ export class ModulesStore implements IModuleStore {
|
||||
|
||||
if (!currentModule.is_favorite) return;
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
|
||||
await this.moduleService.removeModuleFromFavorites(workspaceSlug, projectId, moduleId);
|
||||
} catch (error) {
|
||||
console.error("Failed to remove module from favorites in module store", error);
|
||||
|
||||
const currentModule = this.moduleMap[projectId][moduleId];
|
||||
|
||||
const _moduleMap = set(this.moduleMap, [projectId, moduleId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.moduleMap = {
|
||||
...this.moduleMap,
|
||||
[projectId]: {
|
||||
...this.moduleMap[projectId],
|
||||
[moduleId]: { ...currentModule, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.moduleMap = _moduleMap;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
234
web/store/page.store.ts
Normal file
234
web/store/page.store.ts
Normal file
@ -0,0 +1,234 @@
|
||||
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||
import keyBy from "lodash/keyBy";
|
||||
import set from "lodash/set";
|
||||
import isToday from "date-fns/isToday";
|
||||
import isThisWeek from "date-fns/isThisWeek";
|
||||
import isYesterday from "date-fns/isYesterday";
|
||||
// services
|
||||
import { PageService } from "services/page.service";
|
||||
// types
|
||||
import { IPage, IRecentPages } from "types";
|
||||
// store
|
||||
import { RootStore } from "./root.store";
|
||||
|
||||
export interface IPageStore {
|
||||
pages: Record<string, IPage>;
|
||||
archivedPages: Record<string, IPage>;
|
||||
|
||||
projectPages: IPage[] | undefined;
|
||||
favoriteProjectPages: IPage[] | undefined;
|
||||
privateProjectPages: IPage[] | undefined;
|
||||
sharedProjectPages: IPage[] | undefined;
|
||||
|
||||
fetchProjectPages: (workspaceSlug: string, projectId: string) => Promise<IPage[]>;
|
||||
}
|
||||
|
||||
export class PageStore {
|
||||
pages: Record<string, IPage> = {};
|
||||
archivedPages: Record<string, IPage> = {};
|
||||
// services
|
||||
pageService;
|
||||
// stores
|
||||
router;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
pages: observable,
|
||||
archivedPages: observable,
|
||||
// computed
|
||||
projectPages: computed,
|
||||
favoriteProjectPages: computed,
|
||||
sharedProjectPages: computed,
|
||||
privateProjectPages: computed,
|
||||
// actions
|
||||
fetchProjectPages: action,
|
||||
});
|
||||
// stores
|
||||
this.router = _rootStore.app.router;
|
||||
// services
|
||||
this.pageService = new PageService();
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all pages for a projectId that is available in the url.
|
||||
*/
|
||||
get projectPages() {
|
||||
if (!this.router.projectId) return;
|
||||
return Object.values(this.pages).filter((page) => page.project === this.router.query.projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all favorite pages for a projectId that is available in the url.
|
||||
*/
|
||||
get favoriteProjectPages() {
|
||||
if (!this.projectPages) return;
|
||||
return this.projectPages.filter((page) => page.is_favorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all private pages for a projectId that is available in the url.
|
||||
*/
|
||||
get privateProjectPages() {
|
||||
if (!this.projectPages) return;
|
||||
return this.projectPages.filter((page) => page.access === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all shared pages which are public to everyone in the project for a projectId that is available in the url.
|
||||
*/
|
||||
get sharedProjectPages() {
|
||||
if (!this.projectPages) return;
|
||||
return this.projectPages.filter((page) => page.access === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all recent pages for a projectId that is available in the url.
|
||||
* In format where today, yesterday, this_week, older are keys.
|
||||
*/
|
||||
get recentProjectPages() {
|
||||
if (!this.projectPages) return;
|
||||
const data: IRecentPages = { today: [], yesterday: [], this_week: [], older: [] };
|
||||
data.today = this.projectPages.filter((p) => isToday(new Date(p.created_at))) || [];
|
||||
data.yesterday = this.projectPages.filter((p) => isYesterday(new Date(p.created_at))) || [];
|
||||
data.this_week =
|
||||
this.projectPages.filter(
|
||||
(p) =>
|
||||
isThisWeek(new Date(p.created_at)) && !isToday(new Date(p.created_at)) && !isYesterday(new Date(p.created_at))
|
||||
) || [];
|
||||
data.older =
|
||||
this.projectPages.filter((p) => !isThisWeek(new Date(p.created_at)) && !isYesterday(new Date(p.created_at))) ||
|
||||
[];
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieves all archived pages for a projectId that is available in the url.
|
||||
*/
|
||||
get archivedProjectPages() {
|
||||
if (!this.router.projectId) return;
|
||||
return Object.values(this.archivedPages).filter((page) => page.project === this.router.projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all pages for a project.
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @returns Promise<IPage[]>
|
||||
*/
|
||||
async fetchProjectPages(workspaceSlug: string, projectId: string) {
|
||||
const response = await this.pageService.getProjectPages(workspaceSlug, projectId);
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
...keyBy(response, "id"),
|
||||
};
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all archived pages for a project.
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @returns Promise<IPage[]>
|
||||
*/
|
||||
async fetchArchivedProjectPages(workspaceSlug: string, projectId: string) {
|
||||
const response = await this.pageService.getArchivedPages(workspaceSlug, projectId);
|
||||
runInAction(() => {
|
||||
this.archivedPages = {
|
||||
...this.archivedPages,
|
||||
...keyBy(response, "id"),
|
||||
};
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Page to users favorites list
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param pageId
|
||||
*/
|
||||
addToFavorites = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[pageId]: { ...this.pages[pageId], is_favorite: true },
|
||||
};
|
||||
});
|
||||
await this.pageService.addPageToFavorites(workspaceSlug, projectId, pageId);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[pageId]: { ...this.pages[pageId], is_favorite: false },
|
||||
};
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove page from the users favorites list
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param pageId
|
||||
*/
|
||||
removeFromFavorites = async (workspaceSlug: string, projectId: string, pageId: string) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[pageId]: { ...this.pages[pageId], is_favorite: false },
|
||||
};
|
||||
});
|
||||
await this.pageService.removePageFromFavorites(workspaceSlug, projectId, pageId);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[pageId]: { ...this.pages[pageId], is_favorite: true },
|
||||
};
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new page using the api and updated the local state in store
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param data
|
||||
*/
|
||||
createPage = async (workspaceSlug: string, projectId: string, data: Partial<IPage>) => {
|
||||
const response = await this.pageService.createPage(workspaceSlug, projectId, data);
|
||||
runInAction(() => {
|
||||
this.pages = set(this.pages, [response.id], response);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* updates the page using the api and updates the local state in store
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @param pageId
|
||||
* @param data
|
||||
* @returns
|
||||
*/
|
||||
updatePage = async (workspaceSlug: string, projectId: string, pageId: string, data: Partial<IPage>) => {
|
||||
const originalPage = this.pages[pageId];
|
||||
try {
|
||||
runInAction(() => {
|
||||
this.pages[pageId] = { ...originalPage, ...data };
|
||||
});
|
||||
const response = await this.pageService.patchPage(workspaceSlug, projectId, pageId, data);
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.pages[pageId] = originalPage;
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import set from "lodash/set";
|
||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
||||
// services
|
||||
import { ViewService } from "services/view.service";
|
||||
@ -60,7 +61,7 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
// observables
|
||||
viewId: observable.ref,
|
||||
viewMap: observable.ref,
|
||||
viewMap: observable,
|
||||
|
||||
// actions
|
||||
fetchViews: action,
|
||||
@ -89,12 +90,10 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
const response = await this.viewService.getViews(workspaceSlug, projectId);
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId], response);
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: response,
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -116,15 +115,10 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
const response = await this.viewService.getViewDetails(workspaceSlug, projectId, viewId);
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId], response);
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[response.id]: response,
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -142,15 +136,10 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
try {
|
||||
const response = await this.viewService.createView(workspaceSlug, projectId, data);
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId, response.id], response);
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[response.id]: response,
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
@ -172,14 +161,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
try {
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId], { ...currentView, ...data });
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[viewId]: { ...currentView, ...data },
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
const response = await this.viewService.patchView(workspaceSlug, projectId, viewId, data);
|
||||
@ -201,11 +185,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
const currentProjectViews = this.viewMap[projectId];
|
||||
delete currentProjectViews[viewId];
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId], currentProjectViews);
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: currentProjectViews,
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
await this.viewService.deleteView(workspaceSlug, projectId, viewId);
|
||||
@ -226,14 +208,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
if (currentView.is_favorite) return;
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[viewId]: { ...currentView, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
await this.viewService.addViewToFavorites(workspaceSlug, projectId, {
|
||||
@ -242,15 +219,9 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
} catch (error) {
|
||||
console.error("Failed to add view to favorites in view store", error);
|
||||
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[viewId]: { ...currentView, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -261,29 +232,18 @@ export class ProjectViewsStore implements IProjectViewsStore {
|
||||
|
||||
if (!currentView.is_favorite) return;
|
||||
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[viewId]: { ...currentView, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
|
||||
await this.viewService.removeViewFromFavorites(workspaceSlug, projectId, viewId);
|
||||
} catch (error) {
|
||||
console.error("Failed to remove view from favorites in view store", error);
|
||||
|
||||
const currentView = this.viewMap[projectId][viewId];
|
||||
const _viewMap = set(this.viewMap, [projectId, viewId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.viewMap = {
|
||||
...this.viewMap,
|
||||
[projectId]: {
|
||||
...this.viewMap[projectId],
|
||||
[viewId]: { ...currentView, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.viewMap = _viewMap;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { observable, action, makeObservable, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
// types
|
||||
import { ProjectRootStore } from "./";
|
||||
// services
|
||||
@ -57,12 +58,12 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
constructor(_projectRootStore: ProjectRootStore) {
|
||||
makeObservable(this, {
|
||||
// states
|
||||
generalLoader: observable,
|
||||
fetchSettingsLoader: observable,
|
||||
error: observable,
|
||||
generalLoader: observable.ref,
|
||||
fetchSettingsLoader: observable.ref,
|
||||
error: observable.ref,
|
||||
|
||||
// observables
|
||||
project_id: observable,
|
||||
project_id: observable.ref,
|
||||
projectPublishSettings: observable.ref,
|
||||
|
||||
// actions
|
||||
@ -147,18 +148,14 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
project: response?.project || null,
|
||||
};
|
||||
|
||||
const _projectMap = set(
|
||||
this.projectRootStore.projects.projectMap,
|
||||
[workspaceSlug, projectId, "is_deployed"],
|
||||
true
|
||||
);
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = _projectPublishSettings;
|
||||
this.projectRootStore.projects.projectsMap = {
|
||||
...this.projectRootStore.projects.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectRootStore.projects.projectsMap[workspaceSlug],
|
||||
[projectId]: {
|
||||
...this.projectRootStore.projects.projectsMap[workspaceSlug][projectId],
|
||||
is_deployed: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
this.projectRootStore.projects.projectMap = _projectMap;
|
||||
this.generalLoader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -236,18 +233,14 @@ export class ProjectPublishStore implements IProjectPublishStore {
|
||||
projectPublishId
|
||||
);
|
||||
|
||||
const _projectMap = set(
|
||||
this.projectRootStore.projects.projectMap,
|
||||
[workspaceSlug, projectId, "is_deployed"],
|
||||
false
|
||||
);
|
||||
runInAction(() => {
|
||||
this.projectPublishSettings = "not-initialized";
|
||||
this.projectRootStore.projects.projectsMap = {
|
||||
...this.projectRootStore.projects.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectRootStore.projects.projectsMap[workspaceSlug],
|
||||
[projectId]: {
|
||||
...this.projectRootStore.projects.projectsMap[workspaceSlug][projectId],
|
||||
is_deployed: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
this.projectRootStore.projects.projectMap = _projectMap;
|
||||
this.generalLoader = false;
|
||||
this.error = null;
|
||||
});
|
||||
|
@ -1,9 +1,11 @@
|
||||
import set from "lodash/set";
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
//types
|
||||
import { RootStore } from "../root.store";
|
||||
import { IProject } from "types";
|
||||
//services
|
||||
import { IssueLabelService, IssueService } from "services/issue";
|
||||
import { ProjectService, ProjectStateService } from "services/project";
|
||||
import { RootStore } from "store/root.store";
|
||||
|
||||
import { IProject } from "types";
|
||||
|
||||
export interface IProjectsStore {
|
||||
loader: boolean;
|
||||
@ -11,7 +13,7 @@ export interface IProjectsStore {
|
||||
|
||||
searchQuery: string;
|
||||
projectId: string | null;
|
||||
projectsMap: {
|
||||
projectMap: {
|
||||
[workspaceSlug: string]: {
|
||||
[projectId: string]: IProject; // projectId: project Info
|
||||
};
|
||||
@ -48,11 +50,11 @@ export class ProjectsStore implements IProjectsStore {
|
||||
|
||||
projectId: string | null = null;
|
||||
searchQuery: string = "";
|
||||
projectsMap: {
|
||||
projectMap: {
|
||||
[workspaceSlug: string]: {
|
||||
[projectId: string]: IProject; // projectId: project Info
|
||||
};
|
||||
};
|
||||
} = {};
|
||||
|
||||
// root store
|
||||
rootStore: RootStore;
|
||||
@ -65,12 +67,12 @@ export class ProjectsStore implements IProjectsStore {
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
loader: observable.ref,
|
||||
error: observable.ref,
|
||||
|
||||
searchQuery: observable.ref,
|
||||
projectId: observable.ref,
|
||||
projectsMap: observable.ref,
|
||||
projectMap: observable,
|
||||
|
||||
// computed
|
||||
searchedProjects: computed,
|
||||
@ -104,48 +106,48 @@ export class ProjectsStore implements IProjectsStore {
|
||||
}
|
||||
|
||||
get searchedProjects() {
|
||||
if (!this.rootStore.app.router.query.workspaceSlug) return [];
|
||||
if (!this.rootStore.app.router.workspaceSlug) return [];
|
||||
|
||||
const currentProjectsMap = this.projectsMap[this.rootStore.app.router.query.workspaceSlug.toString()];
|
||||
const projectIds = Object.keys(currentProjectsMap);
|
||||
const currentProjectMap = this.projectMap[this.rootStore.app.router.workspaceSlug];
|
||||
const projectIds = Object.keys(currentProjectMap);
|
||||
return this.searchQuery === ""
|
||||
? projectIds
|
||||
: projectIds?.filter((projectId) => {
|
||||
currentProjectsMap[projectId].name.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
|
||||
currentProjectsMap[projectId].identifier.toLowerCase().includes(this.searchQuery.toLowerCase());
|
||||
currentProjectMap[projectId].name.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
|
||||
currentProjectMap[projectId].identifier.toLowerCase().includes(this.searchQuery.toLowerCase());
|
||||
});
|
||||
}
|
||||
|
||||
get workspaceProjects() {
|
||||
if (!this.rootStore.app.router.workspaceSlug) return null;
|
||||
const currentProjectsMap = this.projectsMap[this.rootStore.app.router.query.workspaceSlug.toString()];
|
||||
const currentProjectMap = this.projectMap[this.rootStore.app.router.workspaceSlug];
|
||||
|
||||
const projectIds = Object.keys(currentProjectsMap);
|
||||
const projectIds = Object.keys(currentProjectMap);
|
||||
if (!projectIds) return null;
|
||||
return projectIds;
|
||||
}
|
||||
|
||||
get currentProjectDetails() {
|
||||
if (!this.rootStore.app.router.query.projectId || !this.rootStore.app.router.query.workspaceSlug) return;
|
||||
return this.projectsMap[!this.rootStore.app.router.query.workspaceSlug][this.projectId];
|
||||
if (!this.rootStore.app.router.projectId || !this.rootStore.app.router.workspaceSlug) return;
|
||||
return this.projectMap[this.rootStore.app.router.workspaceSlug][this.rootStore.app.router.projectId];
|
||||
}
|
||||
|
||||
get joinedProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
if (!this.rootStore.app.router.workspaceSlug) return [];
|
||||
|
||||
const currentProjectsMap = this.projectsMap[this.rootStore.workspace.workspaceSlug];
|
||||
const projectIds = Object.keys(currentProjectsMap);
|
||||
const currentProjectMap = this.projectMap[this.rootStore.app.router.workspaceSlug];
|
||||
const projectIds = Object.keys(currentProjectMap);
|
||||
|
||||
return projectIds?.filter((projectId) => currentProjectsMap[projectId].is_member);
|
||||
return projectIds?.filter((projectId) => currentProjectMap[projectId].is_member);
|
||||
}
|
||||
|
||||
get favoriteProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
if (!this.rootStore.app.router.workspaceSlug) return [];
|
||||
|
||||
const currentProjectsMap = this.projectsMap[this.rootStore.workspace.workspaceSlug];
|
||||
const projectIds = Object.keys(currentProjectsMap);
|
||||
const currentProjectMap = this.projectMap[this.rootStore.app.router.workspaceSlug];
|
||||
const projectIds = Object.keys(currentProjectMap);
|
||||
|
||||
return projectIds?.filter((projectId) => currentProjectsMap[projectId].is_favorite);
|
||||
return projectIds?.filter((projectId) => currentProjectMap[projectId].is_favorite);
|
||||
}
|
||||
|
||||
setSearchQuery = (query: string) => {
|
||||
@ -160,12 +162,11 @@ export class ProjectsStore implements IProjectsStore {
|
||||
*/
|
||||
fetchProjects = async (workspaceSlug: string) => {
|
||||
try {
|
||||
const currentProjectsMap = await this.projectService.getProjects(workspaceSlug);
|
||||
const currentProjectMap = await this.projectService.getProjects(workspaceSlug);
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug], currentProjectMap);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: currentProjectsMap,
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch project from workspace store");
|
||||
@ -177,14 +178,9 @@ export class ProjectsStore implements IProjectsStore {
|
||||
try {
|
||||
const response = await this.projectService.getProject(workspaceSlug, projectId);
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId], response);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectsMap[workspaceSlug],
|
||||
[projectId]: response,
|
||||
},
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
return response;
|
||||
} catch (error) {
|
||||
@ -194,48 +190,47 @@ export class ProjectsStore implements IProjectsStore {
|
||||
};
|
||||
|
||||
getProjectById = (workspaceSlug: string, projectId: string) => {
|
||||
const currentProjectsMap = this.projectsMap?.[workspaceSlug];
|
||||
if (!currentProjectsMap) return null;
|
||||
const currentProjectMap = this.projectMap?.[workspaceSlug];
|
||||
if (!currentProjectMap) return null;
|
||||
|
||||
const projectInfo: IProject | null = currentProjectsMap[projectId] || null;
|
||||
const projectInfo: IProject | null = currentProjectMap[projectId] || null;
|
||||
return projectInfo;
|
||||
};
|
||||
|
||||
addProjectToFavorites = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const currentProject = this.projectsMap?.[workspaceSlug]?.[projectId];
|
||||
const currentProject = this.projectMap?.[workspaceSlug]?.[projectId];
|
||||
|
||||
if (currentProject.is_favorite) return;
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectsMap[workspaceSlug],
|
||||
[projectId]: { ...currentProject, is_favorite: true },
|
||||
},
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
const response = await this.projectService.addProjectToFavorites(workspaceSlug, projectId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to add project to favorite");
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
removeProjectFromFavorites = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const currentProject = this.projectsMap?.[workspaceSlug]?.[projectId];
|
||||
const currentProject = this.projectMap?.[workspaceSlug]?.[projectId];
|
||||
|
||||
if (!currentProject.is_favorite) return;
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId, "is_favorite"], false);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectsMap[workspaceSlug],
|
||||
[projectId]: { ...currentProject, is_favorite: false },
|
||||
},
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
const response = await this.projectService.removeProjectFromFavorites(workspaceSlug, projectId);
|
||||
@ -243,16 +238,21 @@ export class ProjectsStore implements IProjectsStore {
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to add project to favorite");
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId, "is_favorite"], true);
|
||||
runInAction(() => {
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
orderProjectsWithSortOrder = (sortIndex: number, destinationIndex: number, projectId: string) => {
|
||||
try {
|
||||
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||
const workspaceSlug = this.rootStore.app.router.workspaceSlug;
|
||||
if (!workspaceSlug) return 0;
|
||||
|
||||
const projectsList = Object.values(this.projectsMap[workspaceSlug] || {}) || [];
|
||||
const projectsList = Object.values(this.projectMap[workspaceSlug] || {}) || [];
|
||||
let updatedSortOrder = projectsList[sortIndex].sort_order;
|
||||
|
||||
if (destinationIndex === 0) updatedSortOrder = (projectsList[0].sort_order as number) - 1000;
|
||||
@ -268,16 +268,9 @@ export class ProjectsStore implements IProjectsStore {
|
||||
updatedSortOrder = (destinationSortingOrder + relativeDestinationSortingOrder) / 2;
|
||||
}
|
||||
|
||||
const currentProject = this.projectsMap?.[workspaceSlug]?.[projectId];
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId, "sort_order"], updatedSortOrder);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: {
|
||||
...this.projectsMap[workspaceSlug],
|
||||
[projectId]: { ...currentProject, sort_order: updatedSortOrder },
|
||||
},
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
return updatedSortOrder;
|
||||
@ -302,12 +295,12 @@ export class ProjectsStore implements IProjectsStore {
|
||||
createProject = async (workspaceSlug: string, data: any) => {
|
||||
try {
|
||||
const response = await this.projectService.createProject(workspaceSlug, data);
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, response.id], response);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: { ...this.projectsMap[workspaceSlug], [response.id]: response },
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to create project from project store");
|
||||
@ -317,13 +310,11 @@ export class ProjectsStore implements IProjectsStore {
|
||||
|
||||
updateProject = async (workspaceSlug: string, projectId: string, data: Partial<IProject>) => {
|
||||
try {
|
||||
const currentProject = this.projectsMap?.[workspaceSlug]?.[projectId];
|
||||
const currentProject = this.projectMap?.[workspaceSlug]?.[projectId];
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug, projectId], { ...currentProject, ...data });
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: { ...this.projectsMap[workspaceSlug], [projectId]: { ...currentProject, ...data } },
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
const response = await this.projectService.updateProject(workspaceSlug, projectId, data);
|
||||
@ -339,15 +330,13 @@ export class ProjectsStore implements IProjectsStore {
|
||||
|
||||
deleteProject = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const workspaceProjects = { ...this.projectsMap[workspaceSlug] };
|
||||
const workspaceProjects = { ...this.projectMap[workspaceSlug] };
|
||||
|
||||
delete workspaceProjects[projectId];
|
||||
|
||||
const _projectMap = set(this.projectMap, [workspaceSlug], workspaceProjects);
|
||||
runInAction(() => {
|
||||
this.projectsMap = {
|
||||
...this.projectsMap,
|
||||
[workspaceSlug]: { ...workspaceProjects },
|
||||
};
|
||||
this.projectMap = _projectMap;
|
||||
});
|
||||
|
||||
await this.projectService.deleteProject(workspaceSlug, projectId);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { makeObservable, observable, computed, action, runInAction } from "mobx";
|
||||
import groupBy from "lodash/groupBy";
|
||||
import keyBy from "lodash/keyBy";
|
||||
import omit from "lodash/omit";
|
||||
import set from "lodash/set";
|
||||
// store
|
||||
import { RootStore } from "./root.store";
|
||||
// types
|
||||
@ -10,20 +10,20 @@ import { IState } from "types";
|
||||
import { ProjectStateService } from "services/project";
|
||||
|
||||
export interface IStateStore {
|
||||
states: Record<string, IState>;
|
||||
stateMap: Record<string, IState>;
|
||||
projectStates: IState[] | undefined;
|
||||
groupedProjectStates: Record<string, IState[]> | undefined;
|
||||
}
|
||||
|
||||
export class StateStore implements IStateStore {
|
||||
states: Record<string, IState> = {};
|
||||
stateMap: Record<string, IState> = {};
|
||||
router;
|
||||
stateService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observables
|
||||
states: observable.ref,
|
||||
stateMap: observable,
|
||||
// computed
|
||||
projectStates: computed,
|
||||
groupedProjectStates: computed,
|
||||
@ -39,15 +39,15 @@ export class StateStore implements IStateStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the states belongs to a specific project
|
||||
* Returns the stateMap belongs to a specific project
|
||||
*/
|
||||
get projectStates() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
return Object.values(this.states).filter((state) => state.project === this.router.query.projectId);
|
||||
return Object.values(this.stateMap).filter((state) => state.project === this.router.query.projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the states belongs to a specific project grouped by group
|
||||
* Returns the stateMap belongs to a specific project grouped by group
|
||||
*/
|
||||
get groupedProjectStates() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
@ -55,29 +55,30 @@ export class StateStore implements IStateStore {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the states belongs to a project by projectId
|
||||
* Returns the stateMap belongs to a project by projectId
|
||||
* @param projectId
|
||||
* @returns IState[]
|
||||
*/
|
||||
getProjectStates(projectId: string) {
|
||||
return Object.values(this.states).filter((state) => state.project === projectId);
|
||||
return Object.values(this.stateMap).filter((state) => state.project === projectId);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches the states of a project
|
||||
* fetches the stateMap of a project
|
||||
* @param workspaceSlug
|
||||
* @param projectId
|
||||
* @returns
|
||||
*/
|
||||
fetchProjectStates = async (workspaceSlug: string, projectId: string) => {
|
||||
const states = await this.stateService.getStates(workspaceSlug, projectId);
|
||||
const stateMap = await this.stateService.getStates(workspaceSlug, projectId);
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
...keyBy(states, "id"),
|
||||
//todo add iteratively without modifying original reference
|
||||
this.stateMap = {
|
||||
...this.stateMap,
|
||||
...keyBy(stateMap, "id"),
|
||||
};
|
||||
});
|
||||
return states;
|
||||
return stateMap;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -89,11 +90,10 @@ export class StateStore implements IStateStore {
|
||||
*/
|
||||
createState = async (workspaceSlug: string, projectId: string, data: Partial<IState>) => {
|
||||
const response = await this.stateService.createState(workspaceSlug, projectId, data);
|
||||
|
||||
const _stateMap = set(this.stateMap, [response?.id], response);
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
[response?.id]: response,
|
||||
};
|
||||
this.stateMap = _stateMap;
|
||||
});
|
||||
return response;
|
||||
};
|
||||
@ -107,20 +107,18 @@ export class StateStore implements IStateStore {
|
||||
* @returns
|
||||
*/
|
||||
updateState = async (workspaceSlug: string, projectId: string, stateId: string, data: Partial<IState>) => {
|
||||
const originalState = this.states[stateId];
|
||||
const originalState = this.stateMap[stateId];
|
||||
try {
|
||||
const _stateMap = set(this.stateMap, [stateId], { ...this.stateMap?.[stateId], ...data });
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
[stateId]: { ...this.states?.[stateId], ...data },
|
||||
};
|
||||
this.stateMap = _stateMap;
|
||||
});
|
||||
const response = await this.stateService.patchState(workspaceSlug, projectId, stateId, data);
|
||||
return response;
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
this.stateMap = {
|
||||
...this.stateMap,
|
||||
[stateId]: originalState,
|
||||
};
|
||||
});
|
||||
@ -135,15 +133,18 @@ export class StateStore implements IStateStore {
|
||||
* @param stateId
|
||||
*/
|
||||
deleteState = async (workspaceSlug: string, projectId: string, stateId: string) => {
|
||||
const originalStates = this.states;
|
||||
const originalStates = this.stateMap;
|
||||
try {
|
||||
const _stateMap = this.stateMap;
|
||||
delete this.stateMap[stateId];
|
||||
|
||||
runInAction(() => {
|
||||
this.states = omit(this.states, stateId);
|
||||
this.stateMap = _stateMap;
|
||||
});
|
||||
await this.stateService.deleteState(workspaceSlug, projectId, stateId);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.states = originalStates;
|
||||
this.stateMap = originalStates;
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@ -156,18 +157,17 @@ export class StateStore implements IStateStore {
|
||||
* @param stateId
|
||||
*/
|
||||
markStateAsDefault = async (workspaceSlug: string, projectId: string, stateId: string) => {
|
||||
const originalStates = this.states;
|
||||
const originalStates = this.stateMap;
|
||||
try {
|
||||
const _stateMap = set(this.stateMap, [stateId, "default"], true);
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
[stateId]: { ...this.states[stateId], default: true },
|
||||
};
|
||||
this.stateMap = _stateMap;
|
||||
});
|
||||
|
||||
await this.stateService.markDefault(workspaceSlug, projectId, stateId);
|
||||
} catch (error) {
|
||||
runInAction(() => {
|
||||
this.states = originalStates;
|
||||
this.stateMap = originalStates;
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
@ -189,12 +189,12 @@ export class StateStore implements IStateStore {
|
||||
groupIndex: number
|
||||
) => {
|
||||
const SEQUENCE_GAP = 15000;
|
||||
const originalStates = this.states;
|
||||
const originalStates = this.stateMap;
|
||||
try {
|
||||
let newSequence = SEQUENCE_GAP;
|
||||
const states = this.projectStates || [];
|
||||
const selectedState = states?.find((state) => state.id === stateId);
|
||||
const groupStates = states?.filter((state) => state.group === selectedState?.group);
|
||||
const stateMap = this.projectStates || [];
|
||||
const selectedState = stateMap?.find((state) => state.id === stateId);
|
||||
const groupStates = stateMap?.filter((state) => state.group === selectedState?.group);
|
||||
const groupLength = groupStates.length;
|
||||
if (direction === "up") {
|
||||
if (groupIndex === 1) newSequence = groupStates[0].sequence - SEQUENCE_GAP;
|
||||
@ -203,18 +203,18 @@ export class StateStore implements IStateStore {
|
||||
if (groupIndex === groupLength - 2) newSequence = groupStates[groupLength - 1].sequence + SEQUENCE_GAP;
|
||||
else newSequence = (groupStates[groupIndex + 2].sequence + groupStates[groupIndex + 1].sequence) / 2;
|
||||
}
|
||||
// updating using api
|
||||
|
||||
const _stateMap = set(this.stateMap, [stateId, "sequence"], newSequence);
|
||||
runInAction(() => {
|
||||
this.states = {
|
||||
...this.states,
|
||||
[stateId]: { ...this.states[stateId], sequence: newSequence },
|
||||
};
|
||||
this.stateMap = _stateMap;
|
||||
});
|
||||
|
||||
// updating using api
|
||||
await this.stateService.patchState(workspaceSlug, projectId, stateId, { sequence: newSequence });
|
||||
} catch (err) {
|
||||
// reverting back to old state group if api fails
|
||||
runInAction(() => {
|
||||
this.states = originalStates;
|
||||
this.stateMap = originalStates;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -87,33 +87,33 @@ export class UserMembershipStore implements IUserMembershipStore {
|
||||
}
|
||||
|
||||
get currentWorkspaceMemberInfo() {
|
||||
if (!this.router.query?.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.router.query?.workspaceSlug];
|
||||
if (!this.router.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.router.workspaceSlug];
|
||||
}
|
||||
|
||||
get currentWorkspaceRole() {
|
||||
if (!this.router.query?.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.router.query?.workspaceSlug]?.role;
|
||||
if (!this.router.workspaceSlug) return;
|
||||
return this.workspaceMemberInfo[this.router.workspaceSlug]?.role;
|
||||
}
|
||||
|
||||
get currentProjectMemberInfo() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
return this.projectMemberInfo[this.router.query?.projectId];
|
||||
if (!this.router.projectId) return;
|
||||
return this.projectMemberInfo[this.router.projectId];
|
||||
}
|
||||
|
||||
get currentProjectRole() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
return this.projectMemberInfo[this.router.query?.projectId]?.role;
|
||||
if (!this.router.projectId) return;
|
||||
return this.projectMemberInfo[this.router.projectId]?.role;
|
||||
}
|
||||
|
||||
get hasPermissionToCurrentWorkspace() {
|
||||
if (!this.router.query?.workspaceSlug) return;
|
||||
return this.hasPermissionToWorkspace[this.router.query?.workspaceSlug];
|
||||
if (!this.router.workspaceSlug) return;
|
||||
return this.hasPermissionToWorkspace[this.router.workspaceSlug];
|
||||
}
|
||||
|
||||
get hasPermissionToCurrentProject() {
|
||||
if (!this.router.query?.projectId) return;
|
||||
return this.hasPermissionToProject[this.router.query?.projectId];
|
||||
if (!this.router.projectId) return;
|
||||
return this.hasPermissionToProject[this.router.projectId];
|
||||
}
|
||||
|
||||
fetchUserWorkspaceInfo = async (workspaceSlug: string) => {
|
||||
|
Loading…
Reference in New Issue
Block a user