forked from github/plane
chore: updated the store for issues and issue filters
This commit is contained in:
parent
7c5936e463
commit
b9a6a00470
@ -22,22 +22,23 @@ export const IssueContent = ({ columnId, issues }: IssueContentProps) => {
|
||||
{(provided: any, snapshot: any) => (
|
||||
<div
|
||||
key={issue.id}
|
||||
className="p-2"
|
||||
className="p-1.5 hover:cursor-default"
|
||||
{...provided.draggableProps}
|
||||
{...provided.dragHandleProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
<div
|
||||
className={`text-sm rounded p-2 px-3 bg-white shadow space-y-1 border border-transparent`}
|
||||
className={`min-h-[106px] text-sm rounded p-2 px-3 shadow-md space-y-[4px] border transition-all hover:cursor-grab ${
|
||||
snapshot.isDragging
|
||||
? `border-blue-500 bg-blue-50`
|
||||
: `border-transparent bg-white`
|
||||
}`}
|
||||
>
|
||||
<div className="text-xs line-clamp-1 text-gray-500 font-medium">
|
||||
<div className="text-xs line-clamp-1 text-gray-500">
|
||||
ONE-{issue.sequence_id}-{issue.sort_order}
|
||||
</div>
|
||||
<div className="line-clamp-2 h-[42px]">
|
||||
{issue.name} {issue.name} {issue.name} {issue.name} {issue.name} {issue.name}{" "}
|
||||
{issue.name} {issue.name}
|
||||
</div>
|
||||
<div>Footer</div>
|
||||
<div className="line-clamp-2 h-[40px] text-sm font-medium">{issue.name}</div>
|
||||
<div className="h-[22px]">Footer</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
@ -1 +0,0 @@
|
||||
export const IssueFooter = () => <div>Footer</div>;
|
@ -1 +1,22 @@
|
||||
export const IssueHeader = () => <div>Header</div>;
|
||||
// lucide icons
|
||||
import { Plus } from "lucide-react";
|
||||
|
||||
export const IssueHeader = () => (
|
||||
<div className="relative flex flex-colw-full h-full gap-1">
|
||||
{/* default layout */}
|
||||
<div className=" border border-red-500 flex-shrink-0 w-[24px] h-[24px] flex justify-center items-center">
|
||||
I
|
||||
</div>
|
||||
<div className=" border border-red-500 line-clamp-1 font-medium">Kanban Issue Heading</div>
|
||||
<div className=" border border-red-500 flex-shrink-0 w-[24px] h-[24px] flex justify-center items-center">
|
||||
0
|
||||
</div>
|
||||
|
||||
<div className=" border border-red-500 ml-auto flex-shrink-0 w-[24px] h-[24px] flex justify-center items-center cursor-pointer rounded-sm hover:bg-gray-100 transition-all">
|
||||
M
|
||||
</div>
|
||||
<div className=" border border-red-500 flex-shrink-0 w-[24px] h-[24px] flex justify-center items-center cursor-pointer rounded-sm hover:bg-gray-100 transition-all text-blue-800">
|
||||
<Plus size={16} strokeWidth={2} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -4,66 +4,75 @@ import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
||||
// components
|
||||
import { IssueHeader } from "./header";
|
||||
import { IssueContent } from "./content";
|
||||
import { IssueFooter } from "./footer";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const IssueRoot = observer(() => {
|
||||
export const IssueKanBanViewRoot = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { kanban: issueViewStore } = store;
|
||||
const { issueView: issueViewStore } = store;
|
||||
|
||||
const onDragEnd = (result: any) => {
|
||||
if (!result) return;
|
||||
|
||||
if (
|
||||
result.destination &&
|
||||
result.source &&
|
||||
result.destination.droppableId === result.source.droppableId &&
|
||||
result.destination.index === result.source.index
|
||||
)
|
||||
return;
|
||||
|
||||
console.log("result", result);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative w-screen h-screen">
|
||||
<div className="relative w-full h-full">
|
||||
{issueViewStore.loader && issueViewStore?.issues === null ? (
|
||||
<div>Loading...</div>
|
||||
) : (
|
||||
<div className="relative w-full h-full p-2">
|
||||
<>
|
||||
{issueViewStore?.getIssues && Object.keys(issueViewStore?.getIssues).length > 0 ? (
|
||||
<div className="relative overflow-hidden overflow-x-auto w-full h-full flex">
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<DragDropContext onDragEnd={onDragEnd}>
|
||||
<div className="relative w-full h-full overflow-hidden !overflow-x-scroll flex">
|
||||
{Object.keys(issueViewStore?.getIssues).map((_issueStateKey: any) => (
|
||||
<div
|
||||
key={`${_issueStateKey}`}
|
||||
className="flex-shrink-0 w-[380px] h-full relative flex flex-col"
|
||||
>
|
||||
<div className="flex-shrink-0 w-full p-2 py-1">
|
||||
<div className="flex-shrink-0 w-full p-2">
|
||||
<IssueHeader />
|
||||
</div>
|
||||
|
||||
<div className="w-full h-full overflow-auto">
|
||||
<Droppable droppableId={`${_issueStateKey}`}>
|
||||
{(provided: any, snapshot: any) => (
|
||||
<>
|
||||
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||
<IssueContent
|
||||
columnId={_issueStateKey}
|
||||
issues={issueViewStore?.getIssues[_issueStateKey]}
|
||||
/>
|
||||
</div>
|
||||
{provided.placeholder}
|
||||
</>
|
||||
)}
|
||||
</Droppable>
|
||||
</div>
|
||||
|
||||
<div className="flex-shrink-0 w-full p-2 py-1">
|
||||
<IssueFooter />
|
||||
</div>
|
||||
<Droppable droppableId={`${_issueStateKey}`}>
|
||||
{(provided: any, snapshot: any) => (
|
||||
<div
|
||||
className={`w-full h-full relative transition-all py-1.5 overflow-hidden overflow-y-auto ${
|
||||
snapshot.isDraggingOver ? `bg-orange-50` : `bg-gray-50`
|
||||
}`}
|
||||
{...provided.droppableProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
{issueViewStore?.getIssues && (
|
||||
<IssueContent
|
||||
columnId={_issueStateKey}
|
||||
issues={issueViewStore?.getIssues[_issueStateKey]}
|
||||
/>
|
||||
)}
|
||||
{provided.placeholder}
|
||||
</div>
|
||||
)}
|
||||
</Droppable>
|
||||
</div>
|
||||
))}
|
||||
</DragDropContext>
|
||||
</div>
|
||||
</div>
|
||||
</DragDropContext>
|
||||
) : (
|
||||
<div>No Issues are available</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -58,7 +58,7 @@
|
||||
"js-cookie": "^3.0.1",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"lowlight": "^2.9.0",
|
||||
"lucide-react": "^0.263.1",
|
||||
"lucide-react": "^0.274.0",
|
||||
"mobx": "^6.10.0",
|
||||
"mobx-react-lite": "^4.0.3",
|
||||
"next": "12.3.2",
|
||||
|
@ -2,28 +2,175 @@ import React from "react";
|
||||
// swr
|
||||
import useSWR from "swr";
|
||||
// components
|
||||
import { IssueRoot } from "components/issue-layouts/kanban";
|
||||
import { IssueKanBanViewRoot } from "components/issue-layouts/kanban";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
const KanbanViewRoot = () => {
|
||||
const KanBanViewRoot = () => {
|
||||
const workspaceSlug: string = "plane-demo";
|
||||
const projectSlug: string = "5b0e3f6e-c9f1-444d-be22-a8c2706bcf54";
|
||||
const projectSlug: string = "08d59d96-9dfb-40e5-aa30-ecc66319450f";
|
||||
const moduleSlug: string = "05613afc-29ea-4fd8-a025-a3cdfed209d1";
|
||||
const cycleSlug: string = "1f66a767-00d1-422c-8f8f-6925282b7249";
|
||||
const viewSlug: string = "1f66a767-00d1-422c-8f8f-6925282b7249";
|
||||
|
||||
const store: RootStore = useMobxStore();
|
||||
const { kanban: issueViewStore } = store;
|
||||
const { issueView: issueViewStore } = store;
|
||||
|
||||
useSWR(`PROJECT_ISSUES_KANBAN_VIEW`, () => {
|
||||
if (workspaceSlug && projectSlug)
|
||||
issueViewStore.getIssuesAsync(workspaceSlug, projectSlug, "kanban");
|
||||
});
|
||||
React.useEffect(() => {
|
||||
const init = async () => {
|
||||
// my issues under a workspace
|
||||
console.log("started--->");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "list");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "kanban");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "calendar");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "spreadsheet");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "gantt");
|
||||
|
||||
// project issues under and workspace and project
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "list");
|
||||
await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "kanban");
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "calendar");
|
||||
// await issueViewStore.getProjectIssuesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// "issues",
|
||||
// "spreadsheet"
|
||||
// );
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "gantt");
|
||||
|
||||
// module issues under and workspace and project
|
||||
// await issueViewStore.getIssuesForModulesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// moduleSlug,
|
||||
// "modules",
|
||||
// "list"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForModulesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// moduleSlug,
|
||||
// "modules",
|
||||
// "kanban"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForModulesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// moduleSlug,
|
||||
// "modules",
|
||||
// "calendar"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForModulesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// moduleSlug,
|
||||
// "modules",
|
||||
// "spreadsheet"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForModulesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// moduleSlug,
|
||||
// "modules",
|
||||
// "gantt"
|
||||
// );
|
||||
|
||||
// cycle issues under and workspace and project
|
||||
// await issueViewStore.getIssuesForCyclesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// cycleSlug,
|
||||
// "cycles",
|
||||
// "list"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForCyclesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// cycleSlug,
|
||||
// "cycles",
|
||||
// "kanban"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForCyclesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// cycleSlug,
|
||||
// "cycles",
|
||||
// "calendar"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForCyclesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// cycleSlug,
|
||||
// "cycles",
|
||||
// "spreadsheet"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForCyclesAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// cycleSlug,
|
||||
// "cycles",
|
||||
// "gantt"
|
||||
// );
|
||||
|
||||
// cycle issues under and workspace and project
|
||||
// await issueViewStore.getIssuesForViewsAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// viewSlug,
|
||||
// "views",
|
||||
// "list"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForViewsAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// viewSlug,
|
||||
// "views",
|
||||
// "kanban"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForViewsAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// viewSlug,
|
||||
// "views",
|
||||
// "calendar"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForViewsAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// viewSlug,
|
||||
// "views",
|
||||
// "spreadsheet"
|
||||
// );
|
||||
// await issueViewStore.getIssuesForViewsAsync(
|
||||
// workspaceSlug,
|
||||
// projectSlug,
|
||||
// viewSlug,
|
||||
// "views",
|
||||
// "gantt"
|
||||
// );
|
||||
|
||||
console.log("ended--->");
|
||||
};
|
||||
|
||||
init();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<IssueRoot />
|
||||
<div className="w-screen min-h-[600px] h-screen">
|
||||
<div className="w-full h-full relative flex flex-col overflow-hidden">
|
||||
<div
|
||||
className="flex-shrink-0 h-[60px] border-b border-gray-200"
|
||||
// style={{ writingMode: "vertical-lr" }}
|
||||
>
|
||||
Filter Header
|
||||
</div>
|
||||
<div className="w-full h-full relative overflow-hidden">
|
||||
<IssueKanBanViewRoot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default KanbanViewRoot;
|
||||
export default KanBanViewRoot;
|
||||
|
@ -10,7 +10,7 @@ const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
const trackEvent =
|
||||
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||
|
||||
class ProjectCycleServices extends APIService {
|
||||
export class ProjectCycleServices extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
const trackEvent =
|
||||
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||
|
||||
class ProjectIssuesServices extends APIService {
|
||||
export class ProjectIssuesServices extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
const trackEvent =
|
||||
process.env.NEXT_PUBLIC_TRACK_EVENTS === "true" || process.env.NEXT_PUBLIC_TRACK_EVENTS === "1";
|
||||
|
||||
class UserService extends APIService {
|
||||
export class UserService extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
205
web/store/issue-views/Issue_details.ts
Normal file
205
web/store/issue-views/Issue_details.ts
Normal file
@ -0,0 +1,205 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "../root";
|
||||
// services
|
||||
import { ProjectIssuesServices } from "services/issues.service";
|
||||
// types
|
||||
import { TIssueLayouts } from "./issue_filters";
|
||||
|
||||
export interface IIssueViewStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
issues: { [key: string]: { [key: string]: any } } | null;
|
||||
|
||||
getIssuesAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
view: TIssueLayouts | null
|
||||
) => null | Promise<any>;
|
||||
}
|
||||
|
||||
class IssueViewStore implements IIssueViewStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
issues: { [key: string]: { [key: string]: any } } | null = null;
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
issueService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
issues: observable.ref,
|
||||
// action
|
||||
getIssuesAsync: action,
|
||||
// computed
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.issueService = new ProjectIssuesServices();
|
||||
}
|
||||
|
||||
// computed
|
||||
get getIssues() {
|
||||
if (
|
||||
this.rootStore.issueFilters.projectId &&
|
||||
this.issues != null &&
|
||||
this.rootStore.issueFilters.issueView != null
|
||||
)
|
||||
return this.issues[this.rootStore.issueFilters.projectId][
|
||||
this.rootStore.issueFilters.issueView
|
||||
];
|
||||
else return null;
|
||||
}
|
||||
|
||||
// handling kanBan drag and drop events
|
||||
|
||||
// fetching issues
|
||||
getIssuesAsync = async (workspaceId: string, projectId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
"kanBan",
|
||||
"issues"
|
||||
);
|
||||
const issuesResponse = await this.issueService.getIssuesWithParams(
|
||||
workspaceId,
|
||||
projectId,
|
||||
filteredParams
|
||||
);
|
||||
|
||||
if (issuesResponse) {
|
||||
runInAction(() => {
|
||||
this.issues = { ...this.issues, [projectId]: { issues: { ...issuesResponse } } };
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching issues for modules
|
||||
getIssuesForModulesAsync = async (workspaceId: string, projectId: string, moduleId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
"kanBan",
|
||||
"modules"
|
||||
);
|
||||
const issuesResponse = await this.issueService.getIssuesWithParams(
|
||||
workspaceId,
|
||||
projectId,
|
||||
filteredParams
|
||||
);
|
||||
|
||||
if (issuesResponse) {
|
||||
runInAction(() => {
|
||||
this.issues = { ...this.issues, [projectId]: { views: { ...issuesResponse } } };
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching issues for cycles
|
||||
getIssuesForModulesCycles = async (workspaceId: string, projectId: string, moduleId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
"kanBan",
|
||||
"cycles"
|
||||
);
|
||||
const issuesResponse = await this.issueService.getIssuesWithParams(
|
||||
workspaceId,
|
||||
projectId,
|
||||
filteredParams
|
||||
);
|
||||
|
||||
if (issuesResponse) {
|
||||
runInAction(() => {
|
||||
this.issues = { ...this.issues, [projectId]: { views: { ...issuesResponse } } };
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching issues for views
|
||||
getIssuesForViews = async (workspaceId: string, projectId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
"kanBan",
|
||||
"views"
|
||||
);
|
||||
const issuesResponse = await this.issueService.getIssuesWithParams(
|
||||
workspaceId,
|
||||
projectId,
|
||||
filteredParams
|
||||
);
|
||||
|
||||
if (issuesResponse) {
|
||||
runInAction(() => {
|
||||
this.issues = { ...this.issues, [projectId]: { views: { ...issuesResponse } } };
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default IssueViewStore;
|
454
web/store/issue-views/Issues.ts
Normal file
454
web/store/issue-views/Issues.ts
Normal file
@ -0,0 +1,454 @@
|
||||
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: 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,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => null | Promise<any>;
|
||||
getProjectIssuesAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => null | Promise<any>;
|
||||
getIssuesForModulesAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => null | Promise<any>;
|
||||
getIssuesForCyclesAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => null | Promise<any>;
|
||||
getIssuesForViewsAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
viewId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => 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,
|
||||
// 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 currentLayout: TIssueLayouts | null = this.rootStore.issueFilters.issueLayout;
|
||||
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 || !currentLayout || !currentWorkspaceId) return null;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
// fetching my issues
|
||||
getMyIssuesAsync = async (workspaceId: string, _view: TIssueViews, _layout: TIssueLayouts) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
_view,
|
||||
_layout
|
||||
);
|
||||
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,
|
||||
[_layout as string]: issuesResponse,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issueResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching project issues
|
||||
getProjectIssuesAsync = async (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
_view,
|
||||
_layout
|
||||
);
|
||||
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,
|
||||
[_layout as string]: issuesResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issueResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching project issues for modules
|
||||
getIssuesForModulesAsync = async (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
moduleId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
moduleId,
|
||||
null,
|
||||
null,
|
||||
_view,
|
||||
_layout
|
||||
);
|
||||
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],
|
||||
[_layout as string]: issuesResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issueResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching project issues for cycles
|
||||
getIssuesForCyclesAsync = async (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
cycleId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
null,
|
||||
cycleId,
|
||||
null,
|
||||
_view,
|
||||
_layout
|
||||
);
|
||||
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],
|
||||
[_layout as string]: issuesResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issueResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// fetching project issues for views
|
||||
getIssuesForViewsAsync = async (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
viewId: string,
|
||||
_view: TIssueViews,
|
||||
_layout: TIssueLayouts
|
||||
) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
null,
|
||||
null,
|
||||
viewId,
|
||||
_view,
|
||||
_layout
|
||||
);
|
||||
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],
|
||||
[_layout as string]: issuesResponse,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issueResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default IssueViewStore;
|
@ -1,154 +0,0 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "../root";
|
||||
// services
|
||||
import {} from "services/issues.service";
|
||||
|
||||
export type TIssueViews = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt";
|
||||
|
||||
export interface IIssueFilterStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
// current issue view
|
||||
workspaceId: string | null;
|
||||
projectId: string | null;
|
||||
issueView: string | null;
|
||||
|
||||
// filters
|
||||
priority?: null;
|
||||
state?: null;
|
||||
assignees?: null;
|
||||
createdBy?: null;
|
||||
labels?: null;
|
||||
startDate?: null;
|
||||
dueDate?: null;
|
||||
userSelectedParams?: {
|
||||
assignees: undefined | string;
|
||||
created_by: undefined | string;
|
||||
group_by: undefined | string;
|
||||
labels: undefined | string;
|
||||
order_by: undefined | string;
|
||||
priority: undefined | string;
|
||||
start_date: undefined | string;
|
||||
state: undefined | string;
|
||||
sub_issue: boolean;
|
||||
target_date: undefined | string;
|
||||
type: undefined | string;
|
||||
};
|
||||
|
||||
// display properties
|
||||
displayProperties?: {
|
||||
assignee: boolean;
|
||||
attachment_count: boolean;
|
||||
created_on: boolean;
|
||||
due_date: boolean;
|
||||
estimate: boolean;
|
||||
key: boolean;
|
||||
labels: boolean;
|
||||
link: boolean;
|
||||
priority: boolean;
|
||||
start_date: boolean;
|
||||
state: boolean;
|
||||
sub_issue_count: boolean;
|
||||
updated_on: boolean;
|
||||
};
|
||||
|
||||
// extra's
|
||||
showEmptyGroups?: boolean;
|
||||
|
||||
// actions
|
||||
getProjectIssueFilterProperties: () => any | Promise<any>;
|
||||
getProjectIssueDisplayProperties: () => any | Promise<any>;
|
||||
getProjectMembers: () => any | Promise<any>;
|
||||
getProjectStates: () => any | Promise<any>;
|
||||
getProjectLabels: () => any | Promise<any>;
|
||||
}
|
||||
|
||||
class IssueFilterStore implements IIssueFilterStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
workspaceId: string | null = null;
|
||||
projectId: string | null = null;
|
||||
issueView: string | null = null;
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
projectPublishService = null;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
workspaceId: observable,
|
||||
projectId: observable,
|
||||
|
||||
// action
|
||||
getProjectIssueFilterProperties: action,
|
||||
getProjectIssueDisplayProperties: action,
|
||||
getProjectMembers: action,
|
||||
getProjectStates: action,
|
||||
getProjectLabels: action,
|
||||
// computed
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectPublishService = null;
|
||||
}
|
||||
|
||||
// computed functions starts
|
||||
getComputedFilters = (
|
||||
_workspaceId: string,
|
||||
_projectId: string,
|
||||
_view: TIssueViews | null = "kanban"
|
||||
) => {
|
||||
this.workspaceId = _workspaceId;
|
||||
this.projectId = _projectId;
|
||||
this.issueView = _view;
|
||||
|
||||
let filteredRouteParams = {
|
||||
assignees: undefined, // ['user_id', 'user_id']
|
||||
state: undefined, // ['state_id', 'state_id']
|
||||
priority: undefined, // ['low', 'high', 'medium', 'urgent', 'null']
|
||||
type: undefined, // 'active' (started, un_started) || 'backlog' || 'null' (all_the_issues)
|
||||
labels: undefined, // ['label_id', 'label_id']
|
||||
created_by: undefined, // ['user_id', 'user_id']
|
||||
start_date: undefined, // ['yyyy-mm-dd:after/before', 'yyyy-mm-dd:after/before']
|
||||
target_date: undefined, // [yyyy-mm-dd:after, yyyy-mm-dd:before]
|
||||
order_by: "-created_at", // TIssueOrderByOptions
|
||||
group_by: "state", // TIssueGroupByOptions
|
||||
sub_issue: true, // true for all other views except spreadsheet
|
||||
};
|
||||
|
||||
if (_view === "list") filteredRouteParams = { ...filteredRouteParams };
|
||||
if (_view === "kanban") filteredRouteParams = { ...filteredRouteParams };
|
||||
if (_view === "calendar") filteredRouteParams = { ...filteredRouteParams };
|
||||
if (_view === "spreadsheet") filteredRouteParams = { ...filteredRouteParams };
|
||||
if (_view === "gantt") filteredRouteParams = { ...filteredRouteParams };
|
||||
|
||||
return filteredRouteParams;
|
||||
};
|
||||
|
||||
// computed functions ends
|
||||
|
||||
// fetching current user project issue filter and display settings
|
||||
getProjectIssueFilterProperties = () => {};
|
||||
|
||||
// fetching display properties
|
||||
getProjectIssueDisplayProperties = () => {};
|
||||
|
||||
// fetching project members
|
||||
getProjectMembers = () => {};
|
||||
|
||||
// fetching project state <-> groups
|
||||
getProjectStates = () => {};
|
||||
|
||||
// fetching project labels
|
||||
getProjectLabels = () => {};
|
||||
}
|
||||
|
||||
export default IssueFilterStore;
|
@ -1,25 +1,25 @@
|
||||
export const filtersPriority: { key: string; title: string }[] = [
|
||||
{ key: "", title: "Urgent" },
|
||||
{ key: "", title: "High" },
|
||||
{ key: "", title: "Medium" },
|
||||
{ key: "", title: "Low" },
|
||||
{ key: "", title: "None" },
|
||||
{ key: "urgent", title: "Urgent" },
|
||||
{ key: "high", title: "High" },
|
||||
{ key: "medium", title: "Medium" },
|
||||
{ key: "low", title: "Low" },
|
||||
{ key: "null", title: "None" },
|
||||
];
|
||||
|
||||
export const filtersStartDate = [
|
||||
{ key: "", title: "Last Week" },
|
||||
{ key: "", title: "2 weeks from now" },
|
||||
{ key: "", title: "1 month from now" },
|
||||
{ key: "", title: "2 months from now" },
|
||||
{ key: "", title: "Custom" },
|
||||
{ key: "last_week", title: "Last Week" },
|
||||
{ key: "2_weeks_from_now", title: "2 weeks from now" },
|
||||
{ key: "1_month_from_now", title: "1 month from now" },
|
||||
{ key: "2_months_from_now", title: "2 months from now" },
|
||||
{ key: "custom", title: "Custom" },
|
||||
];
|
||||
|
||||
export const filtersDueDate = [
|
||||
{ key: "", title: "Last Week" },
|
||||
{ key: "", title: "2 weeks from now" },
|
||||
{ key: "", title: "1 month from now" },
|
||||
{ key: "", title: "2 months from now" },
|
||||
{ key: "", title: "Custom" },
|
||||
{ key: "last_week", title: "Last Week" },
|
||||
{ key: "2_weeks_from_now", title: "2 weeks from now" },
|
||||
{ key: "1_month_from_now", title: "1 month from now" },
|
||||
{ key: "2_months_from_now", title: "2 months from now" },
|
||||
{ key: "custom", title: "Custom" },
|
||||
];
|
||||
|
||||
export const displayPropertyGroupBy = [
|
330
web/store/issue-views/issue_filters.ts
Normal file
330
web/store/issue-views/issue_filters.ts
Normal file
@ -0,0 +1,330 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "../root";
|
||||
// services
|
||||
import {} from "services/issues.service";
|
||||
// default data
|
||||
import {
|
||||
filtersPriority,
|
||||
filtersStartDate,
|
||||
filtersDueDate,
|
||||
displayPropertyGroupBy,
|
||||
displayPropertyOrderBy,
|
||||
displayPropertyIssueType,
|
||||
displayProperties,
|
||||
} from "./issue_data";
|
||||
|
||||
export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles";
|
||||
export type TIssueLayouts = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt";
|
||||
|
||||
export interface IIssueFilterStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
// current workspace and project id
|
||||
workspaceId: string | null;
|
||||
projectId: string | null;
|
||||
moduleId: string | null;
|
||||
cycleId: string | null;
|
||||
viewId: string | null;
|
||||
// current issue layout:TIssueLayouts and view:TIssueViews
|
||||
issueView: TIssueViews | null;
|
||||
issueLayout: TIssueLayouts | null;
|
||||
|
||||
// filters
|
||||
// static filters data
|
||||
priority: { key: string; title: string }[];
|
||||
startDate: { key: string; title: string }[];
|
||||
dueDate: { key: string; title: string }[];
|
||||
issueType: { key: string; title: string }[];
|
||||
|
||||
// static display filters data
|
||||
groupBy: { key: string; title: string }[];
|
||||
orderBy: { key: string; title: string }[];
|
||||
|
||||
// dynamic filters data
|
||||
state: { [key: string]: { key: string; title: string }[] } | null;
|
||||
members: { [key: string]: { key: string; title: string }[] } | null; // members are used for both assignees and crated_by
|
||||
labels: { [key: string]: { key: string; title: string }[] } | null;
|
||||
|
||||
userSelectedFilters: {
|
||||
priority: string[] | null;
|
||||
state: string[] | null;
|
||||
assignees: string[] | null;
|
||||
created_by: string[] | null;
|
||||
labels: string[] | null;
|
||||
start_date: string[] | null;
|
||||
target_date: string[] | null;
|
||||
type: string;
|
||||
};
|
||||
|
||||
userSelectedDisplayFilters?: {
|
||||
group_by: undefined | string;
|
||||
order_by: undefined | string;
|
||||
sub_issue: boolean;
|
||||
showEmptyGroups: boolean;
|
||||
};
|
||||
|
||||
// static display properties data
|
||||
displayProperties?: { key: string; title: string }[] | null;
|
||||
userSelectedDisplayProperties?: {
|
||||
assignee: boolean;
|
||||
attachment_count: boolean;
|
||||
created_on: boolean;
|
||||
due_date: boolean;
|
||||
estimate: boolean;
|
||||
key: boolean;
|
||||
labels: boolean;
|
||||
link: boolean;
|
||||
priority: boolean;
|
||||
start_date: boolean;
|
||||
state: boolean;
|
||||
sub_issue_count: boolean;
|
||||
updated_on: boolean;
|
||||
};
|
||||
|
||||
// actions
|
||||
getProjectIssueFilterProperties: () => any | Promise<any>;
|
||||
getProjectIssueDisplayProperties: () => any | Promise<any>;
|
||||
getProjectMembers: () => any | Promise<any>;
|
||||
getProjectStates: () => any | Promise<any>;
|
||||
getProjectLabels: () => any | Promise<any>;
|
||||
}
|
||||
|
||||
class IssueFilterStore implements IIssueFilterStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
workspaceId: string | null = null;
|
||||
projectId: string | null = null;
|
||||
moduleId: string | null = null;
|
||||
cycleId: string | null = null;
|
||||
viewId: string | null = null;
|
||||
|
||||
issueLayout: TIssueLayouts | null = null;
|
||||
issueView: TIssueViews | null = null;
|
||||
|
||||
priority: { key: string; title: string }[] = filtersPriority;
|
||||
startDate: { key: string; title: string }[] = filtersStartDate;
|
||||
dueDate: { key: string; title: string }[] = filtersDueDate;
|
||||
issueType: { key: string; title: string }[] = displayPropertyIssueType;
|
||||
|
||||
// static display filters data
|
||||
groupBy: { key: string; title: string }[] = displayPropertyGroupBy;
|
||||
orderBy: { key: string; title: string }[] = displayPropertyOrderBy;
|
||||
|
||||
state: { [key: string]: { key: string; title: string }[] } | null = null;
|
||||
members: { [key: string]: { key: string; title: string }[] } | null = null;
|
||||
labels: { [key: string]: { key: string; title: string }[] } | null = null;
|
||||
|
||||
userSelectedFilters: {
|
||||
priority: string[] | null;
|
||||
state: string[] | null;
|
||||
assignees: string[] | null;
|
||||
created_by: string[] | null;
|
||||
labels: string[] | null;
|
||||
start_date: string[] | null;
|
||||
target_date: string[] | null;
|
||||
type: string;
|
||||
} = {
|
||||
priority: null,
|
||||
state: null,
|
||||
assignees: null,
|
||||
created_by: null,
|
||||
labels: null,
|
||||
start_date: null,
|
||||
target_date: null,
|
||||
type: "all",
|
||||
};
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
projectPublishService = null;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
workspaceId: observable,
|
||||
projectId: observable,
|
||||
moduleId: observable,
|
||||
cycleId: observable,
|
||||
viewId: observable,
|
||||
|
||||
issueLayout: observable,
|
||||
issueView: observable,
|
||||
|
||||
state: observable.ref,
|
||||
members: observable.ref,
|
||||
labels: observable.ref,
|
||||
|
||||
userSelectedFilters: observable.ref,
|
||||
|
||||
// action
|
||||
setWorkspaceId: action,
|
||||
setProjectId: action,
|
||||
setModuleId: action,
|
||||
setCycleId: action,
|
||||
setViewId: action,
|
||||
|
||||
setIssueLayout: action,
|
||||
setIssueView: action,
|
||||
|
||||
getProjectIssueFilterProperties: action,
|
||||
getProjectIssueDisplayProperties: action,
|
||||
getProjectMembers: action,
|
||||
getProjectStates: action,
|
||||
getProjectLabels: action,
|
||||
// computed
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectPublishService = null;
|
||||
}
|
||||
|
||||
setWorkspaceId = (_workspaceId: string | null) => (this.workspaceId = _workspaceId);
|
||||
setProjectId = (_projectId: string | null) => (this.projectId = _projectId);
|
||||
setModuleId = (_moduleId: string | null) => (this.moduleId = _moduleId);
|
||||
setCycleId = (_cycleId: string | null) => (this.cycleId = _cycleId);
|
||||
setViewId = (_viewId: string | null) => (this.viewId = _viewId);
|
||||
setIssueLayout = (_layout: TIssueLayouts | null) => (this.issueLayout = _layout);
|
||||
setIssueView = (_view: TIssueViews | null) => (this.issueView = _view);
|
||||
|
||||
computedFilter = (filters: any, filteredParams: any) => {
|
||||
const computedFilters: any = {};
|
||||
Object.keys(filters).map((key) => {
|
||||
if (filters[key] != undefined && filteredParams.includes(key))
|
||||
computedFilters[key] =
|
||||
typeof filters[key] === "string" || typeof filters[key] === "boolean"
|
||||
? filters[key]
|
||||
: filters[key].join(",");
|
||||
});
|
||||
|
||||
return computedFilters;
|
||||
};
|
||||
|
||||
// computed functions starts
|
||||
getComputedFilters = (
|
||||
_workspaceId: string | null,
|
||||
_projectId: string | null,
|
||||
_moduleId: string | null,
|
||||
_cycleId: string | null,
|
||||
_viewId: string | null,
|
||||
_issueView: TIssueViews,
|
||||
_issueLayout: TIssueLayouts
|
||||
) => {
|
||||
this.setWorkspaceId(_workspaceId);
|
||||
this.setProjectId(_projectId);
|
||||
this.setModuleId(_moduleId);
|
||||
this.setCycleId(_cycleId);
|
||||
this.setViewId(_viewId);
|
||||
this.setIssueView(_issueView);
|
||||
this.setIssueLayout(_issueLayout);
|
||||
|
||||
let filteredRouteParams: any = {
|
||||
priority: this.userSelectedFilters?.priority || undefined,
|
||||
state: this.userSelectedFilters?.state || undefined,
|
||||
assignees: this.userSelectedFilters?.assignees || undefined, // ['user_id', 'user_id']
|
||||
created_by: this.userSelectedFilters?.created_by || undefined, // ['user_id', 'user_id']
|
||||
labels: this.userSelectedFilters?.labels || undefined, // ['label_id', 'label_id']
|
||||
start_date: this.userSelectedFilters?.start_date || undefined, // ['yyyy-mm-dd:after/before', 'yyyy-mm-dd:after/before']
|
||||
target_date: this.userSelectedFilters?.target_date || undefined, // [yyyy-mm-dd:after, yyyy-mm-dd:before]
|
||||
type: this.userSelectedFilters?.type || undefined, // 'active' (started, un_started) || 'backlog' || 'null' (all_the_issues)
|
||||
group_by: "state", // TIssueGroupByOptions
|
||||
order_by: "-created_at", // TIssueOrderByOptions
|
||||
sub_issue: true, // true for all other views except spreadsheet
|
||||
};
|
||||
|
||||
let filteredParams: any = {};
|
||||
|
||||
if (this.issueLayout === "list")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"group_by",
|
||||
"order_by",
|
||||
"sub_issue",
|
||||
];
|
||||
if (this.issueLayout === "kanban")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"group_by",
|
||||
"order_by",
|
||||
"sub_issue",
|
||||
];
|
||||
if (this.issueLayout === "calendar")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
];
|
||||
if (this.issueLayout === "spreadsheet")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
];
|
||||
if (this.issueLayout === "gantt")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"order_by",
|
||||
"sub_issue_id",
|
||||
];
|
||||
|
||||
filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams);
|
||||
|
||||
return filteredRouteParams;
|
||||
};
|
||||
|
||||
// computed functions ends
|
||||
|
||||
// fetching current user project issue filter and display settings
|
||||
getProjectIssueFilterProperties = () => {};
|
||||
|
||||
// fetching display properties
|
||||
getProjectIssueDisplayProperties = () => {};
|
||||
|
||||
// fetching project members
|
||||
getProjectMembers = () => {};
|
||||
|
||||
// fetching project state <-> groups
|
||||
getProjectStates = () => {};
|
||||
|
||||
// fetching project labels
|
||||
getProjectLabels = () => {};
|
||||
}
|
||||
|
||||
export default IssueFilterStore;
|
@ -1,92 +0,0 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "../root";
|
||||
// services
|
||||
import { ProjectIssuesServices } from "services/issues.service";
|
||||
// types
|
||||
import { TIssueViews } from "./filters";
|
||||
|
||||
export interface IKanbanStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
issues: { [key: string]: any } | null;
|
||||
|
||||
getIssuesAsync: (
|
||||
workspaceId: string,
|
||||
projectId: string,
|
||||
view: TIssueViews | null
|
||||
) => null | Promise<any>;
|
||||
}
|
||||
|
||||
class KanbanStore implements IKanbanStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
issues: { [key: string]: any } | null = null;
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
issueService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
issues: observable.ref,
|
||||
// action
|
||||
getIssuesAsync: action,
|
||||
// computed
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.issueService = new ProjectIssuesServices();
|
||||
}
|
||||
|
||||
// computed
|
||||
get getIssues() {
|
||||
if (this.rootStore.issueFilters.projectId && this.issues != null)
|
||||
return this.issues[this.rootStore.issueFilters.projectId];
|
||||
else return null;
|
||||
}
|
||||
|
||||
// fetching issues
|
||||
getIssuesAsync = async (workspaceId: string, projectId: string, view: TIssueViews | null) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const filteredParams = this.rootStore.issueFilters.getComputedFilters(
|
||||
workspaceId,
|
||||
projectId,
|
||||
view
|
||||
);
|
||||
const issuesResponse = await this.issueService.getIssuesWithParams(
|
||||
workspaceId,
|
||||
projectId,
|
||||
filteredParams
|
||||
);
|
||||
|
||||
if (issuesResponse) {
|
||||
runInAction(() => {
|
||||
this.issues = { ...this.issues, [projectId]: { ...issuesResponse } };
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
|
||||
return issuesResponse;
|
||||
} catch (error) {
|
||||
console.warn("error", error);
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
// handle issue drag and drop
|
||||
}
|
||||
|
||||
export default KanbanStore;
|
@ -7,8 +7,8 @@ import ProjectStore, { IProjectStore } from "./project";
|
||||
import ProjectPublishStore, { IProjectPublishStore } from "./project-publish";
|
||||
import IssuesStore from "./issues";
|
||||
// issues views and filters
|
||||
import IssueFilterStore from "./issue-views/filters";
|
||||
import KanbanStore from "./issue-views/kanban";
|
||||
import IssueFilterStore from "./issue-views/issue_filters";
|
||||
import IssueViewStore from "./issue-views/Issues";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
|
||||
@ -19,7 +19,7 @@ export class RootStore {
|
||||
projectPublish: IProjectPublishStore;
|
||||
issues: IssuesStore;
|
||||
issueFilters: IssueFilterStore;
|
||||
kanban: KanbanStore;
|
||||
issueView: IssueViewStore;
|
||||
|
||||
constructor() {
|
||||
this.user = new UserStore(this);
|
||||
@ -28,6 +28,6 @@ export class RootStore {
|
||||
this.projectPublish = new ProjectPublishStore(this);
|
||||
this.issues = new IssuesStore(this);
|
||||
this.issueFilters = new IssueFilterStore(this);
|
||||
this.kanban = new KanbanStore(this);
|
||||
this.issueView = new IssueViewStore(this);
|
||||
}
|
||||
}
|
||||
|
14
yarn.lock
14
yarn.lock
@ -5600,6 +5600,11 @@ lucide-react@^0.263.1:
|
||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.263.1.tgz#a456ee0d171aa373929bd3ee20d6f9fb4429c301"
|
||||
integrity sha512-keqxAx97PlaEN89PXZ6ki1N8nRjGWtDa4021GFYLNj0RgruM5odbpl8GHTExj0hhPq3sF6Up0gnxt6TSHu+ovw==
|
||||
|
||||
lucide-react@^0.274.0:
|
||||
version "0.274.0"
|
||||
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.274.0.tgz#d3b54dcb972b12f1292061448d61d422ef2e269d"
|
||||
integrity sha512-qiWcojRXEwDiSimMX1+arnxha+ROJzZjJaVvCC0rsG6a9pUPjZePXSq7em4ZKMp0NDm1hyzPNkM7UaWC3LU2AA==
|
||||
|
||||
magic-string@^0.25.0, magic-string@^0.25.7:
|
||||
version "0.25.9"
|
||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
|
||||
@ -6623,7 +6628,14 @@ prosemirror-menu@^1.2.1:
|
||||
prosemirror-history "^1.0.0"
|
||||
prosemirror-state "^1.0.0"
|
||||
|
||||
prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.19.0, prosemirror-model@^1.8.1:
|
||||
prosemirror-model@^1.0.0, prosemirror-model@^1.16.0, prosemirror-model@^1.18.1, prosemirror-model@^1.8.1:
|
||||
version "1.18.1"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.18.1.tgz#1d5d6b6de7b983ee67a479dc607165fdef3935bd"
|
||||
integrity sha512-IxSVBKAEMjD7s3n8cgtwMlxAXZrC7Mlag7zYsAKDndAqnDScvSmp/UdnRTV/B33lTCVU3CCm7dyAn/rVVD0mcw==
|
||||
dependencies:
|
||||
orderedmap "^2.0.0"
|
||||
|
||||
prosemirror-model@^1.19.0:
|
||||
version "1.19.3"
|
||||
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.19.3.tgz#f0d55285487fefd962d0ac695f716f4ec6705006"
|
||||
integrity sha512-tgSnwN7BS7/UM0sSARcW+IQryx2vODKX4MI7xpqY2X+iaepJdKBPc7I4aACIsDV/LTaTjt12Z56MhDr9LsyuZQ==
|
||||
|
Loading…
Reference in New Issue
Block a user