forked from github/plane
chore: implemented filters and views in kanaban
This commit is contained in:
parent
698021ab8b
commit
0ec0ad6aba
@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const FilterDisplayProperties = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Display Properties"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1 px-1 flex items-center whitespace-nowrap gap-2 flex-wrap">
|
||||
{issueFilterStore?.issueRenderFilters?.display_properties &&
|
||||
issueFilterStore?.issueRenderFilters?.display_properties.length > 0 &&
|
||||
issueFilterStore?.issueRenderFilters?.display_properties.map((_displayProperties) => (
|
||||
<div
|
||||
key={_displayProperties?.key}
|
||||
className={`cursor-pointer rounded-sm transition-all text-xs border p-0.5 px-1.5 ${
|
||||
issueFilterStore?.userFilters?.display_properties?.[_displayProperties?.key]
|
||||
? `bg-custom-primary-200 border-custom-primary-200 text-white`
|
||||
: `hover:bg-custom-border-100 border-custom-border-100`
|
||||
}`}
|
||||
>
|
||||
{_displayProperties?.title}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
@ -0,0 +1,43 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { FilterOption } from "../helpers/filter-option";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const FilterExtraOptions = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Extra Options"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<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
|
||||
}
|
||||
title={_extraProperties.title}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
44
web/components/issue-layouts/display-filters/group-by.tsx
Normal file
44
web/components/issue-layouts/display-filters/group-by.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { FilterOption } from "../helpers/filter-option";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const FilterGroupBy = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Group By"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
{issueFilterStore?.issueRenderFilters?.group_by &&
|
||||
issueFilterStore?.issueRenderFilters?.group_by.length > 0 &&
|
||||
issueFilterStore?.issueRenderFilters?.group_by.map((_groupBy) => (
|
||||
<FilterOption
|
||||
key={_groupBy?.key}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.display_filters?.group_by === _groupBy?.key
|
||||
? true
|
||||
: false
|
||||
}
|
||||
title={_groupBy.title}
|
||||
multiple={false}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
@ -1,15 +1,45 @@
|
||||
import React from "react";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
// components
|
||||
import { FilterDisplayProperties } from "./display-properties";
|
||||
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";
|
||||
|
||||
export const DisplayPropertiesSelection = () => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
// const store: RootStore = useMobxStore();
|
||||
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div>Filter Selection</div>
|
||||
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 />
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
44
web/components/issue-layouts/display-filters/issue-type.tsx
Normal file
44
web/components/issue-layouts/display-filters/issue-type.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { FilterOption } from "../helpers/filter-option";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const FilterIssueType = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Issue Type"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
{issueFilterStore?.issueRenderFilters?.issue_type &&
|
||||
issueFilterStore?.issueRenderFilters?.issue_type.length > 0 &&
|
||||
issueFilterStore?.issueRenderFilters?.issue_type.map((_issueType) => (
|
||||
<FilterOption
|
||||
key={_issueType?.key}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.display_filters?.type === _issueType?.key
|
||||
? true
|
||||
: false
|
||||
}
|
||||
title={_issueType.title}
|
||||
multiple={false}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
44
web/components/issue-layouts/display-filters/order-by.tsx
Normal file
44
web/components/issue-layouts/display-filters/order-by.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import React from "react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { FilterOption } from "../helpers/filter-option";
|
||||
// mobx react lite
|
||||
import { observer } from "mobx-react-lite";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export const FilterOrderBy = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Order By"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
{issueFilterStore?.issueRenderFilters?.order_by &&
|
||||
issueFilterStore?.issueRenderFilters?.order_by.length > 0 &&
|
||||
issueFilterStore?.issueRenderFilters?.order_by.map((_orderBy) => (
|
||||
<FilterOption
|
||||
key={_orderBy?.key}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.display_filters?.order_by === _orderBy?.key
|
||||
? true
|
||||
: false
|
||||
}
|
||||
title={_orderBy.title}
|
||||
multiple={false}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
});
|
@ -17,7 +17,7 @@ export const MemberIcons = ({
|
||||
display_name: string;
|
||||
avatar: string | null;
|
||||
}) => (
|
||||
<div className="flex-shrink-0 rounded-sm overflow-hidden w-[20px] h-[20px] flex justify-center items-center bg-custom-background-80">
|
||||
<div className="flex-shrink-0 rounded-sm overflow-hidden w-[20px] h-[20px] flex justify-center items-center">
|
||||
{avatar ? (
|
||||
<img src={avatar} alt={display_name || ""} className="" />
|
||||
) : (
|
||||
@ -32,14 +32,14 @@ export const FilterAssignees = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Assignees"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -48,7 +48,12 @@ export const FilterAssignees = observer(() => {
|
||||
issueFilterStore?.projectMembers.map((_member) => (
|
||||
<FilterOption
|
||||
key={`assignees-${_member?.member?.id}`}
|
||||
isChecked={false}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.assignees != null &&
|
||||
issueFilterStore?.userFilters?.filters?.assignees.includes(_member?.member?.id)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={
|
||||
<MemberIcons
|
||||
display_name={_member?.member.display_name}
|
||||
|
@ -15,14 +15,14 @@ export const FilterCreatedBy = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Created By"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -31,7 +31,12 @@ export const FilterCreatedBy = observer(() => {
|
||||
issueFilterStore?.projectMembers.map((_member) => (
|
||||
<FilterOption
|
||||
key={`create-by-${_member?.member?.id}`}
|
||||
isChecked={false}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.created_by != null &&
|
||||
issueFilterStore?.userFilters?.filters?.created_by.includes(_member?.member?.id)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={
|
||||
<MemberIcons
|
||||
display_name={_member?.member.display_name}
|
||||
|
@ -8,50 +8,53 @@ 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";
|
||||
|
||||
export const FilterSelection = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
// const store: RootStore = useMobxStore();
|
||||
// const { issueFilters: issueFilterStore, issueView: issueViewStore } = store;
|
||||
|
||||
return (
|
||||
<div className="container w-full h-full overflow-y-auto mx-auto max-w-[400px] relative select-none">
|
||||
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="py-2 border-b border-custom-border-100">
|
||||
<div className="pb-1 px-2 border-b border-custom-border-200">
|
||||
<FilterPriority />
|
||||
</div>
|
||||
{/* state group */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStateGroup />
|
||||
</div>
|
||||
{/* state */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterState />
|
||||
</div>
|
||||
{/* assignees */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterAssignees />
|
||||
</div>
|
||||
{/* created_by */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterCreatedBy />
|
||||
</div>
|
||||
{/* labels */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterLabels />
|
||||
</div>
|
||||
{/* start_date */}
|
||||
<div className="py-2 border-b border-custom-border-100">
|
||||
<div className="py-1 px-2 border-b border-custom-border-200">
|
||||
<FilterStartDate />
|
||||
</div>
|
||||
{/* due_date */}
|
||||
<div className="py-2">
|
||||
<div className="pt-1 px-2">
|
||||
<FilterTargetDate />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
</div>
|
||||
);
|
||||
|
@ -20,14 +20,14 @@ export const FilterLabels = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"labels"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -35,8 +35,13 @@ export const FilterLabels = observer(() => {
|
||||
issueFilterStore?.projectLabels.length > 0 &&
|
||||
issueFilterStore?.projectLabels.map((_label) => (
|
||||
<FilterOption
|
||||
key={_label?.key}
|
||||
isChecked={false}
|
||||
key={_label?.id}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.labels != null &&
|
||||
issueFilterStore?.userFilters?.filters?.labels.includes(_label?.id)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={<LabelIcons color={_label.color} />}
|
||||
title={_label.name}
|
||||
/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
// lucide icons
|
||||
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban, Check } from "lucide-react";
|
||||
import { AlertCircle, SignalHigh, SignalMedium, SignalLow, Ban } from "lucide-react";
|
||||
// components
|
||||
import { FilterHeader } from "../helpers/filter-header";
|
||||
import { FilterOption } from "../helpers/filter-option";
|
||||
@ -54,14 +54,14 @@ export const FilterPriority = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Priority"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -70,11 +70,21 @@ export const FilterPriority = observer(() => {
|
||||
issueFilterStore?.issueRenderFilters?.priority.map((_priority) => (
|
||||
<FilterOption
|
||||
key={_priority?.key}
|
||||
isChecked={false}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.priority != null &&
|
||||
issueFilterStore?.userFilters?.filters?.priority.includes(_priority?.key)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={<PriorityIcons priority={_priority.key} />}
|
||||
title={_priority.title}
|
||||
/>
|
||||
))}
|
||||
<div className="pl-[32px] flex items-center gap-2 py-[6px] text-xs text-custom-primary-100">
|
||||
<div>View more</div>
|
||||
<div>View less</div>
|
||||
<div>View all</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@ -14,14 +14,14 @@ export const FilterStartDate = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Start Date"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
|
@ -87,14 +87,14 @@ export const FilterStateGroup = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"State Group"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -103,7 +103,12 @@ export const FilterStateGroup = observer(() => {
|
||||
issueFilterStore?.issueRenderFilters?.state_group.map((_stateGroup) => (
|
||||
<FilterOption
|
||||
key={_stateGroup?.key}
|
||||
isChecked={false}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.state_group != null &&
|
||||
issueFilterStore?.userFilters?.filters?.state_group.includes(_stateGroup?.key)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={<StateGroupIcons stateGroup={_stateGroup.key} />}
|
||||
title={_stateGroup.title}
|
||||
/>
|
||||
|
@ -17,14 +17,14 @@ export const FilterState = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"State"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
@ -36,7 +36,12 @@ export const FilterState = observer(() => {
|
||||
issueFilterStore?.projectStates[_stateGroup].map((_state: any) => (
|
||||
<FilterOption
|
||||
key={_state?.id}
|
||||
isChecked={false}
|
||||
isChecked={
|
||||
issueFilterStore?.userFilters?.filters?.state != null &&
|
||||
issueFilterStore?.userFilters?.filters?.state.includes(_state?.id)
|
||||
? true
|
||||
: false
|
||||
}
|
||||
icon={<StateGroupIcons stateGroup={_stateGroup} color={_state?.color} />}
|
||||
title={_state?.name}
|
||||
/>
|
||||
|
@ -14,14 +14,14 @@ export const FilterTargetDate = observer(() => {
|
||||
const store: RootStore = useMobxStore();
|
||||
const { issueFilters: issueFilterStore, issueView: issueStore } = store;
|
||||
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(false);
|
||||
const [previewEnabled, setPreviewEnabled] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FilterHeader
|
||||
title={"Target Date"}
|
||||
isPreviewEnabled={previewEnabled}
|
||||
handleIsPreviewEnabled={setPreviewEnabled}
|
||||
handleIsPreviewEnabled={() => setPreviewEnabled(!previewEnabled)}
|
||||
/>
|
||||
{previewEnabled && (
|
||||
<div className="space-y-[2px] pt-1">
|
||||
|
50
web/components/issue-layouts/helpers/dropdown.tsx
Normal file
50
web/components/issue-layouts/helpers/dropdown.tsx
Normal file
@ -0,0 +1,50 @@
|
||||
import { Fragment } from "react";
|
||||
// headless ui
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
// lucide icons
|
||||
import { ChevronDown, ChevronUp } from "lucide-react";
|
||||
|
||||
interface IIssueDropdown {
|
||||
children: React.ReactNode;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export const IssueDropdown = ({ children, title = "Dropdown" }: IIssueDropdown) => (
|
||||
<Popover className="relative">
|
||||
{({ open }) => {
|
||||
if (open) {
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Popover.Button
|
||||
className={`outline-none border border-custom-border-200 text-xs rounded flex items-center gap-2 p-2 py-1.5 hover:bg-custom-background-100`}
|
||||
>
|
||||
<div className="font-medium">{title}</div>
|
||||
<div className="w-[14px] h-[14px] flex justify-center items-center">
|
||||
{open ? (
|
||||
<ChevronUp width={14} strokeWidth={2} />
|
||||
) : (
|
||||
<ChevronDown width={14} strokeWidth={2} />
|
||||
)}
|
||||
</div>
|
||||
</Popover.Button>
|
||||
<Transition
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0 translate-y-1"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
leave="transition ease-in duration-150"
|
||||
leaveFrom="opacity-100 translate-y-0"
|
||||
leaveTo="opacity-0 translate-y-1"
|
||||
>
|
||||
<Popover.Panel className="absolute right-0 z-10 mt-1 w-[300px] h-[700px]">
|
||||
<div className="w-full h-full overflow-hidden rounded border border-custom-border-200 bg-custom-background-100 shadow-xl">
|
||||
{children}
|
||||
</div>
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Popover>
|
||||
);
|
@ -5,7 +5,7 @@ import { ChevronDown, ChevronUp } from "lucide-react";
|
||||
interface IFilterHeader {
|
||||
title: string;
|
||||
isPreviewEnabled: boolean;
|
||||
handleIsPreviewEnabled: (isPreviewEnabled: boolean) => void;
|
||||
handleIsPreviewEnabled: () => void;
|
||||
}
|
||||
|
||||
export const FilterHeader = ({
|
||||
@ -13,11 +13,11 @@ export const FilterHeader = ({
|
||||
isPreviewEnabled,
|
||||
handleIsPreviewEnabled,
|
||||
}: IFilterHeader) => (
|
||||
<div className="flex items-center justify-between gap-2 p-[6px] pb-2 bg-custom-background-80 sticky top-0">
|
||||
<div className="text-gray-500 text-sm text-custom-text-300 font-medium">{title}</div>
|
||||
<div className="flex items-center justify-between gap-2 p-[6px] pb-1 bg-custom-background-100 sticky top-0">
|
||||
<div className="text-gray-500 text-xs text-custom-text-300 font-medium">{title}</div>
|
||||
<div
|
||||
className="flex-shrink-0 w-[20px] h-[20px] flex justify-center items-center rounded-sm transition-all hover:bg-custom-background-100 cursor-pointer"
|
||||
onClick={() => handleIsPreviewEnabled(!isPreviewEnabled)}
|
||||
className="flex-shrink-0 w-[20px] h-[20px] flex justify-center items-center rounded transition-all hover:bg-custom-background-80 cursor-pointer"
|
||||
onClick={handleIsPreviewEnabled}
|
||||
>
|
||||
{isPreviewEnabled ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@ interface IFilterOption {
|
||||
}
|
||||
|
||||
export const FilterOption = ({ isChecked, icon, title, multiple = true }: IFilterOption) => (
|
||||
<div className="flex items-center gap-3 cursor-pointer rounded-sm p-[6px] py-[5px] transition-all hover:bg-custom-border-100">
|
||||
<div className="flex items-center gap-3 cursor-pointer rounded p-[6px] py-[5px] transition-all hover:bg-custom-border-100">
|
||||
<div
|
||||
className={`flex-shrink-0 w-[14px] h-[14px] flex justify-center items-center border border-custom-border-300 bg-custom-background-90 ${
|
||||
isChecked ? `bg-custom-primary-300 text-white` : ``
|
||||
@ -19,6 +19,6 @@ export const FilterOption = ({ isChecked, icon, title, multiple = true }: IFilte
|
||||
{isChecked && <Check size={10} strokeWidth={2} />}
|
||||
</div>
|
||||
{icon}
|
||||
<div className="hyphens-auto line-clamp-2 text-custom-text-200 text-sm w-full">{title}</div>
|
||||
<div className="hyphens-auto line-clamp-1 text-custom-text-200 text-xs w-full">{title}</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -28,28 +28,6 @@ export const IssueKanBanViewRoot = observer(() => {
|
||||
console.log("result", result);
|
||||
};
|
||||
|
||||
console.log("------");
|
||||
console.log("workspace id -->", issueFilterStore?.workspaceId);
|
||||
console.log("project id -->", issueFilterStore?.projectId);
|
||||
console.log("module id -->", issueFilterStore?.moduleId);
|
||||
console.log("cycle id -->", issueFilterStore?.cycleId);
|
||||
console.log("view id -->", issueFilterStore?.viewId);
|
||||
|
||||
console.log("<-- workspace level -->");
|
||||
console.log("workspace projects -->", issueFilterStore?.workspaceProjects);
|
||||
console.log("workspace labels -->", issueFilterStore?.workspaceLabels);
|
||||
|
||||
console.log("<-- project level -->");
|
||||
console.log("project states -->", issueFilterStore?.projectStates);
|
||||
console.log("project labels -->", issueFilterStore?.projectLabels);
|
||||
console.log("project members -->", issueFilterStore?.projectMembers);
|
||||
|
||||
console.log("project display properties -->", issueFilterStore?.projectDisplayProperties);
|
||||
|
||||
console.log("issue layout -->", issueFilterStore?.issueLayout);
|
||||
console.log("issues -->", issueViewStore?.getIssues);
|
||||
console.log("------");
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-full">
|
||||
{issueViewStore.loader || issueViewStore?.getIssues === null ? (
|
||||
|
@ -94,7 +94,7 @@ export const LayoutSelection = observer(() => {
|
||||
{layoutSelectionFilters.map((_layout) => (
|
||||
<div
|
||||
key={_layout?.key}
|
||||
className={`w-[32px] h-[26px] rounded flex justify-center items-center cursor-pointer transition-all hover:bg-custom-background-100 overflow-hidden group ${
|
||||
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`
|
||||
: ``
|
||||
@ -102,7 +102,7 @@ export const LayoutSelection = observer(() => {
|
||||
onClick={() => handleLayoutSelection(_layout?.key)}
|
||||
>
|
||||
<_layout.icon
|
||||
size={15}
|
||||
size={14}
|
||||
strokeWidth={2}
|
||||
className={`${
|
||||
issueFilterStore?.issueLayout == _layout?.key
|
||||
|
@ -4,7 +4,11 @@ import useSWR from "swr";
|
||||
// components
|
||||
import { IssueKanBanViewRoot } from "components/issue-layouts/kanban";
|
||||
import { LayoutSelection } from "components/issue-layouts/layout-selection";
|
||||
// issue dropdowns
|
||||
import { IssueDropdown } from "components/issue-layouts/helpers/dropdown";
|
||||
// filter components
|
||||
import { FilterSelection } from "components/issue-layouts/filters";
|
||||
import { DisplayFiltersSelection } from "components/issue-layouts/display-filters";
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
import { RootStore } from "store/root";
|
||||
@ -29,8 +33,8 @@ const KanBanViewRoot = () => {
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "spreadsheet");
|
||||
// await issueViewStore.getMyIssuesAsync(workspaceSlug, "my_issues", "gantt");
|
||||
// project issues under and workspace and project
|
||||
await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "list");
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "kanban");
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "list");
|
||||
await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "kanban");
|
||||
// await issueViewStore.getProjectIssuesAsync(workspaceSlug, projectSlug, "issues", "calendar");
|
||||
// await issueViewStore.getProjectIssuesAsync(
|
||||
// workspaceSlug,
|
||||
@ -165,16 +169,18 @@ const KanBanViewRoot = () => {
|
||||
<div>Filter Header</div>
|
||||
</div>
|
||||
<div className="relative flex items-center gap-2">
|
||||
<div>{/* <FilterSelection /> */}</div>
|
||||
<div>
|
||||
<LayoutSelection />
|
||||
</div>
|
||||
<IssueDropdown title={"Filters"}>
|
||||
<FilterSelection />
|
||||
</IssueDropdown>
|
||||
<IssueDropdown title={"View"}>
|
||||
<DisplayFiltersSelection />
|
||||
</IssueDropdown>
|
||||
<LayoutSelection />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full h-full relative overflow-hidden">
|
||||
<FilterSelection />
|
||||
{/* <IssueKanBanViewRoot /> */}
|
||||
<IssueKanBanViewRoot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -131,9 +131,9 @@ class IssueViewStore implements IIssueViewStore {
|
||||
|
||||
const currentLayout: TIssueLayouts = currentProjectId
|
||||
? this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId]
|
||||
?.project_issue_properties?.[currentProjectId]?.renderLayout
|
||||
?.project_issue_properties?.[currentProjectId]?.issues?.display_filters?.layout
|
||||
: this.rootStore.issueFilters.issueFilters?.[currentWorkspaceId]?.my_issue_properties
|
||||
?.renderLayout;
|
||||
?.display_filters?.layout;
|
||||
|
||||
if (currentView === "my_issues")
|
||||
return this.issues?.[currentWorkspaceId]?.my_issues?.[currentLayout];
|
||||
|
@ -12,7 +12,7 @@ export const filtersPriority: { key: string; title: string }[] = [
|
||||
{ key: "high", title: "High" },
|
||||
{ key: "medium", title: "Medium" },
|
||||
{ key: "low", title: "Low" },
|
||||
{ key: "null", title: "None" },
|
||||
{ key: "none", title: "None" },
|
||||
];
|
||||
|
||||
export const filterStateGroup: { key: TStateGroup; title: string }[] = [
|
||||
@ -43,7 +43,7 @@ export const displayPropertyGroupBy: { key: string; title: string }[] = [
|
||||
{ key: "state", title: "States" },
|
||||
{ key: "state_detail.group", title: "State Groups" },
|
||||
{ key: "priority", title: "Priority" },
|
||||
{ key: "Project", title: "project" }, // required this on my issues
|
||||
{ key: "Project", title: "Project" }, // required this on my issues
|
||||
{ key: "labels", title: "Labels" },
|
||||
{ key: "assignees", title: "Assignees" },
|
||||
{ key: "created_by", title: "Created By" },
|
||||
@ -67,7 +67,7 @@ export const displayProperties: { key: string; title: string }[] = [
|
||||
{ key: "assignee", title: "Assignee" },
|
||||
{ key: "start_date", title: "Start Date" },
|
||||
{ key: "due_date", title: "Due Date" },
|
||||
{ key: "key", title: "Id" },
|
||||
{ key: "key", title: "ID" },
|
||||
{ key: "labels", title: "Labels" },
|
||||
{ key: "priority", title: "Priority" },
|
||||
{ key: "state", title: "State" },
|
||||
@ -76,3 +76,10 @@ export const displayProperties: { key: string; title: string }[] = [
|
||||
{ key: "link", title: "Link" },
|
||||
{ key: "estimate", title: "Estimate" },
|
||||
];
|
||||
|
||||
export const extraProperties: { key: string; title: string }[] = [
|
||||
{ key: "sub_issues", 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
|
||||
];
|
||||
|
@ -16,6 +16,7 @@ import {
|
||||
displayPropertyOrderBy,
|
||||
displayPropertyIssueType,
|
||||
displayProperties,
|
||||
extraProperties,
|
||||
} from "./issue_data";
|
||||
|
||||
export type TIssueViews = "my_issues" | "issues" | "modules" | "views" | "cycles";
|
||||
@ -70,6 +71,7 @@ export interface IIssueRenderFilters {
|
||||
order_by: { key: string; title: string }[];
|
||||
issue_type: { key: string; title: string }[];
|
||||
display_properties: { key: string; title: string }[];
|
||||
extra_properties: { key: string; title: string }[];
|
||||
workspace_properties: {
|
||||
[key: string]: {
|
||||
projects: any[];
|
||||
@ -91,7 +93,6 @@ export interface IIssueFilters {
|
||||
filters: IIssueFilter;
|
||||
display_filters: IIssueDisplayFilters;
|
||||
display_properties: IIssueDisplayProperties;
|
||||
renderLayout: TIssueLayouts;
|
||||
};
|
||||
project_issue_properties: {
|
||||
[key: string]: {
|
||||
@ -99,11 +100,22 @@ export interface IIssueFilters {
|
||||
filters: IIssueFilter;
|
||||
display_filters: IIssueDisplayFilters;
|
||||
};
|
||||
cycles: { filters: IIssueFilter; display_filters: IIssueDisplayFilters };
|
||||
modules: { filters: IIssueFilter; display_filters: IIssueDisplayFilters };
|
||||
views: { filters: IIssueFilter; display_filters: IIssueDisplayFilters };
|
||||
cycles: {
|
||||
[key: string]: {
|
||||
filters: IIssueFilter;
|
||||
};
|
||||
};
|
||||
modules: {
|
||||
[key: string]: {
|
||||
filters: IIssueFilter;
|
||||
};
|
||||
};
|
||||
views: {
|
||||
[key: string]: {
|
||||
filters: IIssueFilter;
|
||||
};
|
||||
};
|
||||
display_properties: IIssueDisplayProperties;
|
||||
renderLayout: TIssueLayouts;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -124,6 +136,16 @@ export interface IIssueFilterStore {
|
||||
issueRenderFilters: IIssueRenderFilters;
|
||||
issueFilters: IIssueFilters;
|
||||
|
||||
filterRenderProperties:
|
||||
| {
|
||||
[key: string]: {
|
||||
isPreviewEnabled: boolean;
|
||||
totalElements: number;
|
||||
elementsVisible: number;
|
||||
};
|
||||
}[]
|
||||
| null;
|
||||
|
||||
// actions
|
||||
getWorkspaceMyIssuesFilters: (workspaceId: string) => Promise<any>;
|
||||
updateWorkspaceMyIssuesFilters: () => any | Promise<any>;
|
||||
@ -173,10 +195,21 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
order_by: displayPropertyOrderBy,
|
||||
issue_type: displayPropertyIssueType,
|
||||
display_properties: displayProperties,
|
||||
extra_properties: extraProperties,
|
||||
workspace_properties: {},
|
||||
};
|
||||
issueFilters: IIssueFilters = {};
|
||||
|
||||
filterRenderProperties:
|
||||
| {
|
||||
[key: string]: {
|
||||
isPreviewEnabled: boolean;
|
||||
totalElements: number;
|
||||
elementsVisible: number;
|
||||
};
|
||||
}[]
|
||||
| null = null;
|
||||
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
@ -211,6 +244,8 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
projectMembers: computed,
|
||||
projectDisplayProperties: computed,
|
||||
|
||||
userFilters: computed,
|
||||
|
||||
// action
|
||||
setWorkspaceId: action,
|
||||
setProjectId: action,
|
||||
@ -253,12 +288,11 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
// computed
|
||||
get issueLayout() {
|
||||
if (!this.workspaceId) return null;
|
||||
|
||||
if (!this.projectId)
|
||||
return this.issueFilters?.[this.workspaceId]?.my_issue_properties?.renderLayout;
|
||||
return this.issueFilters?.[this.workspaceId]?.my_issue_properties?.display_filters?.layout;
|
||||
if (this.projectId)
|
||||
return this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.renderLayout;
|
||||
?.issues?.display_filters?.layout;
|
||||
}
|
||||
|
||||
get workspaceProjects() {
|
||||
@ -291,9 +325,68 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
get projectDisplayProperties() {
|
||||
if (!this.workspaceId || !this.projectId) return null;
|
||||
return this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.display_properties;
|
||||
?.display_properties as any;
|
||||
}
|
||||
|
||||
get userFilters() {
|
||||
if (!this.workspaceId) return null;
|
||||
if (this.issueView === "my_issues")
|
||||
return this.issueFilters?.[this.workspaceId]?.my_issue_properties;
|
||||
|
||||
if (!this.projectId) return null;
|
||||
let _issueFilters: {
|
||||
filters: IIssueFilter | null;
|
||||
display_filters: IIssueDisplayFilters;
|
||||
display_properties: IIssueDisplayProperties;
|
||||
} = {
|
||||
filters: null,
|
||||
display_filters:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]?.issues
|
||||
?.display_filters,
|
||||
display_properties:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.display_properties,
|
||||
};
|
||||
if (this.issueView === "issues") {
|
||||
_issueFilters = {
|
||||
..._issueFilters,
|
||||
filters:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]?.issues
|
||||
?.filters,
|
||||
};
|
||||
return _issueFilters;
|
||||
}
|
||||
if (this.issueView === "modules" && this.moduleId) {
|
||||
_issueFilters = {
|
||||
..._issueFilters,
|
||||
filters:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.modules?.[this.moduleId]?.filters,
|
||||
};
|
||||
return _issueFilters;
|
||||
}
|
||||
if (this.issueView === "cycles" && this.cycleId) {
|
||||
_issueFilters = {
|
||||
..._issueFilters,
|
||||
filters:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.cycles?.[this.cycleId]?.filters,
|
||||
};
|
||||
return _issueFilters;
|
||||
}
|
||||
if (this.issueView === "views" && this.viewId) {
|
||||
_issueFilters = {
|
||||
..._issueFilters,
|
||||
filters:
|
||||
this.issueFilters?.[this.workspaceId]?.project_issue_properties?.[this.projectId]
|
||||
?.views?.[this.viewId]?.filters,
|
||||
};
|
||||
return _issueFilters;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
handleUserFilter = () => {};
|
||||
|
||||
computedFilter = (filters: any, filteredParams: any) => {
|
||||
const computedFilters: any = {};
|
||||
Object.keys(filters).map((key) => {
|
||||
@ -322,53 +415,51 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
this.setViewId(_viewId);
|
||||
this.setIssueView(_issueView);
|
||||
|
||||
if (_workspaceId) {
|
||||
if (!_projectId)
|
||||
this.issueFilters = {
|
||||
...this.issueFilters,
|
||||
[_workspaceId]: {
|
||||
...this.issueFilters[_workspaceId],
|
||||
my_issue_properties: {
|
||||
...this.issueFilters[_workspaceId]?.my_issue_properties,
|
||||
renderLayout: _issueLayout,
|
||||
},
|
||||
},
|
||||
};
|
||||
else
|
||||
this.issueFilters = {
|
||||
...this.issueFilters,
|
||||
[_workspaceId]: {
|
||||
...this.issueFilters[_workspaceId],
|
||||
project_issue_properties: {
|
||||
...this.issueFilters[_workspaceId]?.project_issue_properties,
|
||||
[_projectId]: {
|
||||
...this.issueFilters[_workspaceId]?.project_issue_properties?.[_projectId],
|
||||
renderLayout: _issueLayout,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
const _layout = this.userFilters?.display_filters?.layout;
|
||||
|
||||
let filteredRouteParams: any = {
|
||||
priority: [] || undefined,
|
||||
state: [] || undefined,
|
||||
assignees: [] || undefined, // ['user_id', 'user_id']
|
||||
created_by: [] || undefined, // ['user_id', 'user_id']
|
||||
labels: [] || undefined, // ['label_id', 'label_id']
|
||||
start_date: [] || undefined, // ['yyyy-mm-dd:after/before', 'yyyy-mm-dd:after/before']
|
||||
target_date: [] || undefined, // [yyyy-mm-dd:after, yyyy-mm-dd:before]
|
||||
type: "" || undefined, // 'active' (started, un_started) || 'backlog' || 'null' (all_the_issues)
|
||||
group_by: "state", // TIssueGroupByOptions
|
||||
order_by: "-created_at", // TIssueOrderByOptions
|
||||
sub_issue: true, // true for all other views except spreadsheet
|
||||
priority: this.userFilters?.filters?.priority || undefined,
|
||||
state_group: this.userFilters?.filters?.state_group || undefined,
|
||||
state: this.userFilters?.filters?.state || undefined,
|
||||
assignees: this.userFilters?.filters?.assignees || undefined,
|
||||
created_by: this.userFilters?.filters?.created_by || undefined,
|
||||
labels: this.userFilters?.filters?.labels || undefined,
|
||||
start_date: this.userFilters?.filters?.start_date || undefined,
|
||||
target_date: this.userFilters?.filters?.target_date || undefined,
|
||||
type: this.userFilters?.display_filters?.type || undefined,
|
||||
group_by: this.userFilters?.display_filters?.group_by || "state",
|
||||
order_by: this.userFilters?.display_filters?.order_by || "-created_at",
|
||||
sub_issue: this.userFilters?.display_filters?.sub_issue || true,
|
||||
show_empty_groups: this.userFilters?.display_filters?.show_empty_groups || true,
|
||||
calendar_date_range: this.userFilters?.display_filters?.calendar_date_range || undefined,
|
||||
start_target_date: this.userFilters?.display_filters?.start_target_date || true,
|
||||
};
|
||||
|
||||
let filteredParams: any = {};
|
||||
console.log("filteredRouteParams", filteredRouteParams);
|
||||
|
||||
if (_issueLayout === "list")
|
||||
// start date and target date we have to construct the format here
|
||||
|
||||
let filteredParams: any = {};
|
||||
if (_layout === "list")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state_group",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"group_by",
|
||||
"order_by",
|
||||
"type",
|
||||
"sub_issue",
|
||||
"show_empty_groups",
|
||||
];
|
||||
if (_layout === "kanban")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state_group",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
@ -380,7 +471,33 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
"order_by",
|
||||
"sub_issue",
|
||||
];
|
||||
if (_issueLayout === "kanban")
|
||||
if (_layout === "calendar")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state_group",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"calendar_date_range",
|
||||
];
|
||||
if (_layout === "spreadsheet")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state_group",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"sub_issues",
|
||||
];
|
||||
if (_layout === "gantt")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
@ -389,49 +506,17 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"group_by",
|
||||
"order_by",
|
||||
"sub_issue",
|
||||
];
|
||||
if (_issueLayout === "calendar")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
];
|
||||
if (_issueLayout === "spreadsheet")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
];
|
||||
if (_issueLayout === "gantt")
|
||||
filteredParams = [
|
||||
"priority",
|
||||
"state",
|
||||
"assignees",
|
||||
"created_by",
|
||||
"labels",
|
||||
"start_date",
|
||||
"target_date",
|
||||
"type",
|
||||
"order_by",
|
||||
"sub_issue_id",
|
||||
"start_target_date",
|
||||
];
|
||||
|
||||
filteredRouteParams = this.computedFilter(filteredRouteParams, filteredParams);
|
||||
|
||||
// remove few attributes from the object when we are in workspace issues
|
||||
console.log("filteredRouteParams", filteredRouteParams);
|
||||
|
||||
return filteredRouteParams;
|
||||
};
|
||||
|
||||
@ -470,7 +555,6 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
getWorkspaceMyIssuesLabels = async (workspaceId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
@ -523,40 +607,48 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
my_issue_properties: {
|
||||
...this?.issueFilters?.[workspaceId]?.my_issue_properties,
|
||||
filters: {
|
||||
priority: undefined,
|
||||
state: undefined,
|
||||
state_group: undefined,
|
||||
assignees: undefined,
|
||||
created_by: undefined,
|
||||
labels: undefined,
|
||||
start_date: undefined,
|
||||
target_date: undefined,
|
||||
subscriber: undefined,
|
||||
priority: issuesFiltersResponse?.view_props?.filters?.priority ?? null,
|
||||
state: issuesFiltersResponse?.view_props?.filters?.state ?? null,
|
||||
state_group: issuesFiltersResponse?.view_props?.filters?.state_group ?? null,
|
||||
assignees: issuesFiltersResponse?.view_props?.filters?.assignees ?? null,
|
||||
created_by: issuesFiltersResponse?.view_props?.filters?.created_by ?? null,
|
||||
labels: issuesFiltersResponse?.view_props?.filters?.labels ?? null,
|
||||
start_date: issuesFiltersResponse?.view_props?.filters?.start_date ?? null,
|
||||
target_date: issuesFiltersResponse?.view_props?.filters?.target_date ?? null,
|
||||
subscriber: issuesFiltersResponse?.view_props?.filters?.subscriber ?? null,
|
||||
},
|
||||
display_filters: {
|
||||
group_by: undefined,
|
||||
order_by: undefined,
|
||||
type: undefined,
|
||||
sub_issue: undefined,
|
||||
show_empty_groups: undefined,
|
||||
layout: undefined,
|
||||
calendar_date_range: undefined,
|
||||
start_target_date: undefined,
|
||||
group_by: issuesFiltersResponse?.view_props?.display_filters?.group_by ?? null,
|
||||
order_by: issuesFiltersResponse?.view_props?.display_filters?.order_by ?? null,
|
||||
type: issuesFiltersResponse?.view_props?.display_filters?.type ?? null,
|
||||
sub_issue: issuesFiltersResponse?.view_props?.display_filters?.sub_issue ?? false,
|
||||
show_empty_groups:
|
||||
issuesFiltersResponse?.view_props?.display_filters?.show_empty_groups ?? false,
|
||||
layout: issuesFiltersResponse?.view_props?.display_filters?.layout ?? "list",
|
||||
calendar_date_range:
|
||||
issuesFiltersResponse?.view_props?.display_filters?.calendar_date_range ?? false,
|
||||
start_target_date:
|
||||
issuesFiltersResponse?.view_props?.display_filters?.start_target_date ?? true,
|
||||
},
|
||||
display_properties: {
|
||||
assignee: false,
|
||||
attachment_count: false,
|
||||
created_on: false,
|
||||
due_date: false,
|
||||
estimate: false,
|
||||
key: false,
|
||||
labels: false,
|
||||
link: false,
|
||||
priority: false,
|
||||
start_date: false,
|
||||
state: false,
|
||||
sub_issue_count: false,
|
||||
updated_on: false,
|
||||
assignee: issuesFiltersResponse?.view_props?.display_properties?.assignee ?? false,
|
||||
attachment_count:
|
||||
issuesFiltersResponse?.view_props?.display_properties?.attachment_count ?? false,
|
||||
created_on:
|
||||
issuesFiltersResponse?.view_props?.display_properties?.created_on ?? false,
|
||||
due_date: issuesFiltersResponse?.view_props?.display_properties?.due_date ?? false,
|
||||
estimate: issuesFiltersResponse?.view_props?.display_properties?.estimate ?? false,
|
||||
key: issuesFiltersResponse?.view_props?.display_properties?.key ?? false,
|
||||
labels: issuesFiltersResponse?.view_props?.display_properties?.labels ?? false,
|
||||
link: issuesFiltersResponse?.view_props?.display_properties?.link ?? false,
|
||||
priority: issuesFiltersResponse?.view_props?.display_properties?.priority ?? false,
|
||||
start_date:
|
||||
issuesFiltersResponse?.view_props?.display_properties?.start_date ?? false,
|
||||
state: issuesFiltersResponse?.view_props?.display_properties?.state ?? false,
|
||||
sub_issue_count:
|
||||
issuesFiltersResponse?.view_props?.display_properties?.sub_issue_count ?? false,
|
||||
updated_on:
|
||||
issuesFiltersResponse?.view_props?.display_properties?.updated_on ?? false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -652,7 +744,6 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
getProjectLevelLabels = async (workspaceId: string, projectId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
@ -692,7 +783,6 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
return error;
|
||||
}
|
||||
};
|
||||
|
||||
getProjectLevelMembers = async (workspaceId: string, projectId: string) => {
|
||||
try {
|
||||
this.loader = true;
|
||||
@ -755,7 +845,7 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
...this?.issueFilters[workspaceId]?.project_issue_properties,
|
||||
[projectId]: {
|
||||
...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId],
|
||||
display_properties: issuesDisplayPropertiesResponse,
|
||||
display_properties: issuesDisplayPropertiesResponse?.properties,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -822,25 +912,35 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
const workspaceId = "1";
|
||||
const issuesDisplayFiltersResponse = await this.projectService.projectMemberMe(
|
||||
workspaceId,
|
||||
projectId
|
||||
);
|
||||
|
||||
const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId);
|
||||
if (issuesDisplayFiltersResponse) {
|
||||
const _filters = { ...issuesDisplayFiltersResponse?.view_props?.filters };
|
||||
const _displayFilters = { ...issuesDisplayFiltersResponse?.view_props?.display_filters };
|
||||
|
||||
if (issuesFiltersResponse) {
|
||||
// const _issuesFiltersResponse = this.issueFilters;
|
||||
// const _issuesFiltersResponse: any = {
|
||||
// ...this.issues,
|
||||
// [workspaceId]: {
|
||||
// ...this?.issues[workspaceId],
|
||||
// my_issues: {
|
||||
// ...this?.issues[workspaceId]?.my_issues,
|
||||
// [_layout as string]: issuesResponse,
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
const _issuesDisplayFiltersResponse: any = {
|
||||
...this.issueFilters,
|
||||
[workspaceId]: {
|
||||
...this?.issueFilters[workspaceId],
|
||||
project_issue_properties: {
|
||||
...this?.issueFilters[workspaceId]?.project_issue_properties,
|
||||
[projectId]: {
|
||||
...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId],
|
||||
issues: {
|
||||
...this?.issueFilters[workspaceId]?.project_issue_properties?.[projectId]?.issues,
|
||||
filters: _filters,
|
||||
display_filters: _displayFilters,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
// this.issueFilters = _issuesFiltersResponse;
|
||||
this.issueFilters = _issuesDisplayFiltersResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
@ -901,28 +1001,12 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
await this.getProjectLevelLabels(workspaceId, projectId);
|
||||
await this.getProjectLevelMembers(workspaceId, projectId);
|
||||
await this.getProjectDisplayProperties(workspaceId, projectId);
|
||||
await this.getProjectDisplayFilters(workspaceId, projectId);
|
||||
|
||||
const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId);
|
||||
|
||||
if (issuesFiltersResponse) {
|
||||
// const _issuesFiltersResponse = this.issueFilters;
|
||||
// const _issuesFiltersResponse: any = {
|
||||
// ...this.issues,
|
||||
// [workspaceId]: {
|
||||
// ...this?.issues[workspaceId],
|
||||
// my_issues: {
|
||||
// ...this?.issues[workspaceId]?.my_issues,
|
||||
// [_layout as string]: issuesResponse,
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
runInAction(() => {
|
||||
// this.issueFilters = _issuesFiltersResponse;
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
}
|
||||
runInAction(() => {
|
||||
this.loader = false;
|
||||
this.error = null;
|
||||
});
|
||||
|
||||
// return issuesResponse;
|
||||
} catch (error) {
|
||||
@ -937,11 +1021,6 @@ class IssueFilterStore implements IIssueFilterStore {
|
||||
this.loader = true;
|
||||
this.error = null;
|
||||
|
||||
await this.getProjectLevelStates(workspaceId, projectId);
|
||||
await this.getProjectLevelLabels(workspaceId, projectId);
|
||||
await this.getProjectLevelMembers(workspaceId, projectId);
|
||||
// await this.getProjectDisplayProperties(workspaceId, projectId);
|
||||
|
||||
const issuesFiltersResponse = await this.workspaceService.workspaceMemberMe(workspaceId);
|
||||
|
||||
if (issuesFiltersResponse) {
|
||||
|
Loading…
Reference in New Issue
Block a user