= {
buttonConfig?: {
- label?: string;
+ label: string | null;
variant?: TButtonVariant;
className?: string;
defaultOpen?: boolean;
@@ -28,7 +28,7 @@ export const AddFilterButton = observer(
(props: TAddFilterButtonProps
) => {
const { filter, buttonConfig, onFilterSelect } = props;
const {
- label = "Filters",
+ label,
variant = "link-neutral",
className,
defaultOpen = false,
diff --git a/apps/web/core/components/rich-filters/filters-row.tsx b/apps/web/core/components/rich-filters/filters-row.tsx
index cf7cd7821..2733d56b3 100644
--- a/apps/web/core/components/rich-filters/filters-row.tsx
+++ b/apps/web/core/components/rich-filters/filters-row.tsx
@@ -1,11 +1,12 @@
import React, { useCallback, useState } from "react";
import { observer } from "mobx-react";
+import { ListFilterPlus } from "lucide-react";
import { Transition } from "@headlessui/react";
// plane imports
import { Button } from "@plane/propel/button";
import { IFilterInstance } from "@plane/shared-state";
import { TExternalFilter, TFilterProperty } from "@plane/types";
-import { EHeaderVariant, Header } from "@plane/ui";
+import { cn, EHeaderVariant, Header } from "@plane/ui";
// local imports
import { AddFilterButton, TAddFilterButtonProps } from "./add-filters-button";
import { FilterItem } from "./filter-item";
@@ -14,8 +15,7 @@ export type TFiltersRowProps["buttonConfig"];
disabledAllOperations?: boolean;
filter: IFilterInstance;
- variant?: "default" | "header";
- visible?: boolean;
+ variant?: "modal" | "header";
trackerElements?: {
clearFilter?: string;
saveView?: string;
@@ -25,25 +25,35 @@ export type TFiltersRowProps(props: TFiltersRowProps) => {
- const {
- buttonConfig,
- disabledAllOperations = false,
- filter,
- variant = "header",
- visible = true,
- trackerElements,
- } = props;
+ const { buttonConfig, disabledAllOperations = false, filter, variant = "header", trackerElements } = props;
// states
const [isUpdating, setIsUpdating] = useState(false);
+ // derived values
+ const hasAnyConditions = filter.allConditionsForDisplay.length > 0;
+ const hasAvailableOperations =
+ !disabledAllOperations && (filter.canClearFilters || filter.canSaveView || filter.canUpdateView);
+
+ const headerButtonConfig: Partial["buttonConfig"]> = {
+ variant: "link-neutral",
+ className: "bg-custom-background-90",
+ label: null,
+ };
+
+ const modalButtonConfig: Partial["buttonConfig"]> = {
+ variant: "neutral-primary",
+ className: "bg-custom-background-100",
+ label: !hasAnyConditions ? "Filters" : null,
+ };
const handleUpdate = useCallback(async () => {
setIsUpdating(true);
- await filter.updateView();
- setTimeout(() => setIsUpdating(false), 240); // To avoid flickering
+ try {
+ await filter.updateView();
+ } finally {
+ setTimeout(() => setIsUpdating(false), 240); // To avoid flickering
+ }
}, [filter]);
- if (!visible) return null;
-
const leftContent = (
<>
{filter.allConditionsForDisplay.map((condition) => (
@@ -52,7 +62,13 @@ export const FiltersRow = observer(
);
- if (variant === "default") {
- return (
-
- {leftContent}
+ const mainContent = (
+
+
{leftContent}
+
{rightContent}
- );
- }
+
+ );
+
+ const ModalVariant = (
+
+ {mainContent}
+
+ );
+
+ const HeaderVariant = (
+
+ );
return (
-
-
-
{leftContent}
-
{rightContent}
-
-
+
+ {variant === "modal" ? ModalVariant : HeaderVariant}
+
);
}
);
diff --git a/apps/web/core/components/rich-filters/filters-toggle.tsx b/apps/web/core/components/rich-filters/filters-toggle.tsx
new file mode 100644
index 000000000..5c5f9d222
--- /dev/null
+++ b/apps/web/core/components/rich-filters/filters-toggle.tsx
@@ -0,0 +1,76 @@
+import { observer } from "mobx-react";
+import { ListFilter } from "lucide-react";
+// plane imports
+import { IFilterInstance } from "@plane/shared-state";
+import { TExternalFilter, TFilterProperty } from "@plane/types";
+import { cn } from "@plane/ui";
+// components
+import { AddFilterButton } from "@/components/rich-filters/add-filters-button";
+
+type TFiltersToggleProps
= {
+ filter: IFilterInstance
| undefined;
+};
+
+const COMMON_CLASSNAME =
+ "grid place-items-center h-7 w-full py-0.5 px-2 rounded border transition-all duration-200 cursor-pointer";
+
+export const FiltersToggle = observer(
+
(props: TFiltersToggleProps
) => {
+ const { filter } = props;
+ // derived values
+ const hasAnyConditions = (filter?.allConditionsForDisplay.length ?? 0) > 0;
+ const isFilterRowVisible = filter?.isVisible ?? false;
+ const hasUpdates = filter?.canUpdateView === true && filter?.hasChanges === true;
+ const showFilterRowChangesPill = hasUpdates || hasAnyConditions === true;
+ const showAddFilterButton = !hasAnyConditions && !isFilterRowVisible && !hasUpdates;
+
+ const handleToggleFilter = () => {
+ if (!filter) {
+ console.error("Filters toggle error - filter instance not available");
+ return;
+ }
+ filter.toggleVisibility();
+ };
+
+ // Show the add filter button when there are no active conditions, the filter row is hidden, and no unsaved changes exist
+ if (filter && showAddFilterButton) {
+ return (
+ filter?.toggleVisibility(true)}
+ />
+ );
+ }
+
+ return (
+
+
+
+ {showFilterRowChangesPill && (
+
+ )}
+
+
+ );
+ }
+);
diff --git a/apps/web/core/components/views/form.tsx b/apps/web/core/components/views/form.tsx
index 7ce906a30..49597f704 100644
--- a/apps/web/core/components/views/form.tsx
+++ b/apps/web/core/components/views/form.tsx
@@ -23,7 +23,7 @@ import { getComputedDisplayFilters, getComputedDisplayProperties, getTabIndex }
// components
import { Logo } from "@/components/common/logo";
import { DisplayFiltersSelection, FiltersDropdown } from "@/components/issues/issue-layouts/filters";
-import { WorkItemFiltersRow } from "@/components/work-item-filters/work-item-filters-row";
+import { WorkItemFiltersRow } from "@/components/work-item-filters/filters-row";
// hooks
import { useProject } from "@/hooks/store/use-project";
import { usePlatformOS } from "@/hooks/use-platform-os";
@@ -265,11 +265,12 @@ export const ProjectViewForm: React.FC = observer((props) => {
isTemporary
updateFilters={(updateFilters) => onFiltersChange(updateFilters)}
projectId={projectId}
+ showOnMount
workspaceSlug={workspaceSlug}
>
{({ filter: projectViewWorkItemsFilter }) =>
projectViewWorkItemsFilter && (
-
+
)
}
diff --git a/apps/web/core/components/work-item-filters/filters-hoc/base.tsx b/apps/web/core/components/work-item-filters/filters-hoc/base.tsx
index 83d01fa80..eff257d04 100644
--- a/apps/web/core/components/work-item-filters/filters-hoc/base.tsx
+++ b/apps/web/core/components/work-item-filters/filters-hoc/base.tsx
@@ -3,8 +3,8 @@ import { observer } from "mobx-react";
import { v4 as uuidv4 } from "uuid";
// plane imports
import { TSaveViewOptions, TUpdateViewOptions } from "@plane/constants";
-import { IFilterInstance } from "@plane/shared-state";
-import { IIssueFilters, TWorkItemFilterExpression, TWorkItemFilterProperty } from "@plane/types";
+import { IWorkItemFilterInstance } from "@plane/shared-state";
+import { IIssueFilters, TWorkItemFilterExpression } from "@plane/types";
// store hooks
import { useWorkItemFilters } from "@/hooks/store/work-item-filters/use-work-item-filters";
// plane web imports
@@ -39,9 +39,7 @@ export const WorkItemFiltersHOC = observer((props: TWorkItemFiltersHOCProps) =>
type TWorkItemFilterProps = TSharedWorkItemFiltersProps &
TAdditionalWorkItemFiltersProps & {
initialWorkItemFilters: IIssueFilters;
- children:
- | React.ReactNode
- | ((props: { filter: IFilterInstance }) => React.ReactNode);
+ children: React.ReactNode | ((props: { filter: IWorkItemFilterInstance }) => React.ReactNode);
};
const WorkItemFilterRoot = observer((props: TWorkItemFilterProps) => {
@@ -55,6 +53,7 @@ const WorkItemFilterRoot = observer((props: TWorkItemFilterProps) => {
saveViewOptions,
updateFilters,
updateViewOptions,
+ showOnMount,
...entityConfigProps
} = props;
// store hooks
@@ -84,6 +83,7 @@ const WorkItemFilterRoot = observer((props: TWorkItemFilterProps) => {
saveViewOptions,
updateViewOptions,
},
+ showOnMount,
});
// delete filter instance when component unmounts
diff --git a/apps/web/core/components/work-item-filters/filters-hoc/shared.ts b/apps/web/core/components/work-item-filters/filters-hoc/shared.ts
index 775dd45fd..5d0c88e34 100644
--- a/apps/web/core/components/work-item-filters/filters-hoc/shared.ts
+++ b/apps/web/core/components/work-item-filters/filters-hoc/shared.ts
@@ -1,6 +1,6 @@
// plane imports
import { TSaveViewOptions, TUpdateViewOptions } from "@plane/constants";
-import { IFilterInstance } from "@plane/shared-state";
+import { IWorkItemFilterInstance } from "@plane/shared-state";
import { EIssuesStoreType, IIssueFilters, TWorkItemFilterExpression, TWorkItemFilterProperty } from "@plane/types";
export type TSharedWorkItemFiltersProps = {
@@ -8,14 +8,11 @@ export type TSharedWorkItemFiltersProps = {
filtersToShowByLayout: TWorkItemFilterProperty[];
updateFilters: (updatedFilters: TWorkItemFilterExpression) => void;
isTemporary?: boolean;
+ showOnMount?: boolean;
} & ({ isTemporary: true; entityId?: string } | { isTemporary?: false; entityId: string }); // entity id (project_id, cycle_id, workspace_id, etc)
export type TSharedWorkItemFiltersHOCProps = TSharedWorkItemFiltersProps & {
- children:
- | React.ReactNode
- | ((props: {
- filter: IFilterInstance | undefined;
- }) => React.ReactNode);
+ children: React.ReactNode | ((props: { filter: IWorkItemFilterInstance | undefined }) => React.ReactNode);
initialWorkItemFilters: IIssueFilters | undefined;
};
diff --git a/apps/web/core/components/work-item-filters/work-item-filters-row.tsx b/apps/web/core/components/work-item-filters/filters-row.tsx
similarity index 74%
rename from apps/web/core/components/work-item-filters/work-item-filters-row.tsx
rename to apps/web/core/components/work-item-filters/filters-row.tsx
index b2fa56e38..6faa061a3 100644
--- a/apps/web/core/components/work-item-filters/work-item-filters-row.tsx
+++ b/apps/web/core/components/work-item-filters/filters-row.tsx
@@ -1,9 +1,12 @@
import { observer } from "mobx-react";
// plane imports
+import { IWorkItemFilterInstance } from "@plane/shared-state";
import { TWorkItemFilterExpression, TWorkItemFilterProperty } from "@plane/types";
// components
import { FiltersRow, TFiltersRowProps } from "@/components/rich-filters/filters-row";
-type TWorkItemFiltersRowProps = TFiltersRowProps;
+type TWorkItemFiltersRowProps = TFiltersRowProps & {
+ filter: IWorkItemFilterInstance;
+};
export const WorkItemFiltersRow = observer((props: TWorkItemFiltersRowProps) => );
diff --git a/apps/web/core/components/work-item-filters/filters-toggle.tsx b/apps/web/core/components/work-item-filters/filters-toggle.tsx
new file mode 100644
index 000000000..1e839333a
--- /dev/null
+++ b/apps/web/core/components/work-item-filters/filters-toggle.tsx
@@ -0,0 +1,22 @@
+import { observer } from "mobx-react";
+// plane imports
+import { EIssuesStoreType } from "@plane/types";
+// components
+import { FiltersToggle } from "@/components/rich-filters/filters-toggle";
+// hooks
+import { useWorkItemFilters } from "@/hooks/store/work-item-filters/use-work-item-filters";
+
+type TWorkItemFiltersToggleProps = {
+ entityType: EIssuesStoreType;
+ entityId: string;
+};
+
+export const WorkItemFiltersToggle = observer((props: TWorkItemFiltersToggleProps) => {
+ const { entityType, entityId } = props;
+ // store hooks
+ const { getFilter } = useWorkItemFilters();
+ // derived values
+ const filter = getFilter(entityType, entityId);
+
+ return ;
+});
diff --git a/apps/web/core/components/workspace/views/form.tsx b/apps/web/core/components/workspace/views/form.tsx
index 9e79404dc..fbb32edc4 100644
--- a/apps/web/core/components/workspace/views/form.tsx
+++ b/apps/web/core/components/workspace/views/form.tsx
@@ -21,7 +21,7 @@ import { getComputedDisplayFilters, getComputedDisplayProperties } from "@plane/
import { DisplayFiltersSelection, FiltersDropdown } from "@/components/issues/issue-layouts/filters";
import { WorkspaceLevelWorkItemFiltersHOC } from "@/components/work-item-filters/filters-hoc/workspace-level";
// plane web imports
-import { WorkItemFiltersRow } from "@/components/work-item-filters/work-item-filters-row";
+import { WorkItemFiltersRow } from "@/components/work-item-filters/filters-row";
import { AccessController } from "@/plane-web/components/views/access-controller";
type Props = {
@@ -176,11 +176,12 @@ export const WorkspaceViewForm: React.FC = observer((props) => {
initialWorkItemFilters={workItemFilters}
isTemporary
updateFilters={(updateFilters) => onFiltersChange(updateFilters)}
+ showOnMount
workspaceSlug={workspaceSlug}
>
{({ filter: workspaceViewWorkItemsFilter }) =>
workspaceViewWorkItemsFilter && (
-
+
)
}
diff --git a/apps/web/core/hooks/store/work-item-filters/use-work-item-filter-instance.ts b/apps/web/core/hooks/store/work-item-filters/use-work-item-filter-instance.ts
index 6d178eaf6..c0d78f003 100644
--- a/apps/web/core/hooks/store/work-item-filters/use-work-item-filter-instance.ts
+++ b/apps/web/core/hooks/store/work-item-filters/use-work-item-filter-instance.ts
@@ -1,13 +1,13 @@
// plane imports
-import { IFilterInstance } from "@plane/shared-state";
-import { EIssuesStoreType, TWorkItemFilterExpression, TWorkItemFilterProperty } from "@plane/types";
+import { IWorkItemFilterInstance } from "@plane/shared-state";
+import { EIssuesStoreType } from "@plane/types";
// local imports
import { useWorkItemFilters } from "./use-work-item-filters";
export const useWorkItemFilterInstance = (
entityType: EIssuesStoreType,
entityId: string
-): IFilterInstance | undefined => {
+): IWorkItemFilterInstance | undefined => {
const { getFilter } = useWorkItemFilters();
return getFilter(entityType, entityId);
};
diff --git a/packages/constants/src/rich-filters/option.ts b/packages/constants/src/rich-filters/option.ts
index 123585787..8230d2f19 100644
--- a/packages/constants/src/rich-filters/option.ts
+++ b/packages/constants/src/rich-filters/option.ts
@@ -52,6 +52,25 @@ export type TExpressionOptions = {
*/
export const DEFAULT_FILTER_EXPRESSION_OPTIONS: TExpressionOptions = {};
+/**
+ * Auto visibility options.
+ */
+export type TAutoVisibilityOptions =
+ | {
+ autoSetVisibility: true;
+ }
+ | {
+ autoSetVisibility: false;
+ isVisibleOnMount: boolean;
+ };
+
+/**
+ * Default filter visibility options.
+ */
+export const DEFAULT_FILTER_VISIBILITY_OPTIONS: TAutoVisibilityOptions = {
+ autoSetVisibility: true,
+};
+
/**
* Filter options.
* - expression: Filter expression options.
@@ -60,4 +79,5 @@ export const DEFAULT_FILTER_EXPRESSION_OPTIONS: TExpressionOptions = {
expression: Partial>;
config: Partial;
+ visibility: TAutoVisibilityOptions;
};
diff --git a/packages/shared-state/src/store/rich-filters/config-manager.ts b/packages/shared-state/src/store/rich-filters/config-manager.ts
index 88b493723..ae62b5fbc 100644
--- a/packages/shared-state/src/store/rich-filters/config-manager.ts
+++ b/packages/shared-state/src/store/rich-filters/config-manager.ts
@@ -58,7 +58,7 @@ export class FilterConfigManager["filterConfigs"];
configOptions: IFilterConfigManager
["configOptions"];
// parent filter instance
- _filterInstance: IFilterInstance
;
+ private _filterInstance: IFilterInstance
;
/**
* Creates a new FilterConfigManager instance.
diff --git a/packages/shared-state/src/store/rich-filters/filter-helpers.ts b/packages/shared-state/src/store/rich-filters/filter-helpers.ts
index 6f7306d4c..c9483408b 100644
--- a/packages/shared-state/src/store/rich-filters/filter-helpers.ts
+++ b/packages/shared-state/src/store/rich-filters/filter-helpers.ts
@@ -1,7 +1,7 @@
import { cloneDeep } from "lodash-es";
-import { toJS } from "mobx";
+import { action, makeObservable, observable, toJS } from "mobx";
// plane imports
-import { DEFAULT_FILTER_EXPRESSION_OPTIONS, TExpressionOptions } from "@plane/constants";
+import { DEFAULT_FILTER_EXPRESSION_OPTIONS, TAutoVisibilityOptions, TExpressionOptions } from "@plane/constants";
import {
IFilterAdapter,
LOGICAL_OPERATOR,
@@ -14,6 +14,12 @@ import {
TFilterConditionPayload,
} from "@plane/types";
import { addAndCondition, createConditionNode, updateNodeInExpression } from "@plane/utils";
+// local imports
+import { type IFilterInstance } from "./filter";
+
+type TFilterInstanceHelperParams
= {
+ adapter: IFilterAdapter
;
+};
/**
* Interface for filter instance helper utilities.
@@ -23,9 +29,13 @@ import { addAndCondition, createConditionNode, updateNodeInExpression } from "@p
* @template E - The external filter type extending TExternalFilter
*/
export interface IFilterInstanceHelper
{
+ isVisible: boolean;
// initialization
initializeExpression: (initialExpression?: E) => TFilterExpression
| null;
initializeExpressionOptions: (expressionOptions?: Partial>) => TExpressionOptions;
+ // visibility
+ setInitialVisibility: (visibilityOption: TAutoVisibilityOptions) => void;
+ toggleVisibility: (isVisible?: boolean) => void;
// condition operations
addConditionToExpression: (
expression: TFilterExpression | null,
@@ -54,15 +64,28 @@ export interface IFilterInstanceHelper
implements IFilterInstanceHelper
{
+ // parent filter instance
+ private _filterInstance: IFilterInstance
;
+ // adapter
private adapter: IFilterAdapter
;
+ // visibility
+ isVisible: boolean;
/**
* Creates a new FilterInstanceHelper instance.
*
* @param adapter - The filter adapter for converting between internal and external formats
*/
- constructor(adapter: IFilterAdapter
) {
- this.adapter = adapter;
+ constructor(filterInstance: IFilterInstance
, params: TFilterInstanceHelperParams
) {
+ this._filterInstance = filterInstance;
+ this.adapter = params.adapter;
+ this.isVisible = false;
+
+ makeObservable(this, {
+ isVisible: observable,
+ setInitialVisibility: action,
+ toggleVisibility: action,
+ });
}
// ------------ initialization ------------
@@ -87,6 +110,41 @@ export class FilterInstanceHelper
["setInitialVisibility"] = action((visibilityOption) => {
+ // If explicit initial visibility is provided, use it
+ if (visibilityOption.autoSetVisibility === false) {
+ this.isVisible = visibilityOption.isVisibleOnMount;
+ return;
+ }
+
+ // If filter has active filters, make it visible
+ if (this._filterInstance.hasActiveFilters) {
+ this.isVisible = true;
+ return;
+ }
+
+ // Default to hidden if no active filters
+ this.isVisible = false;
+ return;
+ });
+
+ /**
+ * Toggles the visibility of the filter.
+ * @param isVisible - The visibility to set.
+ */
+ toggleVisibility: IFilterInstanceHelper
["toggleVisibility"] = action((isVisible) => {
+ if (isVisible !== undefined) {
+ this.isVisible = isVisible;
+ return;
+ }
+ this.isVisible = !this.isVisible;
+ });
+
// ------------ condition operations ------------
/**
diff --git a/packages/shared-state/src/store/rich-filters/filter.ts b/packages/shared-state/src/store/rich-filters/filter.ts
index 67545433c..be13c7f88 100644
--- a/packages/shared-state/src/store/rich-filters/filter.ts
+++ b/packages/shared-state/src/store/rich-filters/filter.ts
@@ -4,6 +4,7 @@ import { computedFn } from "mobx-utils";
import { v4 as uuidv4 } from "uuid";
// plane imports
import {
+ DEFAULT_FILTER_VISIBILITY_OPTIONS,
TClearFilterOptions,
TExpressionOptions,
TFilterOptions,
@@ -71,6 +72,7 @@ export interface IFilterInstance
[];
allConditionsForDisplay: TFilterConditionNodeForDisplay
[];
// computed option helpers
@@ -81,6 +83,8 @@ export interface IFilterInstance
void;
// filter expression actions
resetExpression: (externalExpression: E, shouldResetInitialExpression?: boolean) => void;
// filter condition
@@ -108,7 +112,7 @@ export interface IFilterInstance
>) => void;
}
-export type TFilterParams
= {
+type TFilterParams
= {
adapter: IFilterAdapter
;
options?: Partial>;
initialExpression?: E;
@@ -131,7 +135,9 @@ export class FilterInstance) {
this.id = uuidv4();
this.adapter = params.adapter;
- this.helper = new FilterInstanceHelper
(this.adapter);
+ this.helper = new FilterInstanceHelper
(this, {
+ adapter: this.adapter,
+ });
this.configManager = new FilterConfigManager
(this, {
options: params.options?.config,
});
@@ -141,6 +147,7 @@ export class FilterInstance
["isVisible"] {
+ return this.helper.isVisible;
+ }
+
/**
* Returns all conditions from the filter expression.
* @returns An array of filter conditions.
@@ -279,6 +295,14 @@ export class FilterInstance
["toggleVisibility"] = action((isVisible) => {
+ this.helper.toggleVisibility(isVisible);
+ });
+
/**
* Resets the filter expression to the initial expression.
* @param externalExpression - The external expression to reset to.
diff --git a/packages/shared-state/src/store/work-item-filters/filter.store.ts b/packages/shared-state/src/store/work-item-filters/filter.store.ts
index 6c43b7fbf..e07b9855d 100644
--- a/packages/shared-state/src/store/work-item-filters/filter.store.ts
+++ b/packages/shared-state/src/store/work-item-filters/filter.store.ts
@@ -6,10 +6,12 @@ import { EIssuesStoreType, LOGICAL_OPERATOR, TWorkItemFilterExpression, TWorkIte
import { getOperatorForPayload } from "@plane/utils";
// local imports
import { buildWorkItemFilterExpressionFromConditions, TWorkItemFilterCondition } from "../../utils";
-import { FilterInstance, IFilterInstance } from "../rich-filters/filter";
+import { FilterInstance } from "../rich-filters/filter";
import { workItemFiltersAdapter } from "./adapter";
+import { IWorkItemFilterInstance, TWorkItemFilterKey } from "./shared";
type TGetOrCreateFilterParams = {
+ showOnMount?: boolean;
entityId: string;
entityType: EIssuesStoreType;
expressionOptions?: TExpressionOptions;
@@ -17,17 +19,10 @@ type TGetOrCreateFilterParams = {
onExpressionChange?: (expression: TWorkItemFilterExpression) => void;
};
-type TWorkItemFilterKey = `${EIssuesStoreType}-${string}`;
-
export interface IWorkItemFilterStore {
- filters: Map>; // key is the entity id (project, cycle, workspace, teamspace, etc)
- getFilter: (
- entityType: EIssuesStoreType,
- entityId: string
- ) => IFilterInstance | undefined;
- getOrCreateFilter: (
- params: TGetOrCreateFilterParams
- ) => IFilterInstance;
+ filters: Map; // key is the entity id (project, cycle, workspace, teamspace, etc)
+ getFilter: (entityType: EIssuesStoreType, entityId: string) => IWorkItemFilterInstance | undefined;
+ getOrCreateFilter: (params: TGetOrCreateFilterParams) => IWorkItemFilterInstance;
resetExpression: (entityType: EIssuesStoreType, entityId: string, expression: TWorkItemFilterExpression) => void;
updateFilterExpressionFromConditions: (
entityType: EIssuesStoreType,
@@ -48,7 +43,7 @@ export class WorkItemFilterStore implements IWorkItemFilterStore {
filters: IWorkItemFilterStore["filters"];
constructor() {
- this.filters = new Map>();
+ this.filters = new Map();
makeObservable(this, {
filters: observable,
getOrCreateFilter: action,
@@ -87,12 +82,17 @@ export class WorkItemFilterStore implements IWorkItemFilterStore {
if (params.onExpressionChange) {
existingFilter.onExpressionChange = params.onExpressionChange;
}
+ // Update visibility if provided
+ if (params.showOnMount !== undefined) {
+ existingFilter.toggleVisibility(params.showOnMount);
+ }
return existingFilter;
}
// create new filter instance
const newFilter = this._initializeFilterInstance(params);
- this.filters.set(this._getFilterKey(params.entityType, params.entityId), newFilter);
+ const filterKey = this._getFilterKey(params.entityType, params.entityId);
+ this.filters.set(filterKey, newFilter);
return newFilter;
});
@@ -210,6 +210,9 @@ export class WorkItemFilterStore implements IWorkItemFilterStore {
onExpressionChange: params.onExpressionChange,
options: {
expression: params.expressionOptions,
+ visibility: params.showOnMount
+ ? { autoSetVisibility: false, isVisibleOnMount: true }
+ : { autoSetVisibility: true },
},
});
}
diff --git a/packages/shared-state/src/store/work-item-filters/index.ts b/packages/shared-state/src/store/work-item-filters/index.ts
index e4acf3b74..073c940fe 100644
--- a/packages/shared-state/src/store/work-item-filters/index.ts
+++ b/packages/shared-state/src/store/work-item-filters/index.ts
@@ -1,2 +1,3 @@
export * from "./adapter";
export * from "./filter.store";
+export * from "./shared";
diff --git a/packages/shared-state/src/store/work-item-filters/shared.ts b/packages/shared-state/src/store/work-item-filters/shared.ts
new file mode 100644
index 000000000..c8e9a6a84
--- /dev/null
+++ b/packages/shared-state/src/store/work-item-filters/shared.ts
@@ -0,0 +1,8 @@
+// plane imports
+import { EIssuesStoreType, TWorkItemFilterExpression, TWorkItemFilterProperty } from "@plane/types";
+// local imports
+import { IFilterInstance } from "../rich-filters";
+
+export type TWorkItemFilterKey = `${EIssuesStoreType}-${string}`;
+
+export type IWorkItemFilterInstance = IFilterInstance;