forked from github/plane
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
|
// 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>
|
||||||
|
@ -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>
|
);
|
||||||
);
|
});
|
||||||
|
@ -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>
|
);
|
||||||
);
|
});
|
||||||
|
@ -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={
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -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"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user