mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
chore: filter, layout, display filters, extra filters and display properties render validation
This commit is contained in:
parent
f579712092
commit
c67f08fca4
@ -7,6 +7,8 @@ import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
// default data
|
||||
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
|
||||
|
||||
export const FilterExtraOptions = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
@ -18,6 +20,13 @@ export const FilterExtraOptions = observer(() => {
|
||||
issueFilterStore.handleUserFilter("display_filters", key, !value);
|
||||
};
|
||||
|
||||
const handleExtraOptionsSectionVisibility = (key: string) =>
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterStore?.issueLayout &&
|
||||
issueFilterVisibilityData[
|
||||
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
|
||||
]?.extra_options?.[issueFilterStore?.issueLayout].values?.includes(key);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
@ -29,23 +38,26 @@ export const FilterExtraOptions = observer(() => {
|
||||
<div className="space-y-[2px] pt-1">
|
||||
{issueFilterStore?.issueRenderFilters?.extra_properties &&
|
||||
issueFilterStore?.issueRenderFilters?.extra_properties.length > 0 &&
|
||||
issueFilterStore?.issueRenderFilters?.extra_properties.map((_extraProperties) => (
|
||||
<FilterOption
|
||||
key={_extraProperties?.key}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onClick={() =>
|
||||
handleExtraOptions(
|
||||
_extraProperties?.key,
|
||||
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
|
||||
)
|
||||
}
|
||||
title={_extraProperties.title}
|
||||
/>
|
||||
))}
|
||||
issueFilterStore?.issueRenderFilters?.extra_properties.map(
|
||||
(_extraProperties) =>
|
||||
handleExtraOptionsSectionVisibility(_extraProperties?.key) && (
|
||||
<FilterOption
|
||||
key={_extraProperties?.key}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
|
||||
? true
|
||||
: false
|
||||
}
|
||||
onClick={() =>
|
||||
handleExtraOptions(
|
||||
_extraProperties?.key,
|
||||
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
|
||||
)
|
||||
}
|
||||
title={_extraProperties.title}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -5,41 +5,78 @@ import { FilterGroupBy } from "./group-by";
|
||||
import { FilterOrderBy } from "./order-by";
|
||||
import { FilterIssueType } from "./issue-type";
|
||||
import { FilterExtraOptions } from "./extra-options";
|
||||
// // mobx react lite
|
||||
// import { observer } from "mobx-react-lite";
|
||||
// // mobx store
|
||||
// import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// import { RootStore } from "store/root";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
// default data
|
||||
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
|
||||
|
||||
// const store: RootStore = useMobxStore();
|
||||
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store;
|
||||
export const DisplayFiltersSelection = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore } = store;
|
||||
|
||||
export const DisplayFiltersSelection = () => (
|
||||
<div className="w-full h-full overflow-hidden select-none relative flex flex-col">
|
||||
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200">
|
||||
Search container
|
||||
</div>
|
||||
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
|
||||
{/* display properties */}
|
||||
<div className="pb-2 px-2 border-b border-custom-border-200">
|
||||
<FilterDisplayProperties />
|
||||
const handleDisplayPropertiesSectionVisibility =
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterStore?.issueLayout &&
|
||||
issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"]
|
||||
?.display_properties?.[issueFilterStore?.issueLayout];
|
||||
|
||||
const handleDisplayFilterSectionVisibility = (section_key: string) =>
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterStore?.issueLayout &&
|
||||
issueFilterVisibilityData[
|
||||
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
|
||||
]?.display_filters?.[issueFilterStore?.issueLayout].includes(section_key);
|
||||
|
||||
const handleExtraOptionsSectionVisibility =
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterStore?.issueLayout &&
|
||||
issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"]
|
||||
?.extra_options?.[issueFilterStore?.issueLayout].access;
|
||||
|
||||
return (
|
||||
<div className="w-full h-full overflow-hidden select-none relative flex flex-col">
|
||||
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200">
|
||||
Search container
|
||||
</div>
|
||||
{/* group by */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterGroupBy />
|
||||
</div>
|
||||
{/* order by */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterOrderBy />
|
||||
</div>
|
||||
{/* issue type */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterIssueType />
|
||||
</div>
|
||||
{/* Options */}
|
||||
<div className="pt-1 px-2">
|
||||
<FilterExtraOptions />
|
||||
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
|
||||
{/* display properties */}
|
||||
{handleDisplayPropertiesSectionVisibility && (
|
||||
<div className="pb-2 px-2 border-b border-custom-border-200">
|
||||
<FilterDisplayProperties />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* group by */}
|
||||
{handleDisplayFilterSectionVisibility("group_by") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterGroupBy />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* order by */}
|
||||
{handleDisplayFilterSectionVisibility("order_by") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterOrderBy />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* issue type */}
|
||||
{handleDisplayFilterSectionVisibility("issue_type") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterIssueType />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Options */}
|
||||
{handleExtraOptionsSectionVisibility && (
|
||||
<div className="pt-1 px-2">
|
||||
<FilterExtraOptions />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
});
|
||||
|
@ -8,53 +8,86 @@ import { FilterCreatedBy } from "./created-by";
|
||||
import { FilterLabels } from "./labels";
|
||||
import { FilterStartDate } from "./start-date";
|
||||
import { FilterTargetDate } from "./target-date";
|
||||
// // mobx react lite
|
||||
// import { observer } from "mobx-react-lite";
|
||||
// // mobx store
|
||||
// import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// import { RootStore } from "store/root";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
// default data
|
||||
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
|
||||
|
||||
// const store: RootStore = useMobxStore();
|
||||
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store;
|
||||
export const FilterSelection = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore } = store;
|
||||
|
||||
export const FilterSelection = () => (
|
||||
<div className="w-full h-full overflow-hidden select-none relative flex flex-col">
|
||||
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200">
|
||||
Search container
|
||||
</div>
|
||||
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
|
||||
{/* priority */}
|
||||
<div className="pb-1 px-2 border-b border-custom-border-200">
|
||||
<FilterPriority />
|
||||
const handleFilterSectionVisibility = (section_key: string) =>
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterVisibilityData[
|
||||
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
|
||||
].filters.includes(section_key);
|
||||
|
||||
return (
|
||||
<div className="w-full h-full overflow-hidden select-none relative flex flex-col">
|
||||
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200">
|
||||
Search container
|
||||
</div>
|
||||
{/* state group */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStateGroup />
|
||||
</div>
|
||||
{/* state */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterState />
|
||||
</div>
|
||||
{/* assignees */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterAssignees />
|
||||
</div>
|
||||
{/* created_by */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterCreatedBy />
|
||||
</div>
|
||||
{/* labels */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterLabels />
|
||||
</div>
|
||||
{/* start_date */}
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStartDate />
|
||||
</div>
|
||||
{/* due_date */}
|
||||
<div className="pt-1 px-2">
|
||||
<FilterTargetDate />
|
||||
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
|
||||
{/* priority */}
|
||||
{handleFilterSectionVisibility("priority") && (
|
||||
<div className="pb-1 px-2 border-b border-custom-border-200">
|
||||
<FilterPriority />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* state group */}
|
||||
{handleFilterSectionVisibility("state_group") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStateGroup />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* state */}
|
||||
{handleFilterSectionVisibility("state") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterState />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* assignees */}
|
||||
{handleFilterSectionVisibility("assignees") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterAssignees />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* created_by */}
|
||||
{handleFilterSectionVisibility("created_by") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterCreatedBy />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* labels */}
|
||||
{handleFilterSectionVisibility("labels") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterLabels />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* start_date */}
|
||||
{handleFilterSectionVisibility("start_date") && (
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStartDate />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* due_date */}
|
||||
{handleFilterSectionVisibility("due_date") && (
|
||||
<div className="pt-1 px-2">
|
||||
<FilterTargetDate />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
);
|
||||
});
|
||||
|
@ -32,18 +32,23 @@ export const FilterLabels = observer(() => {
|
||||
issueFilterStore.handleUserFilter("filters", key, _value);
|
||||
};
|
||||
|
||||
const handleLabels =
|
||||
issueFilterStore.issueView && issueFilterStore.issueView === "my_issues"
|
||||
? issueFilterStore?.workspaceLabels
|
||||
: issueFilterStore?.projectLabels;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={`Labels (${issueFilterStore?.projectLabels?.length || 0})`}
|
||||
title={`Labels (${(handleLabels && handleLabels?.length) || 0})`}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
{issueFilterStore?.projectLabels &&
|
||||
issueFilterStore?.projectLabels.length > 0 &&
|
||||
issueFilterStore?.projectLabels.map((_label) => (
|
||||
{handleLabels &&
|
||||
handleLabels.length > 0 &&
|
||||
handleLabels.map((_label) => (
|
||||
<FilterOption
|
||||
key={_label?.id}
|
||||
isChecked={
|
||||
|
@ -5,8 +5,10 @@ import { Columns, Grid3x3, Calendar, GanttChart, List } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { RootStore } from "store/root";
|
||||
import { TIssueLayouts } from "store/issue-views/issue_filters";
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// types and default data
|
||||
import { TIssueLayouts } from "store/issue-views/issue_filters";
|
||||
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
|
||||
|
||||
export const LayoutSelection = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
@ -40,11 +42,18 @@ export const LayoutSelection = observer(() => {
|
||||
},
|
||||
];
|
||||
|
||||
const handleLayoutSectionVisibility = (layout_key: string) =>
|
||||
issueFilterStore?.issueView &&
|
||||
issueFilterVisibilityData[
|
||||
issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
|
||||
].layout.includes(layout_key);
|
||||
|
||||
const handleLayoutSelection = (_layoutKey: string) => {
|
||||
issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey);
|
||||
};
|
||||
|
||||
console.log("----");
|
||||
console.log("my_user_id", issueFilterStore.myUserId);
|
||||
console.log("workspace_id", issueFilterStore.workspaceId);
|
||||
console.log("project_id", issueFilterStore.projectId);
|
||||
console.log("module_id", issueFilterStore.moduleId);
|
||||
@ -54,31 +63,38 @@ export const LayoutSelection = observer(() => {
|
||||
console.log("issue_view", issueFilterStore.issueView);
|
||||
console.log("issue_layout", issueFilterStore.issueLayout);
|
||||
|
||||
console.log("user_filters", issueFilterStore.userFilters);
|
||||
console.log("issues", issueStore.issues);
|
||||
console.log("issues", issueStore.getIssues);
|
||||
|
||||
console.log("----");
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center p-1 rounded gap-1 bg-custom-background-80">
|
||||
{layoutSelectionFilters.map((_layout) => (
|
||||
<div
|
||||
key={_layout?.key}
|
||||
className={`w-[28px] h-[22px] rounded flex justify-center items-center cursor-pointer transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||
issueFilterStore?.issueLayout == _layout?.key
|
||||
? `bg-custom-background-100 shadow shadow-gray-200`
|
||||
: ``
|
||||
}}`}
|
||||
onClick={() => handleLayoutSelection(_layout?.key)}
|
||||
>
|
||||
<_layout.icon
|
||||
size={14}
|
||||
strokeWidth={2}
|
||||
className={`${
|
||||
issueFilterStore?.issueLayout == _layout?.key
|
||||
? `text-custom-text-100`
|
||||
: `text-custom-text-100 group-hover:text-custom-text-200`
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
{layoutSelectionFilters.map(
|
||||
(_layout) =>
|
||||
handleLayoutSectionVisibility(_layout?.key) && (
|
||||
<div
|
||||
key={_layout?.key}
|
||||
className={`w-[28px] h-[22px] rounded flex justify-center items-center cursor-pointer transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||
issueFilterStore?.issueLayout == _layout?.key
|
||||
? `bg-custom-background-100 shadow shadow-gray-200`
|
||||
: ``
|
||||
}}`}
|
||||
onClick={() => handleLayoutSelection(_layout?.key)}
|
||||
>
|
||||
<_layout.icon
|
||||
size={14}
|
||||
strokeWidth={2}
|
||||
className={`${
|
||||
issueFilterStore?.issueLayout == _layout?.key
|
||||
? `text-custom-text-100`
|
||||
: `text-custom-text-100 group-hover:text-custom-text-200`
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
@ -78,8 +78,73 @@ export const displayProperties: { key: string; title: string }[] = [
|
||||
];
|
||||
|
||||
export const extraProperties: { key: string; title: string }[] = [
|
||||
{ key: "sub_issues", title: "Show sub-issues" }, // in spreadsheet its always false
|
||||
{ key: "sub_issue", title: "Show sub-issues" }, // in spreadsheet its always false
|
||||
{ key: "show_empty_groups", title: "Show empty states" }, // filter on front-end
|
||||
{ key: "calendar_date_range", title: "Calendar Date Range" }, // calendar date range yyyy-mm-dd;before range yyyy-mm-dd;after
|
||||
{ key: "start_target_date", title: "Start target Date" }, // gantt always be true
|
||||
];
|
||||
|
||||
export const issueFilterVisibilityData: any = {
|
||||
my_issues: {
|
||||
layout: ["list", "kanban"],
|
||||
filters: ["priority", "state_group", "labels", "start_date", "due_date"],
|
||||
display_properties: {
|
||||
list: true,
|
||||
kanban: true,
|
||||
},
|
||||
display_filters: {
|
||||
list: ["group_by", "order_by", "issue_type"],
|
||||
kanban: ["group_by", "order_by", "issue_type"],
|
||||
},
|
||||
extra_options: {
|
||||
list: {
|
||||
access: true,
|
||||
values: ["show_empty_groups"],
|
||||
},
|
||||
kanban: {
|
||||
access: true,
|
||||
values: ["show_empty_groups"],
|
||||
},
|
||||
},
|
||||
},
|
||||
others: {
|
||||
layout: ["list", "kanban", "calendar", "spreadsheet", "gantt"],
|
||||
filters: ["priority", "state", "assignees", "created_by", "labels", "start_date", "due_date"],
|
||||
display_properties: {
|
||||
list: true,
|
||||
kanban: true,
|
||||
calendar: true,
|
||||
spreadsheet: true,
|
||||
gantt: false,
|
||||
},
|
||||
display_filters: {
|
||||
list: ["group_by", "order_by", "issue_type", "sub_issue", "show_empty_groups"],
|
||||
kanban: ["group_by", "order_by", "issue_type", "sub_issue", "show_empty_groups"],
|
||||
calendar: ["issue_type"],
|
||||
spreadsheet: ["issue_type"],
|
||||
gantt: ["order_by", "issue_type", "sub_issue"],
|
||||
},
|
||||
extra_options: {
|
||||
list: {
|
||||
access: true,
|
||||
values: ["show_empty_groups", "sub_issue"],
|
||||
},
|
||||
kanban: {
|
||||
access: true,
|
||||
values: ["show_empty_groups", "sub_issue"],
|
||||
},
|
||||
calendar: {
|
||||
access: false,
|
||||
values: [],
|
||||
},
|
||||
spreadsheet: {
|
||||
access: false,
|
||||
values: [],
|
||||
},
|
||||
gantt: {
|
||||
access: true,
|
||||
values: ["sub_issue"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user