forked from github/plane
refactor: project card component refactor
This commit is contained in:
parent
2b419c02a5
commit
310a2ca904
66
web/components/project/card-list.tsx
Normal file
66
web/components/project/card-list.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import { FC } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { ProjectCard } from "components/project";
|
||||
import { Loader, EmptyState } from "components/ui";
|
||||
// images
|
||||
import emptyProject from "public/empty-state/project.svg";
|
||||
// icons
|
||||
import { Plus } from "lucide-react";
|
||||
|
||||
export interface IProjectCardList {
|
||||
workspaceSlug: string;
|
||||
}
|
||||
|
||||
export const ProjectCardList: FC<IProjectCardList> = observer((props) => {
|
||||
const { workspaceSlug } = props;
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
|
||||
|
||||
if (!projects) {
|
||||
return (
|
||||
<Loader className="grid grid-cols-3 gap-4">
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
</Loader>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{projects.length > 0 ? (
|
||||
<div className="h-full p-8 overflow-y-auto">
|
||||
<div className="grid grid-cols-1 gap-9 md:grid-cols-2 lg:grid-cols-3">
|
||||
{projectStore.searchedProjects.map((project) => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState
|
||||
image={emptyProject}
|
||||
title="No projects yet"
|
||||
description="Get started by creating your first project"
|
||||
primaryButton={{
|
||||
icon: <Plus className="h-4 w-4" />,
|
||||
text: "New Project",
|
||||
onClick: () => {
|
||||
const e = new KeyboardEvent("keydown", {
|
||||
key: "p",
|
||||
});
|
||||
document.dispatchEvent(e);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
});
|
@ -1,18 +1,16 @@
|
||||
import React from "react";
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
import Link from "next/link";
|
||||
|
||||
import { mutate } from "swr";
|
||||
|
||||
import { observer } from "mobx-react-lite";
|
||||
// icons
|
||||
import { CalendarDaysIcon, LinkIcon, PencilIcon, PlusIcon, StarIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// ui
|
||||
import { CustomMenu, Tooltip } from "components/ui";
|
||||
// icons
|
||||
import { CalendarDaysIcon, LinkIcon, PencilIcon, PlusIcon, StarIcon, TrashIcon } from "@heroicons/react/24/outline";
|
||||
// helpers
|
||||
import { renderShortDateWithYearFormat } from "helpers/date-time.helper";
|
||||
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
|
||||
@ -21,18 +19,23 @@ import { renderEmoji } from "helpers/emoji.helper";
|
||||
import type { IProject } from "types";
|
||||
// fetch-keys
|
||||
import { PROJECTS_LIST } from "constants/fetch-keys";
|
||||
// components
|
||||
import { DeleteProjectModal, JoinProjectModal } from "components/project";
|
||||
|
||||
export type ProjectCardProps = {
|
||||
project: IProject;
|
||||
setToJoinProject: (id: string | null) => void;
|
||||
setDeleteProject: (id: string | null) => void;
|
||||
};
|
||||
|
||||
export const SingleProjectCard: React.FC<ProjectCardProps> = ({ project, setToJoinProject, setDeleteProject }) => {
|
||||
export const ProjectCard: React.FC<ProjectCardProps> = observer((props) => {
|
||||
const { project } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
// toast
|
||||
const { setToastAlert } = useToast();
|
||||
// states
|
||||
const [deleteProjectModalOpen, setDeleteProjectModal] = useState(false);
|
||||
const [joinProjectModalOpen, setJoinProjectModal] = useState(false);
|
||||
|
||||
const isOwner = project.member_role === 20;
|
||||
const isMember = project.member_role === 15;
|
||||
@ -105,6 +108,22 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({ project, setToJo
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Delete Project Modal */}
|
||||
<DeleteProjectModal
|
||||
project={project}
|
||||
isOpen={deleteProjectModalOpen}
|
||||
onClose={() => setDeleteProjectModal(false)}
|
||||
/>
|
||||
{workspaceSlug && (
|
||||
<JoinProjectModal
|
||||
workspaceSlug={workspaceSlug?.toString()}
|
||||
project={project}
|
||||
isOpen={joinProjectModalOpen}
|
||||
handleClose={() => setJoinProjectModal(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Card Information */}
|
||||
<div className="flex flex-col rounded-[10px] bg-custom-background-90 shadow">
|
||||
<Link href={`/${workspaceSlug as string}/projects/${project.id}/issues`}>
|
||||
<a>
|
||||
@ -124,7 +143,7 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({ project, setToJo
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setToJoinProject(project.id);
|
||||
setJoinProjectModal(true);
|
||||
}}
|
||||
className="flex cursor-pointer items-center gap-1 rounded bg-green-600 px-2 py-1 text-xs"
|
||||
>
|
||||
@ -180,7 +199,7 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({ project, setToJo
|
||||
)}
|
||||
<CustomMenu width="auto" verticalEllipsis>
|
||||
{isOwner && (
|
||||
<CustomMenu.MenuItem onClick={() => setDeleteProject(project.id)}>
|
||||
<CustomMenu.MenuItem onClick={() => setDeleteProjectModal(true)}>
|
||||
<span className="flex items-center justify-start gap-2">
|
||||
<TrashIcon className="h-4 w-4" />
|
||||
<span>Delete project</span>
|
||||
@ -216,4 +235,4 @@ export const SingleProjectCard: React.FC<ProjectCardProps> = ({ project, setToJo
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
@ -3,10 +3,12 @@ export * from "./delete-project-modal";
|
||||
export * from "./sidebar-list";
|
||||
export * from "./settings-sidebar";
|
||||
export * from "./single-integration-card";
|
||||
export * from "./single-project-card";
|
||||
export * from "./sidebar-list-item";
|
||||
export * from "./leave-project-modal";
|
||||
export * from "./member-select";
|
||||
export * from "./members-select";
|
||||
export * from "./label-select";
|
||||
export * from "./priority-select";
|
||||
export * from "./card-list";
|
||||
export * from "./card";
|
||||
export * from "./join-project-modal";
|
||||
|
@ -1,26 +1,32 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
// headless ui
|
||||
import { useState, Fragment } from "react";
|
||||
import { Transition, Dialog } from "@headlessui/react";
|
||||
// ui
|
||||
import { PrimaryButton, SecondaryButton } from "components/ui";
|
||||
// types
|
||||
import type { IProject } from "types";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
|
||||
// type
|
||||
type TJoinProjectModalProps = {
|
||||
data?: IProject;
|
||||
onClose: () => void;
|
||||
onJoin: () => Promise<void>;
|
||||
isOpen: boolean;
|
||||
workspaceSlug: string;
|
||||
project: IProject;
|
||||
handleClose: () => void;
|
||||
};
|
||||
|
||||
export const JoinProjectModal: React.FC<TJoinProjectModalProps> = ({ onClose, onJoin, data }) => {
|
||||
export const JoinProjectModal: React.FC<TJoinProjectModalProps> = (props) => {
|
||||
const { handleClose, isOpen, project, workspaceSlug } = props;
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
// states
|
||||
const [isJoiningLoading, setIsJoiningLoading] = useState(false);
|
||||
|
||||
const handleJoin = () => {
|
||||
setIsJoiningLoading(true);
|
||||
|
||||
onJoin()
|
||||
projectStore
|
||||
.joinProject(workspaceSlug, [project.id])
|
||||
.then(() => {
|
||||
setIsJoiningLoading(false);
|
||||
handleClose();
|
||||
@ -30,15 +36,11 @@ export const JoinProjectModal: React.FC<TJoinProjectModalProps> = ({ onClose, on
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Transition.Root show={Boolean(data)} as={React.Fragment}>
|
||||
<Transition.Root show={isOpen} as={Fragment}>
|
||||
<Dialog as="div" className="relative z-20" onClose={handleClose}>
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
@ -52,7 +54,7 @@ export const JoinProjectModal: React.FC<TJoinProjectModalProps> = ({ onClose, on
|
||||
<div className="fixed inset-0 z-20 overflow-y-auto">
|
||||
<div className="flex min-h-full items-center justify-center p-4 text-center sm:p-0">
|
||||
<Transition.Child
|
||||
as={React.Fragment}
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
enterTo="opacity-100 translate-y-0 sm:scale-100"
|
||||
@ -62,15 +64,11 @@ export const JoinProjectModal: React.FC<TJoinProjectModalProps> = ({ onClose, on
|
||||
>
|
||||
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 border border-custom-border-300 px-5 py-8 text-left shadow-xl transition-all sm:w-full sm:max-w-xl sm:p-6">
|
||||
<div className="space-y-5">
|
||||
<Dialog.Title
|
||||
as="h3"
|
||||
className="text-lg font-medium leading-6 text-custom-text-100"
|
||||
>
|
||||
<Dialog.Title as="h3" className="text-lg font-medium leading-6 text-custom-text-100">
|
||||
Join Project?
|
||||
</Dialog.Title>
|
||||
<p>
|
||||
Are you sure you want to join{" "}
|
||||
<span className="font-semibold">{data?.name}</span>?
|
||||
Are you sure you want to join <span className="font-semibold">{project?.name}</span>?
|
||||
</p>
|
||||
<div className="space-y-3" />
|
||||
</div>
|
||||
|
@ -34,12 +34,11 @@ export const ProjectSidebarList: FC = observer(() => {
|
||||
// swr
|
||||
useSWR(
|
||||
workspaceSlug ? "PROJECTS_LIST" : null,
|
||||
workspaceSlug ? () => workspaceStore.getWorkspaceProjects(workspaceSlug?.toString()) : null
|
||||
workspaceSlug ? () => projectStore.fetchProjects(workspaceSlug?.toString()) : null
|
||||
);
|
||||
// states
|
||||
const [isFavoriteProjectCreate, setIsFavoriteProjectCreate] = useState(false);
|
||||
const [isProjectModalOpen, setIsProjectModalOpen] = useState(false);
|
||||
const [deleteProjectModal, setDeleteProjectModal] = useState(false);
|
||||
|
||||
const [isScrolled, setIsScrolled] = useState(false); // scroll animation state
|
||||
|
||||
@ -48,8 +47,8 @@ export const ProjectSidebarList: FC = observer(() => {
|
||||
const { user } = useUserAuth();
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const joinedProjects = workspaceSlug && workspaceStore.workspaceJoinedProjects;
|
||||
const favoriteProjects = workspaceSlug && workspaceStore.workspaceFavoriteProjects;
|
||||
const joinedProjects = workspaceSlug && projectStore.joinedProjects;
|
||||
const favoriteProjects = workspaceSlug && projectStore.favoriteProjects;
|
||||
|
||||
const orderedJoinedProjects: IProject[] | undefined = joinedProjects
|
||||
? orderArrayBy(joinedProjects, "sort_order", "ascending")
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import { mutate } from "swr";
|
||||
|
||||
import type { NextPage } from "next";
|
||||
// services
|
||||
import projectService from "services/project.service";
|
||||
// hooks
|
||||
@ -12,48 +10,26 @@ import useWorkspaces from "hooks/use-workspaces";
|
||||
import useUserAuth from "hooks/use-user-auth";
|
||||
// layouts
|
||||
import { WorkspaceAuthorizationLayout } from "layouts/auth-layout";
|
||||
// components
|
||||
import { JoinProjectModal } from "components/project/join-project-modal";
|
||||
import { DeleteProjectModal, SingleProjectCard } from "components/project";
|
||||
// ui
|
||||
import { EmptyState, Icon, Loader, PrimaryButton } from "components/ui";
|
||||
import { Icon, PrimaryButton } from "components/ui";
|
||||
import { Breadcrumbs, BreadcrumbItem } from "components/breadcrumbs";
|
||||
// icons
|
||||
import { PlusIcon } from "@heroicons/react/24/outline";
|
||||
// images
|
||||
import emptyProject from "public/empty-state/project.svg";
|
||||
// types
|
||||
import type { NextPage } from "next";
|
||||
// fetch-keys
|
||||
import { PROJECT_MEMBERS } from "constants/fetch-keys";
|
||||
// helper
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
// lib
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
import { ProjectCardList } from "components/project";
|
||||
|
||||
const ProjectsPage: NextPage = () => {
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const [query, setQuery] = useState("");
|
||||
|
||||
const { user } = useUserAuth();
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
// context data
|
||||
const { activeWorkspace } = useWorkspaces();
|
||||
const { projects, mutateProjects } = useProjects();
|
||||
// states
|
||||
const [deleteProject, setDeleteProject] = useState<string | null>(null);
|
||||
const [selectedProjectToJoin, setSelectedProjectToJoin] = useState<string | null>(null);
|
||||
|
||||
const filteredProjectList =
|
||||
query === ""
|
||||
? projects
|
||||
: projects?.filter(
|
||||
(project) =>
|
||||
project.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
project.identifier.toLowerCase().includes(query.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<WorkspaceAuthorizationLayout
|
||||
@ -71,8 +47,8 @@ const ProjectsPage: NextPage = () => {
|
||||
<Icon iconName="search" className="!text-xl !leading-5 !text-custom-sidebar-text-400" />
|
||||
<input
|
||||
className="w-full border-none bg-transparent text-xs text-custom-text-200 focus:outline-none"
|
||||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
value={projectStore.searchQuery}
|
||||
onChange={(e) => projectStore.setSearchQuery(e.target.value)}
|
||||
placeholder="Search"
|
||||
/>
|
||||
</div>
|
||||
@ -90,83 +66,7 @@ const ProjectsPage: NextPage = () => {
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<JoinProjectModal
|
||||
data={projects?.find((item) => item.id === selectedProjectToJoin)}
|
||||
onClose={() => setSelectedProjectToJoin(null)}
|
||||
onJoin={async () => {
|
||||
const project = projects?.find((item) => item.id === selectedProjectToJoin);
|
||||
if (!project) return;
|
||||
|
||||
await projectService
|
||||
.joinProject(workspaceSlug as string, {
|
||||
project_ids: [project.id],
|
||||
})
|
||||
.then(async () => {
|
||||
mutate(PROJECT_MEMBERS(project.id));
|
||||
mutateProjects<IProject[]>(
|
||||
(prevData) =>
|
||||
(prevData ?? []).map((p) => ({
|
||||
...p,
|
||||
is_member: p.id === project.id ? true : p.is_member,
|
||||
})),
|
||||
false
|
||||
);
|
||||
setSelectedProjectToJoin(null);
|
||||
})
|
||||
.catch(() => {
|
||||
setSelectedProjectToJoin(null);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<DeleteProjectModal
|
||||
isOpen={!!deleteProject}
|
||||
onClose={() => setDeleteProject(null)}
|
||||
data={projects?.find((item) => item.id === deleteProject) ?? null}
|
||||
user={user}
|
||||
/>
|
||||
{filteredProjectList ? (
|
||||
<div className="h-full w-full overflow-hidden">
|
||||
{filteredProjectList.length > 0 ? (
|
||||
<div className="h-full p-8 overflow-y-auto">
|
||||
<div className="grid grid-cols-1 gap-9 md:grid-cols-2 lg:grid-cols-3">
|
||||
{filteredProjectList.map((project) => (
|
||||
<SingleProjectCard
|
||||
key={project.id}
|
||||
project={project}
|
||||
setToJoinProject={setSelectedProjectToJoin}
|
||||
setDeleteProject={setDeleteProject}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<EmptyState
|
||||
image={emptyProject}
|
||||
title="No projects yet"
|
||||
description="Get started by creating your first project"
|
||||
primaryButton={{
|
||||
icon: <PlusIcon className="h-4 w-4" />,
|
||||
text: "New Project",
|
||||
onClick: () => {
|
||||
const e = new KeyboardEvent("keydown", {
|
||||
key: "p",
|
||||
});
|
||||
document.dispatchEvent(e);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Loader className="grid grid-cols-3 gap-4">
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
<Loader.Item height="100px" />
|
||||
</Loader>
|
||||
)}
|
||||
{workspaceSlug && <ProjectCardList workspaceSlug={workspaceSlug.toString()} />}
|
||||
</WorkspaceAuthorizationLayout>
|
||||
);
|
||||
};
|
||||
|
@ -124,8 +124,8 @@ export class ProjectService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async joinProject(workspaceSlug: string, data: any): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/join/`, data)
|
||||
async joinProject(workspaceSlug: string, project_ids: string[]): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/join/`, { project_ids })
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
|
@ -5,12 +5,17 @@ import { RootStore } from "./root";
|
||||
import { ProjectService } from "services/project.service";
|
||||
import { IssueService } from "services/issue.service";
|
||||
import { ICycle } from "types";
|
||||
import { CycleService } from "services/cycles.service";
|
||||
|
||||
export interface ICycleStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
cycles: {
|
||||
[project_id: string]: ICycle[];
|
||||
};
|
||||
|
||||
cycle_details: {
|
||||
[cycle_id: string]: ICycle;
|
||||
};
|
||||
}
|
||||
@ -20,6 +25,10 @@ class CycleStore implements ICycleStore {
|
||||
error: any | null = null;
|
||||
|
||||
cycles: {
|
||||
[project_id: string]: ICycle[];
|
||||
} = {};
|
||||
|
||||
cycle_details: {
|
||||
[cycle_id: string]: ICycle;
|
||||
} = {};
|
||||
|
||||
@ -28,6 +37,7 @@ class CycleStore implements ICycleStore {
|
||||
// services
|
||||
projectService;
|
||||
issueService;
|
||||
cycleService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
@ -44,11 +54,37 @@ class CycleStore implements ICycleStore {
|
||||
this.rootStore = _rootStore;
|
||||
this.projectService = new ProjectService();
|
||||
this.issueService = new IssueService();
|
||||
this.cycleService = new CycleService();
|
||||
}
|
||||
|
||||
// computed
|
||||
get projectCycles() {
|
||||
if (!this.rootStore.project.projectId) return null;
|
||||
return this.cycles[this.rootStore.project.projectId] || null;
|
||||
}
|
||||
|
||||
// actions
|
||||
fetchCycles = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectSlug, "all");
|
||||
|
||||
runInAction(() => {
|
||||
this.cycles = {
|
||||
...this.cycles,
|
||||
[projectSlug]: cyclesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project cycles in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default CycleStore;
|
||||
|
@ -3,15 +3,24 @@ import { action, computed, observable, makeObservable, runInAction } from "mobx"
|
||||
import { RootStore } from "./root";
|
||||
// services
|
||||
import { ProjectService } from "services/project.service";
|
||||
import { IssueService } from "services/issue.service";
|
||||
import { ModuleService } from "services/modules.service";
|
||||
import { IModule } from "@/types";
|
||||
|
||||
export interface IModuleStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
moduleId: string | null;
|
||||
modules: {
|
||||
[project_id: string]: IModule[];
|
||||
};
|
||||
module_details: {
|
||||
[module_id: string]: IModule;
|
||||
};
|
||||
|
||||
setModuleId: (moduleSlug: string) => void;
|
||||
|
||||
fetchModules: (workspaceSlug: string, projectSlug: string) => void;
|
||||
}
|
||||
|
||||
class ModuleStore implements IModuleStore {
|
||||
@ -20,11 +29,19 @@ class ModuleStore implements IModuleStore {
|
||||
|
||||
moduleId: string | null = null;
|
||||
|
||||
modules: {
|
||||
[project_id: string]: IModule[];
|
||||
} = {};
|
||||
|
||||
module_details: {
|
||||
[module_id: string]: IModule;
|
||||
} = {};
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
projectService;
|
||||
issueService;
|
||||
moduleService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
@ -41,15 +58,41 @@ class ModuleStore implements IModuleStore {
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectService = new ProjectService();
|
||||
this.issueService = new IssueService();
|
||||
this.moduleService = new ModuleService();
|
||||
}
|
||||
|
||||
// computed
|
||||
get projectModules() {
|
||||
if (!this.rootStore.project.projectId) return null;
|
||||
return this.modules[this.rootStore.project.projectId] || null;
|
||||
}
|
||||
|
||||
// actions
|
||||
setModuleId = (moduleSlug: string) => {
|
||||
this.moduleId = moduleSlug ?? null;
|
||||
};
|
||||
|
||||
fetchModules = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.modules = {
|
||||
...this.modules,
|
||||
[projectSlug]: modulesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch modules list in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default ModuleStore;
|
||||
|
104
web/store/page.ts
Normal file
104
web/store/page.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "./root";
|
||||
import { IProject, IIssueLabels, IProjectMember, IStateResponse, IState, IPage } from "types";
|
||||
// services
|
||||
import { ProjectService } from "services/project.service";
|
||||
import { IssueService } from "services/issue.service";
|
||||
import { ProjectStateServices } from "services/project_state.service";
|
||||
import { CycleService } from "services/cycles.service";
|
||||
import { ModuleService } from "services/modules.service";
|
||||
import { ViewService } from "services/views.service";
|
||||
import { PageService } from "services/page.service";
|
||||
|
||||
export interface IPageStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
pageId: string | null;
|
||||
pages: {
|
||||
[project_id: string]: IPage[];
|
||||
};
|
||||
page_details: {
|
||||
[page_id: string]: IPage;
|
||||
};
|
||||
|
||||
//computed
|
||||
projectPages: IPage[];
|
||||
// actions
|
||||
setPageId: (pageId: string) => void;
|
||||
fetchPages: (workspaceSlug: string, projectSlug: string) => void;
|
||||
}
|
||||
|
||||
class PageStore implements IPageStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
pageId: string | null = null;
|
||||
pages: {
|
||||
[project_id: string]: IPage[];
|
||||
} = {};
|
||||
page_details: {
|
||||
[page_id: string]: IPage;
|
||||
} = {};
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
projectService;
|
||||
pageService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
pageId: observable.ref,
|
||||
pages: observable.ref,
|
||||
|
||||
// computed
|
||||
projectPages: computed,
|
||||
// action
|
||||
setPageId: action,
|
||||
fetchPages: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectService = new ProjectService();
|
||||
this.pageService = new PageService();
|
||||
}
|
||||
|
||||
get projectPages() {
|
||||
if (!this.rootStore.project.projectId) return [];
|
||||
return this.pages?.[this.rootStore.project.projectId] || [];
|
||||
}
|
||||
|
||||
setPageId = (pageId: string) => {
|
||||
this.pageId = pageId;
|
||||
};
|
||||
|
||||
fetchPages = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const pagesResponse = await this.pageService.getPagesWithParams(workspaceSlug, projectSlug, "all");
|
||||
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[projectSlug]: pagesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project pages in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default PageStore;
|
@ -1,7 +1,7 @@
|
||||
import { observable, action, computed, makeObservable, runInAction } from "mobx";
|
||||
// types
|
||||
import { RootStore } from "./root";
|
||||
import { IProject, IIssueLabels, IProjectMember, IStateResponse, IState, ICycle, IModule, IView, IPage } from "types";
|
||||
import { IProject, IIssueLabels, IProjectMember, IStateResponse, IState } from "types";
|
||||
// services
|
||||
import { ProjectService } from "services/project.service";
|
||||
import { IssueService } from "services/issue.service";
|
||||
@ -15,9 +15,10 @@ export interface IProjectStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
searchQuery: string;
|
||||
projectId: string | null;
|
||||
|
||||
projects: {
|
||||
projects: { [key: string]: IProject[] };
|
||||
project_details: {
|
||||
[projectId: string]: IProject; // projectId: project Info
|
||||
} | null;
|
||||
states: {
|
||||
@ -29,32 +30,26 @@ export interface IProjectStore {
|
||||
members: {
|
||||
[projectId: string]: IProjectMember[] | null; // project_id: members
|
||||
} | null;
|
||||
cycles: {
|
||||
[projectId: string]: ICycle[] | null; // project_id: cycles
|
||||
} | null;
|
||||
modules: {
|
||||
[projectId: string]: IModule[] | null; // project_id: modules
|
||||
} | null;
|
||||
views: {
|
||||
[projectId: string]: IView[] | null; // project_id: views
|
||||
} | null;
|
||||
pages: {
|
||||
[projectId: string]: IPage[] | null; // project_id: pages
|
||||
} | null;
|
||||
|
||||
// computed
|
||||
searchedProjects: IProject[];
|
||||
projectStatesByGroups: IStateResponse | null;
|
||||
projectStates: IState[] | null;
|
||||
projectLabels: IIssueLabels[] | null;
|
||||
projectMembers: IProjectMember[] | null;
|
||||
|
||||
joinedProjects: IProject[];
|
||||
favoriteProjects: IProject[];
|
||||
|
||||
// actions
|
||||
setProjectId: (projectId: string) => void;
|
||||
setSearchQuery: (query: string) => void;
|
||||
|
||||
getProjectStateById: (stateId: string) => IState | null;
|
||||
getProjectLabelById: (labelId: string) => IIssueLabels | null;
|
||||
getProjectMemberById: (memberId: string) => IProjectMember | null;
|
||||
|
||||
fetchProjects: (workspaceSlug: string) => Promise<void>;
|
||||
fetchProjectStates: (workspaceSlug: string, projectSlug: string) => Promise<void>;
|
||||
fetchProjectLabels: (workspaceSlug: string, projectSlug: string) => Promise<void>;
|
||||
fetchProjectMembers: (workspaceSlug: string, projectSlug: string) => Promise<void>;
|
||||
@ -65,8 +60,7 @@ export interface IProjectStore {
|
||||
orderProjectsWithSortOrder: (sourceIndex: number, destinationIndex: number, projectId: string) => number;
|
||||
updateProjectView: (workspaceSlug: string, projectId: string, viewProps: any) => Promise<any>;
|
||||
|
||||
handleProjectLeaveModal: (project: any | null) => void;
|
||||
|
||||
joinProject: (workspaceSlug: string, projectIds: string[]) => Promise<void>;
|
||||
leaveProject: (workspaceSlug: string, projectSlug: string) => Promise<void>;
|
||||
deleteProject: (workspaceSlug: string, projectSlug: string) => Promise<void>;
|
||||
}
|
||||
@ -75,26 +69,12 @@ class ProjectStore implements IProjectStore {
|
||||
loader: boolean = false;
|
||||
error: any | null = null;
|
||||
|
||||
projectLeaveModal: boolean = false;
|
||||
projectLeaveDetails: IProject | null = null;
|
||||
|
||||
searchQuery: string = "";
|
||||
projectId: string | null = null;
|
||||
|
||||
projects: {
|
||||
projects: { [workspaceSlug: string]: IProject[] } = {}; // workspace_id: project[]
|
||||
project_details: {
|
||||
[key: string]: IProject; // project_id: project
|
||||
} | null = {};
|
||||
cycles: {
|
||||
[key: string]: ICycle[]; // project_id: cycles
|
||||
} = {};
|
||||
modules: {
|
||||
[key: string]: IModule[]; // project_id: modules
|
||||
} = {};
|
||||
views: {
|
||||
[key: string]: IView[]; // project_id: views
|
||||
} = {};
|
||||
pages: {
|
||||
[key: string]: IPage[]; // project_id: pages
|
||||
} = {};
|
||||
states: {
|
||||
[key: string]: IStateResponse; // project_id: states
|
||||
} | null = {};
|
||||
@ -122,23 +102,27 @@ class ProjectStore implements IProjectStore {
|
||||
loader: observable,
|
||||
error: observable,
|
||||
|
||||
searchQuery: observable.ref,
|
||||
projectId: observable.ref,
|
||||
projects: observable.ref,
|
||||
project_details: observable.ref,
|
||||
states: observable.ref,
|
||||
labels: observable.ref,
|
||||
members: observable.ref,
|
||||
|
||||
projectLeaveModal: observable,
|
||||
projectLeaveDetails: observable.ref,
|
||||
|
||||
// computed
|
||||
searchedProjects: computed,
|
||||
projectStatesByGroups: computed,
|
||||
projectStates: computed,
|
||||
projectLabels: computed,
|
||||
projectMembers: computed,
|
||||
|
||||
joinedProjects: computed,
|
||||
favoriteProjects: computed,
|
||||
|
||||
// action
|
||||
setProjectId: action,
|
||||
setSearchQuery: action,
|
||||
|
||||
getProjectStateById: action,
|
||||
getProjectLabelById: action,
|
||||
@ -153,8 +137,6 @@ class ProjectStore implements IProjectStore {
|
||||
|
||||
orderProjectsWithSortOrder: action,
|
||||
updateProjectView: action,
|
||||
|
||||
handleProjectLeaveModal: action,
|
||||
leaveProject: action,
|
||||
});
|
||||
|
||||
@ -168,6 +150,30 @@ class ProjectStore implements IProjectStore {
|
||||
this.cycleService = new CycleService();
|
||||
}
|
||||
|
||||
get searchedProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
|
||||
const projects = this.projects[this.rootStore.workspace.workspaceSlug];
|
||||
|
||||
return this.searchQuery === ""
|
||||
? projects
|
||||
: projects?.filter(
|
||||
(project) =>
|
||||
project.name.toLowerCase().includes(this.searchQuery.toLowerCase()) ||
|
||||
project.identifier.toLowerCase().includes(this.searchQuery.toLowerCase())
|
||||
);
|
||||
}
|
||||
|
||||
get joinedProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
return this.projects?.[this.rootStore.workspace.workspaceSlug]?.filter((p) => p.is_member);
|
||||
}
|
||||
|
||||
get favoriteProjects() {
|
||||
if (!this.rootStore.workspace.workspaceSlug) return [];
|
||||
return this.projects?.[this.rootStore.workspace.workspaceSlug]?.filter((p) => p.is_favorite);
|
||||
}
|
||||
|
||||
get projectStatesByGroups() {
|
||||
if (!this.projectId) return null;
|
||||
return this.states?.[this.projectId] || null;
|
||||
@ -196,31 +202,34 @@ class ProjectStore implements IProjectStore {
|
||||
return this.members?.[this.projectId] || null;
|
||||
}
|
||||
|
||||
get projectCycles() {
|
||||
if (!this.projectId) return null;
|
||||
return this.cycles[this.projectId] || null;
|
||||
}
|
||||
|
||||
get projectModules() {
|
||||
if (!this.projectId) return null;
|
||||
return this.modules[this.projectId] || null;
|
||||
}
|
||||
|
||||
get projectViews() {
|
||||
if (!this.projectId) return null;
|
||||
return this.views[this.projectId] || null;
|
||||
}
|
||||
|
||||
get projectPages() {
|
||||
if (!this.projectId) return null;
|
||||
return this.pages[this.projectId] || null;
|
||||
}
|
||||
|
||||
// actions
|
||||
setProjectId = (projectSlug: string) => {
|
||||
this.projectId = projectSlug ?? null;
|
||||
};
|
||||
|
||||
setSearchQuery = (query: string) => {
|
||||
this.searchQuery = query;
|
||||
};
|
||||
|
||||
/**
|
||||
* get Workspace projects using workspace slug
|
||||
* @param workspaceSlug
|
||||
* @returns
|
||||
*/
|
||||
fetchProjects = async (workspaceSlug: string) => {
|
||||
try {
|
||||
const projects = await this.projectService.getProjects(workspaceSlug, { is_favorite: "all" });
|
||||
runInAction(() => {
|
||||
this.projects = {
|
||||
...this.projects,
|
||||
[workspaceSlug]: projects,
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch project from workspace store");
|
||||
}
|
||||
};
|
||||
|
||||
getProjectStateById = (stateId: string) => {
|
||||
if (!this.projectId) return null;
|
||||
const states = this.projectStates;
|
||||
@ -314,99 +323,10 @@ class ProjectStore implements IProjectStore {
|
||||
}
|
||||
};
|
||||
|
||||
fetchProjectCycles = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const cyclesResponse = await this.cycleService.getCyclesWithParams(workspaceSlug, projectSlug, "all");
|
||||
|
||||
runInAction(() => {
|
||||
this.cycles = {
|
||||
...this.cycles,
|
||||
[projectSlug]: cyclesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project cycles in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
fetchProjectModules = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const modulesResponse = await this.moduleService.getModules(workspaceSlug, projectSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.modules = {
|
||||
...this.modules,
|
||||
[projectSlug]: modulesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch modules list in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
fetchProjectViews = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const viewsResponse = await this.viewService.getViews(workspaceSlug, projectSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.views = {
|
||||
...this.views,
|
||||
[projectSlug]: viewsResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project views in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
fetchProjectPages = async (workspaceSlug: string, projectSlug: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const pagesResponse = await this.pageService.getPagesWithParams(workspaceSlug, projectSlug, "all");
|
||||
|
||||
runInAction(() => {
|
||||
this.pages = {
|
||||
...this.pages,
|
||||
[projectSlug]: pagesResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project pages in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
|
||||
addProjectToFavorites = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const response = await this.projectService.addProjectToFavorites(workspaceSlug, projectId);
|
||||
console.log("res", response);
|
||||
await this.rootStore.workspace.getWorkspaceProjects(workspaceSlug);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to add project to favorite");
|
||||
@ -416,8 +336,8 @@ class ProjectStore implements IProjectStore {
|
||||
|
||||
removeProjectFromFavorites = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
const response = this.projectService.removeProjectFromFavorites(workspaceSlug, projectId);
|
||||
this.rootStore.workspace.getWorkspaceProjects(workspaceSlug);
|
||||
const response = await this.projectService.removeProjectFromFavorites(workspaceSlug, projectId);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to add project to favorite");
|
||||
@ -430,7 +350,7 @@ class ProjectStore implements IProjectStore {
|
||||
const workspaceSlug = this.rootStore.workspace.workspaceSlug;
|
||||
if (!workspaceSlug) return 0;
|
||||
|
||||
const projectsList = this.rootStore.workspace.projects[workspaceSlug] || [];
|
||||
const projectsList = this.projects[workspaceSlug] || [];
|
||||
let updatedSortOrder = projectsList[sortIndex].sort_order;
|
||||
|
||||
if (destinationIndex === 0) updatedSortOrder = (projectsList[0].sort_order as number) - 1000;
|
||||
@ -451,8 +371,8 @@ class ProjectStore implements IProjectStore {
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
this.rootStore.workspace.projects = {
|
||||
...this.rootStore.workspace.projects,
|
||||
this.projects = {
|
||||
...this.projects,
|
||||
[workspaceSlug]: updatedProjectsList,
|
||||
};
|
||||
});
|
||||
@ -467,7 +387,8 @@ class ProjectStore implements IProjectStore {
|
||||
updateProjectView = async (workspaceSlug: string, projectId: string, viewProps: any) => {
|
||||
try {
|
||||
const response = await this.projectService.setProjectView(workspaceSlug, projectId, viewProps);
|
||||
await this.rootStore.workspace.getWorkspaceProjects(workspaceSlug);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.log("Failed to update sort order of the projects");
|
||||
@ -475,13 +396,24 @@ class ProjectStore implements IProjectStore {
|
||||
}
|
||||
};
|
||||
|
||||
handleProjectLeaveModal = (project: IProject | null = null) => {
|
||||
if (project && project?.id) {
|
||||
this.projectLeaveModal = !this.projectLeaveModal;
|
||||
this.projectLeaveDetails = project;
|
||||
} else {
|
||||
this.projectLeaveModal = !this.projectLeaveModal;
|
||||
this.projectLeaveDetails = null;
|
||||
joinProject = async (workspaceSlug: string, projectIds: string[]) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const response = await this.projectService.joinProject(workspaceSlug, projectIds);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
@ -491,7 +423,7 @@ class ProjectStore implements IProjectStore {
|
||||
this.error = null;
|
||||
|
||||
const response = await this.projectService.leaveProject(workspaceSlug, projectSlug, this.rootStore.user);
|
||||
await this.rootStore.workspace.getWorkspaceProjects(workspaceSlug);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
@ -509,7 +441,7 @@ class ProjectStore implements IProjectStore {
|
||||
deleteProject = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
await this.projectService.deleteProject(workspaceSlug, projectId, this.rootStore.user.currentUser);
|
||||
await this.rootStore.workspace.getWorkspaceProjects(workspaceSlug);
|
||||
await this.fetchProjects(workspaceSlug);
|
||||
} catch (error) {
|
||||
console.log("Failed to delete project from project store");
|
||||
}
|
||||
|
@ -4,14 +4,20 @@ import { RootStore } from "./root";
|
||||
// services
|
||||
import { ProjectService } from "services/project.service";
|
||||
import { IssueService } from "services/issue.service";
|
||||
import { ViewService } from "services/views.service";
|
||||
|
||||
export interface IViewStore {
|
||||
loader: boolean;
|
||||
error: any | null;
|
||||
|
||||
viewId: string | null;
|
||||
views: {
|
||||
[project_id: string]: any[];
|
||||
};
|
||||
|
||||
setViewId: (viewSlug: string) => void;
|
||||
|
||||
fetchViews: (workspaceSlug: string, projectSlug: string) => Promise<any>;
|
||||
}
|
||||
|
||||
class ViewStore implements IViewStore {
|
||||
@ -19,12 +25,15 @@ class ViewStore implements IViewStore {
|
||||
error: any | null = null;
|
||||
|
||||
viewId: string | null = null;
|
||||
views: {
|
||||
[project_id: string]: any[];
|
||||
} = {};
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// services
|
||||
projectService;
|
||||
issueService;
|
||||
viewService;
|
||||
|
||||
constructor(_rootStore: RootStore) {
|
||||
makeObservable(this, {
|
||||
@ -32,24 +41,51 @@ class ViewStore implements IViewStore {
|
||||
error: observable.ref,
|
||||
|
||||
viewId: observable.ref,
|
||||
views: observable.ref,
|
||||
|
||||
// computed
|
||||
|
||||
projectViews: computed,
|
||||
// actions
|
||||
setViewId: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.projectService = new ProjectService();
|
||||
this.issueService = new IssueService();
|
||||
this.viewService = new ViewService();
|
||||
}
|
||||
|
||||
// computed
|
||||
get projectViews() {
|
||||
if (!this.rootStore.project.projectId) return null;
|
||||
return this.views[this.rootStore.project.projectId] || null;
|
||||
}
|
||||
|
||||
// actions
|
||||
setViewId = (viewSlug: string) => {
|
||||
this.viewId = viewSlug ?? null;
|
||||
};
|
||||
|
||||
fetchViews = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const viewsResponse = await this.viewService.getViews(workspaceSlug, projectId);
|
||||
|
||||
runInAction(() => {
|
||||
this.views = {
|
||||
...this.views,
|
||||
[projectId]: viewsResponse,
|
||||
};
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch project views in project store", error);
|
||||
this.loader = false;
|
||||
this.error = error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default ViewStore;
|
||||
|
@ -12,19 +12,15 @@ export interface IWorkspaceStore {
|
||||
error: any | null;
|
||||
// observables
|
||||
workspaces: IWorkspace[];
|
||||
projects: { [key: string]: IProject[] };
|
||||
labels: { [key: string]: IIssueLabels[] } | {}; // workspace_id: labels[]
|
||||
workspaceSlug: string | null;
|
||||
// computed
|
||||
currentWorkspace: IWorkspace | null;
|
||||
workspaceLabels: IIssueLabels[];
|
||||
workspaceJoinedProjects: IProject[];
|
||||
workspaceFavoriteProjects: IProject[];
|
||||
// actions
|
||||
setWorkspaceSlug: (workspaceSlug: string) => void;
|
||||
getWorkspaceBySlug: (workspaceSlug: string) => IWorkspace | null;
|
||||
getWorkspaceLabelById: (workspaceSlug: string, labelId: string) => IIssueLabels | null;
|
||||
getWorkspaceProjects: (workspaceSlug: string) => void;
|
||||
fetchWorkspaces: () => Promise<void>;
|
||||
fetchWorkspaceLabels: (workspaceSlug: string) => Promise<void>;
|
||||
}
|
||||
@ -52,17 +48,13 @@ class WorkspaceStore implements IWorkspaceStore {
|
||||
workspaces: observable.ref,
|
||||
labels: observable.ref,
|
||||
workspaceSlug: observable.ref,
|
||||
projects: observable.ref,
|
||||
// computed
|
||||
currentWorkspace: computed,
|
||||
workspaceLabels: computed,
|
||||
workspaceJoinedProjects: computed,
|
||||
workspaceFavoriteProjects: computed,
|
||||
// actions
|
||||
setWorkspaceSlug: action,
|
||||
getWorkspaceBySlug: action,
|
||||
getWorkspaceLabelById: action,
|
||||
getWorkspaceProjects: action,
|
||||
fetchWorkspaces: action,
|
||||
fetchWorkspaceLabels: action,
|
||||
});
|
||||
@ -90,16 +82,6 @@ class WorkspaceStore implements IWorkspaceStore {
|
||||
return _labels && Object.keys(_labels).length > 0 ? _labels : [];
|
||||
}
|
||||
|
||||
get workspaceJoinedProjects() {
|
||||
if (!this.workspaceSlug) return [];
|
||||
return this.projects?.[this.workspaceSlug]?.filter((p) => p.is_member);
|
||||
}
|
||||
|
||||
get workspaceFavoriteProjects() {
|
||||
if (!this.workspaceSlug) return [];
|
||||
return this.projects?.[this.workspaceSlug]?.filter((p) => p.is_favorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* set workspace slug in the store
|
||||
* @param workspaceSlug
|
||||
@ -113,25 +95,6 @@ class WorkspaceStore implements IWorkspaceStore {
|
||||
*/
|
||||
getWorkspaceBySlug = (workspaceSlug: string) => this.workspaces.find((w) => w.slug == workspaceSlug) || null;
|
||||
|
||||
/**
|
||||
* get Workspace projects using workspace slug
|
||||
* @param workspaceSlug
|
||||
* @returns
|
||||
*/
|
||||
getWorkspaceProjects = async (workspaceSlug: string) => {
|
||||
try {
|
||||
const projects = await this.projectService.getProjects(workspaceSlug, { is_favorite: "all" });
|
||||
runInAction(() => {
|
||||
this.projects = {
|
||||
...this.projects,
|
||||
[workspaceSlug]: projects,
|
||||
};
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Failed to fetch project from workspace store");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get workspace label information from the workspace labels
|
||||
* @param labelId
|
||||
@ -188,50 +151,6 @@ class WorkspaceStore implements IWorkspaceStore {
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user