chore: store setup

This commit is contained in:
gurusainath 2023-09-20 12:22:48 +05:30
parent 906caa636b
commit 491592614d
28 changed files with 2289 additions and 2207 deletions

View File

@ -8,7 +8,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
import { issueFilterVisibilityData } from "store/helpers/issue-data";
export const FilterExtraOptions = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -11,7 +11,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
import { issueFilterVisibilityData } from "store/helpers/issue-data";
export const DisplayFiltersSelection = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -14,7 +14,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
import { issueFilterVisibilityData } from "store/helpers/issue-data";
export const FilterPreview = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -10,7 +10,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// store default data
import { stateGroups } from "store/issue-views/issue_data";
import { stateGroups } from "store/helpers/issue-data";
export const FilterState = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -14,7 +14,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
import { issueFilterVisibilityData } from "store/helpers/issue-data";
export const FilterSelection = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -9,7 +9,7 @@ import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
// store default data
import { stateGroups } from "store/issue-views/issue_data";
import { stateGroups } from "store/helpers/issue-data";
export const FilterState = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -7,8 +7,8 @@ import { observer } from "mobx-react-lite";
import { RootStore } from "store/root";
import { useMobxStore } from "lib/mobx/store-provider";
// types and default data
import { TIssueLayouts } from "store/issue-views/issue_filters";
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
import { TIssueLayouts } from "store/issue-filters";
import { issueFilterVisibilityData } from "store/helpers/issue-data";
export const LayoutSelection = observer(() => {
const store: RootStore = useMobxStore();

View File

@ -19,7 +19,42 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root";
export const IssuesRoot = observer(() => {
const { issueFilters: issueFilterStore }: RootStore = useMobxStore();
const {
workspace: workspaceStore,
project: projectStore,
issue: issueStore,
issueFilter: issueFilterStore,
}: RootStore = useMobxStore();
// console.log("---");
// console.log("--- workspace store");
// console.log("workspaces", workspaceStore?.workspaces);
// console.log("workspace id", workspaceStore?.workspaceId);
// console.log("current workspace", workspaceStore?.currentWorkspace);
// console.log("workspace by id", workspaceStore?.workspaceById("plane"));
// console.log("workspace labels", workspaceStore?.workspaceLabels);
// console.log("workspace label by id", workspaceStore?.workspaceLabelById("1fe1031b-8986-4e6a-86cc-0d2fe3ac272f"));
// console.log("--- project store");
// console.log("workspace projects", projectStore?.workspaceProjects);
// console.log("project id", projectStore?.projectId);
// console.log("project state by groups", projectStore?.projectStatesByGroups);
// console.log("project states", projectStore?.projectStates);
// console.log("project labels", projectStore?.projectLabels);
// console.log("project members", projectStore?.projectMembers);
// projectStore?.projectStates &&
// console.log("project state by id", projectStore?.projectStateById(projectStore?.projectStates?.[0]?.id));
// projectStore?.projectLabels &&
// console.log("project label by id", projectStore?.projectLabelById(projectStore?.projectLabels?.[0]?.id));
// projectStore?.projectMembers &&
// console.log("project member by id", projectStore?.projectMemberById(projectStore?.projectMembers?.[0]?.id));
// console.log("--- issue filter store");
// console.log("issues filters", issueFilterStore?.issueFilters);
// console.log("--- issue store");
// console.log("issues", issueStore?.issues);
// console.log("---");
return (
<div className="w-full h-full relative flex flex-col overflow-hidden">

View File

@ -115,9 +115,7 @@ export const WorkspaceAuthorizationLayout: React.FC<Props> = ({
noHeader={noHeader}
/>
<div className="h-full w-full overflow-hidden">
<div className="relative h-full w-full overflow-x-hidden overflow-y-scroll">
{children}
</div>
<div className="relative h-full w-full overflow-x-hidden overflow-y-scroll">{children}</div>
</div>
</main>
)}

View File

@ -14,15 +14,26 @@ const KanBanViewRoot = () => {
project_slug: string;
};
const store: RootStore = useMobxStore();
const { issueView: issueViewStore } = store;
const { issue: issueViewStore, workspace: workspaceStore, project: projectStore }: RootStore = useMobxStore();
React.useEffect(() => {
console.log("request init--->");
const init = async () => await issueViewStore.getProjectIssuesAsync(workspace_slug, project_slug);
const init = async () => {
workspaceStore.setWorkspaceId(workspace_slug);
await workspaceStore.getWorkspaces();
await workspaceStore.getWorkspaceLabels(workspace_slug);
projectStore.setProject(project_slug);
await projectStore.getWorkspaceProjects(workspace_slug);
await projectStore.getProjectStates(workspace_slug, project_slug);
await projectStore.getProjectLabels(workspace_slug, project_slug);
await projectStore.getProjectMembers(workspace_slug, project_slug);
await issueViewStore.getProjectIssuesAsync(workspace_slug, project_slug);
};
if (workspace_slug && project_slug) init();
console.log("request completed--->");
}, [workspace_slug, project_slug, issueViewStore]);
}, [workspace_slug, project_slug, issueViewStore, workspaceStore, projectStore]);
return (
<div className="w-screen min-h-[600px] h-screen">

View File

@ -87,11 +87,7 @@ export class ProjectServices extends APIService {
});
}
async deleteProject(
workspaceSlug: string,
projectId: string,
user: ICurrentUserResponse | undefined
): Promise<any> {
async deleteProject(workspaceSlug: string, projectId: string, user: ICurrentUserResponse | undefined): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/`)
.then((response) => {
trackEventServices.trackProjectEvent({ projectId }, "DELETE_PROJECT", user);
@ -136,11 +132,7 @@ export class ProjectServices extends APIService {
});
}
async leaveProject(
workspaceSlug: string,
projectId: string,
user: ICurrentUserResponse
): Promise<any> {
async leaveProject(workspaceSlug: string, projectId: string, user: ICurrentUserResponse): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/leave/`)
.then((response) => {
trackEventServices.trackProjectEvent(
@ -175,10 +167,7 @@ export class ProjectServices extends APIService {
});
}
async projectMembersWithEmail(
workspaceSlug: string,
projectId: string
): Promise<IProjectMember[]> {
async projectMembersWithEmail(workspaceSlug: string, projectId: string): Promise<IProjectMember[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/`)
.then((response) => response?.data)
.catch((error) => {
@ -194,11 +183,7 @@ export class ProjectServices extends APIService {
});
}
async getProjectMember(
workspaceSlug: string,
projectId: string,
memberId: string
): Promise<IProjectMember> {
async getProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<IProjectMember> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
@ -212,34 +197,22 @@ export class ProjectServices extends APIService {
memberId: string,
data: Partial<IProjectMember>
): Promise<IProjectMember> {
return this.patch(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`,
data
)
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`, data)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectMember(
workspaceSlug: string,
projectId: string,
memberId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`
)
async deleteProjectMember(workspaceSlug: string, projectId: string, memberId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/members/${memberId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async projectInvitations(
workspaceSlug: string,
projectId: string
): Promise<IProjectMemberInvitation[]> {
async projectInvitations(workspaceSlug: string, projectId: string): Promise<IProjectMemberInvitation[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`)
.then((response) => response?.data)
.catch((error) => {
@ -247,10 +220,7 @@ export class ProjectServices extends APIService {
});
}
async projectInvitationsWithEmail(
workspaceSlug: string,
projectId: string
): Promise<IProjectMemberInvitation[]> {
async projectInvitationsWithEmail(workspaceSlug: string, projectId: string): Promise<IProjectMemberInvitation[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/`)
.then((response) => response?.data)
.catch((error) => {
@ -258,28 +228,16 @@ export class ProjectServices extends APIService {
});
}
async updateProjectInvitation(
workspaceSlug: string,
projectId: string,
invitationId: string
): Promise<any> {
return this.put(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`
)
async updateProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.put(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async deleteProjectInvitation(
workspaceSlug: string,
projectId: string,
invitationId: string
): Promise<any> {
return this.delete(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`
)
async deleteProjectInvitation(workspaceSlug: string, projectId: string, invitationId: string): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/invitations/${invitationId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
@ -332,11 +290,7 @@ export class ProjectServices extends APIService {
});
}
async getProjectGithubRepository(
workspaceSlug: string,
projectId: string,
integrationId: string
): Promise<any> {
async getProjectGithubRepository(workspaceSlug: string, projectId: string, integrationId: string): Promise<any> {
return this.get(
`/api/workspaces/${workspaceSlug}/projects/${projectId}/workspace-integrations/${integrationId}/github-repository-sync/`
)

View File

@ -37,10 +37,7 @@ export class WorkspaceService extends APIService {
});
}
async createWorkspace(
data: Partial<IWorkspace>,
user: ICurrentUserResponse | undefined
): Promise<IWorkspace> {
async createWorkspace(data: Partial<IWorkspace>, user: ICurrentUserResponse | undefined): Promise<IWorkspace> {
return this.post("/api/workspaces/", data)
.then((response) => {
trackEventServices.trackWorkspaceEvent(response.data, "CREATE_WORKSPACE", user);
@ -66,10 +63,7 @@ export class WorkspaceService extends APIService {
});
}
async deleteWorkspace(
workspaceSlug: string,
user: ICurrentUserResponse | undefined
): Promise<any> {
async deleteWorkspace(workspaceSlug: string, user: ICurrentUserResponse | undefined): Promise<any> {
return this.delete(`/api/workspaces/${workspaceSlug}/`)
.then((response) => {
trackEventServices.trackWorkspaceEvent({ workspaceSlug }, "DELETE_WORKSPACE", user);
@ -101,13 +95,9 @@ export class WorkspaceService extends APIService {
data: any,
user: ICurrentUserResponse | undefined
): Promise<any> {
return this.post(
`/api/users/me/invitations/workspaces/${workspaceSlug}/${invitationId}/join/`,
data,
{
return this.post(`/api/users/me/invitations/workspaces/${workspaceSlug}/${invitationId}/join/`, data, {
headers: {},
}
)
})
.then((response) => {
trackEventServices.trackWorkspaceEvent(response.data, "WORKSPACE_USER_INVITE_ACCEPT", user);
return response?.data;
@ -165,10 +155,7 @@ export class WorkspaceService extends APIService {
});
}
async updateWorkspaceView(
workspaceSlug: string,
data: { view_props: IWorkspaceViewProps }
): Promise<any> {
async updateWorkspaceView(workspaceSlug: string, data: { view_props: IWorkspaceViewProps }): Promise<any> {
return this.post(`/api/workspaces/${workspaceSlug}/workspace-views/`, data)
.then((response) => response?.data)
.catch((error) => {
@ -204,9 +191,7 @@ export class WorkspaceService extends APIService {
});
}
async workspaceInvitationsWithEmail(
workspaceSlug: string
): Promise<IWorkspaceMemberInvitation[]> {
async workspaceInvitationsWithEmail(workspaceSlug: string): Promise<IWorkspaceMemberInvitation[]> {
return this.get(`/api/workspaces/${workspaceSlug}/invitations/`)
.then((response) => response?.data)
.catch((error) => {

55
web/store/cycles.ts Normal file
View File

@ -0,0 +1,55 @@
import { action, computed, observable, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
// services
import { ProjectServices } from "services/project.service";
import { ProjectIssuesServices as IssueServices } from "services/issues.service";
export interface ICycleStore {
loader: boolean;
error: any | null;
cycleId: string | null;
setCycleId: (cycleSlug: string) => void;
}
class CycleStore implements ICycleStore {
loader: boolean = false;
error: any | null = null;
cycleId: string | null = null;
// root store
rootStore;
// services
projectService;
issueService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
loader: observable,
error: observable.ref,
cycleId: observable.ref,
// computed
// actions
setCycleId: action,
});
this.rootStore = _rootStore;
this.projectService = new ProjectServices();
this.issueService = new IssueServices();
}
// computed
// actions
setCycleId = (cycleSlug: string) => {
this.cycleId = cycleSlug ?? null;
};
}
export default CycleStore;

View File

@ -1,6 +1,6 @@
import { renderDateFormat } from "helpers/date-time.helper";
// types
import { TIssueLayouts, TIssueParams } from "./issue_filters";
import { TIssueLayouts, TIssueParams } from "../issue-filters";
export type TStateGroup = "backlog" | "unstarted" | "started" | "completed" | "cancelled";

1085
web/store/issue-filters.ts Normal file

File diff suppressed because it is too large Load Diff

417
web/store/issue-store.ts Normal file
View File

@ -0,0 +1,417 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
// services
import { UserService } from "services/user.service";
import { ProjectIssuesServices } from "services/issues.service";
import { ProjectIssuesServices as ProjectModuleServices } from "services/modules.service";
import { ProjectCycleServices } from "services/cycles.service";
// types
import { TIssueLayouts, TIssueViews } from "./issue-filters";
export interface IIssues {
[key: string]: any;
}
export interface IIssuesLayout {
list: IIssues[];
kanban: IIssues[];
calendar: IIssues[];
spreadsheet: IIssues[];
gantt_chart: IIssues[];
}
export interface IIssueState {
[key: string]: {
// project_id: layout_view
issues: {
[key: string]: IIssuesLayout; // project_id: layout_key: ...issues, It's always one project id here
};
cycles: {
[key: string]: IIssuesLayout; // cycle_id: layout_key: ...issues
};
modules: {
[key: string]: IIssuesLayout; // module_id: layout_key: ...issues
};
views: {
[key: string]: IIssuesLayout; // view_id: layout_key: ...issues
};
};
}
export interface IIssueStore {
loader: boolean;
error: any | null;
issues: IIssueState;
// computed
getIssues: IIssues | null | undefined;
// actions
updateIssues: (data: any) => void;
getProjectIssuesAsync: (workspaceId: string, projectId: string, fetchFilterToggle?: boolean) => null | Promise<any>;
getIssuesForModulesAsync: (
workspaceId: string,
projectId: string,
moduleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
getIssuesForCyclesAsync: (
workspaceId: string,
projectId: string,
cycleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
getIssuesForViewsAsync: (
workspaceId: string,
projectId: string,
viewId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
}
class IssueStore implements IIssueStore {
loader: boolean = false;
error: any | null = null;
issues: IIssueState = {};
// root store
rootStore;
// service
issueService;
userService;
modulesService;
cyclesService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable,
error: observable,
issues: observable.ref,
// computed
getIssues: computed,
// action
updateIssues: action,
getProjectIssuesAsync: action,
getIssuesForModulesAsync: action,
getIssuesForCyclesAsync: action,
getIssuesForViewsAsync: action,
});
this.rootStore = _rootStore;
this.issueService = new ProjectIssuesServices();
this.userService = new UserService();
this.modulesService = new ProjectModuleServices();
this.cyclesService = new ProjectCycleServices();
}
// computed
get getIssues() {
if (this.issues != null) {
const issueView: TIssueViews | null = this.rootStore.issueFilter.issueView;
const projectId: string | null = this.rootStore.project.projectId;
const moduleId: string | null = this.rootStore.module.moduleId;
const cycleId: string | null = this.rootStore.cycle.cycleId;
const viewId: string | null = this.rootStore.view.viewId;
const issueLayout: TIssueLayouts | null = this.rootStore.issueFilter.issueLayout;
if (!issueView || !projectId) return null;
const currentViewIdIndex: string | null =
issueView === "issues" && projectId
? projectId
: issueView === "modules" && moduleId
? moduleId
: issueView === "cycles" && cycleId
? cycleId
: issueView === "cycles" && viewId
? viewId
: null;
if (!issueLayout || !currentViewIdIndex) return null;
return this.issues[projectId][issueView][currentViewIdIndex][issueLayout];
}
return null;
}
updateIssues = (data: any) => {
const issueView: TIssueViews | null = this.rootStore.issueFilter.issueView;
const projectId: string | null = this.rootStore.project.projectId;
const moduleId: string | null = this.rootStore.module.moduleId;
const cycleId: string | null = this.rootStore.cycle.cycleId;
const viewId: string | null = this.rootStore.view.viewId;
const issueLayout: TIssueLayouts | null = this.rootStore.issueFilter.issueLayout;
const { groupId, issueId, issueData } = data as {
groupId?: any;
issueId: string | null;
issueData: any;
};
if (!issueView || !projectId) return null;
const currentViewIdIndex: string | null =
issueView === "issues" && projectId
? projectId
: issueView === "modules" && moduleId
? moduleId
: issueView === "cycles" && cycleId
? cycleId
: issueView === "cycles" && viewId
? viewId
: null;
if (!issueLayout || !currentViewIdIndex) return null;
let _issues = this?.issues?.[projectId]?.[issueView]?.[currentViewIdIndex]?.[issueLayout];
if (groupId && groupId != null && ["list", "kanban"].includes(issueLayout)) {
_issues = {
..._issues,
[groupId]:
_issues?.[groupId] && _issues?.[groupId].length > 0
? _issues?.[groupId]?.map((item: any) => (item.id === issueId ? { ...item, ...issueData } : { ...item }))
: [],
};
} else {
_issues = {
..._issues,
..._issues.map((item: any) => (item.id === issueId ? { ...item, ...issueData } : { ...item })),
};
}
this.issues = {
...this.issues,
[projectId]: {
...this?.issues?.[projectId],
[issueView]: {
...this?.issues?.[projectId]?.[issueView],
[currentViewIdIndex]: {
...this?.issues?.[projectId]?.[issueView]?.[currentViewIdIndex],
[issueLayout]: {
...this?.issues?.[projectId]?.[issueView]?.[currentViewIdIndex]?.[issueLayout],
..._issues,
},
},
},
},
};
};
// fetching project issues
getProjectIssuesAsync = async (workspaceId: string, projectId: string, fetchFilterToggle: boolean = true) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle) await this.rootStore.issueFilter.getProjectIssueFilters(workspaceId, projectId);
// const filteredParams = this.rootStore.issueFilter.getComputedFilters(
// workspaceId,
// projectId,
// null,
// null,
// null,
// "issues"
// );
// const issuesResponse = await this.issueService.getIssuesWithParams(workspaceId, projectId, filteredParams);
// if (issuesResponse) {
// const _issueResponse: any = {
// ...this.issues,
// [projectId]: {
// ...this?.issues?.[projectId],
// issues: {
// ...this?.issues?.[projectId]?.issues,
// [this.rootStore?.issueFilter?.userFilters?.display_filters?.layout as string]: issuesResponse,
// },
// },
// };
// runInAction(() => {
// this.issues = _issueResponse;
// this.loader = false;
// this.error = null;
// });
// }
// return issuesResponse;
} catch (error) {
console.warn("error in fetching the project issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for modules
getIssuesForModulesAsync = async (
workspaceId: string,
projectId: string,
moduleId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilter.getProjectIssueModuleFilters(workspaceId, projectId, moduleId);
const filteredParams = this.rootStore.issueFilter.getComputedFilters(
workspaceId,
projectId,
moduleId,
null,
null,
"modules"
);
const issuesResponse = await this.modulesService.getModuleIssuesWithParams(
workspaceId,
projectId,
moduleId,
filteredParams
);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[projectId]: {
...this?.issues?.[projectId],
modules: {
...this?.issues?.[projectId]?.modules,
[moduleId]: {
...this?.issues?.[projectId]?.modules?.[moduleId],
[this.rootStore?.issueFilter?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project module issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for cycles
getIssuesForCyclesAsync = async (
workspaceId: string,
projectId: string,
cycleId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilter.getProjectIssueCyclesFilters(workspaceId, projectId, cycleId);
const filteredParams = this.rootStore.issueFilter.getComputedFilters(
workspaceId,
projectId,
null,
cycleId,
null,
"cycles"
);
const issuesResponse = await this.cyclesService.getCycleIssuesWithParams(
workspaceId,
projectId,
cycleId,
filteredParams
);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[projectId]: {
...this?.issues?.[projectId],
cycles: {
...this?.issues?.[projectId]?.cycles,
[cycleId]: {
...this?.issues?.[projectId]?.cycles?.[cycleId],
[this.rootStore?.issueFilter?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project cycles issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for views
getIssuesForViewsAsync = async (
workspaceId: string,
projectId: string,
viewId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilter.getProjectIssueViewsFilters(workspaceId, projectId, viewId);
const filteredParams = this.rootStore.issueFilter.getComputedFilters(
workspaceId,
projectId,
null,
null,
viewId,
"views"
);
const issuesResponse = await this.issueService.getIssuesWithParams(workspaceId, projectId, filteredParams);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[projectId]: {
...this?.issues?.[projectId],
views: {
...this?.issues?.[projectId]?.views,
[viewId]: {
...this?.issues?.[projectId]?.views?.[viewId],
[this.rootStore?.issueFilter?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project view issues", error);
this.loader = false;
this.error = null;
return error;
}
};
}
export default IssueStore;

View File

@ -1,524 +0,0 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
// services
import { UserService } from "services/user.service";
import { ProjectIssuesServices } from "services/issues.service";
import { ProjectIssuesServices as ProjectModuleServices } from "services/modules.service";
import { ProjectCycleServices } from "services/cycles.service";
// types
import { TIssueLayouts, TIssueViews } from "./issue_filters";
export interface IIssues {
[key: string]: any;
}
export interface IIssuesLayout {
list: IIssues[];
kanban: IIssues[];
calendar: IIssues[];
spreadsheet: IIssues[];
gantt_chart: IIssues[];
}
export interface IIssueState {
[key: string]: {
my_issues: IIssuesLayout;
project_issues: {
[key: string]: {
issues: IIssuesLayout;
cycles: {
[key: string]: IIssuesLayout;
};
modules: {
[key: string]: IIssuesLayout;
};
views: {
[key: string]: IIssuesLayout;
};
};
};
};
}
export interface IIssueViewStore {
loader: boolean;
error: any | null;
issues: IIssueState;
// computed
getIssues: IIssues | null | undefined;
// actions
getMyIssuesAsync: (workspaceId: string, fetchFilterToggle: boolean) => null | Promise<any>;
getProjectIssuesAsync: (workspaceId: string, projectId: string, fetchFilterToggle: boolean) => null | Promise<any>;
getIssuesForModulesAsync: (
workspaceId: string,
projectId: string,
moduleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
getIssuesForCyclesAsync: (
workspaceId: string,
projectId: string,
cycleId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
getIssuesForViewsAsync: (
workspaceId: string,
projectId: string,
viewId: string,
fetchFilterToggle: boolean
) => null | Promise<any>;
}
class IssueViewStore implements IIssueViewStore {
loader: boolean = false;
error: any | null = null;
issues: IIssueState = {};
// root store
rootStore;
// service
issueService;
userService;
modulesService;
cyclesService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable,
error: observable,
issues: observable.ref,
// action
getMyIssuesAsync: action,
getProjectIssuesAsync: action,
getIssuesForModulesAsync: action,
getIssuesForCyclesAsync: action,
getIssuesForViewsAsync: action,
updateIssues: action,
// computed
getIssues: computed,
});
this.rootStore = _rootStore;
this.issueService = new ProjectIssuesServices();
this.userService = new UserService();
this.modulesService = new ProjectModuleServices();
this.cyclesService = new ProjectCycleServices();
}
// computed
get getIssues() {
if (this.issues != null) {
const currentView: TIssueViews | null = this.rootStore.issueFilters.issueView;
const currentWorkspaceId: string | null = this.rootStore.issueFilters.workspaceId;
const currentProjectId: string | null = this.rootStore.issueFilters.projectId;
const currentModuleId: string | null = this.rootStore.issueFilters.moduleId;
const currentCycleId: string | null = this.rootStore.issueFilters.cycleId;
const currentViewId: string | null = this.rootStore.issueFilters.viewId;
if (!currentView || !currentWorkspaceId) return null;
const currentLayout: TIssueLayouts = currentProjectId
? this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId]?.project_issue_properties?.[currentProjectId]
?.issues?.display_filters?.layout
: this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId]?.my_issue_properties?.display_filters?.layout;
if (currentView === "my_issues") return this.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout];
else if (currentView === "issues" && currentProjectId)
return this.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues?.[currentLayout];
else if (currentView === "modules" && currentProjectId && currentModuleId)
return this.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.modules?.[currentModuleId]?.[
currentLayout
];
else if (currentView === "cycles" && currentProjectId && currentCycleId)
return this.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.cycles?.[currentCycleId]?.[
currentLayout
];
else if (currentView === "views" && currentProjectId && currentViewId)
return this.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.views?.[currentViewId]?.[
currentLayout
];
}
return null;
}
updateIssues = (group_id: any = null, issue_id: string | null, data: any) => {
const currentWorkspaceId: string | null = this.rootStore.issueFilters.workspaceId;
const currentProjectId: string | null = this.rootStore.issueFilters.projectId;
// const currentModuleId: string | null = this.rootStore.issueFilters.moduleId;
// const currentCycleId: string | null = this.rootStore.issueFilters.cycleId;
// const currentViewId: string | null = this.rootStore.issueFilters.viewId;
const currentView: TIssueViews | null = this.rootStore.issueFilters.issueView;
const currentLayout: TIssueLayouts | null = this.rootStore.issueFilters.issueLayout;
if (!currentView || !currentWorkspaceId || !currentLayout || !issue_id) return null;
if (currentView === "my_issues") {
if (group_id) {
this.issues = {
...this.issues,
[currentWorkspaceId]: {
...this?.issues?.[currentWorkspaceId],
my_issues: {
...this?.issues?.[currentWorkspaceId]?.my_issues,
[currentLayout]: {
...this?.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout],
[group_id]: this?.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout]?.[group_id].map(
(item: any) => (item.id === issue_id ? { ...item, ...data } : { ...item })
),
},
},
},
} as any;
} else {
this.issues = {
...this.issues,
[currentWorkspaceId]: {
...this?.issues?.[currentWorkspaceId],
my_issues: {
...this?.issues?.[currentWorkspaceId]?.my_issues,
[currentLayout]: this?.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout].map((item: any) =>
item.id === issue_id ? { ...item, ...data } : { ...item }
),
},
},
} as any;
}
}
if (!currentProjectId) return null;
if (currentView) {
if (group_id) {
this.issues = {
...this.issues,
[currentWorkspaceId]: {
...this?.issues?.[currentWorkspaceId],
project_issues: {
...this?.issues?.[currentWorkspaceId]?.project_issues,
[currentProjectId]: {
...this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId],
[currentView]: {
...this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues,
[currentLayout]: {
...this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues?.[currentLayout],
[group_id]: this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues?.[
currentLayout
]?.[group_id].map((item: any) => (item.id === issue_id ? { ...item, ...data } : { ...item })),
},
},
},
},
},
} as any;
} else {
this.issues = {
...this.issues,
[currentWorkspaceId]: {
...this?.issues?.[currentWorkspaceId],
project_issues: {
...this?.issues?.[currentWorkspaceId]?.project_issues,
[currentProjectId]: {
...this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId],
[currentView]: {
...this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues,
[currentLayout]: this?.issues?.[currentWorkspaceId]?.project_issues?.[currentProjectId]?.issues?.[
currentLayout
].map((item: any) => (item.id === issue_id ? { ...item, ...data } : { ...item })),
},
},
},
},
} as any;
}
}
};
// fetching my issues
getMyIssuesAsync = async (workspaceId: string, fetchFilterToggle: boolean = true) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle) await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
null,
null,
null,
null,
"my_issues"
);
const issuesResponse = await this.userService.userIssues(workspaceId, filteredParams);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[workspaceId]: {
...this?.issues[workspaceId],
my_issues: {
...this?.issues[workspaceId]?.my_issues,
[this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the my issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues
getProjectIssuesAsync = async (workspaceId: string, projectId: string, fetchFilterToggle: boolean = true) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle) await this.rootStore.issueFilters.getProjectIssueFilters(workspaceId, projectId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
null,
null,
null,
"issues"
);
const issuesResponse = await this.issueService.getIssuesWithParams(workspaceId, projectId, filteredParams);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[workspaceId]: {
...this?.issues?.[workspaceId],
project_issues: {
...this?.issues?.[workspaceId]?.project_issues,
[projectId]: {
...this?.issues?.[workspaceId]?.project_issues?.[projectId],
issues: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.issues,
[this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for modules
getIssuesForModulesAsync = async (
workspaceId: string,
projectId: string,
moduleId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilters.getProjectIssueModuleFilters(workspaceId, projectId, moduleId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
moduleId,
null,
null,
"modules"
);
const issuesResponse = await this.modulesService.getModuleIssuesWithParams(
workspaceId,
projectId,
moduleId,
filteredParams
);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[workspaceId]: {
...this?.issues?.[workspaceId],
project_issues: {
...this?.issues?.[workspaceId]?.project_issues,
[projectId]: {
...this?.issues?.[workspaceId]?.project_issues?.[projectId],
modules: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.modules,
[moduleId]: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.modules?.[moduleId],
[this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project module issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for cycles
getIssuesForCyclesAsync = async (
workspaceId: string,
projectId: string,
cycleId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilters.getProjectIssueCyclesFilters(workspaceId, projectId, cycleId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
null,
cycleId,
null,
"cycles"
);
const issuesResponse = await this.cyclesService.getCycleIssuesWithParams(
workspaceId,
projectId,
cycleId,
filteredParams
);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[workspaceId]: {
...this?.issues?.[workspaceId],
project_issues: {
...this?.issues?.[workspaceId]?.project_issues,
[projectId]: {
...this?.issues?.[workspaceId]?.project_issues?.[projectId],
cycles: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.cycles,
[cycleId]: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.cycles?.[cycleId],
[this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project cycles issues", error);
this.loader = false;
this.error = null;
return error;
}
};
// fetching project issues for views
getIssuesForViewsAsync = async (
workspaceId: string,
projectId: string,
viewId: string,
fetchFilterToggle: boolean = true
) => {
try {
this.loader = true;
this.error = null;
if (fetchFilterToggle)
await this.rootStore.issueFilters.getProjectIssueViewsFilters(workspaceId, projectId, viewId);
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
workspaceId,
projectId,
null,
null,
viewId,
"views"
);
const issuesResponse = await this.issueService.getIssuesWithParams(workspaceId, projectId, filteredParams);
if (issuesResponse) {
const _issueResponse: any = {
...this.issues,
[workspaceId]: {
...this?.issues?.[workspaceId],
project_issues: {
...this?.issues?.[workspaceId]?.project_issues,
[projectId]: {
...this?.issues?.[workspaceId]?.project_issues?.[projectId],
views: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.views,
[viewId]: {
...this?.issues[workspaceId]?.project_issues?.[projectId]?.views?.[viewId],
[this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
},
},
},
},
},
};
runInAction(() => {
this.issues = _issueResponse;
this.loader = false;
this.error = null;
});
}
return issuesResponse;
} catch (error) {
console.warn("error in fetching the project view issues", error);
this.loader = false;
this.error = null;
return error;
}
};
}
export default IssueViewStore;

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
import { action, computed, makeObservable } from "mobx";
// types
import { RootStore } from "../root";
export interface IIssueProject {}
class IssueProject implements IIssueProject {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// computed
// actions
});
this.rootStore = _rootStore;
}
}
export default IssueProject;

View File

@ -1,21 +0,0 @@
import { action, computed, makeObservable } from "mobx";
// types
import { RootStore } from "../root";
export interface IIssueWorkspace {}
class IssueWorkspace implements IIssueWorkspace {
// root store
rootStore;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// computed
// actions
});
this.rootStore = _rootStore;
}
}
export default IssueWorkspace;

View File

@ -1,6 +1,6 @@
import { observable, action, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "../root";
import { RootStore } from "./root";
// services
import { ProjectIssuesServices } from "services/issues.service";

View File

@ -31,10 +31,7 @@ class IssuesStore {
loadIssues = async (workspaceSlug: string, projectId: string) => {
this.isIssuesLoading = true;
try {
const issuesResponse: IIssue[] = (await issueService.getIssuesWithParams(
workspaceSlug,
projectId
)) as IIssue[];
const issuesResponse: IIssue[] = (await issueService.getIssuesWithParams(workspaceSlug, projectId)) as IIssue[];
const issues: { [kye: string]: IIssue } = {};
issuesResponse.forEach((issue) => {
@ -51,11 +48,7 @@ class IssuesStore {
}
};
getIssueById = async (
workspaceSlug: string,
projectId: string,
issueId: string
): Promise<IIssue> => {
getIssueById = async (workspaceSlug: string, projectId: string, issueId: string): Promise<IIssue> => {
if (this.issues[issueId]) return this.issues[issueId];
try {
@ -83,12 +76,7 @@ class IssuesStore {
user: ICurrentUserResponse
): Promise<IIssue> => {
try {
const issueResponse = await issueService.createIssues(
workspaceSlug,
projectId,
issueForm,
user
);
const issueResponse = await issueService.createIssues(workspaceSlug, projectId, issueForm, user);
const issues = {
...this.issues,
@ -125,13 +113,7 @@ class IssuesStore {
});
// make a patch request to update the issue
const issueResponse: IIssue = await issueService.patchIssue(
workspaceSlug,
projectId,
issueId,
issueForm,
user
);
const issueResponse: IIssue = await issueService.patchIssue(workspaceSlug, projectId, issueId, issueForm, user);
const updatedIssues = { ...this.issues };
updatedIssues[issueId] = { ...issueResponse };
@ -149,12 +131,7 @@ class IssuesStore {
}
};
deleteIssue = async (
workspaceSlug: string,
projectId: string,
issueId: string,
user: ICurrentUserResponse
) => {
deleteIssue = async (workspaceSlug: string, projectId: string, issueId: string, user: ICurrentUserResponse) => {
const issues = { ...this.issues };
delete issues[issueId];

55
web/store/modules.ts Normal file
View File

@ -0,0 +1,55 @@
import { action, computed, observable, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
// services
import { ProjectServices } from "services/project.service";
import { ProjectIssuesServices as IssueServices } from "services/issues.service";
export interface IModuleStore {
loader: boolean;
error: any | null;
moduleId: string | null;
setModuleId: (moduleSlug: string) => void;
}
class ModuleStore implements IModuleStore {
loader: boolean = false;
error: any | null = null;
moduleId: string | null = null;
// root store
rootStore;
// services
projectService;
issueService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
loader: observable,
error: observable.ref,
moduleId: observable.ref,
// computed
// actions
setModuleId: action,
});
this.rootStore = _rootStore;
this.projectService = new ProjectServices();
this.issueService = new IssueServices();
}
// computed
// actions
setModuleId = (moduleSlug: string) => {
this.moduleId = moduleSlug ?? null;
};
}
export default ModuleStore;

View File

@ -1,86 +0,0 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
// services
import { ProjectServices } from "services/project.service";
export interface IProject {
id: string;
name: string;
workspaceSlug: string;
}
export interface IProjectStore {
loader: boolean;
error: any | null;
projectLeaveModal: boolean;
projectLeaveDetails: IProject | any;
handleProjectLeaveModal: (project: IProject | null) => void;
leaveProject: (workspace_slug: string, project_slug: string, user: any) => Promise<void>;
}
class ProjectStore implements IProjectStore {
loader: boolean = false;
error: any | null = null;
projectLeaveModal: boolean = false;
projectLeaveDetails: IProject | null = null;
// root store
rootStore;
// service
projectService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable,
error: observable,
projectLeaveModal: observable,
projectLeaveDetails: observable.ref,
// action
handleProjectLeaveModal: action,
leaveProject: action,
// computed
});
this.rootStore = _rootStore;
this.projectService = new ProjectServices();
}
handleProjectLeaveModal = (project: IProject | null = null) => {
if (project && project?.id) {
this.projectLeaveModal = !this.projectLeaveModal;
this.projectLeaveDetails = project;
} else {
this.projectLeaveModal = !this.projectLeaveModal;
this.projectLeaveDetails = null;
}
};
leaveProject = async (workspace_slug: string, project_slug: string, user: any) => {
try {
this.loader = true;
this.error = null;
const response = await this.projectService.leaveProject(workspace_slug, project_slug, user);
runInAction(() => {
this.loader = false;
this.error = null;
});
return response;
} catch (error) {
this.loader = false;
this.error = error;
return error;
}
};
}
export default ProjectStore;

309
web/store/projects.ts Normal file
View File

@ -0,0 +1,309 @@
import { observable, action, computed, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
import { IProject, IIssueLabels, IProjectMember, IStateResponse, IState } from "types";
// services
import { ProjectServices } from "services/project.service";
import { ProjectIssuesServices } from "services/issues.service";
import { ProjectStateServices } from "services/state.service";
export interface IProjectStore {
loader: boolean;
error: any | null;
projectLeaveModal: boolean;
projectLeaveDetails: IProject | any;
projectId: string | null;
projects: {
[key: string]: { [key: string]: IProject }; // workspace_id: project_id: projects
} | null;
states: {
[key: string]: IStateResponse; // project_id: states
} | null;
labels: {
[key: string]: IIssueLabels[]; // project_id: labels
} | null;
members: {
[key: string]: IProjectMember[]; // project_id: members
} | null;
// computed
projectStatesByGroups: IStateResponse | null;
projectStates: IState[] | null;
projectLabels: IIssueLabels[] | null;
projectMembers: IProjectMember[] | null;
workspaceProjects: { [key: string]: IProject } | null;
// actions
projectStateById: (stateId: string) => IState | null;
projectLabelById: (labelId: string) => IIssueLabels | null;
projectMemberById: (memberId: string) => IProjectMember | null;
setProject: (projectSlug: string) => void;
getWorkspaceProjects: (workspaceSlug: string, is_favorite?: "all" | boolean) => Promise<void>;
getProjectStates: (workspaceSlug: string, projectSlug: string) => Promise<void>;
getProjectLabels: (workspaceSlug: string, projectSlug: string) => Promise<void>;
getProjectMembers: (workspaceSlug: string, projectSlug: string) => Promise<void>;
handleProjectLeaveModal: (project: IProject | null) => void;
leaveProject: (workspaceSlug: string, projectSlug: string, user: any) => Promise<void>;
}
class ProjectStore implements IProjectStore {
loader: boolean = false;
error: any | null = null;
projectLeaveModal: boolean = false;
projectLeaveDetails: IProject | null = null;
projectId: string | null = null;
projects: {
[key: string]: { [key: string]: IProject }; // workspace_id: project_id: projects
} | null = null;
states: {
[key: string]: IStateResponse; // project_id: states
} | null = null;
labels: {
[key: string]: IIssueLabels[]; // project_id: labels
} | null = null;
members: {
[key: string]: IProjectMember[]; // project_id: members
} | null = null;
// root store
rootStore;
// service
projectService;
issueService;
stateService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
// observable
loader: observable,
error: observable,
projectId: observable.ref,
projects: observable.ref,
states: observable.ref,
labels: observable.ref,
members: observable.ref,
projectLeaveModal: observable,
projectLeaveDetails: observable.ref,
// computed
workspaceProjects: computed,
projectStatesByGroups: computed,
projectStates: computed,
projectLabels: computed,
projectMembers: computed,
// action
setProject: action,
projectStateById: action,
projectLabelById: action,
projectMemberById: action,
getWorkspaceProjects: action,
getProjectStates: action,
getProjectLabels: action,
getProjectMembers: action,
handleProjectLeaveModal: action,
leaveProject: action,
});
this.rootStore = _rootStore;
this.projectService = new ProjectServices();
this.issueService = new ProjectIssuesServices();
this.stateService = new ProjectStateServices();
}
// computed
get workspaceProjects() {
if (!this.rootStore.workspace.workspaceId) return null;
return this.projects?.[this.rootStore.workspace.workspaceId] || null;
}
get projectStatesByGroups() {
if (!this.projectId) return null;
return this.states?.[this.projectId] || null;
}
get projectStates() {
if (!this.projectId) return null;
const stateByGroups: IStateResponse | null = this.projectStatesByGroups;
if (!stateByGroups) return null;
const _states: IState[] = [];
Object.keys(stateByGroups).forEach((_stateGroup: string) => {
stateByGroups[_stateGroup].map((state) => {
_states.push(state);
});
});
return _states && _states.length > 0 ? _states : null;
}
get projectLabels() {
if (!this.projectId) return null;
return this.labels?.[this.projectId] || null;
}
get projectMembers() {
if (!this.projectId) return null;
return this.members?.[this.projectId] || null;
}
// actions
projectStateById = (stateId: string) => {
if (!this.projectId) return null;
const states = this.projectStates;
if (!states) return null;
const stateInfo: IState | null = states.find((state) => state.id === stateId) || null;
return stateInfo;
};
projectLabelById = (labelId: string) => {
if (!this.projectId) return null;
const labels = this.projectLabels;
if (!labels) return null;
const labelInfo: IIssueLabels | null = labels.find((label) => label.id === labelId) || null;
return labelInfo;
};
projectMemberById = (memberId: string) => {
if (!this.projectId) return null;
const members = this.projectMembers;
if (!members) return null;
const memberInfo: IProjectMember | null = members.find((member) => member.id === memberId) || null;
return memberInfo;
};
setProject = (projectSlug: string) => {
this.projectId = projectSlug ?? null;
};
getWorkspaceProjects = async (workspaceSlug: string, is_favorite: "all" | boolean = "all") => {
try {
this.loader = true;
this.error = null;
const params: { is_favorite: "all" | boolean } = { is_favorite: is_favorite };
const projectsResponse = await this.projectService.getProjects(workspaceSlug, params);
let _projects: { [key: string]: IProject } = {};
projectsResponse.map((project) => {
_projects = { ..._projects, [project.id]: project };
});
runInAction(() => {
this.projects = {
...this.projects,
[workspaceSlug]: _projects,
};
this.loader = false;
this.error = null;
});
} catch (error) {
console.error(error);
this.loader = false;
this.error = error;
}
};
getProjectStates = async (workspaceSlug: string, projectSlug: string) => {
try {
this.loader = true;
this.error = null;
const stateResponse = await this.stateService.getStates(workspaceSlug, projectSlug);
const _states = {
...this.states,
[projectSlug]: stateResponse,
};
runInAction(() => {
this.states = _states;
this.loader = false;
this.error = null;
});
} catch (error) {
console.error(error);
this.loader = false;
this.error = error;
}
};
getProjectLabels = async (workspaceSlug: string, projectSlug: string) => {
try {
this.loader = true;
this.error = null;
const labelResponse = await this.issueService.getIssueLabels(workspaceSlug, projectSlug);
const _labels = {
...this.labels,
[projectSlug]: labelResponse,
};
runInAction(() => {
this.labels = _labels;
this.loader = false;
this.error = null;
});
} catch (error) {
console.error(error);
this.loader = false;
this.error = error;
}
};
getProjectMembers = async (workspaceSlug: string, projectSlug: string) => {
try {
this.loader = true;
this.error = null;
const membersResponse = await this.projectService.projectMembers(workspaceSlug, projectSlug);
const _members = {
...this.members,
[projectSlug]: membersResponse,
};
runInAction(() => {
this.members = _members;
this.loader = false;
this.error = null;
});
} catch (error) {
console.error(error);
this.loader = false;
this.error = error;
}
};
handleProjectLeaveModal = (project: IProject | null = null) => {
if (project && project?.id) {
this.projectLeaveModal = !this.projectLeaveModal;
this.projectLeaveDetails = project;
} else {
this.projectLeaveModal = !this.projectLeaveModal;
this.projectLeaveDetails = null;
}
};
leaveProject = async (workspaceSlug: string, projectSlug: string, user: any) => {
try {
this.loader = true;
this.error = null;
const response = await this.projectService.leaveProject(workspaceSlug, projectSlug, user);
runInAction(() => {
this.loader = false;
this.error = null;
});
return response;
} catch (error) {
this.loader = false;
this.error = error;
return error;
}
};
}
export default ProjectStore;

View File

@ -3,15 +3,18 @@ import { enableStaticRendering } from "mobx-react-lite";
// store imports
import UserStore from "./user";
import ThemeStore from "./theme";
import ProjectStore, { IProjectStore } from "./project";
import ProjectPublishStore, { IProjectPublishStore } from "./project-publish";
import IssuesStore from "./issues";
// issues views and filters
import IssueWorkspace from "./issue-views/workspace";
import IssueProject from "./issue-views/project";
import IssueFilterStore from "./issue-views/issue_filters";
import IssueViewStore from "./issue-views/Issues";
import IssueViewDetailStore from "./issue-views/issue_detail";
import WorkspaceStore, { IWorkspaceStore } from "./workspaces";
import ProjectStore, { IProjectStore } from "./projects";
import IssueStore, { IIssueStore } from "./issue-store";
import ModuleStore, { IModuleStore } from "./modules";
import CycleStore, { ICycleStore } from "./cycles";
import ViewStore, { IViewStore } from "./views";
import IssueFilterStore, { IIssueFilterStore } from "./issue-filters";
import IssueViewDetailStore from "./issue_detail";
import IssueKanBanViewStore from "./issue-views/kanban-view";
enableStaticRendering(typeof window === "undefined");
@ -19,28 +22,33 @@ enableStaticRendering(typeof window === "undefined");
export class RootStore {
user;
theme;
project: IProjectStore;
projectPublish: IProjectPublishStore;
issues: IssuesStore;
// issues views and filters
issueWorkspace: IssueWorkspace;
issueProject: IssueProject;
issueFilters: IssueFilterStore;
issueView: IssueViewStore;
workspace: IWorkspaceStore;
project: IProjectStore;
issue: IIssueStore;
module: IModuleStore;
cycle: ICycleStore;
view: IViewStore;
issueFilter: IIssueFilterStore;
issueDetail: IssueViewDetailStore;
issueKanBanView: IssueKanBanViewStore;
constructor() {
this.user = new UserStore(this);
this.theme = new ThemeStore(this);
this.project = new ProjectStore(this);
this.projectPublish = new ProjectPublishStore(this);
this.issues = new IssuesStore(this);
// issues views and filters
this.issueWorkspace = new IssueWorkspace(this);
this.issueProject = new IssueProject(this);
this.issueFilters = new IssueFilterStore(this);
this.issueView = new IssueViewStore(this);
this.workspace = new WorkspaceStore(this);
this.project = new ProjectStore(this);
this.issue = new IssueStore(this);
this.module = new ModuleStore(this);
this.cycle = new CycleStore(this);
this.view = new ViewStore(this);
this.issueFilter = new IssueFilterStore(this);
this.issueDetail = new IssueViewDetailStore(this);
this.issueKanBanView = new IssueKanBanViewStore(this);
}

55
web/store/views.ts Normal file
View File

@ -0,0 +1,55 @@
import { action, computed, observable, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
// services
import { ProjectServices } from "services/project.service";
import { ProjectIssuesServices as IssueServices } from "services/issues.service";
export interface IViewStore {
loader: boolean;
error: any | null;
viewId: string | null;
setViewId: (viewSlug: string) => void;
}
class ViewStore implements IViewStore {
loader: boolean = false;
error: any | null = null;
viewId: string | null = null;
// root store
rootStore;
// services
projectService;
issueService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
loader: observable,
error: observable.ref,
viewId: observable.ref,
// computed
// actions
setViewId: action,
});
this.rootStore = _rootStore;
this.projectService = new ProjectServices();
this.issueService = new IssueServices();
}
// computed
// actions
setViewId = (viewSlug: string) => {
this.viewId = viewSlug ?? null;
};
}
export default ViewStore;

198
web/store/workspaces.ts Normal file
View File

@ -0,0 +1,198 @@
import { action, computed, observable, makeObservable, runInAction } from "mobx";
// types
import { RootStore } from "./root";
import { IIssueLabels, IWorkspace } from "types";
// services
import { WorkspaceService } from "services/workspace.service";
import { ProjectServices } from "services/project.service";
import { ProjectIssuesServices as IssueServices } from "services/issues.service";
export interface IWorkspaceStore {
loader: boolean;
error: any | null;
workspaces: {
[key: string]: IWorkspace; // workspace_id: workspace
} | null;
labels: { [key: string]: { [key: string]: IIssueLabels } } | null; // workspace_id: label_id: labels
workspaceId: string | null;
// computed
currentWorkspace: IWorkspace | null;
workspaceLabels: { [key: string]: IIssueLabels } | null;
// actions
setWorkspaceId: (workspaceSlug: string) => void;
workspaceById: (workspaceId: string) => IWorkspace | null;
workspaceLabelById: (labelId: string) => IIssueLabels | null;
getWorkspaces: () => Promise<void>;
getWorkspaceLabels: (workspaceSlug: string) => Promise<void>;
}
class WorkspaceStore implements IWorkspaceStore {
loader: boolean = false;
error: any | null = null;
workspaces: {
[key: string]: IWorkspace;
} | null = null;
labels: {
[key: string]: { [key: string]: IIssueLabels };
} | null = null;
workspaceId: string | null = null;
// root store
rootStore;
// services
workspaceService;
projectService;
issueService;
constructor(_rootStore: RootStore) {
makeObservable(this, {
loader: observable,
error: observable.ref,
workspaces: observable.ref,
labels: observable.ref,
workspaceId: observable.ref,
// computed
currentWorkspace: computed,
workspaceLabels: computed,
// actions
setWorkspaceId: action,
workspaceById: action,
workspaceLabelById: action,
getWorkspaces: action,
getWorkspaceLabels: action,
});
this.rootStore = _rootStore;
this.workspaceService = new WorkspaceService();
this.projectService = new ProjectServices();
this.issueService = new IssueServices();
}
// computed
get currentWorkspace() {
if (!this.workspaceId) return null;
return this.workspaces?.[this.workspaceId] || null;
}
get workspaceLabels() {
if (!this.workspaceId) return null;
const _labels = this.labels?.[this.workspaceId];
return _labels && Object.keys(_labels).length > 0 ? _labels : null;
}
// actions
workspaceById = (workspaceId: string) => this.workspaces?.[workspaceId] || null;
workspaceLabelById = (labelId: string) => {
if (!this.workspaceId) return null;
return this.labels?.[this.workspaceId]?.[labelId] || null;
};
setWorkspaceId = (workspaceSlug: string) => {
this.workspaceId = workspaceSlug ?? null;
};
getWorkspaces = async () => {
try {
this.loader = true;
this.error = null;
const workspaceResponse = await this.workspaceService.userWorkspaces();
let _workspaces: { [key: string]: IWorkspace } = {};
workspaceResponse.map((_workspace) => {
_workspaces = { ..._workspaces, [_workspace.slug]: _workspace };
});
runInAction(() => {
this.workspaces = _workspaces;
this.loader = false;
this.error = null;
});
} catch (error) {
console.log(error);
this.loader = false;
this.error = error;
}
};
getWorkspaceLabels = async (workspaceSlug: string) => {
try {
this.loader = true;
this.error = null;
const labelsResponse = await this.issueService.getWorkspaceLabels(workspaceSlug);
let _labels: { [key: string]: IIssueLabels } = {};
labelsResponse.map((_label) => {
_labels = { ..._labels, [_label.id]: _label };
});
runInAction(() => {
this.labels = {
...this.labels,
[workspaceSlug]: _labels,
};
this.loader = false;
this.error = null;
});
} catch (error) {
console.log(error);
this.loader = false;
this.error = error;
}
};
// getMyIssuesAsync = async (workspaceId: string, fetchFilterToggle: boolean = true) => {
// try {
// this.loader = true;
// this.error = null;
// if (fetchFilterToggle) await this.rootStore.issueFilters.getWorkspaceMyIssuesFilters(workspaceId);
// const filteredParams = this.rootStore.issueFilters.getComputedFilters(
// workspaceId,
// null,
// null,
// null,
// null,
// "my_issues"
// );
// const issuesResponse = await this.userService.userIssues(workspaceId, filteredParams);
// if (issuesResponse) {
// const _issueResponse: any = {
// ...this.issues,
// [workspaceId]: {
// ...this?.issues[workspaceId],
// my_issues: {
// ...this?.issues[workspaceId]?.my_issues,
// [this.rootStore?.issueFilters?.userFilters?.display_filters?.layout as string]: issuesResponse,
// },
// },
// };
// runInAction(() => {
// this.issues = _issueResponse;
// this.loader = false;
// this.error = null;
// });
// }
// return issuesResponse;
// } catch (error) {
// console.warn("error in fetching the my issues", error);
// this.loader = false;
// this.error = null;
// return error;
// }
// };
}
export default WorkspaceStore;