refactor: views & filter (#490)

* fix: not saving filters on views detail page

* refactor: using issues endpoint to get issues in views detail page

feat: showing toast alert on saving view
This commit is contained in:
Dakshesh Jain 2023-03-22 18:18:19 +05:30 committed by GitHub
parent 9a97c97336
commit a830808f9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 52 deletions

View File

@ -34,7 +34,7 @@ import { GROUP_BY_OPTIONS, ORDER_BY_OPTIONS, FILTER_ISSUE_OPTIONS } from "consta
export const IssuesFilterView: React.FC = () => { export const IssuesFilterView: React.FC = () => {
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId } = router.query; const { workspaceSlug, projectId, viewId } = router.query;
const { const {
issueView, issueView,
@ -102,13 +102,16 @@ export const IssuesFilterView: React.FC = () => {
<MultiLevelDropdown <MultiLevelDropdown
label="Filters" label="Filters"
onSelect={(option) => { onSelect={(option) => {
setFilters({ setFilters(
{
...filters, ...filters,
[option.key]: [ [option.key]: [
...((filters?.[option.key as keyof typeof filters] as any[]) ?? []), ...((filters?.[option.key as keyof typeof filters] as any[]) ?? []),
option.value, option.value,
], ],
}); },
!Boolean(viewId)
);
}} }}
direction="left" direction="left"
options={[ options={[

View File

@ -12,6 +12,7 @@ import stateService from "services/state.service";
import projectService from "services/project.service"; import projectService from "services/project.service";
import modulesService from "services/modules.service"; import modulesService from "services/modules.service";
// hooks // hooks
import useToast from "hooks/use-toast";
import useIssuesView from "hooks/use-issues-view"; import useIssuesView from "hooks/use-issues-view";
// components // components
import { AllLists, AllBoards } from "components/core"; import { AllLists, AllBoards } from "components/core";
@ -81,6 +82,8 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query;
const { setToastAlert } = useToast();
const { const {
groupedByIssues, groupedByIssues,
issueView, issueView,
@ -443,9 +446,12 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
<span <span
className="cursor-pointer" className="cursor-pointer"
onClick={() => onClick={() =>
setFilters({ setFilters(
{
state: filters.state?.filter((s: any) => s !== stateId), state: filters.state?.filter((s: any) => s !== stateId),
}) },
!Boolean(viewId)
)
} }
> >
<XMarkIcon className="h-3 w-3" /> <XMarkIcon className="h-3 w-3" />
@ -474,9 +480,14 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
<span <span
className="cursor-pointer" className="cursor-pointer"
onClick={() => onClick={() =>
setFilters({ setFilters(
priority: filters.priority?.filter((p: any) => p !== priority), {
}) priority: filters.priority?.filter(
(p: any) => p !== priority
),
},
!Boolean(viewId)
)
} }
> >
<XMarkIcon className="h-3 w-3" /> <XMarkIcon className="h-3 w-3" />
@ -497,11 +508,14 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
<span <span
className="cursor-pointer" className="cursor-pointer"
onClick={() => onClick={() =>
setFilters({ setFilters(
{
assignees: filters.assignees?.filter( assignees: filters.assignees?.filter(
(p: any) => p !== memberId (p: any) => p !== memberId
), ),
}) },
!Boolean(viewId)
)
} }
> >
<XMarkIcon className="h-3 w-3" /> <XMarkIcon className="h-3 w-3" />
@ -519,18 +533,24 @@ export const IssuesView: React.FC<Props> = ({ type = "issue", openIssuesListModa
})} })}
</div> </div>
{Object.keys(filters).length > 0 && {Object.keys(filters).length > 0 && nullFilters.length !== Object.keys(filters).length && (
nullFilters.length !== Object.keys(filters).length &&
!viewId && (
<PrimaryButton <PrimaryButton
onClick={() => onClick={() => {
if (viewId) {
setFilters({}, true);
setToastAlert({
title: "View updated",
message: "Your view has been updated",
type: "success",
});
} else
setCreateViewModal({ setCreateViewModal({
query: filters, query: filters,
}) });
} }}
className="flex items-center gap-2 text-sm" className="flex items-center gap-2 text-sm"
> >
<PlusIcon className="h-4 w-4" /> {!viewId && <PlusIcon className="h-4 w-4" />}
Save view Save view
</PrimaryButton> </PrimaryButton>
)} )}

View File

@ -44,7 +44,7 @@ type ReducerActionType = {
type ContextType = IssueViewProps & { type ContextType = IssueViewProps & {
setGroupByProperty: (property: "state" | "priority" | "labels" | null) => void; setGroupByProperty: (property: "state" | "priority" | "labels" | null) => void;
setOrderBy: (property: "created_at" | "updated_at" | "priority" | "sort_order") => void; setOrderBy: (property: "created_at" | "updated_at" | "priority" | "sort_order") => void;
setFilters: (filters: Partial<IIssueFilterOptions>) => void; setFilters: (filters: Partial<IIssueFilterOptions>, saveToServer?: boolean) => void;
resetFilterToDefault: () => void; resetFilterToDefault: () => void;
setNewFilterDefaultView: () => void; setNewFilterDefaultView: () => void;
setIssueViewToKanban: () => void; setIssueViewToKanban: () => void;
@ -335,7 +335,7 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
); );
const setFilters = useCallback( const setFilters = useCallback(
(property: Partial<IIssueFilterOptions>) => { (property: Partial<IIssueFilterOptions>, saveToServer = true) => {
Object.keys(property).forEach((key) => { Object.keys(property).forEach((key) => {
if (property[key as keyof typeof property]?.length === 0) { if (property[key as keyof typeof property]?.length === 0) {
property[key as keyof typeof property] = null; property[key as keyof typeof property] = null;
@ -380,13 +380,14 @@ export const IssueViewContextProvider: React.FC<{ children: React.ReactNode }> =
}, },
}; };
}, false); }, false);
if (saveToServer)
sendFilterDataToServer(workspaceSlug as string, projectId as string, viewId as string, { sendFilterDataToServer(workspaceSlug as string, projectId as string, viewId as string, {
query_data: { query_data: {
...state.filters, ...state.filters,
...property, ...property,
}, },
}); });
} else } else if (saveToServer)
saveDataToServer(workspaceSlug as string, projectId as string, { saveDataToServer(workspaceSlug as string, projectId as string, {
...state, ...state,
filters: { filters: {

View File

@ -38,7 +38,7 @@ const useIssuesView = () => {
} = useContext(issueViewContext); } = useContext(issueViewContext);
const router = useRouter(); const router = useRouter();
const { workspaceSlug, projectId, cycleId, moduleId, viewId } = router.query; const { workspaceSlug, projectId, cycleId, moduleId } = router.query;
const params: any = { const params: any = {
order_by: orderBy, order_by: orderBy,
@ -66,14 +66,6 @@ const useIssuesView = () => {
: null : null
); );
const { data: viewIssues } = useSWR(
workspaceSlug && projectId && viewId ? VIEW_ISSUES(viewId as string) : null,
workspaceSlug && projectId && viewId
? () =>
viewsService.getViewIssues(workspaceSlug as string, projectId as string, viewId as string)
: null
);
const { data: cycleIssues } = useSWR( const { data: cycleIssues } = useSWR(
workspaceSlug && projectId && cycleId && params workspaceSlug && projectId && cycleId && params
? CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params) ? CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params)
@ -109,11 +101,11 @@ const useIssuesView = () => {
[key: string]: IIssue[]; [key: string]: IIssue[];
} }
| undefined = useMemo(() => { | undefined = useMemo(() => {
const issuesToGroup = viewIssues ?? cycleIssues ?? moduleIssues ?? projectIssues; const issuesToGroup = cycleIssues ?? moduleIssues ?? projectIssues;
if (Array.isArray(issuesToGroup)) return { allIssues: issuesToGroup }; if (Array.isArray(issuesToGroup)) return { allIssues: issuesToGroup };
else return issuesToGroup; else return issuesToGroup;
}, [projectIssues, cycleIssues, moduleIssues, viewIssues]); }, [projectIssues, cycleIssues, moduleIssues]);
return { return {
groupedByIssues, groupedByIssues,