[WEB-5099] improvement: enhance rich filters with new components and configurations (#7916)
* feat: enhance rich filters with new components and configurations - Added `AdditionalFilterValueInput` for unsupported filter types. - Introduced `FilterItem` and related components for better filter item management. - Updated filter configurations to include new properties and support for multiple values. - Improved loading states and error handling in filter components. - Refactored existing filter logic to streamline operations and enhance performance. * Refactor rich filters component structure and enhance filter item functionality - Moved AddFilterButton and AddFilterDropdown to a new directory structure for better organization. - Updated FilterItemProperty to handle filter selection and condition updates more effectively. - Enhanced the FilterInstance class with methods to update condition properties and operators, improving filter management. - Added new functionality to handle invalid filter states and improve user feedback. * [WEB-5111] feat: add 'created_at' and 'updated_at' filters to work item configuration - Introduced new filter configurations for 'created_at' and 'updated_at' in the work item filters. - Updated relevant components to utilize these new filters, enhancing filtering capabilities. - Added corresponding filter configuration functions in the utils for better date handling. * fix: build
This commit is contained in:
parent
9f41e92d21
commit
cfb4a8212c
49 changed files with 854 additions and 247 deletions
|
|
@ -14,6 +14,7 @@ export * from "./file";
|
|||
export * from "./filter";
|
||||
export * from "./get-icon-for-link";
|
||||
export * from "./intake";
|
||||
export * from "./loader";
|
||||
export * from "./math";
|
||||
export * from "./module";
|
||||
export * from "./notification";
|
||||
|
|
|
|||
4
packages/utils/src/loader.ts
Normal file
4
packages/utils/src/loader.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import { TLoader } from "@plane/types";
|
||||
|
||||
// checks if a loader has finished initialization
|
||||
export const isLoaderReady = (loader: TLoader | undefined) => loader !== "init-loader";
|
||||
|
|
@ -1,2 +1,3 @@
|
|||
export * from "./core";
|
||||
export * from "./shared";
|
||||
export * from "./properties";
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
// plane imports
|
||||
import { TFilterProperty } from "@plane/types";
|
||||
// local imports
|
||||
import { createFilterConfig, TCreateDateFilterParams, TCreateFilterConfig } from "../shared";
|
||||
import { getSupportedDateOperators, TCustomPropertyFilterParams } from "./shared";
|
||||
|
||||
/**
|
||||
* Date property filter specific params
|
||||
*/
|
||||
export type TCreateDatePropertyFilterParams = TCustomPropertyFilterParams<Date> & TCreateDateFilterParams;
|
||||
|
||||
/**
|
||||
* Get the date property filter config
|
||||
* @param params - The filter params
|
||||
* @returns The date property filter config
|
||||
*/
|
||||
export const getDatePropertyFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDatePropertyFilterParams> =>
|
||||
(params: TCreateDatePropertyFilterParams) =>
|
||||
createFilterConfig({
|
||||
id: key,
|
||||
...params,
|
||||
label: params.propertyDisplayName,
|
||||
icon: params.filterIcon,
|
||||
allowMultipleFilters: true,
|
||||
supportedOperatorConfigsMap: getSupportedDateOperators(params),
|
||||
});
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export * from "./date";
|
||||
export * from "./member-picker";
|
||||
export * from "./shared";
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// plane imports
|
||||
import { EQUALITY_OPERATOR, IUserLite, TFilterProperty } from "@plane/types";
|
||||
// local imports
|
||||
import { createFilterConfig, createOperatorConfigEntry, TCreateFilterConfig } from "../shared";
|
||||
import { getMemberMultiSelectConfig, TCreateUserFilterParams, TCustomPropertyFilterParams } from "./shared";
|
||||
|
||||
/**
|
||||
* Member picker property filter specific params
|
||||
*/
|
||||
type TCreateMemberPickerPropertyFilterParams = TCustomPropertyFilterParams<IUserLite> & TCreateUserFilterParams;
|
||||
|
||||
/**
|
||||
* Get the member picker property filter config
|
||||
* @param params - The filter params
|
||||
* @returns The member picker property filter config
|
||||
*/
|
||||
export const getMemberPickerPropertyFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateMemberPickerPropertyFilterParams> =>
|
||||
(params: TCreateMemberPickerPropertyFilterParams) =>
|
||||
createFilterConfig({
|
||||
id: key,
|
||||
...params,
|
||||
label: params.propertyDisplayName,
|
||||
icon: params.filterIcon,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(EQUALITY_OPERATOR.EXACT, params, (updatedParams) =>
|
||||
getMemberMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
// plane imports
|
||||
import {
|
||||
COMPARISON_OPERATOR,
|
||||
EQUALITY_OPERATOR,
|
||||
IProject,
|
||||
IUserLite,
|
||||
TOperatorConfigMap,
|
||||
TSupportedOperators,
|
||||
} from "@plane/types";
|
||||
// local imports
|
||||
import { getDatePickerConfig, getDateRangePickerConfig, getMultiSelectConfig } from "../core";
|
||||
import {
|
||||
createOperatorConfigEntry,
|
||||
IFilterIconConfig,
|
||||
TCreateDateFilterParams,
|
||||
TCreateFilterConfigParams,
|
||||
} from "../shared";
|
||||
|
||||
// ------------ Base User Filter Types ------------
|
||||
|
||||
/**
|
||||
* User filter specific params
|
||||
*/
|
||||
export type TCreateUserFilterParams = TCreateFilterConfigParams &
|
||||
IFilterIconConfig<IUserLite> & {
|
||||
members: IUserLite[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to get the member multi select config
|
||||
* @param params - The filter params
|
||||
* @returns The member multi select config
|
||||
*/
|
||||
export const getMemberMultiSelectConfig = (params: TCreateUserFilterParams, singleValueOperator: TSupportedOperators) =>
|
||||
getMultiSelectConfig<IUserLite, string, IUserLite>(
|
||||
{
|
||||
items: params.members,
|
||||
getId: (member) => member.id,
|
||||
getLabel: (member) => member.display_name,
|
||||
getValue: (member) => member.id,
|
||||
getIconData: (member) => member,
|
||||
},
|
||||
{
|
||||
singleValueOperator,
|
||||
...params,
|
||||
},
|
||||
{
|
||||
...params,
|
||||
}
|
||||
);
|
||||
|
||||
// ------------ Date Operators ------------
|
||||
|
||||
export const getSupportedDateOperators = (params: TCreateDateFilterParams): TOperatorConfigMap<Date> =>
|
||||
new Map([
|
||||
createOperatorConfigEntry(EQUALITY_OPERATOR.EXACT, params, (updatedParams) => getDatePickerConfig(updatedParams)),
|
||||
createOperatorConfigEntry(COMPARISON_OPERATOR.RANGE, params, (updatedParams) =>
|
||||
getDateRangePickerConfig(updatedParams)
|
||||
),
|
||||
]);
|
||||
|
||||
// ------------ Project filter ------------
|
||||
|
||||
/**
|
||||
* Project filter specific params
|
||||
*/
|
||||
export type TCreateProjectFilterParams = TCreateFilterConfigParams &
|
||||
IFilterIconConfig<IProject> & {
|
||||
projects: IProject[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to get the project multi select config
|
||||
* @param params - The filter params
|
||||
* @returns The member multi select config
|
||||
*/
|
||||
export const getProjectMultiSelectConfig = (
|
||||
params: TCreateProjectFilterParams,
|
||||
singleValueOperator: TSupportedOperators
|
||||
) =>
|
||||
getMultiSelectConfig<IProject, string, IProject>(
|
||||
{
|
||||
items: params.projects,
|
||||
getId: (project) => project.id,
|
||||
getLabel: (project) => project.name,
|
||||
getValue: (project) => project.id,
|
||||
getIconData: (project) => project,
|
||||
},
|
||||
{
|
||||
singleValueOperator,
|
||||
...params,
|
||||
},
|
||||
{
|
||||
...params,
|
||||
}
|
||||
);
|
||||
|
|
@ -29,14 +29,21 @@ export const createFilterConfig = <P extends TFilterProperty, V extends TFilterV
|
|||
export type TCreateFilterConfigParams = Omit<TBaseFilterFieldConfig, "isOperatorEnabled"> & {
|
||||
isEnabled: boolean;
|
||||
allowedOperators: Set<TSupportedOperators>;
|
||||
rightContent?: React.ReactNode; // content to display on the right side of the filter option in the dropdown
|
||||
tooltipContent?: React.ReactNode; // content to display when hovering over the applied filter item in the filter list
|
||||
};
|
||||
|
||||
/**
|
||||
* Type for filter icon type
|
||||
*/
|
||||
export type TFilterIconType = string | number | boolean | object | undefined;
|
||||
|
||||
/**
|
||||
* Icon configuration for filters and their options.
|
||||
* - filterIcon: Optional icon for the filter
|
||||
* - getOptionIcon: Function to get icon for specific option values
|
||||
*/
|
||||
export interface IFilterIconConfig<T extends string | number | boolean | object | undefined = undefined> {
|
||||
export interface IFilterIconConfig<T extends TFilterIconType = undefined> {
|
||||
filterIcon?: React.FC<React.SVGAttributes<SVGElement>>;
|
||||
getOptionIcon?: (value: T) => React.ReactNode;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
export * from "./configs/core";
|
||||
export * from "./configs/shared";
|
||||
export * from "./configs/properties";
|
||||
export * from "./nodes/core";
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ export const getCycleFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Cycle",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getCycleMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
// plane imports
|
||||
import { TFilterProperty } from "@plane/types";
|
||||
// local imports
|
||||
import { createFilterConfig, TCreateFilterConfig, TCreateDateFilterParams } from "../../../rich-filters";
|
||||
import { getSupportedDateOperators } from "./shared";
|
||||
import {
|
||||
createFilterConfig,
|
||||
TCreateFilterConfig,
|
||||
TCreateDateFilterParams,
|
||||
getSupportedDateOperators,
|
||||
} from "../../../rich-filters";
|
||||
|
||||
// ------------ Date filters ------------
|
||||
|
||||
|
|
@ -18,8 +22,8 @@ export const getStartDateFilterConfig =
|
|||
createFilterConfig<P, Date>({
|
||||
id: key,
|
||||
label: "Start date",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
allowMultipleFilters: true,
|
||||
supportedOperatorConfigsMap: getSupportedDateOperators(params),
|
||||
});
|
||||
|
|
@ -36,8 +40,44 @@ export const getTargetDateFilterConfig =
|
|||
createFilterConfig<P, Date>({
|
||||
id: key,
|
||||
label: "Target date",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
allowMultipleFilters: true,
|
||||
supportedOperatorConfigsMap: getSupportedDateOperators(params),
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the created at filter config
|
||||
* @template K - The filter key
|
||||
* @param key - The filter key to use
|
||||
* @returns A function that takes parameters and returns the created at filter config
|
||||
*/
|
||||
export const getCreatedAtFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
id: key,
|
||||
label: "Created at",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
allowMultipleFilters: true,
|
||||
supportedOperatorConfigsMap: getSupportedDateOperators(params),
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the updated at filter config
|
||||
* @template K - The filter key
|
||||
* @param key - The filter key to use
|
||||
* @returns A function that takes parameters and returns the updated at filter config
|
||||
*/
|
||||
export const getUpdatedAtFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
id: key,
|
||||
label: "Updated at",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
allowMultipleFilters: true,
|
||||
supportedOperatorConfigsMap: getSupportedDateOperators(params),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ export const getLabelFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Label",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getLabelMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ export const getModuleFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Module",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getModuleMultiSelectConfig(updatedParams)
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ export const getPriorityFilterConfig =
|
|||
createFilterConfig<P, TIssuePriorities>({
|
||||
id: key,
|
||||
label: "Priority",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getPriorityMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
// plane imports
|
||||
import { EQUALITY_OPERATOR, TFilterProperty, COLLECTION_OPERATOR } from "@plane/types";
|
||||
// local imports
|
||||
import { createFilterConfig, createOperatorConfigEntry, TCreateFilterConfig } from "../../../rich-filters";
|
||||
import { getProjectMultiSelectConfig, TCreateProjectFilterParams } from "./shared";
|
||||
import {
|
||||
createFilterConfig,
|
||||
createOperatorConfigEntry,
|
||||
getProjectMultiSelectConfig,
|
||||
TCreateFilterConfig,
|
||||
TCreateProjectFilterParams,
|
||||
} from "../../../rich-filters";
|
||||
|
||||
// ------------ Project filter ------------
|
||||
|
||||
|
|
@ -18,8 +23,8 @@ export const getProjectFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Projects",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getProjectMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
|
|
|
|||
|
|
@ -63,8 +63,8 @@ export const getStateGroupFilterConfig =
|
|||
createFilterConfig<P, TStateGroups>({
|
||||
id: key,
|
||||
label: "State Group",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getStateGroupMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
|
|
@ -87,7 +87,7 @@ export type TCreateStateFilterParams = TCreateFilterConfigParams &
|
|||
* @param params - The filter params
|
||||
* @returns The state multi select config
|
||||
*/
|
||||
export const getStateMultiSelectConfig = (params: TCreateStateFilterParams) =>
|
||||
export const getStateMultiSelectConfig = (params: TCreateStateFilterParams, singleValueOperator: TSupportedOperators) =>
|
||||
getMultiSelectConfig<IState, string, IState>(
|
||||
{
|
||||
items: params.states,
|
||||
|
|
@ -97,7 +97,7 @@ export const getStateMultiSelectConfig = (params: TCreateStateFilterParams) =>
|
|||
getIconData: (state) => state,
|
||||
},
|
||||
{
|
||||
singleValueOperator: EQUALITY_OPERATOR.EXACT,
|
||||
singleValueOperator,
|
||||
...params,
|
||||
},
|
||||
{
|
||||
|
|
@ -117,11 +117,11 @@ export const getStateFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "State",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getStateMultiSelectConfig(updatedParams)
|
||||
getStateMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,48 +1,14 @@
|
|||
// plane imports
|
||||
import { EQUALITY_OPERATOR, IUserLite, TFilterProperty, COLLECTION_OPERATOR } from "@plane/types";
|
||||
import { EQUALITY_OPERATOR, TFilterProperty, COLLECTION_OPERATOR } from "@plane/types";
|
||||
// local imports
|
||||
import {
|
||||
createFilterConfig,
|
||||
TCreateFilterConfigParams,
|
||||
IFilterIconConfig,
|
||||
TCreateFilterConfig,
|
||||
getMultiSelectConfig,
|
||||
createOperatorConfigEntry,
|
||||
getMemberMultiSelectConfig,
|
||||
TCreateUserFilterParams,
|
||||
} from "../../../rich-filters";
|
||||
|
||||
// ------------ Base User Filter Types ------------
|
||||
|
||||
/**
|
||||
* User filter specific params
|
||||
*/
|
||||
export type TCreateUserFilterParams = TCreateFilterConfigParams &
|
||||
IFilterIconConfig<IUserLite> & {
|
||||
members: IUserLite[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to get the member multi select config
|
||||
* @param params - The filter params
|
||||
* @returns The member multi select config
|
||||
*/
|
||||
export const getMemberMultiSelectConfig = (params: TCreateUserFilterParams) =>
|
||||
getMultiSelectConfig<IUserLite, string, IUserLite>(
|
||||
{
|
||||
items: params.members,
|
||||
getId: (member) => member.id,
|
||||
getLabel: (member) => member.display_name,
|
||||
getValue: (member) => member.id,
|
||||
getIconData: (member) => member,
|
||||
},
|
||||
{
|
||||
singleValueOperator: EQUALITY_OPERATOR.EXACT,
|
||||
...params,
|
||||
},
|
||||
{
|
||||
...params,
|
||||
}
|
||||
);
|
||||
|
||||
// ------------ Assignee filter ------------
|
||||
|
||||
/**
|
||||
|
|
@ -62,11 +28,11 @@ export const getAssigneeFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Assignees",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getMemberMultiSelectConfig(updatedParams)
|
||||
getMemberMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
@ -90,11 +56,11 @@ export const getMentionFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Mentions",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getMemberMultiSelectConfig(updatedParams)
|
||||
getMemberMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
@ -118,11 +84,11 @@ export const getCreatedByFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Created by",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getMemberMultiSelectConfig(updatedParams)
|
||||
getMemberMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
@ -146,11 +112,11 @@ export const getSubscriberFilterConfig =
|
|||
createFilterConfig<P, string>({
|
||||
id: key,
|
||||
label: "Subscriber",
|
||||
...params,
|
||||
icon: params.filterIcon,
|
||||
isEnabled: params.isEnabled,
|
||||
supportedOperatorConfigsMap: new Map([
|
||||
createOperatorConfigEntry(COLLECTION_OPERATOR.IN, params, (updatedParams) =>
|
||||
getMemberMultiSelectConfig(updatedParams)
|
||||
getMemberMultiSelectConfig(updatedParams, EQUALITY_OPERATOR.EXACT)
|
||||
),
|
||||
]),
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue