mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
fix: store updates
This commit is contained in:
parent
984f7ed6b8
commit
d57d91e530
59
packages/types/src/view/base.d.ts
vendored
59
packages/types/src/view/base.d.ts
vendored
@ -1,34 +1,45 @@
|
|||||||
import { TFilters, TDisplayFilters, TDisplayProperties } from "./filter";
|
import {
|
||||||
|
TViewFilters,
|
||||||
|
TViewDisplayFilters,
|
||||||
|
TViewDisplayProperties,
|
||||||
|
} from "./filter";
|
||||||
|
|
||||||
declare enum EGlobalViewAccess {
|
export type TViewTypes =
|
||||||
|
| "WORKSPACE_YOUR_VIEWS"
|
||||||
|
| "WORKSPACE_VIEWS"
|
||||||
|
| "WORKSPACE_PROJECT_VIEWS"
|
||||||
|
| "PROJECT_VIEWS"
|
||||||
|
| "PROJECT_YOUR_VIEWS";
|
||||||
|
|
||||||
|
declare enum EViewAccess {
|
||||||
"public" = 0,
|
"public" = 0,
|
||||||
"private" = 1,
|
"private" = 1,
|
||||||
"shared" = 2,
|
"shared" = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TViewAccess =
|
export type TViewAccess =
|
||||||
| EGlobalViewAccess.public
|
| EViewAccess.public
|
||||||
| EGlobalViewAccess.private
|
| EViewAccess.private
|
||||||
| EGlobalViewAccess.shared;
|
| EViewAccess.shared;
|
||||||
|
|
||||||
export type TView = {
|
export type TView = {
|
||||||
readonly id: string;
|
id: string | undefined;
|
||||||
readonly workspace: string;
|
workspace: string | undefined;
|
||||||
readonly project: string | undefined;
|
project: string | undefined;
|
||||||
name: string;
|
name: string | undefined;
|
||||||
description: string;
|
description: string | undefined;
|
||||||
readonly query: string;
|
query: string | undefined;
|
||||||
filters: TFilters;
|
filters: TViewFilters | undefined;
|
||||||
display_filters: TDisplayFilters;
|
display_filters: TViewDisplayFilters | undefined;
|
||||||
display_properties: TDisplayProperties;
|
display_properties: TViewDisplayProperties | undefined;
|
||||||
readonly access: TViewAccess;
|
access: TViewAccess | undefined;
|
||||||
readonly owned_by: string;
|
owned_by: string | undefined;
|
||||||
readonly sort_order: number;
|
sort_order: number | undefined;
|
||||||
readonly is_locked: boolean;
|
is_locked: boolean | undefined;
|
||||||
readonly is_pinned: boolean;
|
is_pinned: boolean | undefined;
|
||||||
readonly is_favorite: boolean;
|
is_favorite: boolean | undefined;
|
||||||
readonly created_by: string;
|
created_by: string | undefined;
|
||||||
readonly updated_by: string;
|
updated_by: string | undefined;
|
||||||
readonly created_at: Date;
|
created_at: Date | undefined;
|
||||||
readonly updated_at: Date;
|
updated_at: Date | undefined;
|
||||||
};
|
};
|
||||||
|
37
packages/types/src/view/filter.d.ts
vendored
37
packages/types/src/view/filter.d.ts
vendored
@ -1,8 +1,13 @@
|
|||||||
export type TLayouts = "list" | "kanban" | "calendar" | "spreadsheet" | "gantt";
|
export type TViewLayouts =
|
||||||
|
| "list"
|
||||||
|
| "kanban"
|
||||||
|
| "calendar"
|
||||||
|
| "spreadsheet"
|
||||||
|
| "gantt";
|
||||||
|
|
||||||
export type TCalendarLayouts = "month" | "week";
|
export type TViewCalendarLayouts = "month" | "week";
|
||||||
|
|
||||||
export type TFilters = {
|
export type TViewFilters = {
|
||||||
project: string[];
|
project: string[];
|
||||||
priority: string[];
|
priority: string[];
|
||||||
state: string[];
|
state: string[];
|
||||||
@ -16,8 +21,8 @@ export type TFilters = {
|
|||||||
target_date: string[];
|
target_date: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TDisplayFilters = {
|
export type TViewDisplayFilters = {
|
||||||
layout: TLayouts;
|
layout: TViewLayouts;
|
||||||
group_by: string | undefined;
|
group_by: string | undefined;
|
||||||
sub_group_by: string | undefined;
|
sub_group_by: string | undefined;
|
||||||
order_by: string;
|
order_by: string;
|
||||||
@ -26,11 +31,11 @@ export type TDisplayFilters = {
|
|||||||
show_empty_groups: boolean;
|
show_empty_groups: boolean;
|
||||||
calendar: {
|
calendar: {
|
||||||
show_weekends: boolean;
|
show_weekends: boolean;
|
||||||
layout: TCalendarLayouts;
|
layout: TViewCalendarLayouts;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TDisplayProperties = {
|
export type TViewDisplayProperties = {
|
||||||
assignee: boolean;
|
assignee: boolean;
|
||||||
start_date: boolean;
|
start_date: boolean;
|
||||||
due_date: boolean;
|
due_date: boolean;
|
||||||
@ -46,19 +51,19 @@ export type TDisplayProperties = {
|
|||||||
updated_on: boolean;
|
updated_on: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TFilterProps = {
|
export type TViewFilterProps = {
|
||||||
filters: TFilters;
|
filters: TViewFilters | undefined;
|
||||||
display_filters: TDisplayFilters;
|
display_filters: TViewDisplayFilters | undefined;
|
||||||
display_properties: TDisplayProperties;
|
display_properties: TViewDisplayProperties | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TFilterPartialProps = {
|
export type TViewFilterPartialProps = {
|
||||||
filters: Partial<TFilters>;
|
filters: Partial<TViewFilters> | undefined;
|
||||||
display_filters: Partial<TDisplayFilters>;
|
display_filters: Partial<TViewDisplayFilters> | undefined;
|
||||||
display_properties: Partial<TDisplayProperties>;
|
display_properties: Partial<TViewDisplayProperties> | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TFilterQueryParams =
|
export type TViewFilterQueryParams =
|
||||||
| "project"
|
| "project"
|
||||||
| "priority"
|
| "priority"
|
||||||
| "state"
|
| "state"
|
||||||
|
1
packages/types/src/view/root.d.ts
vendored
1
packages/types/src/view/root.d.ts
vendored
@ -1,2 +1,3 @@
|
|||||||
export * from "./filter";
|
export * from "./filter";
|
||||||
export * from "./base";
|
export * from "./base";
|
||||||
|
export * from "./user-base";
|
||||||
|
21
packages/types/src/view/user-base.d.ts
vendored
Normal file
21
packages/types/src/view/user-base.d.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import {
|
||||||
|
TViewFilters,
|
||||||
|
TViewDisplayFilters,
|
||||||
|
TViewDisplayProperties,
|
||||||
|
} from "./filter";
|
||||||
|
|
||||||
|
export type TUserView = {
|
||||||
|
id: string | undefined;
|
||||||
|
workspace: string | undefined;
|
||||||
|
project: string | undefined;
|
||||||
|
module: string | undefined;
|
||||||
|
cycle: string | undefined;
|
||||||
|
filters: TViewFilters | undefined;
|
||||||
|
display_filters: TViewDisplayFilters | undefined;
|
||||||
|
display_properties: TViewDisplayProperties | undefined;
|
||||||
|
user: string | undefined;
|
||||||
|
created_by: string | undefined;
|
||||||
|
updated_by: string | undefined;
|
||||||
|
created_at: Date | undefined;
|
||||||
|
updated_at: Date | undefined;
|
||||||
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import { FC, useMemo } from "react";
|
import { FC, } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
// components
|
// components
|
||||||
import { IssuePeekOverview } from "components/issues";
|
import { IssuePeekOverview } from "components/issues";
|
||||||
|
17
web/components/view/applied-filters/filter-item.tsx
Normal file
17
web/components/view/applied-filters/filter-item.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
|
||||||
|
type TViewFiltersItem = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewFiltersItem: FC<TViewFiltersItem> = (props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>ViewFiltersItem</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
51
web/components/view/applied-filters/filter.tsx
Normal file
51
web/components/view/applied-filters/filter.tsx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
|
import { X } from "lucide-react";
|
||||||
|
// hooks
|
||||||
|
import { useViewDetail } from "hooks/store";
|
||||||
|
// helpers
|
||||||
|
import { generateTitle } from "./helper";
|
||||||
|
// types
|
||||||
|
import { TFilters } from "@plane/types";
|
||||||
|
|
||||||
|
type TViewAppliedFilters = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string;
|
||||||
|
filterKey: keyof TFilters;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewAppliedFilters: FC<TViewAppliedFilters> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId, filterKey } = props;
|
||||||
|
|
||||||
|
const view = useViewDetail("WORKSPACE", workspaceSlug, projectId, viewId);
|
||||||
|
|
||||||
|
const filterKeyValue =
|
||||||
|
view?.appliedFilters?.filters && !isEmpty(view?.appliedFilters?.filters)
|
||||||
|
? view?.appliedFilters?.filters?.[filterKey] || undefined
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!filterKeyValue || filterKeyValue.length <= 0) return <></>;
|
||||||
|
return (
|
||||||
|
<div key={filterKey} className="relative flex items-center gap-2 border border-custom-border-300 rounded p-1.5">
|
||||||
|
<div className="flex-shrink-0 text-xs">{generateTitle(filterKey)}</div>
|
||||||
|
<div className="border border-red-500 relative flex items-center">
|
||||||
|
{/* <div className="relative flex items-center">
|
||||||
|
<div>Icon</div>
|
||||||
|
<div>Title</div>
|
||||||
|
<div>Close</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div>Icon</div>
|
||||||
|
<div>Title</div>
|
||||||
|
<div>Close</div>
|
||||||
|
</div> */}
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 relative flex justify-center items-center w-4 h-4 rounded-full cursor-pointer transition-all bg-custom-background-80 hover:bg-custom-background-90 text-custom-text-300 hover:text-custom-text-200">
|
||||||
|
<X size={10} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
66
web/components/view/applied-filters/helper.tsx
Normal file
66
web/components/view/applied-filters/helper.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
|
// types
|
||||||
|
import { TFilters } from "@plane/types";
|
||||||
|
|
||||||
|
type TComputedAppliedFilters = {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
selectedOptions?: { id: string; icon: ""; title: ""; component: ReactNode }[];
|
||||||
|
dropdownOptions?: { id: string; icon: ""; title: ""; component: ReactNode }[];
|
||||||
|
}[];
|
||||||
|
|
||||||
|
export const filterOptions = (key: keyof TFilters, selectedFilters: string[]) => {
|
||||||
|
switch (key) {
|
||||||
|
case "project":
|
||||||
|
return [];
|
||||||
|
case "priority":
|
||||||
|
return [];
|
||||||
|
case "state":
|
||||||
|
return [];
|
||||||
|
case "state_group":
|
||||||
|
return [];
|
||||||
|
case "assignees":
|
||||||
|
return [];
|
||||||
|
case "mentions":
|
||||||
|
return [];
|
||||||
|
case "subscriber":
|
||||||
|
return [];
|
||||||
|
case "created_by":
|
||||||
|
return [];
|
||||||
|
case "labels":
|
||||||
|
return [];
|
||||||
|
case "start_date":
|
||||||
|
return [];
|
||||||
|
case "target_date":
|
||||||
|
return [];
|
||||||
|
default:
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const generateTitle = (title: string) =>
|
||||||
|
title
|
||||||
|
.split("_")
|
||||||
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
||||||
|
.join(" ");
|
||||||
|
|
||||||
|
export const constructAppliedFilters = (filters: TFilters): TComputedAppliedFilters => {
|
||||||
|
const appliedFilters: TComputedAppliedFilters = [];
|
||||||
|
|
||||||
|
if (filters && !isEmpty(filters)) {
|
||||||
|
Object.keys(filters).forEach((_filterKey) => {
|
||||||
|
const _key = _filterKey as keyof TFilters;
|
||||||
|
const _value = filters[_key];
|
||||||
|
|
||||||
|
if (_value && !isEmpty(_value)) {
|
||||||
|
appliedFilters.push({
|
||||||
|
key: _key,
|
||||||
|
title: generateTitle(_key),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return appliedFilters;
|
||||||
|
};
|
45
web/components/view/applied-filters/root.tsx
Normal file
45
web/components/view/applied-filters/root.tsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
import isEmpty from "lodash/isEmpty";
|
||||||
|
// hooks
|
||||||
|
import { useViewDetail } from "hooks/store";
|
||||||
|
// components
|
||||||
|
import { ViewAppliedFilters } from "./filter";
|
||||||
|
// types
|
||||||
|
import { TFilters } from "@plane/types";
|
||||||
|
import { TViewOperations } from "../types";
|
||||||
|
|
||||||
|
type TViewAppliedFiltersRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string;
|
||||||
|
viewOperations: TViewOperations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewAppliedFiltersRoot: FC<TViewAppliedFiltersRoot> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId } = props;
|
||||||
|
// hooks
|
||||||
|
const view = useViewDetail("WORKSPACE", workspaceSlug, projectId, viewId);
|
||||||
|
|
||||||
|
const filterKeys =
|
||||||
|
view?.appliedFilters && !isEmpty(view?.appliedFilters?.filters)
|
||||||
|
? Object.keys(view?.appliedFilters?.filters)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
if (!filterKeys) return <></>;
|
||||||
|
return (
|
||||||
|
<div className="relative flex items-center gap-2 flex-wrap border border-red-500 p-4">
|
||||||
|
{filterKeys.map((key) => {
|
||||||
|
const filterKey = key as keyof TFilters;
|
||||||
|
return (
|
||||||
|
<ViewAppliedFilters
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
|
viewId={viewId}
|
||||||
|
filterKey={filterKey}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
17
web/components/view/display-filters/root.tsx
Normal file
17
web/components/view/display-filters/root.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
|
||||||
|
type TViewDisplayFiltersRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewDisplayFiltersRoot: FC<TViewDisplayFiltersRoot> = (props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>ViewDisplayFiltersRoot</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
17
web/components/view/display-properties/root.tsx
Normal file
17
web/components/view/display-properties/root.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
|
||||||
|
type TViewDisplayPropertiesRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewDisplayPropertiesRoot: FC<TViewDisplayPropertiesRoot> = (props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>ViewDisplayPropertiesRoot</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
34
web/components/view/filters/root.tsx
Normal file
34
web/components/view/filters/root.tsx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
// types
|
||||||
|
import { TViewOperations } from "../types";
|
||||||
|
|
||||||
|
type TViewFiltersRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
viewOperations: TViewOperations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewFiltersRoot: FC<TViewFiltersRoot> = (props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId, viewOperations } = props;
|
||||||
|
|
||||||
|
const filters = {
|
||||||
|
project: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
priority: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
state: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
state_group: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
assignees: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
mentions: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
subscriber: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
created_by: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
labels: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
start_date: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
target_date: ["1", "2", "3", "4", "5", "6"],
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border border-red-500">
|
||||||
|
<div>ViewFiltersRoot</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
18
web/components/view/index.ts
Normal file
18
web/components/view/index.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
export * from "./root";
|
||||||
|
|
||||||
|
// views
|
||||||
|
export * from "./views/root";
|
||||||
|
export * from "./views/create-edit";
|
||||||
|
export * from "./views/create-edit-form";
|
||||||
|
|
||||||
|
// view filters
|
||||||
|
export * from "./filters/root";
|
||||||
|
|
||||||
|
// view display filters
|
||||||
|
export * from "./display-filters/root";
|
||||||
|
|
||||||
|
// view display properties
|
||||||
|
export * from "./display-properties/root";
|
||||||
|
|
||||||
|
// view applied filters
|
||||||
|
export * from "./applied-filters/root";
|
77
web/components/view/root.tsx
Normal file
77
web/components/view/root.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import { FC, ReactNode, useEffect, useMemo } from "react";
|
||||||
|
import { observer } from "mobx-react-lite";
|
||||||
|
// hooks
|
||||||
|
import { useView } from "hooks/store/use-view";
|
||||||
|
// components
|
||||||
|
import { ViewRoot, ViewCreateEdit, ViewFiltersRoot, ViewAppliedFiltersRoot } from "./";
|
||||||
|
// types
|
||||||
|
import { TViewOperations } from "./types";
|
||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
type TWorkspaceViewRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
viewType: TViewTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const WorkspaceViewRoot: FC<TWorkspaceViewRoot> = observer((props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId, viewType } = props;
|
||||||
|
// hooks
|
||||||
|
const views = useView(workspaceSlug, projectId, viewType);
|
||||||
|
|
||||||
|
const viewOperations: TViewOperations = useMemo(
|
||||||
|
() => ({
|
||||||
|
create: async (data) => {
|
||||||
|
await views?.create(data);
|
||||||
|
},
|
||||||
|
fetch: async () => {
|
||||||
|
await views?.fetch();
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[views]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (workspaceSlug && viewId && viewOperations) viewOperations.fetch();
|
||||||
|
}, [workspaceSlug, viewId, viewOperations]);
|
||||||
|
|
||||||
|
console.log("views?.viewMap", Object.keys(views?.viewMap).length);
|
||||||
|
|
||||||
|
Object.keys(views?.viewMap).map((viewId) => {
|
||||||
|
console.log(views?.viewMap?.[viewId]?.access);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative w-full h-full border border-red-500">
|
||||||
|
<ViewCreateEdit
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
|
viewId={viewId}
|
||||||
|
viewType={viewType}
|
||||||
|
viewOperations={viewOperations}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* <ViewRoot
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
|
viewId={viewId}
|
||||||
|
viewType={viewType}
|
||||||
|
viewOperations={viewOperations}
|
||||||
|
/> */}
|
||||||
|
|
||||||
|
{/* <ViewFiltersRoot
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
|
viewId={"61d6b507-ae5c-45d6-b169-da7162f016a0"}
|
||||||
|
viewOperations={viewOperations}
|
||||||
|
/>
|
||||||
|
<ViewAppliedFiltersRoot
|
||||||
|
workspaceSlug={workspaceSlug}
|
||||||
|
projectId={projectId}
|
||||||
|
viewId={"61d6b507-ae5c-45d6-b169-da7162f016a0"}
|
||||||
|
viewOperations={viewOperations}
|
||||||
|
/> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
6
web/components/view/types.d.ts
vendored
Normal file
6
web/components/view/types.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { TView } from "@plane/types";
|
||||||
|
|
||||||
|
export type TViewOperations = {
|
||||||
|
create: (data: Partial<TView>) => void;
|
||||||
|
fetch: () => void;
|
||||||
|
};
|
104
web/components/view/views/create-edit-form.tsx
Normal file
104
web/components/view/views/create-edit-form.tsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { FC, Fragment } from "react";
|
||||||
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
import { Trash2, Plus, X } from "lucide-react";
|
||||||
|
// ui
|
||||||
|
import { Input, Button } from "@plane/ui";
|
||||||
|
// types
|
||||||
|
import { TViewOperations } from "../types";
|
||||||
|
|
||||||
|
type TViewCreateEditForm = {
|
||||||
|
modalToggle: boolean;
|
||||||
|
|
||||||
|
handleModalClose: () => void;
|
||||||
|
viewOperations?: TViewOperations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewCreateEditForm: FC<TViewCreateEditForm> = (props) => {
|
||||||
|
const { modalToggle, handleModalClose, viewOperations } = props;
|
||||||
|
|
||||||
|
const createView = () => {
|
||||||
|
viewOperations?.create({ name: "create" });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Transition.Root show={modalToggle} as={Fragment}>
|
||||||
|
<Dialog as="div" className="relative z-20" onClose={handleModalClose}>
|
||||||
|
<Transition.Child
|
||||||
|
as={Fragment}
|
||||||
|
enter="ease-out duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0 bg-custom-backdrop transition-opacity" />
|
||||||
|
</Transition.Child>
|
||||||
|
|
||||||
|
<div className="fixed inset-0 z-20 overflow-y-auto">
|
||||||
|
<div className="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
|
||||||
|
<Transition.Child
|
||||||
|
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"
|
||||||
|
leave="ease-in duration-200"
|
||||||
|
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
>
|
||||||
|
<Dialog.Panel className="relative transform overflow-hidden rounded-lg bg-custom-background-100 text-left shadow-custom-shadow-md transition-all sm:my-8 sm:w-[40rem] py-5 border-[0.1px] border-custom-border-100">
|
||||||
|
<div className="p-3 px-5 relative flex items-center gap-2">
|
||||||
|
<div className="relative rounded p-1.5 px-2 flex items-center gap-1 border border-custom-border-100 bg-custom-background-80">
|
||||||
|
<div className="flex-shrink-0 relative flex justify-center items-center w-4 h-4 overflow-hidden">
|
||||||
|
<Trash2 className="w-3.5 h-3.5" />
|
||||||
|
</div>
|
||||||
|
<div className="text-xs uppercase">Project Identifier</div>
|
||||||
|
</div>
|
||||||
|
<div className="">Create|Edit View</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-3 px-5">
|
||||||
|
<Input
|
||||||
|
id="email"
|
||||||
|
name="email"
|
||||||
|
type="email"
|
||||||
|
// value={value}
|
||||||
|
// onChange={onChange}
|
||||||
|
// hasError={Boolean(errors.email)}
|
||||||
|
placeholder="What do you want to call this view?"
|
||||||
|
className="h-[46px] w-full border border-onboarding-border-100 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-3 px-5 relative flex justify-between items-center gap-2">
|
||||||
|
<div className="relative rounded p-1.5 px-2 flex items-center gap-1 border border-custom-border-100 bg-custom-background-80">
|
||||||
|
<div className="flex-shrink-0 relative flex justify-center items-center w-4 h-4 overflow-hidden">
|
||||||
|
<Plus className="w-3 h-3" />
|
||||||
|
</div>
|
||||||
|
<div className="text-xs">Filters</div>
|
||||||
|
</div>
|
||||||
|
<div className="relative rounded p-1.5 px-2 flex items-center gap-1 border border-dashed border-custom-border-100 bg-custom-background-80">
|
||||||
|
<div className="text-xs">Clear all filters</div>
|
||||||
|
<div className="flex-shrink-0 relative flex justify-center items-center w-4 h-4 overflow-hidden">
|
||||||
|
<X className="w-3 h-3" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="p-3 px-5 relative bg-custom-background-80">Applied Filters with each dropdown</div>
|
||||||
|
|
||||||
|
<div className="p-3 px-5 relative flex justify-end items-center gap-2">
|
||||||
|
<Button variant="neutral-primary" onClick={handleModalClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="primary">Create View</Button>
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</Transition.Child>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</Transition.Root>
|
||||||
|
);
|
||||||
|
};
|
42
web/components/view/views/create-edit.tsx
Normal file
42
web/components/view/views/create-edit.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { FC, useState } from "react";
|
||||||
|
import { Plus } from "lucide-react";
|
||||||
|
// ui
|
||||||
|
import { Button } from "@plane/ui";
|
||||||
|
// components
|
||||||
|
import { ViewCreateEditForm } from "./create-edit-form";
|
||||||
|
// types
|
||||||
|
import { TViewOperations } from "../types";
|
||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
type TViewCreateEdit = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
viewType: TViewTypes;
|
||||||
|
viewOperations: TViewOperations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewCreateEdit: FC<TViewCreateEdit> = (props) => {
|
||||||
|
const { workspaceSlug, projectId, viewId, viewOperations } = props;
|
||||||
|
// states
|
||||||
|
const [modalToggle, setModalToggle] = useState(false);
|
||||||
|
|
||||||
|
const handleModalOpen = () => setModalToggle(true);
|
||||||
|
const handleModalClose = () => setModalToggle(false);
|
||||||
|
|
||||||
|
const createView = () => {
|
||||||
|
viewOperations?.create({ name: "create" });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ViewCreateEditForm modalToggle={modalToggle} handleModalClose={handleModalClose} />
|
||||||
|
<div className="border border-red-500 p-5">
|
||||||
|
<Button size="sm" className="flex justify-center items-center" onClick={createView}>
|
||||||
|
<Plus size={12} />
|
||||||
|
<span>New View</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
36
web/components/view/views/root.tsx
Normal file
36
web/components/view/views/root.tsx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { FC } from "react";
|
||||||
|
import { ChevronRight } from "lucide-react";
|
||||||
|
// types
|
||||||
|
import { TViewOperations } from "../types";
|
||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
type TViewRoot = {
|
||||||
|
workspaceSlug: string;
|
||||||
|
projectId: string | undefined;
|
||||||
|
viewId: string | undefined;
|
||||||
|
viewType: TViewTypes;
|
||||||
|
viewOperations: TViewOperations;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewRoot: FC<TViewRoot> = (props) => {
|
||||||
|
const {} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border border-red-500 relative flex items-center gap-2">
|
||||||
|
{/* header */}
|
||||||
|
<div className="">Workspace Views</div>
|
||||||
|
{/* divider */}
|
||||||
|
<div className="relative w-[50px] h-[50px] flex justify-center items-center">
|
||||||
|
<div className="absolute top-0 bottom-0 border border-red-500 w-[0.5px]" />
|
||||||
|
<div className="flex-shrink-0 w-4 h-4 relative flex justify-center items-center rounded-full bg-red-500">
|
||||||
|
<ChevronRight size={12} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* views content */}
|
||||||
|
<div className=" relative flex items-center">
|
||||||
|
<div>Icon</div>
|
||||||
|
<div>Title</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
47
web/constants/view.ts
Normal file
47
web/constants/view.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
export const VIEW_TYPES: Record<TViewTypes, TViewTypes> = {
|
||||||
|
WORKSPACE_YOUR_VIEWS: "WORKSPACE_YOUR_VIEWS",
|
||||||
|
WORKSPACE_VIEWS: "WORKSPACE_VIEWS",
|
||||||
|
WORKSPACE_PROJECT_VIEWS: "WORKSPACE_PROJECT_VIEWS",
|
||||||
|
PROJECT_VIEWS: "PROJECT_VIEWS",
|
||||||
|
PROJECT_YOUR_VIEWS: "PROJECT_YOUR_VIEWS",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const VIEW_DEFAULT_FILTER_PARAMETERS = {
|
||||||
|
filters: {
|
||||||
|
default: [
|
||||||
|
"project",
|
||||||
|
"priority",
|
||||||
|
"state",
|
||||||
|
"state_group",
|
||||||
|
"assignees",
|
||||||
|
"mentions",
|
||||||
|
"subscriber",
|
||||||
|
"created_by",
|
||||||
|
"labels",
|
||||||
|
"start_date",
|
||||||
|
"target_date",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
display_filters: {
|
||||||
|
default: ["layout", "group_by", "sub_group_by", "order_by", "type", "sub_issue", "show_empty_groups", "calendar"],
|
||||||
|
},
|
||||||
|
display_properties: {
|
||||||
|
default: [
|
||||||
|
"assignee",
|
||||||
|
"start_date",
|
||||||
|
"due_date",
|
||||||
|
"labels",
|
||||||
|
"key",
|
||||||
|
"priority",
|
||||||
|
"state",
|
||||||
|
"sub_issue_count",
|
||||||
|
"link",
|
||||||
|
"attachment_count",
|
||||||
|
"estimate",
|
||||||
|
"created_on",
|
||||||
|
"updated_on",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
@ -21,3 +21,7 @@ export * from "./use-kanban-view";
|
|||||||
export * from "./use-issue-detail";
|
export * from "./use-issue-detail";
|
||||||
export * from "./use-inbox";
|
export * from "./use-inbox";
|
||||||
export * from "./use-inbox-issues";
|
export * from "./use-inbox-issues";
|
||||||
|
|
||||||
|
// new store
|
||||||
|
export * from "./use-view";
|
||||||
|
export * from "./use-view-detail";
|
||||||
|
38
web/hooks/store/use-view-detail.tsx
Normal file
38
web/hooks/store/use-view-detail.tsx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
// mobx store
|
||||||
|
import { StoreContext } from "contexts/store-context";
|
||||||
|
// store
|
||||||
|
import { TViewStore } from "store/view/view.store";
|
||||||
|
// types
|
||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
export const useViewDetail = (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string | undefined,
|
||||||
|
viewId: string,
|
||||||
|
viewType: TViewTypes | undefined
|
||||||
|
): TViewStore | undefined => {
|
||||||
|
const context = useContext(StoreContext);
|
||||||
|
if (context === undefined) throw new Error("useViewDetail must be used within StoreProvider");
|
||||||
|
|
||||||
|
if (!workspaceSlug) throw new Error("useViewDetail hook must require workspaceSlug");
|
||||||
|
|
||||||
|
if (!viewId) throw new Error("useViewDetail hook must require viewId");
|
||||||
|
|
||||||
|
switch (viewType) {
|
||||||
|
case "WORKSPACE_YOUR_VIEWS":
|
||||||
|
return context.view.workspaceViewStore.viewById(viewId);
|
||||||
|
case "WORKSPACE_VIEWS":
|
||||||
|
return context.view.workspaceViewMeStore.viewById(viewId);
|
||||||
|
case "WORKSPACE_PROJECT_VIEWS":
|
||||||
|
return context.view.workspaceViewMeStore.viewById(viewId);
|
||||||
|
case "PROJECT_YOUR_VIEWS":
|
||||||
|
if (!projectId) throw new Error("useView hook must require projectId");
|
||||||
|
return context.view.projectViewMeStore.viewById(viewId);
|
||||||
|
case "PROJECT_VIEWS":
|
||||||
|
if (!projectId) throw new Error("useView hook must require projectId");
|
||||||
|
return context.view.projectViewStore.viewById(viewId);
|
||||||
|
default:
|
||||||
|
throw new Error("useView hook must require viewType");
|
||||||
|
}
|
||||||
|
};
|
35
web/hooks/store/use-view.tsx
Normal file
35
web/hooks/store/use-view.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { useContext } from "react";
|
||||||
|
// mobx store
|
||||||
|
import { StoreContext } from "contexts/store-context";
|
||||||
|
// types
|
||||||
|
import { ViewRoot } from "store/view/view-root.store";
|
||||||
|
// types
|
||||||
|
import { TViewTypes } from "@plane/types";
|
||||||
|
|
||||||
|
export const useView = (
|
||||||
|
workspaceSlug: string,
|
||||||
|
projectId: string | undefined,
|
||||||
|
viewType: TViewTypes | undefined
|
||||||
|
): ViewRoot => {
|
||||||
|
const context = useContext(StoreContext);
|
||||||
|
if (context === undefined) throw new Error("useView must be used within StoreProvider");
|
||||||
|
|
||||||
|
if (!workspaceSlug) throw new Error("useView hook must require workspaceSlug");
|
||||||
|
|
||||||
|
switch (viewType) {
|
||||||
|
case "WORKSPACE_YOUR_VIEWS":
|
||||||
|
return context.view.workspaceViewStore;
|
||||||
|
case "WORKSPACE_VIEWS":
|
||||||
|
return context.view.workspaceViewMeStore;
|
||||||
|
case "WORKSPACE_PROJECT_VIEWS":
|
||||||
|
return context.view.workspaceViewMeStore;
|
||||||
|
case "PROJECT_YOUR_VIEWS":
|
||||||
|
if (!projectId) throw new Error("useView hook must require projectId");
|
||||||
|
return context.view.projectViewMeStore;
|
||||||
|
case "PROJECT_VIEWS":
|
||||||
|
if (!projectId) throw new Error("useView hook must require projectId");
|
||||||
|
return context.view.projectViewStore;
|
||||||
|
default:
|
||||||
|
throw new Error("useView hook must require viewType");
|
||||||
|
}
|
||||||
|
};
|
@ -10,23 +10,24 @@ export class IssueFiltersService extends APIService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// // workspace issue filters
|
// // workspace issue filters
|
||||||
// async fetchWorkspaceFilters(workspaceSlug: string): Promise<IIssueFiltersResponse> {
|
async fetchWorkspaceFilters(workspaceSlug: string): Promise<IIssueFiltersResponse> {
|
||||||
// return this.get(`/api/workspaces/${workspaceSlug}/user-properties/`)
|
return this.get(`/api/workspaces/${workspaceSlug}/user-properties/`)
|
||||||
// .then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
// .catch((error) => {
|
.catch((error) => {
|
||||||
// throw error?.response?.data;
|
throw error?.response?.data;
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// async patchWorkspaceFilters(
|
|
||||||
// workspaceSlug: string,
|
async patchWorkspaceFilters(
|
||||||
// data: Partial<IIssueFiltersResponse>
|
workspaceSlug: string,
|
||||||
// ): Promise<IIssueFiltersResponse> {
|
data: Partial<IIssueFiltersResponse>
|
||||||
// return this.patch(`/api/workspaces/${workspaceSlug}/user-properties/`, data)
|
): Promise<IIssueFiltersResponse> {
|
||||||
// .then((response) => response?.data)
|
return this.patch(`/api/workspaces/${workspaceSlug}/user-properties/`, data)
|
||||||
// .catch((error) => {
|
.then((response) => response?.data)
|
||||||
// throw error?.response?.data;
|
.catch((error) => {
|
||||||
// });
|
throw error?.response?.data;
|
||||||
// }
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// project issue filters
|
// project issue filters
|
||||||
async fetchProjectIssueFilters(workspaceSlug: string, projectId: string): Promise<IIssueFiltersResponse> {
|
async fetchProjectIssueFilters(workspaceSlug: string, projectId: string): Promise<IIssueFiltersResponse> {
|
||||||
|
14
web/services/view/index.ts
Normal file
14
web/services/view/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// view services
|
||||||
|
export * from "./workspace_me.service";
|
||||||
|
export * from "./workspace.service";
|
||||||
|
export * from "./project_me.service";
|
||||||
|
export * from "./project.service";
|
||||||
|
|
||||||
|
// user view services
|
||||||
|
export * from "./user/workspace.service";
|
||||||
|
export * from "./user/project.service";
|
||||||
|
export * from "./user/module.service";
|
||||||
|
export * from "./user/cycle.service";
|
||||||
|
|
||||||
|
// views that are being stored in the local-store
|
||||||
|
// export * from "./user/local_storage.service";
|
@ -91,7 +91,7 @@ export class ProjectViewService extends APIService implements TViewService {
|
|||||||
projectId: string | undefined = undefined
|
projectId: string | undefined = undefined
|
||||||
): Promise<TView | undefined> {
|
): Promise<TView | undefined> {
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/unlock/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/lock/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
@ -130,7 +130,7 @@ export class ProjectViewService extends APIService implements TViewService {
|
|||||||
projectId: string | undefined = undefined
|
projectId: string | undefined = undefined
|
||||||
): Promise<TView | undefined> {
|
): Promise<TView | undefined> {
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/unfavorite/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/favorite/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
|
@ -91,7 +91,7 @@ export class ProjectViewMeService extends APIService implements TViewService {
|
|||||||
projectId: string | undefined = undefined
|
projectId: string | undefined = undefined
|
||||||
): Promise<TView | undefined> {
|
): Promise<TView | undefined> {
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
return this.post(`/api/users/me/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/unlock/`)
|
return this.delete(`/api/users/me/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/lock/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
@ -130,7 +130,7 @@ export class ProjectViewMeService extends APIService implements TViewService {
|
|||||||
projectId: string | undefined = undefined
|
projectId: string | undefined = undefined
|
||||||
): Promise<TView | undefined> {
|
): Promise<TView | undefined> {
|
||||||
if (!projectId) return undefined;
|
if (!projectId) return undefined;
|
||||||
return this.post(`/api/users/me/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/unfavorite/`)
|
return this.delete(`/api/users/me/workspaces/${workspaceSlug}/projects/${projectId}/views/${viewId}/favorite/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
|
25
web/services/view/types.d.ts
vendored
25
web/services/view/types.d.ts
vendored
@ -1,4 +1,15 @@
|
|||||||
import { TView } from "@plane/types";
|
import { TView, TUserView } from "@plane/types";
|
||||||
|
|
||||||
|
export type TUserViewService = {
|
||||||
|
// featureId represents moduleId/cycleId
|
||||||
|
fetch: (workspaceSlug: string, projectId?: string, featureId?: string) => Promise<TUserView | undefined>;
|
||||||
|
update: (
|
||||||
|
workspaceSlug: string,
|
||||||
|
data: Partial<TView>,
|
||||||
|
projectId?: string,
|
||||||
|
featureId?: string
|
||||||
|
) => Promise<TUserView | undefined>;
|
||||||
|
};
|
||||||
|
|
||||||
export type TViewService = {
|
export type TViewService = {
|
||||||
fetch: (workspaceSlug: string, projectId?: string) => Promise<TView[] | undefined>;
|
fetch: (workspaceSlug: string, projectId?: string) => Promise<TView[] | undefined>;
|
||||||
@ -10,10 +21,10 @@ export type TViewService = {
|
|||||||
data: Partial<TView>,
|
data: Partial<TView>,
|
||||||
projectId?: string
|
projectId?: string
|
||||||
) => Promise<TView | undefined>;
|
) => Promise<TView | undefined>;
|
||||||
remove: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<void> | undefined;
|
remove?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<void> | undefined;
|
||||||
lock: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
lock?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
||||||
unlock: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
unlock?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
||||||
duplicate: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
duplicate?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
||||||
makeFavorite: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
makeFavorite?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
||||||
removeFavorite: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
removeFavorite?: (workspaceSlug: string, viewId: string, projectId?: string) => Promise<TView | undefined>;
|
||||||
};
|
};
|
||||||
|
36
web/services/view/user/cycle.service.ts
Normal file
36
web/services/view/user/cycle.service.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// services
|
||||||
|
import { APIService } from "services/api.service";
|
||||||
|
// types
|
||||||
|
import type { TViewFilterProps, TUserView } from "@plane/types";
|
||||||
|
import { TUserViewService } from "../types";
|
||||||
|
// helpers
|
||||||
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
|
export class CycleFiltersService extends APIService implements TUserViewService {
|
||||||
|
constructor() {
|
||||||
|
super(API_BASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(workspaceSlug: string, projectId?: string, cycleId?: string): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId || !cycleId) return undefined;
|
||||||
|
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}user-properties/`)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
workspaceSlug: string,
|
||||||
|
data: Partial<TViewFilterProps>,
|
||||||
|
projectId?: string,
|
||||||
|
cycleId?: string
|
||||||
|
): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId || !cycleId) return undefined;
|
||||||
|
return this.patch(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}user-properties/`, data)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
39
web/services/view/user/module.service.ts
Normal file
39
web/services/view/user/module.service.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// services
|
||||||
|
import { APIService } from "services/api.service";
|
||||||
|
// types
|
||||||
|
import type { TViewFilterProps, TUserView } from "@plane/types";
|
||||||
|
import { TUserViewService } from "../types";
|
||||||
|
// helpers
|
||||||
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
|
export class ModuleFiltersService extends APIService implements TUserViewService {
|
||||||
|
constructor() {
|
||||||
|
super(API_BASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(workspaceSlug: string, projectId?: string, moduleId?: string): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId || !moduleId) return undefined;
|
||||||
|
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}user-properties/`)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
workspaceSlug: string,
|
||||||
|
data: Partial<TViewFilterProps>,
|
||||||
|
projectId?: string,
|
||||||
|
moduleId?: string
|
||||||
|
): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId || !moduleId) return undefined;
|
||||||
|
return this.patch(
|
||||||
|
`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}user-properties/`,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
35
web/services/view/user/project.service.ts
Normal file
35
web/services/view/user/project.service.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// services
|
||||||
|
import { APIService } from "services/api.service";
|
||||||
|
// types
|
||||||
|
import type { TViewFilterProps, TUserView } from "@plane/types";
|
||||||
|
import { TUserViewService } from "../types";
|
||||||
|
// helpers
|
||||||
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
|
export class ProjectFiltersService extends APIService implements TUserViewService {
|
||||||
|
constructor() {
|
||||||
|
super(API_BASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(workspaceSlug: string, projectId?: string): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId) return undefined;
|
||||||
|
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/user-properties/`)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(
|
||||||
|
workspaceSlug: string,
|
||||||
|
data: Partial<TViewFilterProps>,
|
||||||
|
projectId?: string
|
||||||
|
): Promise<TUserView | undefined> {
|
||||||
|
if (!projectId) return undefined;
|
||||||
|
return this.patch(`/api/workspaces/${workspaceSlug}/user-properties/`, data)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
29
web/services/view/user/workspace.service.ts
Normal file
29
web/services/view/user/workspace.service.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// services
|
||||||
|
import { APIService } from "services/api.service";
|
||||||
|
// types
|
||||||
|
import type { TViewFilterProps, TUserView } from "@plane/types";
|
||||||
|
import { TUserViewService } from "../types";
|
||||||
|
// helpers
|
||||||
|
import { API_BASE_URL } from "helpers/common.helper";
|
||||||
|
|
||||||
|
export class WorkspaceFiltersService extends APIService implements TUserViewService {
|
||||||
|
constructor() {
|
||||||
|
super(API_BASE_URL);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch(workspaceSlug: string): Promise<TUserView | undefined> {
|
||||||
|
return this.get(`/api/workspaces/${workspaceSlug}/user-properties/`)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(workspaceSlug: string, data: Partial<TViewFilterProps>): Promise<TUserView | undefined> {
|
||||||
|
return this.patch(`/api/workspaces/${workspaceSlug}/user-properties/`, data)
|
||||||
|
.then((response) => response?.data)
|
||||||
|
.catch((error) => {
|
||||||
|
throw error?.response?.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -59,7 +59,7 @@ export class WorkspaceViewService extends APIService implements TViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async unlock(workspaceSlug: string, viewId: string): Promise<TView> {
|
async unlock(workspaceSlug: string, viewId: string): Promise<TView> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/views/${viewId}/unlock/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/views/${viewId}/lock/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
@ -83,7 +83,7 @@ export class WorkspaceViewService extends APIService implements TViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeFavorite(workspaceSlug: string, viewId: string): Promise<TView> {
|
async removeFavorite(workspaceSlug: string, viewId: string): Promise<TView> {
|
||||||
return this.post(`/api/workspaces/${workspaceSlug}/views/${viewId}/unfavorite/`)
|
return this.delete(`/api/workspaces/${workspaceSlug}/views/${viewId}/favorite/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
|
@ -11,7 +11,7 @@ export class WorkspaceMeViewService extends APIService implements TViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fetch(workspaceSlug: string): Promise<TView[]> {
|
async fetch(workspaceSlug: string): Promise<TView[]> {
|
||||||
return this.get(`/api/users/me/workspaces/${workspaceSlug}/views/`)
|
return this.get(`/api/users/me/workspaces/${workspaceSlug}/views/?type=workspace`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
@ -59,7 +59,7 @@ export class WorkspaceMeViewService extends APIService implements TViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async unlock(workspaceSlug: string, viewId: string): Promise<TView> {
|
async unlock(workspaceSlug: string, viewId: string): Promise<TView> {
|
||||||
return this.post(`/api/users/me/workspaces/${workspaceSlug}/views/${viewId}/unlock/`)
|
return this.delete(`/api/users/me/workspaces/${workspaceSlug}/views/${viewId}/lock/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
@ -83,7 +83,7 @@ export class WorkspaceMeViewService extends APIService implements TViewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeFavorite(workspaceSlug: string, viewId: string): Promise<TView> {
|
async removeFavorite(workspaceSlug: string, viewId: string): Promise<TView> {
|
||||||
return this.post(`/api/users/me/workspaces/${workspaceSlug}/views/${viewId}/unfavorite/`)
|
return this.delete(`/api/users/me/workspaces/${workspaceSlug}/views/${viewId}/favorite/`)
|
||||||
.then((response) => response?.data)
|
.then((response) => response?.data)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
throw error?.response;
|
throw error?.response;
|
||||||
|
@ -17,10 +17,14 @@ import { IMentionStore, MentionStore } from "./mention.store";
|
|||||||
import { DashboardStore, IDashboardStore } from "./dashboard.store";
|
import { DashboardStore, IDashboardStore } from "./dashboard.store";
|
||||||
import { IProjectPageStore, ProjectPageStore } from "./project-page.store";
|
import { IProjectPageStore, ProjectPageStore } from "./project-page.store";
|
||||||
import { ILabelStore, LabelStore } from "./label.store";
|
import { ILabelStore, LabelStore } from "./label.store";
|
||||||
|
// new stores
|
||||||
|
import { GlobalViewRootStore } from "./view/root.store";
|
||||||
|
|
||||||
enableStaticRendering(typeof window === "undefined");
|
enableStaticRendering(typeof window === "undefined");
|
||||||
|
|
||||||
export class RootStore {
|
export class RootStore {
|
||||||
|
view: GlobalViewRootStore;
|
||||||
|
// old store structure
|
||||||
app: IAppRootStore;
|
app: IAppRootStore;
|
||||||
user: IUserRootStore;
|
user: IUserRootStore;
|
||||||
workspaceRoot: IWorkspaceRootStore;
|
workspaceRoot: IWorkspaceRootStore;
|
||||||
@ -40,6 +44,8 @@ export class RootStore {
|
|||||||
projectPages: IProjectPageStore;
|
projectPages: IProjectPageStore;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.view = new GlobalViewRootStore(this);
|
||||||
|
// old store structure
|
||||||
this.app = new AppRootStore(this);
|
this.app = new AppRootStore(this);
|
||||||
this.user = new UserRootStore(this);
|
this.user = new UserRootStore(this);
|
||||||
this.workspaceRoot = new WorkspaceRootStore(this);
|
this.workspaceRoot = new WorkspaceRootStore(this);
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
import isEmpty from "lodash/isEmpty";
|
import isEmpty from "lodash/isEmpty";
|
||||||
// types
|
// types
|
||||||
import { TFilters, TDisplayFilters, TDisplayProperties, TFilterProps, TFilterQueryParams } from "@plane/types";
|
import {
|
||||||
|
TViewFilters,
|
||||||
|
TViewDisplayFilters,
|
||||||
|
TViewDisplayProperties,
|
||||||
|
TViewFilterProps,
|
||||||
|
TViewFilterQueryParams,
|
||||||
|
} from "@plane/types";
|
||||||
|
|
||||||
export class FiltersHelper {
|
export class FiltersHelper {
|
||||||
// computed filters
|
// computed filters
|
||||||
computedFilters = (filters: TFilters, defaultValues?: Partial<TFilters>): TFilters => ({
|
computedFilters = (filters: TViewFilters, defaultValues?: Partial<TViewFilters>): TViewFilters => ({
|
||||||
project: filters?.project || defaultValues?.project || [],
|
project: filters?.project || defaultValues?.project || [],
|
||||||
priority: filters?.priority || defaultValues?.priority || [],
|
priority: filters?.priority || defaultValues?.priority || [],
|
||||||
state: filters?.state || defaultValues?.state || [],
|
state: filters?.state || defaultValues?.state || [],
|
||||||
@ -20,9 +26,9 @@ export class FiltersHelper {
|
|||||||
|
|
||||||
// computed display filters
|
// computed display filters
|
||||||
computedDisplayFilters = (
|
computedDisplayFilters = (
|
||||||
displayFilters: TDisplayFilters,
|
displayFilters: TViewDisplayFilters,
|
||||||
defaultValues?: Partial<TDisplayFilters>
|
defaultValues?: Partial<TViewDisplayFilters>
|
||||||
): TDisplayFilters => ({
|
): TViewDisplayFilters => ({
|
||||||
layout: displayFilters?.layout || defaultValues?.layout || "list",
|
layout: displayFilters?.layout || defaultValues?.layout || "list",
|
||||||
group_by: displayFilters?.group_by || defaultValues?.group_by || "none",
|
group_by: displayFilters?.group_by || defaultValues?.group_by || "none",
|
||||||
sub_group_by: displayFilters?.sub_group_by || defaultValues?.sub_group_by || undefined,
|
sub_group_by: displayFilters?.sub_group_by || defaultValues?.sub_group_by || undefined,
|
||||||
@ -38,9 +44,9 @@ export class FiltersHelper {
|
|||||||
|
|
||||||
// computed display properties
|
// computed display properties
|
||||||
computedDisplayProperties = (
|
computedDisplayProperties = (
|
||||||
displayProperties: TDisplayProperties,
|
displayProperties: TViewDisplayProperties,
|
||||||
defaultValues?: Partial<TDisplayProperties>
|
defaultValues?: Partial<TViewDisplayProperties>
|
||||||
): TDisplayProperties => ({
|
): TViewDisplayProperties => ({
|
||||||
assignee: displayProperties?.assignee || defaultValues?.assignee || true,
|
assignee: displayProperties?.assignee || defaultValues?.assignee || true,
|
||||||
start_date: displayProperties?.start_date || defaultValues?.start_date || true,
|
start_date: displayProperties?.start_date || defaultValues?.start_date || true,
|
||||||
due_date: displayProperties?.due_date || defaultValues?.due_date || true,
|
due_date: displayProperties?.due_date || defaultValues?.due_date || true,
|
||||||
@ -58,13 +64,13 @@ export class FiltersHelper {
|
|||||||
|
|
||||||
// compute filters and display_filters issue query parameters
|
// compute filters and display_filters issue query parameters
|
||||||
computeAppliedFiltersQueryParameters = (
|
computeAppliedFiltersQueryParameters = (
|
||||||
filters: TFilterProps,
|
filters: TViewFilterProps,
|
||||||
acceptableParamsByLayout: string[]
|
acceptableParamsByLayout: string[]
|
||||||
): { params: any; query: string } => {
|
): { params: any; query: string } => {
|
||||||
const paramsObject: Partial<Record<TFilterQueryParams, string | boolean>> = {};
|
const paramsObject: Partial<Record<TViewFilterQueryParams, string | boolean>> = {};
|
||||||
let paramsString = "";
|
let paramsString = "";
|
||||||
|
|
||||||
const filteredParams: Partial<Record<TFilterQueryParams, undefined | string[] | boolean | string>> = {
|
const filteredParams: Partial<Record<TViewFilterQueryParams, undefined | string[] | boolean | string>> = {
|
||||||
// issue filters
|
// issue filters
|
||||||
priority: filters.filters?.priority || undefined,
|
priority: filters.filters?.priority || undefined,
|
||||||
state_group: filters.filters?.state_group || undefined,
|
state_group: filters.filters?.state_group || undefined,
|
||||||
@ -83,7 +89,7 @@ export class FiltersHelper {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(filteredParams).forEach((key) => {
|
Object.keys(filteredParams).forEach((key) => {
|
||||||
const _key = key as TFilterQueryParams;
|
const _key = key as TViewFilterQueryParams;
|
||||||
const _value: string | boolean | string[] | undefined = filteredParams[_key];
|
const _value: string | boolean | string[] | undefined = filteredParams[_key];
|
||||||
if (_value != undefined && acceptableParamsByLayout.includes(_key))
|
if (_value != undefined && acceptableParamsByLayout.includes(_key))
|
||||||
paramsObject[_key] = Array.isArray(_value) ? _value.join(",") : _value;
|
paramsObject[_key] = Array.isArray(_value) ? _value.join(",") : _value;
|
||||||
@ -92,7 +98,7 @@ export class FiltersHelper {
|
|||||||
if (paramsObject && !isEmpty(paramsObject)) {
|
if (paramsObject && !isEmpty(paramsObject)) {
|
||||||
paramsString = Object.keys(paramsObject)
|
paramsString = Object.keys(paramsObject)
|
||||||
.map((key) => {
|
.map((key) => {
|
||||||
const _key = key as TFilterQueryParams;
|
const _key = key as TViewFilterQueryParams;
|
||||||
const _value: string | boolean | undefined = paramsObject[_key];
|
const _value: string | boolean | undefined = paramsObject[_key];
|
||||||
if (!undefined) return `${_key}=${_value}`;
|
if (!undefined) return `${_key}=${_value}`;
|
||||||
})
|
})
|
@ -1,23 +1,70 @@
|
|||||||
// services
|
// services
|
||||||
import { WorkspaceViewService } from "services/view/workspace.service";
|
|
||||||
import { WorkspaceMeViewService } from "services/view/workspace_me.service";
|
import {
|
||||||
import { ProjectViewService } from "services/view/project.service";
|
WorkspaceViewService,
|
||||||
import { ProjectViewMeService } from "services/view/project_me.service";
|
WorkspaceMeViewService,
|
||||||
|
ProjectViewService,
|
||||||
|
ProjectViewMeService,
|
||||||
|
WorkspaceFiltersService,
|
||||||
|
ProjectFiltersService,
|
||||||
|
ModuleFiltersService,
|
||||||
|
CycleFiltersService,
|
||||||
|
// LocalStorageFiltersService,
|
||||||
|
} from "services/view";
|
||||||
// stores
|
// stores
|
||||||
import { ViewRoot } from "./view-root.store";
|
import { ViewRootStore } from "./view-root.store";
|
||||||
|
import { userViewRootStore } from "./user/view-root.store";
|
||||||
// types
|
// types
|
||||||
import { RootStore } from "store/root.store";
|
import { RootStore } from "store/root.store";
|
||||||
|
|
||||||
export class ViewRootStore {
|
export class GlobalViewRootStore {
|
||||||
workspaceViewStore: ViewRoot;
|
// views root
|
||||||
workspaceViewMeStore: ViewRoot;
|
workspaceViewMeStore: ViewRootStore;
|
||||||
projectViewStore: ViewRoot;
|
workspaceViewStore: ViewRootStore;
|
||||||
projectViewMeStore: ViewRoot;
|
workspaceViewProjectStore: ViewRootStore;
|
||||||
|
projectViewStore: ViewRootStore;
|
||||||
|
projectViewMeStore: ViewRootStore;
|
||||||
|
|
||||||
|
// user views root
|
||||||
|
workspaceUserViewStore?: userViewRootStore;
|
||||||
|
projectUserViewStore?: userViewRootStore;
|
||||||
|
moduleUserViewStore?: userViewRootStore;
|
||||||
|
cycleUserViewStore?: userViewRootStore;
|
||||||
|
|
||||||
constructor(private store: RootStore) {
|
constructor(private store: RootStore) {
|
||||||
this.workspaceViewStore = new ViewRoot(this.store, new WorkspaceViewService());
|
// views root
|
||||||
this.workspaceViewMeStore = new ViewRoot(this.store, new WorkspaceMeViewService());
|
this.workspaceViewMeStore = new ViewRootStore(this.store, new WorkspaceMeViewService());
|
||||||
this.projectViewStore = new ViewRoot(this.store, new ProjectViewService());
|
this.workspaceViewStore = new ViewRootStore(this.store, new WorkspaceViewService());
|
||||||
this.projectViewMeStore = new ViewRoot(this.store, new ProjectViewMeService());
|
this.workspaceViewProjectStore = new ViewRootStore(this.store, new WorkspaceMeViewService());
|
||||||
|
this.projectViewStore = new ViewRootStore(this.store, new ProjectViewService());
|
||||||
|
this.projectViewMeStore = new ViewRootStore(this.store, new ProjectViewMeService());
|
||||||
|
|
||||||
|
// user views root
|
||||||
|
this.workspaceUserViewStore = new userViewRootStore(
|
||||||
|
new WorkspaceFiltersService(),
|
||||||
|
store.app?.router?.workspaceSlug,
|
||||||
|
undefined,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
this.projectUserViewStore = new userViewRootStore(
|
||||||
|
new ProjectFiltersService(),
|
||||||
|
store.app?.router?.workspaceSlug,
|
||||||
|
store.app?.router?.projectId,
|
||||||
|
undefined
|
||||||
|
);
|
||||||
|
this.moduleUserViewStore = new userViewRootStore(
|
||||||
|
new ModuleFiltersService(),
|
||||||
|
store.app?.router?.workspaceSlug,
|
||||||
|
store.app?.router?.projectId,
|
||||||
|
store.app?.router?.moduleId
|
||||||
|
);
|
||||||
|
this.cycleUserViewStore = new userViewRootStore(
|
||||||
|
new CycleFiltersService(),
|
||||||
|
store.app?.router?.workspaceSlug,
|
||||||
|
store.app?.router?.projectId,
|
||||||
|
store.app?.router?.cycleId
|
||||||
|
);
|
||||||
|
// this.archivedUserViewStore = new userViewRootStore( new LocalStorageFiltersService());
|
||||||
|
// this.draftUserViewStore = new userViewRootStore( new LocalStorageFiltersService());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
64
web/store/view/user/view-root.store.ts
Normal file
64
web/store/view/user/view-root.store.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
|
import set from "lodash/set";
|
||||||
|
// stores
|
||||||
|
import { RootStore } from "store/root.store";
|
||||||
|
import { UserViewStore } from "./view.store";
|
||||||
|
// types
|
||||||
|
import { TUserViewService } from "services/view/types";
|
||||||
|
|
||||||
|
type TUserViewRootStore = {
|
||||||
|
// observables
|
||||||
|
viewMap: Record<string, UserViewStore>;
|
||||||
|
// computed
|
||||||
|
viewIds: string[];
|
||||||
|
// helper actions
|
||||||
|
viewById: (viewId: string) => UserViewStore | undefined;
|
||||||
|
// actions
|
||||||
|
fetch: () => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class userViewRootStore implements TUserViewRootStore {
|
||||||
|
// observables
|
||||||
|
viewMap: Record<string, UserViewStore> = {};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private service: TUserViewService,
|
||||||
|
private workspaceSlug: string | undefined,
|
||||||
|
private projectId: string | undefined,
|
||||||
|
private featureId: string | undefined // moduleId/cycleId
|
||||||
|
) {
|
||||||
|
makeObservable(this, {
|
||||||
|
// observables
|
||||||
|
viewMap: observable.ref,
|
||||||
|
// computed
|
||||||
|
viewIds: computed,
|
||||||
|
// actions
|
||||||
|
fetch: action,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// computed
|
||||||
|
get viewIds() {
|
||||||
|
return Object.keys(this.viewMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper actions
|
||||||
|
viewById = (viewId: string) => this.viewMap?.[viewId] || undefined;
|
||||||
|
|
||||||
|
// actions
|
||||||
|
fetch = async () => {
|
||||||
|
if (!this.workspaceSlug) return;
|
||||||
|
|
||||||
|
const view = await this.service.fetch(this.workspaceSlug, this.projectId, this.featureId);
|
||||||
|
if (!view) return;
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
if (this.workspaceSlug && view.id)
|
||||||
|
set(
|
||||||
|
this.viewMap,
|
||||||
|
[view.id],
|
||||||
|
new UserViewStore(view, this.service, this.workspaceSlug, this.projectId, this.featureId)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
183
web/store/view/user/view.store.ts
Normal file
183
web/store/view/user/view.store.ts
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
|
import set from "lodash/set";
|
||||||
|
// types
|
||||||
|
import { TUserViewService } from "services/view/types";
|
||||||
|
import {
|
||||||
|
TUserView,
|
||||||
|
TViewFilters,
|
||||||
|
TViewDisplayFilters,
|
||||||
|
TViewDisplayProperties,
|
||||||
|
TViewFilterProps,
|
||||||
|
TViewFilterPartialProps,
|
||||||
|
} from "@plane/types";
|
||||||
|
// helpers
|
||||||
|
import { FiltersHelper } from "../helpers/filters_helpers";
|
||||||
|
|
||||||
|
type TLoader = "submitting" | "submit" | undefined;
|
||||||
|
|
||||||
|
export type TUserViewStore = TUserView & {
|
||||||
|
// observables
|
||||||
|
loader: TLoader;
|
||||||
|
filtersToUpdate: TViewFilterPartialProps;
|
||||||
|
// computed
|
||||||
|
appliedFilters: TViewFilterProps | undefined;
|
||||||
|
appliedFiltersQueryParams: string | undefined;
|
||||||
|
// helper actions
|
||||||
|
updateFilters: (filters: Partial<TViewFilters>) => void;
|
||||||
|
updateDisplayFilters: (display_filters: Partial<TViewDisplayFilters>) => void;
|
||||||
|
updateDisplayProperties: (display_properties: Partial<TViewDisplayProperties>) => void;
|
||||||
|
resetFilterChanges: () => void;
|
||||||
|
saveFilterChanges: () => void;
|
||||||
|
// actions
|
||||||
|
update: (viewData: Partial<TUserView>) => Promise<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class UserViewStore extends FiltersHelper implements TUserViewStore {
|
||||||
|
id: string | undefined;
|
||||||
|
workspace: string | undefined;
|
||||||
|
project: string | undefined;
|
||||||
|
module: string | undefined;
|
||||||
|
cycle: string | undefined;
|
||||||
|
filters: TViewFilters | undefined;
|
||||||
|
display_filters: TViewDisplayFilters | undefined;
|
||||||
|
display_properties: TViewDisplayProperties | undefined;
|
||||||
|
user: string | undefined;
|
||||||
|
created_by: string | undefined;
|
||||||
|
updated_by: string | undefined;
|
||||||
|
created_at: Date | undefined;
|
||||||
|
updated_at: Date | undefined;
|
||||||
|
|
||||||
|
loader: TLoader = undefined;
|
||||||
|
filtersToUpdate: TViewFilterPartialProps = {
|
||||||
|
filters: {},
|
||||||
|
display_filters: {},
|
||||||
|
display_properties: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
_view: TUserView,
|
||||||
|
private service: TUserViewService,
|
||||||
|
private workspaceSlug: string,
|
||||||
|
private projectId: string | undefined,
|
||||||
|
private featureId: string | undefined // moduleId/cycleId
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this.id = _view.id;
|
||||||
|
this.workspace = _view.workspace;
|
||||||
|
this.project = _view.project;
|
||||||
|
this.filters = _view.filters ? this.computedFilters(_view.filters) : undefined;
|
||||||
|
this.display_filters = _view.display_filters ? this.computedDisplayFilters(_view.display_filters) : undefined;
|
||||||
|
this.display_properties = _view.display_properties
|
||||||
|
? this.computedDisplayProperties(_view.display_properties)
|
||||||
|
: undefined;
|
||||||
|
this.user = _view.user;
|
||||||
|
this.created_by = _view.created_by;
|
||||||
|
this.updated_by = _view.updated_by;
|
||||||
|
this.created_at = _view.created_at;
|
||||||
|
this.updated_at = _view.updated_at;
|
||||||
|
|
||||||
|
makeObservable(this, {
|
||||||
|
// observables
|
||||||
|
loader: observable,
|
||||||
|
filtersToUpdate: observable.ref,
|
||||||
|
// computed
|
||||||
|
appliedFilters: computed,
|
||||||
|
appliedFiltersQueryParams: computed,
|
||||||
|
// helper actions
|
||||||
|
updateFilters: action,
|
||||||
|
updateDisplayFilters: action,
|
||||||
|
updateDisplayProperties: action,
|
||||||
|
resetFilterChanges: action,
|
||||||
|
saveFilterChanges: action,
|
||||||
|
// actions
|
||||||
|
update: action,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// computed
|
||||||
|
get appliedFilters() {
|
||||||
|
return {
|
||||||
|
filters: this.filters ? this.computedFilters(this.filters, this.filtersToUpdate.filters) : undefined,
|
||||||
|
display_filters: this.display_filters
|
||||||
|
? this.computedDisplayFilters(this.display_filters, this.filtersToUpdate.display_filters)
|
||||||
|
: undefined,
|
||||||
|
display_properties: this.display_properties
|
||||||
|
? this.computedDisplayProperties(this.display_properties, this.filtersToUpdate.display_properties)
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get appliedFiltersQueryParams() {
|
||||||
|
const filters = this.appliedFilters;
|
||||||
|
if (!filters) return undefined;
|
||||||
|
return this.computeAppliedFiltersQueryParameters(filters, [])?.query || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper actions
|
||||||
|
updateFilters = (filters: Partial<TViewFilters>) => {
|
||||||
|
runInAction(() => {
|
||||||
|
this.loader = "submit";
|
||||||
|
this.filtersToUpdate.filters = filters;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
updateDisplayFilters = async (display_filters: Partial<TViewDisplayFilters>) => {
|
||||||
|
const appliedFilters = this.appliedFilters;
|
||||||
|
|
||||||
|
const layout = appliedFilters?.display_filters?.layout;
|
||||||
|
const sub_group_by = appliedFilters?.display_filters?.sub_group_by;
|
||||||
|
const group_by = appliedFilters?.display_filters?.group_by;
|
||||||
|
const sub_issue = appliedFilters?.display_filters?.sub_issue;
|
||||||
|
|
||||||
|
if (group_by === undefined) display_filters.sub_group_by = undefined;
|
||||||
|
if (layout === "kanban") {
|
||||||
|
if (sub_group_by === group_by) display_filters.group_by = undefined;
|
||||||
|
if (group_by === null) display_filters.group_by = "state";
|
||||||
|
}
|
||||||
|
if (layout === "spreadsheet" && sub_issue === true) display_filters.sub_issue = false;
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
this.loader = "submit";
|
||||||
|
this.filtersToUpdate.display_filters = display_filters;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
updateDisplayProperties = async (display_properties: Partial<TViewDisplayProperties>) => {
|
||||||
|
runInAction(() => {
|
||||||
|
this.loader = "submit";
|
||||||
|
this.filtersToUpdate.display_properties = display_properties;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
resetFilterChanges = () => {
|
||||||
|
runInAction(() => {
|
||||||
|
this.loader = undefined;
|
||||||
|
this.filtersToUpdate = {
|
||||||
|
filters: {},
|
||||||
|
display_filters: {},
|
||||||
|
display_properties: {},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
saveFilterChanges = async () => {
|
||||||
|
this.loader = "submitting";
|
||||||
|
if (this.appliedFilters) await this.update(this.appliedFilters);
|
||||||
|
this.loader = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
// actions
|
||||||
|
update = async (viewData: Partial<TViewFilterProps>) => {
|
||||||
|
if (!this.workspaceSlug || !this.id) return;
|
||||||
|
|
||||||
|
const view = await this.service.update(this.workspaceSlug, viewData, this.projectId, this.featureId);
|
||||||
|
if (!view) return;
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
Object.keys(viewData).forEach((key) => {
|
||||||
|
const _key = key as keyof TViewFilterProps;
|
||||||
|
set(this, _key, viewData[_key]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
@ -1,20 +1,21 @@
|
|||||||
// types
|
|
||||||
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
import { action, computed, makeObservable, observable, runInAction } from "mobx";
|
||||||
|
import set from "lodash/set";
|
||||||
// stores
|
// stores
|
||||||
import { RootStore } from "store/root.store";
|
import { RootStore } from "store/root.store";
|
||||||
import { ViewsStore } from "./view.store";
|
import { ViewStore } from "./view.store";
|
||||||
// types
|
// types
|
||||||
import { TViewService } from "services/view/types";
|
import { TViewService } from "services/view/types";
|
||||||
import { TView } from "@plane/types";
|
import { TView } from "@plane/types";
|
||||||
import { set } from "lodash";
|
|
||||||
|
|
||||||
export type TLoader = "" | undefined;
|
export type TLoader = "" | undefined;
|
||||||
|
|
||||||
type TViewRoot = {
|
type TViewRootStore = {
|
||||||
// observables
|
// observables
|
||||||
viewMap: Record<string, ViewsStore>;
|
viewMap: Record<string, ViewStore>;
|
||||||
// computed
|
// computed
|
||||||
viewIds: string[];
|
viewIds: string[];
|
||||||
|
// helper actions
|
||||||
|
viewById: (viewId: string) => ViewStore | undefined;
|
||||||
// actions
|
// actions
|
||||||
fetch: () => Promise<void>;
|
fetch: () => Promise<void>;
|
||||||
create: (view: Partial<TView>) => Promise<void>;
|
create: (view: Partial<TView>) => Promise<void>;
|
||||||
@ -22,13 +23,13 @@ type TViewRoot = {
|
|||||||
duplicate: (viewId: string) => Promise<void>;
|
duplicate: (viewId: string) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ViewRoot implements TViewRoot {
|
export class ViewRootStore implements TViewRootStore {
|
||||||
viewMap: Record<string, ViewsStore> = {};
|
viewMap: Record<string, ViewStore> = {};
|
||||||
|
|
||||||
constructor(private store: RootStore, private service: TViewService) {
|
constructor(private store: RootStore, private service: TViewService) {
|
||||||
makeObservable(this, {
|
makeObservable(this, {
|
||||||
// observables
|
// observables
|
||||||
viewMap: observable,
|
viewMap: observable.ref,
|
||||||
// computed
|
// computed
|
||||||
viewIds: computed,
|
viewIds: computed,
|
||||||
// actions
|
// actions
|
||||||
@ -44,15 +45,10 @@ export class ViewRoot implements TViewRoot {
|
|||||||
return Object.keys(this.viewMap);
|
return Object.keys(this.viewMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
get views() {
|
// helper actions
|
||||||
return Object.values(this.viewMap);
|
viewById = (viewId: string) => this.viewMap?.[viewId] || undefined;
|
||||||
}
|
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
/**
|
|
||||||
* @description This method is used to fetch all the views
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
fetch = async () => {
|
fetch = async () => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
@ -62,16 +58,11 @@ export class ViewRoot implements TViewRoot {
|
|||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
views.forEach((view) => {
|
views.forEach((view) => {
|
||||||
set(this.viewMap, [view.id], new ViewsStore(this.store, view, this.service));
|
if (view.id) set(this.viewMap, [view.id], new ViewStore(this.store, view, this.service));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to create a view
|
|
||||||
* @param data: Partial<TView>
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
create = async (data: Partial<TView>) => {
|
create = async (data: Partial<TView>) => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug) return;
|
||||||
@ -80,40 +71,30 @@ export class ViewRoot implements TViewRoot {
|
|||||||
if (!view) return;
|
if (!view) return;
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
set(this.viewMap, [view.id], new ViewsStore(this.store, view, this.service));
|
if (view.id) set(this.viewMap, [view.id], new ViewStore(this.store, view, this.service));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to remove a view
|
|
||||||
* @param viewId: string
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
remove = async (viewId: string) => {
|
remove = async (viewId: string) => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !viewId) return;
|
||||||
|
|
||||||
await this.service.remove(workspaceSlug, viewId, projectId);
|
await this.service.remove?.(workspaceSlug, viewId, projectId);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
delete this.viewMap[viewId];
|
delete this.viewMap[viewId];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to duplicate a view
|
|
||||||
* @param viewId: string
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
duplicate = async (viewId: string) => {
|
duplicate = async (viewId: string) => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.service.duplicate) return;
|
||||||
|
|
||||||
const view = await this.service.duplicate(workspaceSlug, viewId, projectId);
|
const view = await this.service.duplicate(workspaceSlug, viewId, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
set(this.viewMap, [view.id], new ViewsStore(this.store, view, this.service));
|
if (view.id) set(this.viewMap, [view.id], new ViewStore(this.store, view, this.service));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,29 +6,29 @@ import { RootStore } from "store/root.store";
|
|||||||
import { TViewService } from "services/view/types";
|
import { TViewService } from "services/view/types";
|
||||||
import {
|
import {
|
||||||
TView,
|
TView,
|
||||||
TFilters,
|
TViewFilters,
|
||||||
TDisplayFilters,
|
TViewDisplayFilters,
|
||||||
TDisplayProperties,
|
TViewDisplayProperties,
|
||||||
TFilterProps,
|
TViewFilterProps,
|
||||||
TFilterPartialProps,
|
TViewFilterPartialProps,
|
||||||
TViewAccess,
|
TViewAccess,
|
||||||
} from "@plane/types";
|
} from "@plane/types";
|
||||||
// helpers
|
// helpers
|
||||||
import { FiltersHelper } from "./filters_helpers";
|
import { FiltersHelper } from "./helpers/filters_helpers";
|
||||||
|
|
||||||
type TLoader = "submitting" | "submit" | undefined;
|
type TLoader = "submitting" | "submit" | undefined;
|
||||||
|
|
||||||
export type TViewsStore = TView & {
|
export type TViewStore = TView & {
|
||||||
// observables
|
// observables
|
||||||
loader: TLoader;
|
loader: TLoader;
|
||||||
filtersToUpdate: TFilterPartialProps;
|
filtersToUpdate: TViewFilterPartialProps;
|
||||||
// computed
|
// computed
|
||||||
appliedFilters: TFilterProps | undefined;
|
appliedFilters: TViewFilterProps | undefined;
|
||||||
appliedFiltersQueryParams: string | undefined;
|
appliedFiltersQueryParams: string | undefined;
|
||||||
// helper actions
|
// helper actions
|
||||||
updateFilters: (filters: Partial<TFilters>) => void;
|
updateFilters: (filters: Partial<TViewFilters>) => void;
|
||||||
updateDisplayFilters: (display_filters: Partial<TDisplayFilters>) => void;
|
updateDisplayFilters: (display_filters: Partial<TViewDisplayFilters>) => void;
|
||||||
updateDisplayProperties: (display_properties: Partial<TDisplayProperties>) => void;
|
updateDisplayProperties: (display_properties: Partial<TViewDisplayProperties>) => void;
|
||||||
resetFilterChanges: () => void;
|
resetFilterChanges: () => void;
|
||||||
saveFilterChanges: () => void;
|
saveFilterChanges: () => void;
|
||||||
// actions
|
// actions
|
||||||
@ -39,29 +39,29 @@ export type TViewsStore = TView & {
|
|||||||
update: (viewData: Partial<TView>) => Promise<void>;
|
update: (viewData: Partial<TView>) => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class ViewsStore extends FiltersHelper implements TViewsStore {
|
export class ViewStore extends FiltersHelper implements TViewStore {
|
||||||
id: string;
|
id: string | undefined;
|
||||||
workspace: string;
|
workspace: string | undefined;
|
||||||
project: string | undefined;
|
project: string | undefined;
|
||||||
name: string;
|
name: string | undefined;
|
||||||
description: string;
|
description: string | undefined;
|
||||||
query: string;
|
query: string | undefined;
|
||||||
filters: TFilters;
|
filters: TViewFilters | undefined;
|
||||||
display_filters: TDisplayFilters;
|
display_filters: TViewDisplayFilters | undefined;
|
||||||
display_properties: TDisplayProperties;
|
display_properties: TViewDisplayProperties | undefined;
|
||||||
access: TViewAccess;
|
access: TViewAccess | undefined;
|
||||||
owned_by: string;
|
owned_by: string | undefined;
|
||||||
sort_order: number;
|
sort_order: number | undefined;
|
||||||
is_locked: boolean;
|
is_locked: boolean | undefined;
|
||||||
is_pinned: boolean;
|
is_pinned: boolean | undefined;
|
||||||
is_favorite: boolean;
|
is_favorite: boolean | undefined;
|
||||||
created_by: string;
|
created_by: string | undefined;
|
||||||
updated_by: string;
|
updated_by: string | undefined;
|
||||||
created_at: Date;
|
created_at: Date | undefined;
|
||||||
updated_at: Date;
|
updated_at: Date | undefined;
|
||||||
|
|
||||||
loader: TLoader = undefined;
|
loader: TLoader = undefined;
|
||||||
filtersToUpdate: TFilterPartialProps = {
|
filtersToUpdate: TViewFilterPartialProps = {
|
||||||
filters: {},
|
filters: {},
|
||||||
display_filters: {},
|
display_filters: {},
|
||||||
display_properties: {},
|
display_properties: {},
|
||||||
@ -75,9 +75,11 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
this.name = _view.name;
|
this.name = _view.name;
|
||||||
this.description = _view.description;
|
this.description = _view.description;
|
||||||
this.query = _view.query;
|
this.query = _view.query;
|
||||||
this.filters = this.computedFilters(_view.filters);
|
this.filters = _view.filters ? this.computedFilters(_view.filters) : undefined;
|
||||||
this.display_filters = this.computedDisplayFilters(_view.display_filters);
|
this.display_filters = _view.display_filters ? this.computedDisplayFilters(_view.display_filters) : undefined;
|
||||||
this.display_properties = this.computedDisplayProperties(_view.display_properties);
|
this.display_properties = _view.display_properties
|
||||||
|
? this.computedDisplayProperties(_view.display_properties)
|
||||||
|
: undefined;
|
||||||
this.access = _view.access;
|
this.access = _view.access;
|
||||||
this.owned_by = _view.owned_by;
|
this.owned_by = _view.owned_by;
|
||||||
this.sort_order = _view.sort_order;
|
this.sort_order = _view.sort_order;
|
||||||
@ -112,51 +114,43 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
// computed
|
// computed
|
||||||
get appliedFilters() {
|
get appliedFilters() {
|
||||||
return {
|
return {
|
||||||
filters: this.computedFilters(this.filters, this.filtersToUpdate.filters),
|
filters: this.filters ? this.computedFilters(this.filters, this.filtersToUpdate.filters) : undefined,
|
||||||
display_filters: this.computedDisplayFilters(this.display_filters, this.filtersToUpdate.display_filters),
|
display_filters: this.display_filters
|
||||||
display_properties: this.computedDisplayProperties(
|
? this.computedDisplayFilters(this.display_filters, this.filtersToUpdate.display_filters)
|
||||||
this.display_properties,
|
: undefined,
|
||||||
this.filtersToUpdate.display_properties
|
display_properties: this.display_properties
|
||||||
),
|
? this.computedDisplayProperties(this.display_properties, this.filtersToUpdate.display_properties)
|
||||||
|
: undefined,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get appliedFiltersQueryParams() {
|
get appliedFiltersQueryParams() {
|
||||||
const filters = this.appliedFilters;
|
const filters = this.appliedFilters;
|
||||||
|
if (!filters) return undefined;
|
||||||
return this.computeAppliedFiltersQueryParameters(filters, [])?.query || undefined;
|
return this.computeAppliedFiltersQueryParameters(filters, [])?.query || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper actions
|
// helper actions
|
||||||
/**
|
updateFilters = (filters: Partial<TViewFilters>) => {
|
||||||
* @description This method is used to update the filters of the view
|
|
||||||
* @param filters: Partial<TFilters>
|
|
||||||
*/
|
|
||||||
updateFilters = (filters: Partial<TFilters>) => {
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = "submit";
|
this.loader = "submit";
|
||||||
this.filtersToUpdate.filters = filters;
|
this.filtersToUpdate.filters = filters;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
updateDisplayFilters = async (display_filters: Partial<TViewDisplayFilters>) => {
|
||||||
* @description This method is used to update the display filters of the view
|
|
||||||
* @param display_filters: Partial<TDisplayFilters>
|
|
||||||
*/
|
|
||||||
updateDisplayFilters = async (display_filters: Partial<TDisplayFilters>) => {
|
|
||||||
const appliedFilters = this.appliedFilters;
|
const appliedFilters = this.appliedFilters;
|
||||||
|
|
||||||
const layout = appliedFilters.display_filters.layout;
|
const layout = appliedFilters?.display_filters?.layout;
|
||||||
const sub_group_by = appliedFilters.display_filters.sub_group_by;
|
const sub_group_by = appliedFilters?.display_filters?.sub_group_by;
|
||||||
const group_by = appliedFilters.display_filters.group_by;
|
const group_by = appliedFilters?.display_filters?.group_by;
|
||||||
const sub_issue = appliedFilters.display_filters.sub_issue;
|
const sub_issue = appliedFilters?.display_filters?.sub_issue;
|
||||||
|
|
||||||
if (group_by === undefined) display_filters.sub_group_by = undefined;
|
if (group_by === undefined) display_filters.sub_group_by = undefined;
|
||||||
|
|
||||||
if (layout === "kanban") {
|
if (layout === "kanban") {
|
||||||
if (sub_group_by === group_by) display_filters.group_by = undefined;
|
if (sub_group_by === group_by) display_filters.group_by = undefined;
|
||||||
if (group_by === null) display_filters.group_by = "state";
|
if (group_by === null) display_filters.group_by = "state";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layout === "spreadsheet" && sub_issue === true) display_filters.sub_issue = false;
|
if (layout === "spreadsheet" && sub_issue === true) display_filters.sub_issue = false;
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
@ -165,20 +159,13 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
updateDisplayProperties = async (display_properties: Partial<TViewDisplayProperties>) => {
|
||||||
* @description This method is used to update the display properties of the view
|
|
||||||
* @param display_properties: Partial<TDisplayProperties>
|
|
||||||
*/
|
|
||||||
updateDisplayProperties = async (display_properties: Partial<TDisplayProperties>) => {
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = "submit";
|
this.loader = "submit";
|
||||||
this.filtersToUpdate.display_properties = display_properties;
|
this.filtersToUpdate.display_properties = display_properties;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to reset the changes made to the filters
|
|
||||||
*/
|
|
||||||
resetFilterChanges = () => {
|
resetFilterChanges = () => {
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.loader = undefined;
|
this.loader = undefined;
|
||||||
@ -190,9 +177,6 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to save the changes made to the filters
|
|
||||||
*/
|
|
||||||
saveFilterChanges = async () => {
|
saveFilterChanges = async () => {
|
||||||
this.loader = "submitting";
|
this.loader = "submitting";
|
||||||
if (this.appliedFilters) await this.update(this.appliedFilters);
|
if (this.appliedFilters) await this.update(this.appliedFilters);
|
||||||
@ -200,13 +184,9 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
/**
|
|
||||||
* @description This method is used to update the view lock
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
lockView = async () => {
|
lockView = async () => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.id || !this.service.lock) return;
|
||||||
|
|
||||||
const view = await this.service.lock(workspaceSlug, this.id, projectId);
|
const view = await this.service.lock(workspaceSlug, this.id, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
@ -216,13 +196,9 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to remove the view lock
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
unlockView = async () => {
|
unlockView = async () => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.id || !this.service.unlock) return;
|
||||||
|
|
||||||
const view = await this.service.unlock(workspaceSlug, this.id, projectId);
|
const view = await this.service.unlock(workspaceSlug, this.id, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
@ -232,13 +208,9 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to update the view favorite
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
makeFavorite = async () => {
|
makeFavorite = async () => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.id || !this.service.makeFavorite) return;
|
||||||
|
|
||||||
const view = await this.service.makeFavorite(workspaceSlug, this.id, projectId);
|
const view = await this.service.makeFavorite(workspaceSlug, this.id, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
@ -248,13 +220,9 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to remove the view favorite
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
removeFavorite = async () => {
|
removeFavorite = async () => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.id || !this.service.removeFavorite) return;
|
||||||
|
|
||||||
const view = await this.service.removeFavorite(workspaceSlug, this.id, projectId);
|
const view = await this.service.removeFavorite(workspaceSlug, this.id, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
@ -264,13 +232,9 @@ export class ViewsStore extends FiltersHelper implements TViewsStore {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @description This method is used to update the view
|
|
||||||
* @param viewData
|
|
||||||
*/
|
|
||||||
update = async (viewData: Partial<TView>) => {
|
update = async (viewData: Partial<TView>) => {
|
||||||
const { workspaceSlug, projectId } = this.store.app.router;
|
const { workspaceSlug, projectId } = this.store.app.router;
|
||||||
if (!workspaceSlug) return;
|
if (!workspaceSlug || !this.id) return;
|
||||||
|
|
||||||
const view = await this.service.update(workspaceSlug, this.id, viewData, projectId);
|
const view = await this.service.update(workspaceSlug, this.id, viewData, projectId);
|
||||||
if (!view) return;
|
if (!view) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user