chore: filter, layout, display filters, extra filters and display properties render validation

This commit is contained in:
gurusainath 2023-09-14 16:03:35 +05:30
parent f579712092
commit c67f08fca4
6 changed files with 290 additions and 122 deletions

View File

@ -7,6 +7,8 @@ import { observer } from "mobx-react-lite";
// mobx store // mobx store
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
import { RootStore } from "store/root"; import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
export const FilterExtraOptions = observer(() => { export const FilterExtraOptions = observer(() => {
const store: RootStore = useMobxStore(); const store: RootStore = useMobxStore();
@ -18,6 +20,13 @@ export const FilterExtraOptions = observer(() => {
issueFilterStore.handleUserFilter("display_filters", key, !value); 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 ( return (
<div> <div>
<FilterHeader <FilterHeader
@ -29,23 +38,26 @@ export const FilterExtraOptions = observer(() => {
<div className="space-y-[2px] pt-1"> <div className="space-y-[2px] pt-1">
{issueFilterStore?.issueRenderFilters?.extra_properties && {issueFilterStore?.issueRenderFilters?.extra_properties &&
issueFilterStore?.issueRenderFilters?.extra_properties.length > 0 && issueFilterStore?.issueRenderFilters?.extra_properties.length > 0 &&
issueFilterStore?.issueRenderFilters?.extra_properties.map((_extraProperties) => ( issueFilterStore?.issueRenderFilters?.extra_properties.map(
<FilterOption (_extraProperties) =>
key={_extraProperties?.key} handleExtraOptionsSectionVisibility(_extraProperties?.key) && (
isChecked={ <FilterOption
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key] key={_extraProperties?.key}
? true isChecked={
: false issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
} ? true
onClick={() => : false
handleExtraOptions( }
_extraProperties?.key, onClick={() =>
issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key] handleExtraOptions(
) _extraProperties?.key,
} issueFilterStore?.userFilters?.display_filters?.[_extraProperties?.key]
title={_extraProperties.title} )
/> }
))} title={_extraProperties.title}
/>
)
)}
</div> </div>
)} )}
</div> </div>

View File

@ -5,41 +5,78 @@ import { FilterGroupBy } from "./group-by";
import { FilterOrderBy } from "./order-by"; import { FilterOrderBy } from "./order-by";
import { FilterIssueType } from "./issue-type"; import { FilterIssueType } from "./issue-type";
import { FilterExtraOptions } from "./extra-options"; import { FilterExtraOptions } from "./extra-options";
// // mobx react lite // mobx react lite
// import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// // mobx store // mobx store
// import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// import { RootStore } from "store/root"; import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
// const store: RootStore = useMobxStore(); export const DisplayFiltersSelection = observer(() => {
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store; const store: RootStore = useMobxStore();
const { issueFilters: issueFilterStore } = store;
export const DisplayFiltersSelection = () => ( const handleDisplayPropertiesSectionVisibility =
<div className="w-full h-full overflow-hidden select-none relative flex flex-col"> issueFilterStore?.issueView &&
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200"> issueFilterStore?.issueLayout &&
Search container issueFilterVisibilityData[issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"]
</div> ?.display_properties?.[issueFilterStore?.issueLayout];
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
{/* display properties */} const handleDisplayFilterSectionVisibility = (section_key: string) =>
<div className="pb-2 px-2 border-b border-custom-border-200"> issueFilterStore?.issueView &&
<FilterDisplayProperties /> 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> </div>
{/* group by */} <div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
<div className="py-1 px-2 border-b border-custom-border-200"> {/* display properties */}
<FilterGroupBy /> {handleDisplayPropertiesSectionVisibility && (
</div> <div className="pb-2 px-2 border-b border-custom-border-200">
{/* order by */} <FilterDisplayProperties />
<div className="py-1 px-2 border-b border-custom-border-200"> </div>
<FilterOrderBy /> )}
</div>
{/* issue type */} {/* group by */}
<div className="py-1 px-2 border-b border-custom-border-200"> {handleDisplayFilterSectionVisibility("group_by") && (
<FilterIssueType /> <div className="py-1 px-2 border-b border-custom-border-200">
</div> <FilterGroupBy />
{/* Options */} </div>
<div className="pt-1 px-2"> )}
<FilterExtraOptions />
{/* 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> </div>
</div> );
); });

View File

@ -8,53 +8,86 @@ import { FilterCreatedBy } from "./created-by";
import { FilterLabels } from "./labels"; import { FilterLabels } from "./labels";
import { FilterStartDate } from "./start-date"; import { FilterStartDate } from "./start-date";
import { FilterTargetDate } from "./target-date"; import { FilterTargetDate } from "./target-date";
// // mobx react lite // mobx react lite
// import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// // mobx store // mobx store
// import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// import { RootStore } from "store/root"; import { RootStore } from "store/root";
// default data
import { issueFilterVisibilityData } from "store/issue-views/issue_data";
// const store: RootStore = useMobxStore(); export const FilterSelection = observer(() => {
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store; const store: RootStore = useMobxStore();
const { issueFilters: issueFilterStore } = store;
export const FilterSelection = () => ( const handleFilterSectionVisibility = (section_key: string) =>
<div className="w-full h-full overflow-hidden select-none relative flex flex-col"> issueFilterStore?.issueView &&
<div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200"> issueFilterVisibilityData[
Search container issueFilterStore?.issueView === "my_issues" ? "my_issues" : "others"
</div> ].filters.includes(section_key);
<div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
{/* priority */} return (
<div className="pb-1 px-2 border-b border-custom-border-200"> <div className="w-full h-full overflow-hidden select-none relative flex flex-col">
<FilterPriority /> <div className="flex-shrink-0 p-2 text-sm border-b border-custom-border-200">
Search container
</div> </div>
{/* state group */} <div className="w-full h-full overflow-hidden overflow-y-auto relative pb-2">
<div className="py-1 px-2 border-b border-custom-border-200"> {/* priority */}
<FilterStateGroup /> {handleFilterSectionVisibility("priority") && (
</div> <div className="pb-1 px-2 border-b border-custom-border-200">
{/* state */} <FilterPriority />
<div className="py-1 px-2 border-b border-custom-border-200"> </div>
<FilterState /> )}
</div>
{/* assignees */} {/* state group */}
<div className="py-1 px-2 border-b border-custom-border-200"> {handleFilterSectionVisibility("state_group") && (
<FilterAssignees /> <div className="py-1 px-2 border-b border-custom-border-200">
</div> <FilterStateGroup />
{/* created_by */} </div>
<div className="py-1 px-2 border-b border-custom-border-200"> )}
<FilterCreatedBy />
</div> {/* state */}
{/* labels */} {handleFilterSectionVisibility("state") && (
<div className="py-1 px-2 border-b border-custom-border-200"> <div className="py-1 px-2 border-b border-custom-border-200">
<FilterLabels /> <FilterState />
</div> </div>
{/* start_date */} )}
<div className="py-1 px-2 border-b border-custom-border-200">
<FilterStartDate /> {/* assignees */}
</div> {handleFilterSectionVisibility("assignees") && (
{/* due_date */} <div className="py-1 px-2 border-b border-custom-border-200">
<div className="pt-1 px-2"> <FilterAssignees />
<FilterTargetDate /> </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> </div>
</div> );
); });

View File

@ -32,18 +32,23 @@ export const FilterLabels = observer(() => {
issueFilterStore.handleUserFilter("filters", key, _value); issueFilterStore.handleUserFilter("filters", key, _value);
}; };
const handleLabels =
issueFilterStore.issueView && issueFilterStore.issueView === "my_issues"
? issueFilterStore?.workspaceLabels
: issueFilterStore?.projectLabels;
return ( return (
<div> <div>
<FilterHeader <FilterHeader
title={`Labels (${issueFilterStore?.projectLabels?.length || 0})`} title={`Labels (${(handleLabels && handleLabels?.length) || 0})`}
isPreviewEnabled={previewEnabled} isPreviewEnabled={previewEnabled}
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)} handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
/> />
{previewEnabled && ( {previewEnabled && (
<div className="space-y-[2px] pt-1"> <div className="space-y-[2px] pt-1">
{issueFilterStore?.projectLabels && {handleLabels &&
issueFilterStore?.projectLabels.length > 0 && handleLabels.length > 0 &&
issueFilterStore?.projectLabels.map((_label) => ( handleLabels.map((_label) => (
<FilterOption <FilterOption
key={_label?.id} key={_label?.id}
isChecked={ isChecked={

View File

@ -5,8 +5,10 @@ import { Columns, Grid3x3, Calendar, GanttChart, List } from "lucide-react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// mobx store // mobx store
import { RootStore } from "store/root"; import { RootStore } from "store/root";
import { TIssueLayouts } from "store/issue-views/issue_filters";
import { useMobxStore } from "lib/mobx/store-provider"; 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(() => { export const LayoutSelection = observer(() => {
const store: RootStore = useMobxStore(); 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) => { const handleLayoutSelection = (_layoutKey: string) => {
issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey); issueFilterStore.handleUserFilter("display_filters", "layout", _layoutKey);
}; };
console.log("----"); console.log("----");
console.log("my_user_id", issueFilterStore.myUserId);
console.log("workspace_id", issueFilterStore.workspaceId); console.log("workspace_id", issueFilterStore.workspaceId);
console.log("project_id", issueFilterStore.projectId); console.log("project_id", issueFilterStore.projectId);
console.log("module_id", issueFilterStore.moduleId); console.log("module_id", issueFilterStore.moduleId);
@ -54,31 +63,38 @@ export const LayoutSelection = observer(() => {
console.log("issue_view", issueFilterStore.issueView); console.log("issue_view", issueFilterStore.issueView);
console.log("issue_layout", issueFilterStore.issueLayout); console.log("issue_layout", issueFilterStore.issueLayout);
console.log("user_filters", issueFilterStore.userFilters);
console.log("issues", issueStore.issues);
console.log("issues", issueStore.getIssues);
console.log("----"); console.log("----");
return ( return (
<div className="relative flex items-center p-1 rounded gap-1 bg-custom-background-80"> <div className="relative flex items-center p-1 rounded gap-1 bg-custom-background-80">
{layoutSelectionFilters.map((_layout) => ( {layoutSelectionFilters.map(
<div (_layout) =>
key={_layout?.key} handleLayoutSectionVisibility(_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 ${ <div
issueFilterStore?.issueLayout == _layout?.key key={_layout?.key}
? `bg-custom-background-100 shadow shadow-gray-200` 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 onClick={() => handleLayoutSelection(_layout?.key)}
size={14} >
strokeWidth={2} <_layout.icon
className={`${ size={14}
issueFilterStore?.issueLayout == _layout?.key strokeWidth={2}
? `text-custom-text-100` className={`${
: `text-custom-text-100 group-hover:text-custom-text-200` issueFilterStore?.issueLayout == _layout?.key
}`} ? `text-custom-text-100`
/> : `text-custom-text-100 group-hover:text-custom-text-200`
</div> }`}
))} />
</div>
)
)}
</div> </div>
); );
}); });

View File

@ -78,8 +78,73 @@ export const displayProperties: { key: string; title: string }[] = [
]; ];
export const extraProperties: { 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: "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: "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 { 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"],
},
},
},
};