feat: project settings state, filter by cycle
refractor: added types for cycle in IIssue, improved common function used for grouping, made custom hook for my issue filter
This commit is contained in:
parent
dd319deea1
commit
676355d673
20 changed files with 532 additions and 154 deletions
105
apps/app/lib/hooks/useMyIssueFilter.tsx
Normal file
105
apps/app/lib/hooks/useMyIssueFilter.tsx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import { useEffect, useState } from "react";
|
||||
// hooks
|
||||
import useUser from "./useUser";
|
||||
// types
|
||||
import { Properties, NestedKeyOf, IIssue } from "types";
|
||||
// services
|
||||
import userService from "lib/services/user.service";
|
||||
// common
|
||||
import { groupBy } from "constants/common";
|
||||
|
||||
import { PRIORITIES } from "constants/";
|
||||
|
||||
const initialValues: Properties = {
|
||||
key: true,
|
||||
state: true,
|
||||
assignee: true,
|
||||
priority: false,
|
||||
start_date: false,
|
||||
target_date: false,
|
||||
cycle: false,
|
||||
};
|
||||
|
||||
const useMyIssuesProperties = (issues?: IIssue[]) => {
|
||||
const [properties, setProperties] = useState<Properties>(initialValues);
|
||||
const [groupByProperty, setGroupByProperty] = useState<NestedKeyOf<IIssue> | null>(null);
|
||||
|
||||
const { states, user } = useUser();
|
||||
|
||||
useEffect(() => {
|
||||
if (!user) return;
|
||||
setProperties({ ...initialValues, ...user.my_issues_prop?.properties });
|
||||
setGroupByProperty(user.my_issues_prop?.groupBy ?? null);
|
||||
}, [user]);
|
||||
|
||||
let groupedByIssues: {
|
||||
[key: string]: IIssue[];
|
||||
} = {
|
||||
...(groupByProperty === "state_detail.name"
|
||||
? Object.fromEntries(
|
||||
states
|
||||
?.sort((a, b) => a.sequence - b.sequence)
|
||||
?.map((state) => [
|
||||
state.name,
|
||||
issues?.filter((issue) => issue.state === state.name) ?? [],
|
||||
]) ?? []
|
||||
)
|
||||
: groupByProperty === "priority"
|
||||
? Object.fromEntries(
|
||||
PRIORITIES.map((priority) => [
|
||||
priority,
|
||||
issues?.filter((issue) => issue.priority === priority) ?? [],
|
||||
])
|
||||
)
|
||||
: {}),
|
||||
...groupBy(issues ?? [], groupByProperty ?? ""),
|
||||
};
|
||||
|
||||
const setMyIssueProperty = (key: keyof Properties) => {
|
||||
if (!user) return;
|
||||
userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } });
|
||||
setProperties((prevData) => ({
|
||||
...prevData,
|
||||
[key]: !prevData[key],
|
||||
}));
|
||||
localStorage.setItem(
|
||||
"my_issues_prop",
|
||||
JSON.stringify({
|
||||
properties: {
|
||||
...properties,
|
||||
[key]: !properties[key],
|
||||
},
|
||||
groupBy: groupByProperty,
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const setMyIssueGroupByProperty = (groupByProperty: NestedKeyOf<IIssue> | null) => {
|
||||
if (!user) return;
|
||||
userService.updateUser({ my_issues_prop: { properties, groupBy: groupByProperty } });
|
||||
setGroupByProperty(groupByProperty);
|
||||
localStorage.setItem(
|
||||
"my_issues_prop",
|
||||
JSON.stringify({ properties, groupBy: groupByProperty })
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const viewProps = localStorage.getItem("my_issues_prop");
|
||||
if (viewProps) {
|
||||
const { properties, groupBy } = JSON.parse(viewProps);
|
||||
setProperties(properties);
|
||||
setGroupByProperty(groupBy);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
filteredIssues: groupedByIssues,
|
||||
groupByProperty,
|
||||
properties,
|
||||
setMyIssueProperty,
|
||||
setMyIssueGroupByProperty,
|
||||
} as const;
|
||||
};
|
||||
|
||||
export default useMyIssuesProperties;
|
||||
|
|
@ -132,6 +132,20 @@ class ProjectServices extends APIService {
|
|||
});
|
||||
}
|
||||
|
||||
async getProjectMember(
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
memberId: string
|
||||
): Promise<IProjectMember> {
|
||||
return this.get(PROJECT_MEMBER_DETAIL(workspacSlug, projectId, memberId))
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async updateProjectMember(
|
||||
workspacSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -207,7 +221,7 @@ class ProjectServices extends APIService {
|
|||
projectId: string,
|
||||
data: ProjectViewTheme
|
||||
): Promise<any> {
|
||||
await this.patch(PROJECT_VIEW_ENDPOINT(workspacSlug, projectId), data)
|
||||
await this.post(PROJECT_VIEW_ENDPOINT(workspacSlug, projectId), data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// services
|
||||
import { USER_ENDPOINT, USER_ISSUES_ENDPOINT, USER_ONBOARD_ENDPOINT } from "constants/api-routes";
|
||||
import APIService from "lib/services/api.service";
|
||||
import type { IUser } from "types";
|
||||
|
||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
|
|
@ -38,7 +39,7 @@ class UserService extends APIService {
|
|||
});
|
||||
}
|
||||
|
||||
async updateUser(data = {}): Promise<any> {
|
||||
async updateUser(data: Partial<IUser>): Promise<any> {
|
||||
return this.patch(USER_ENDPOINT, data)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,12 @@ import APIService from "lib/services/api.service";
|
|||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
// types
|
||||
import { IWorkspace, IWorkspaceMember, IWorkspaceMemberInvitation } from "types";
|
||||
import {
|
||||
IWorkspace,
|
||||
IWorkspaceMember,
|
||||
IWorkspaceMemberInvitation,
|
||||
ILastActiveWorkspaceDetails,
|
||||
} from "types";
|
||||
|
||||
class WorkspaceService extends APIService {
|
||||
constructor() {
|
||||
|
|
@ -98,6 +103,16 @@ class WorkspaceService extends APIService {
|
|||
});
|
||||
}
|
||||
|
||||
async getLastActiveWorkspaceAndProjects(): Promise<ILastActiveWorkspaceDetails> {
|
||||
return this.get(LAST_ACTIVE_WORKSPACE_AND_PROJECTS)
|
||||
.then((response) => {
|
||||
return response?.data;
|
||||
})
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async userWorkspaceInvitations(): Promise<IWorkspaceMemberInvitation[]> {
|
||||
return this.get(USER_WORKSPACE_INVITATIONS)
|
||||
.then((response) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue