[WEB-5804] refactor: decouple filter value types from filter configurations (#8441)
* [WEB-5804] refactor: decouple filter value types from filter configurations Remove value type constraints from filter configurations to support operator-specific value types. Different operators can accept different value types for the same filter property, so value types should be determined at the operator level rather than the filter level. - Remove generic value type parameter from TFilterConfig - Update TOperatorConfigMap to accept union of all value types - Simplify filter config factory signatures across all filter types - Add forceUpdate parameter to updateConditionValue method * refactor: remove filter value type constraints from filter configurations Eliminate the generic value type parameter from filter configurations to allow for operator-specific value types. This change enhances flexibility by enabling different operators to accept various value types for the same filter property. - Updated TFilterConfig and related interfaces to remove value type constraints - Adjusted filter configuration methods and types accordingly - Refactored date operator support to align with the new structure
This commit is contained in:
parent
5499e49b72
commit
f04be48f61
20 changed files with 126 additions and 133 deletions
|
|
@ -1,8 +1,9 @@
|
|||
import { useCallback, useMemo } from "react";
|
||||
import { AtSign, Briefcase, Calendar } from "lucide-react";
|
||||
import { AtSign, Briefcase } from "lucide-react";
|
||||
// plane imports
|
||||
import { Logo } from "@plane/propel/emoji-icon-picker";
|
||||
import {
|
||||
CalendarLayoutIcon,
|
||||
CycleGroupIcon,
|
||||
CycleIcon,
|
||||
ModuleIcon,
|
||||
|
|
@ -21,7 +22,6 @@ import type {
|
|||
IState,
|
||||
IUserLite,
|
||||
TFilterConfig,
|
||||
TFilterValue,
|
||||
IIssueLabel,
|
||||
IModule,
|
||||
IProject,
|
||||
|
|
@ -74,9 +74,9 @@ export type TUseWorkItemFiltersConfigProps = {
|
|||
|
||||
export type TWorkItemFiltersConfig = {
|
||||
areAllConfigsInitialized: boolean;
|
||||
configs: TFilterConfig<TWorkItemFilterProperty, TFilterValue>[];
|
||||
configs: TFilterConfig<TWorkItemFilterProperty>[];
|
||||
configMap: {
|
||||
[key in TWorkItemFilterProperty]?: TFilterConfig<TWorkItemFilterProperty, TFilterValue>;
|
||||
[key in TWorkItemFilterProperty]?: TFilterConfig<TWorkItemFilterProperty>;
|
||||
};
|
||||
isFilterEnabled: (key: TWorkItemFilterProperty) => boolean;
|
||||
members: IUserLite[];
|
||||
|
|
@ -326,7 +326,7 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps):
|
|||
() =>
|
||||
getCreatedAtFilterConfig<TWorkItemFilterProperty>("created_at")({
|
||||
isEnabled: true,
|
||||
filterIcon: Calendar,
|
||||
filterIcon: CalendarLayoutIcon,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
|
|
@ -337,7 +337,7 @@ export const useWorkItemFiltersConfig = (props: TUseWorkItemFiltersConfigProps):
|
|||
() =>
|
||||
getUpdatedAtFilterConfig<TWorkItemFilterProperty>("updated_at")({
|
||||
isEnabled: true,
|
||||
filterIcon: Calendar,
|
||||
filterIcon: CalendarLayoutIcon,
|
||||
...operatorConfigs,
|
||||
}),
|
||||
[operatorConfigs]
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { computedFn } from "mobx-utils";
|
|||
// plane imports
|
||||
import type { TConfigOptions } from "@plane/constants";
|
||||
import { DEFAULT_FILTER_CONFIG_OPTIONS } from "@plane/constants";
|
||||
import type { TExternalFilter, TFilterConfig, TFilterProperty, TFilterValue } from "@plane/types";
|
||||
import type { TExternalFilter, TFilterConfig, TFilterProperty } from "@plane/types";
|
||||
// local imports
|
||||
import type { IFilterConfig } from "./config";
|
||||
import { FilterConfig } from "./config";
|
||||
|
|
@ -24,17 +24,17 @@ import type { IFilterInstance } from "./filter";
|
|||
*/
|
||||
export interface IFilterConfigManager<P extends TFilterProperty> {
|
||||
// observables
|
||||
filterConfigs: Map<P, IFilterConfig<P, TFilterValue>>; // filter property -> config
|
||||
filterConfigs: Map<P, IFilterConfig<P>>; // filter property -> config
|
||||
configOptions: TConfigOptions;
|
||||
areConfigsReady: boolean;
|
||||
// computed
|
||||
allAvailableConfigs: IFilterConfig<P, TFilterValue>[];
|
||||
allAvailableConfigs: IFilterConfig<P>[];
|
||||
// computed functions
|
||||
getConfigByProperty: (property: P) => IFilterConfig<P, TFilterValue> | undefined;
|
||||
getConfigByProperty: (property: P) => IFilterConfig<P> | undefined;
|
||||
// helpers
|
||||
register: <C extends TFilterConfig<P, TFilterValue>>(config: C) => void;
|
||||
registerAll: (configs: TFilterConfig<P, TFilterValue>[]) => void;
|
||||
updateConfigByProperty: (property: P, configUpdates: Partial<TFilterConfig<P, TFilterValue>>) => void;
|
||||
register: <C extends TFilterConfig<P>>(config: C) => void;
|
||||
registerAll: (configs: TFilterConfig<P>[]) => void;
|
||||
updateConfigByProperty: (property: P, configUpdates: Partial<TFilterConfig<P>>) => void;
|
||||
setAreConfigsReady: (value: boolean) => void;
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ export class FilterConfigManager<
|
|||
* @returns The config for the property, or undefined if not found.
|
||||
*/
|
||||
getConfigByProperty: IFilterConfigManager<P>["getConfigByProperty"] = computedFn(
|
||||
(property) => this.filterConfigs.get(property) as IFilterConfig<P, TFilterValue>
|
||||
(property) => this.filterConfigs.get(property) as IFilterConfig<P>
|
||||
);
|
||||
|
||||
// ------------ helpers ------------
|
||||
|
|
@ -165,7 +165,7 @@ export class FilterConfigManager<
|
|||
|
||||
// ------------ private computed ------------
|
||||
|
||||
private get _allConfigs(): IFilterConfig<P, TFilterValue>[] {
|
||||
private get _allConfigs(): IFilterConfig<P>[] {
|
||||
return Array.from(this.filterConfigs.values());
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +173,7 @@ export class FilterConfigManager<
|
|||
* Returns all enabled filterConfigs.
|
||||
* @returns All enabled filterConfigs.
|
||||
*/
|
||||
private get _allEnabledConfigs(): IFilterConfig<P, TFilterValue>[] {
|
||||
private get _allEnabledConfigs(): IFilterConfig<P>[] {
|
||||
return this._allConfigs.filter((config) => config.isEnabled);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,41 +25,35 @@ type TOperatorOptionForDisplay = {
|
|||
label: string;
|
||||
};
|
||||
|
||||
export interface IFilterConfig<P extends TFilterProperty, V extends TFilterValue = TFilterValue> extends TFilterConfig<
|
||||
P,
|
||||
V
|
||||
> {
|
||||
export interface IFilterConfig<P extends TFilterProperty> extends TFilterConfig<P> {
|
||||
// computed
|
||||
allEnabledSupportedOperators: TSupportedOperators[];
|
||||
firstOperator: TSupportedOperators | undefined;
|
||||
// computed functions
|
||||
getOperatorConfig: (
|
||||
operator: TAllAvailableOperatorsForDisplay
|
||||
) => TOperatorSpecificConfigs<V>[keyof TOperatorSpecificConfigs<V>] | undefined;
|
||||
) => TOperatorSpecificConfigs[keyof TOperatorSpecificConfigs] | undefined;
|
||||
getLabelForOperator: (operator: TAllAvailableOperatorsForDisplay | undefined) => string;
|
||||
getDisplayOperatorByValue: <T extends TSupportedOperators>(operator: T, value: V) => T;
|
||||
getAllDisplayOperatorOptionsByValue: (value: V) => TOperatorOptionForDisplay[];
|
||||
getDisplayOperatorByValue: <T extends TSupportedOperators>(operator: T, value: TFilterValue) => T;
|
||||
getAllDisplayOperatorOptionsByValue: (value: TFilterValue) => TOperatorOptionForDisplay[];
|
||||
// actions
|
||||
mutate: (updates: Partial<TFilterConfig<P, V>>) => void;
|
||||
mutate: (updates: Partial<TFilterConfig<P>>) => void;
|
||||
}
|
||||
|
||||
export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TFilterValue> implements IFilterConfig<
|
||||
P,
|
||||
V
|
||||
> {
|
||||
export class FilterConfig<P extends TFilterProperty> implements IFilterConfig<P> {
|
||||
// observables
|
||||
id: IFilterConfig<P, V>["id"];
|
||||
label: IFilterConfig<P, V>["label"];
|
||||
icon?: IFilterConfig<P, V>["icon"];
|
||||
isEnabled: IFilterConfig<P, V>["isEnabled"];
|
||||
supportedOperatorConfigsMap: IFilterConfig<P, V>["supportedOperatorConfigsMap"];
|
||||
allowMultipleFilters: IFilterConfig<P, V>["allowMultipleFilters"];
|
||||
id: IFilterConfig<P>["id"];
|
||||
label: IFilterConfig<P>["label"];
|
||||
icon?: IFilterConfig<P>["icon"];
|
||||
isEnabled: IFilterConfig<P>["isEnabled"];
|
||||
supportedOperatorConfigsMap: IFilterConfig<P>["supportedOperatorConfigsMap"];
|
||||
allowMultipleFilters: IFilterConfig<P>["allowMultipleFilters"];
|
||||
|
||||
/**
|
||||
* Creates a new FilterConfig instance.
|
||||
* @param params - The parameters for the filter config.
|
||||
*/
|
||||
constructor(params: TFilterConfig<P, V>) {
|
||||
constructor(params: TFilterConfig<P>) {
|
||||
this.id = params.id;
|
||||
this.label = params.label;
|
||||
this.icon = params.icon;
|
||||
|
|
@ -88,7 +82,7 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* Returns all supported operators.
|
||||
* @returns All supported operators.
|
||||
*/
|
||||
get allEnabledSupportedOperators(): IFilterConfig<P, V>["allEnabledSupportedOperators"] {
|
||||
get allEnabledSupportedOperators(): IFilterConfig<P>["allEnabledSupportedOperators"] {
|
||||
return Array.from(this.supportedOperatorConfigsMap.entries())
|
||||
.filter(([, operatorConfig]) => operatorConfig.isOperatorEnabled)
|
||||
.map(([operator]) => operator);
|
||||
|
|
@ -98,7 +92,7 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* Returns the first operator.
|
||||
* @returns The first operator.
|
||||
*/
|
||||
get firstOperator(): IFilterConfig<P, V>["firstOperator"] {
|
||||
get firstOperator(): IFilterConfig<P>["firstOperator"] {
|
||||
return this.allEnabledSupportedOperators[0];
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +103,7 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* @param operator - The operator.
|
||||
* @returns The operator config.
|
||||
*/
|
||||
getOperatorConfig: IFilterConfig<P, V>["getOperatorConfig"] = computedFn((operator) =>
|
||||
getOperatorConfig: IFilterConfig<P>["getOperatorConfig"] = computedFn((operator) =>
|
||||
this.supportedOperatorConfigsMap.get(getOperatorForPayload(operator).operator)
|
||||
);
|
||||
|
||||
|
|
@ -118,7 +112,7 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* @param operator - The operator.
|
||||
* @returns The label for the operator.
|
||||
*/
|
||||
getLabelForOperator: IFilterConfig<P, V>["getLabelForOperator"] = computedFn((operator) => {
|
||||
getLabelForOperator: IFilterConfig<P>["getLabelForOperator"] = computedFn((operator) => {
|
||||
if (!operator) return EMPTY_OPERATOR_LABEL;
|
||||
|
||||
const operatorConfig = this.getOperatorConfig(operator);
|
||||
|
|
@ -139,7 +133,7 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* @param value - The value.
|
||||
* @returns The operator for the value.
|
||||
*/
|
||||
getDisplayOperatorByValue: IFilterConfig<P, V>["getDisplayOperatorByValue"] = computedFn((operator, value) => {
|
||||
getDisplayOperatorByValue: IFilterConfig<P>["getDisplayOperatorByValue"] = computedFn((operator, value) => {
|
||||
const operatorConfig = this.getOperatorConfig(operator);
|
||||
if (operatorConfig?.type === FILTER_FIELD_TYPE.MULTI_SELECT && (Array.isArray(value) ? value.length : 0) <= 1) {
|
||||
return operatorConfig.singleValueOperator as typeof operator;
|
||||
|
|
@ -155,28 +149,26 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* @param value - The current filter value used to determine the appropriate operator variant
|
||||
* @returns Array of operator options with their display labels and values
|
||||
*/
|
||||
getAllDisplayOperatorOptionsByValue: IFilterConfig<P, V>["getAllDisplayOperatorOptionsByValue"] = computedFn(
|
||||
(value) => {
|
||||
const operatorOptions: TOperatorOptionForDisplay[] = [];
|
||||
getAllDisplayOperatorOptionsByValue: IFilterConfig<P>["getAllDisplayOperatorOptionsByValue"] = computedFn((value) => {
|
||||
const operatorOptions: TOperatorOptionForDisplay[] = [];
|
||||
|
||||
// Process each supported operator to build display options
|
||||
for (const operator of this.allEnabledSupportedOperators) {
|
||||
const displayOperator = this.getDisplayOperatorByValue(operator, value);
|
||||
const displayOperatorLabel = this.getLabelForOperator(displayOperator);
|
||||
operatorOptions.push({
|
||||
value: operator,
|
||||
label: displayOperatorLabel,
|
||||
});
|
||||
// Process each supported operator to build display options
|
||||
for (const operator of this.allEnabledSupportedOperators) {
|
||||
const displayOperator = this.getDisplayOperatorByValue(operator, value);
|
||||
const displayOperatorLabel = this.getLabelForOperator(displayOperator);
|
||||
operatorOptions.push({
|
||||
value: operator,
|
||||
label: displayOperatorLabel,
|
||||
});
|
||||
|
||||
const additionalOperatorOption = this._getAdditionalOperatorOptions(operator, value);
|
||||
if (additionalOperatorOption) {
|
||||
operatorOptions.push(additionalOperatorOption);
|
||||
}
|
||||
const additionalOperatorOption = this._getAdditionalOperatorOptions(operator, value);
|
||||
if (additionalOperatorOption) {
|
||||
operatorOptions.push(additionalOperatorOption);
|
||||
}
|
||||
|
||||
return operatorOptions;
|
||||
}
|
||||
);
|
||||
|
||||
return operatorOptions;
|
||||
});
|
||||
|
||||
// ------------ actions ------------
|
||||
|
||||
|
|
@ -184,11 +176,11 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
* Mutates the config.
|
||||
* @param updates - The updates to apply to the config.
|
||||
*/
|
||||
mutate: IFilterConfig<P, V>["mutate"] = action((updates) => {
|
||||
mutate: IFilterConfig<P>["mutate"] = action((updates) => {
|
||||
runInAction(() => {
|
||||
for (const key in updates) {
|
||||
if (updates.hasOwnProperty(key)) {
|
||||
const configKey = key as keyof TFilterConfig<P, V>;
|
||||
const configKey = key as keyof TFilterConfig<P>;
|
||||
set(this, configKey, updates[configKey]);
|
||||
}
|
||||
}
|
||||
|
|
@ -199,6 +191,6 @@ export class FilterConfig<P extends TFilterProperty, V extends TFilterValue = TF
|
|||
|
||||
private _getAdditionalOperatorOptions = (
|
||||
_operator: TSupportedOperators,
|
||||
_value: V
|
||||
_value: TFilterValue
|
||||
): TOperatorOptionForDisplay | undefined => undefined;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,11 @@ export interface IFilterInstance<P extends TFilterProperty, E extends TExternalF
|
|||
isNegation: boolean
|
||||
) => void;
|
||||
updateConditionOperator: (conditionId: string, operator: TSupportedOperators, isNegation: boolean) => void;
|
||||
updateConditionValue: <V extends TFilterValue>(conditionId: string, value: SingleOrArray<V>) => void;
|
||||
updateConditionValue: <V extends TFilterValue>(
|
||||
conditionId: string,
|
||||
value: SingleOrArray<V>,
|
||||
forceUpdate?: boolean
|
||||
) => void;
|
||||
removeCondition: (conditionId: string) => void;
|
||||
// config actions
|
||||
clearFilters: () => Promise<void>;
|
||||
|
|
@ -439,9 +443,10 @@ export class FilterInstance<P extends TFilterProperty, E extends TExternalFilter
|
|||
* Updates the value of a condition in the filter expression with automatic optimization.
|
||||
* @param conditionId - The id of the condition to update.
|
||||
* @param value - The new value for the condition.
|
||||
* @param forceUpdate - Whether to force the update even if the value is the same as the condition before update.
|
||||
*/
|
||||
updateConditionValue: IFilterInstance<P, E>["updateConditionValue"] = action(
|
||||
<V extends TFilterValue>(conditionId: string, value: SingleOrArray<V>) => {
|
||||
<V extends TFilterValue>(conditionId: string, value: SingleOrArray<V>, forceUpdate: boolean = false) => {
|
||||
// If the expression is not valid, return
|
||||
if (!this.expression) return;
|
||||
|
||||
|
|
@ -458,7 +463,7 @@ export class FilterInstance<P extends TFilterProperty, E extends TExternalFilter
|
|||
}
|
||||
|
||||
// If the value is the same as the condition before update, return
|
||||
if (isEqual(conditionBeforeUpdate.value, value)) {
|
||||
if (!forceUpdate && isEqual(conditionBeforeUpdate.value, value)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import type { TFilterProperty, TFilterValue } from "../expression";
|
||||
import type { TFilterProperty } from "../expression";
|
||||
import type { TOperatorConfigMap } from "../operator-configs";
|
||||
|
||||
/**
|
||||
|
|
@ -8,13 +8,13 @@ import type { TOperatorConfigMap } from "../operator-configs";
|
|||
* @template P - Property key type (e.g., 'state_id', 'priority', 'assignee')
|
||||
* @template V - Value type for the filter
|
||||
*/
|
||||
export type TFilterConfig<P extends TFilterProperty, V extends TFilterValue = TFilterValue> = {
|
||||
export type TFilterConfig<P extends TFilterProperty> = {
|
||||
id: P;
|
||||
label: string;
|
||||
icon?: React.FC<React.SVGAttributes<SVGElement>>;
|
||||
isEnabled: boolean;
|
||||
allowMultipleFilters?: boolean;
|
||||
supportedOperatorConfigsMap: TOperatorConfigMap<V>;
|
||||
supportedOperatorConfigsMap: TOperatorConfigMap;
|
||||
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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -14,23 +14,23 @@ import type { TFilterOperatorHelper } from "./shared";
|
|||
* Union type representing all core operators that support single date filter types.
|
||||
*/
|
||||
export type TCoreSupportedSingleDateFilterOperators<V extends TFilterValue = TFilterValue> = {
|
||||
[K in keyof TCoreOperatorSpecificConfigs<V>]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs<V>,
|
||||
[K in keyof TCoreOperatorSpecificConfigs]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs,
|
||||
K,
|
||||
TDateFilterFieldConfig<V>
|
||||
>;
|
||||
}[keyof TCoreOperatorSpecificConfigs<V>];
|
||||
}[keyof TCoreOperatorSpecificConfigs];
|
||||
|
||||
/**
|
||||
* Union type representing all core operators that support range date filter types.
|
||||
*/
|
||||
export type TCoreSupportedRangeDateFilterOperators<V extends TFilterValue = TFilterValue> = {
|
||||
[K in keyof TCoreOperatorSpecificConfigs<V>]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs<V>,
|
||||
[K in keyof TCoreOperatorSpecificConfigs]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs,
|
||||
K,
|
||||
TDateRangeFilterFieldConfig<V>
|
||||
>;
|
||||
}[keyof TCoreOperatorSpecificConfigs<V>];
|
||||
}[keyof TCoreOperatorSpecificConfigs];
|
||||
|
||||
/**
|
||||
* Union type representing all core operators that support date filter types.
|
||||
|
|
@ -48,23 +48,23 @@ export type TCoreAllAvailableDateFilterOperatorsForDisplay<V extends TFilterValu
|
|||
* Union type representing all core operators that support single select filter types.
|
||||
*/
|
||||
export type TCoreSupportedSingleSelectFilterOperators<V extends TFilterValue = TFilterValue> = {
|
||||
[K in keyof TCoreOperatorSpecificConfigs<V>]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs<V>,
|
||||
[K in keyof TCoreOperatorSpecificConfigs]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs,
|
||||
K,
|
||||
TSingleSelectFilterFieldConfig<V>
|
||||
>;
|
||||
}[keyof TCoreOperatorSpecificConfigs<V>];
|
||||
}[keyof TCoreOperatorSpecificConfigs];
|
||||
|
||||
/**
|
||||
* Union type representing all core operators that support multi select filter types.
|
||||
*/
|
||||
export type TCoreSupportedMultiSelectFilterOperators<V extends TFilterValue = TFilterValue> = {
|
||||
[K in keyof TCoreOperatorSpecificConfigs<V>]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs<V>,
|
||||
[K in keyof TCoreOperatorSpecificConfigs]: TFilterOperatorHelper<
|
||||
TCoreOperatorSpecificConfigs,
|
||||
K,
|
||||
TMultiSelectFilterFieldConfig<V>
|
||||
>;
|
||||
}[keyof TCoreOperatorSpecificConfigs<V>];
|
||||
}[keyof TCoreOperatorSpecificConfigs];
|
||||
|
||||
/**
|
||||
* Union type representing all core operators that support any select filter types.
|
||||
|
|
|
|||
|
|
@ -8,19 +8,19 @@ import type {
|
|||
import type { CORE_COLLECTION_OPERATOR, CORE_COMPARISON_OPERATOR, CORE_EQUALITY_OPERATOR } from "../operators";
|
||||
|
||||
// ----------------------------- EXACT Operator -----------------------------
|
||||
export type TCoreExactOperatorConfigs<V extends TFilterValue> =
|
||||
| TSingleSelectFilterFieldConfig<V>
|
||||
| TDateFilterFieldConfig<V>;
|
||||
export type TCoreExactOperatorConfigs =
|
||||
| TSingleSelectFilterFieldConfig<TFilterValue>
|
||||
| TDateFilterFieldConfig<TFilterValue>;
|
||||
|
||||
// ----------------------------- IN Operator -----------------------------
|
||||
export type TCoreInOperatorConfigs<V extends TFilterValue> = TMultiSelectFilterFieldConfig<V>;
|
||||
export type TCoreInOperatorConfigs = TMultiSelectFilterFieldConfig<TFilterValue>;
|
||||
|
||||
// ----------------------------- RANGE Operator -----------------------------
|
||||
export type TCoreRangeOperatorConfigs<V extends TFilterValue> = TDateRangeFilterFieldConfig<V>;
|
||||
export type TCoreRangeOperatorConfigs = TDateRangeFilterFieldConfig<TFilterValue>;
|
||||
|
||||
// ----------------------------- Core Operator Specific Configs -----------------------------
|
||||
export type TCoreOperatorSpecificConfigs<V extends TFilterValue> = {
|
||||
[CORE_EQUALITY_OPERATOR.EXACT]: TCoreExactOperatorConfigs<V>;
|
||||
[CORE_COLLECTION_OPERATOR.IN]: TCoreInOperatorConfigs<V>;
|
||||
[CORE_COMPARISON_OPERATOR.RANGE]: TCoreRangeOperatorConfigs<V>;
|
||||
export type TCoreOperatorSpecificConfigs = {
|
||||
[CORE_EQUALITY_OPERATOR.EXACT]: TCoreExactOperatorConfigs;
|
||||
[CORE_COLLECTION_OPERATOR.IN]: TCoreInOperatorConfigs;
|
||||
[CORE_COMPARISON_OPERATOR.RANGE]: TCoreRangeOperatorConfigs;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import type { TFilterValue } from "../expression";
|
||||
|
||||
// ----------------------------- EXACT Operator -----------------------------
|
||||
export type TExtendedExactOperatorConfigs<_V extends TFilterValue> = never;
|
||||
export type TExtendedExactOperatorConfigs = never;
|
||||
|
||||
// ----------------------------- IN Operator -----------------------------
|
||||
export type TExtendedInOperatorConfigs<_V extends TFilterValue> = never;
|
||||
export type TExtendedInOperatorConfigs = never;
|
||||
|
||||
// ----------------------------- RANGE Operator -----------------------------
|
||||
export type TExtendedRangeOperatorConfigs<_V extends TFilterValue> = never;
|
||||
export type TExtendedRangeOperatorConfigs = never;
|
||||
|
||||
// ----------------------------- Extended Operator Specific Configs -----------------------------
|
||||
export type TExtendedOperatorSpecificConfigs<_V extends TFilterValue> = unknown;
|
||||
export type TExtendedOperatorSpecificConfigs = unknown;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import type { TFilterValue } from "../expression";
|
||||
import type { EQUALITY_OPERATOR, COLLECTION_OPERATOR, COMPARISON_OPERATOR } from "../operators";
|
||||
import type { TCoreExactOperatorConfigs, TCoreInOperatorConfigs, TCoreRangeOperatorConfigs } from "./core";
|
||||
import type {
|
||||
|
|
@ -13,21 +12,17 @@ import type {
|
|||
/**
|
||||
* EXACT operator - combines core and extended configurations
|
||||
*/
|
||||
export type TExactOperatorConfigs<V extends TFilterValue> =
|
||||
| TCoreExactOperatorConfigs<V>
|
||||
| TExtendedExactOperatorConfigs<V>;
|
||||
export type TExactOperatorConfigs = TCoreExactOperatorConfigs | TExtendedExactOperatorConfigs;
|
||||
|
||||
/**
|
||||
* IN operator - combines core and extended configurations
|
||||
*/
|
||||
export type TInOperatorConfigs<V extends TFilterValue> = TCoreInOperatorConfigs<V> | TExtendedInOperatorConfigs<V>;
|
||||
export type TInOperatorConfigs = TCoreInOperatorConfigs | TExtendedInOperatorConfigs;
|
||||
|
||||
/**
|
||||
* RANGE operator - combines core and extended configurations
|
||||
*/
|
||||
export type TRangeOperatorConfigs<V extends TFilterValue> =
|
||||
| TCoreRangeOperatorConfigs<V>
|
||||
| TExtendedRangeOperatorConfigs<V>;
|
||||
export type TRangeOperatorConfigs = TCoreRangeOperatorConfigs | TExtendedRangeOperatorConfigs;
|
||||
|
||||
// ----------------------------- Final Operator Specific Configs -----------------------------
|
||||
|
||||
|
|
@ -35,19 +30,19 @@ export type TRangeOperatorConfigs<V extends TFilterValue> =
|
|||
* Type-safe mapping of specific operators to their supported filter type configurations.
|
||||
* Each operator maps to its composed (core + extended) configurations.
|
||||
*/
|
||||
export type TOperatorSpecificConfigs<V extends TFilterValue> = {
|
||||
[EQUALITY_OPERATOR.EXACT]: TExactOperatorConfigs<V>;
|
||||
[COLLECTION_OPERATOR.IN]: TInOperatorConfigs<V>;
|
||||
[COMPARISON_OPERATOR.RANGE]: TRangeOperatorConfigs<V>;
|
||||
} & TExtendedOperatorSpecificConfigs<V>;
|
||||
export type TOperatorSpecificConfigs = {
|
||||
[EQUALITY_OPERATOR.EXACT]: TExactOperatorConfigs;
|
||||
[COLLECTION_OPERATOR.IN]: TInOperatorConfigs;
|
||||
[COMPARISON_OPERATOR.RANGE]: TRangeOperatorConfigs;
|
||||
} & TExtendedOperatorSpecificConfigs;
|
||||
|
||||
/**
|
||||
* Operator filter configuration mapping - for different operators.
|
||||
* Provides type-safe mapping of operators to their specific supported configurations.
|
||||
*/
|
||||
export type TOperatorConfigMap<V extends TFilterValue> = Map<
|
||||
keyof TOperatorSpecificConfigs<V>,
|
||||
TOperatorSpecificConfigs<V>[keyof TOperatorSpecificConfigs<V>]
|
||||
export type TOperatorConfigMap = Map<
|
||||
keyof TOperatorSpecificConfigs,
|
||||
TOperatorSpecificConfigs[keyof TOperatorSpecificConfigs]
|
||||
>;
|
||||
|
||||
// -------- RE-EXPORTS --------
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export const getMemberMultiSelectConfig = (params: TCreateUserFilterParams, sing
|
|||
|
||||
// ------------ Date Operators ------------
|
||||
|
||||
export const getSupportedDateOperators = (params: TCreateDateFilterParams): TOperatorConfigMap<Date> =>
|
||||
export const getSupportedDateOperators = (params: TCreateDateFilterParams): TOperatorConfigMap =>
|
||||
new Map([
|
||||
createOperatorConfigEntry(EQUALITY_OPERATOR.EXACT, params, (updatedParams) => getDatePickerConfig(updatedParams)),
|
||||
createOperatorConfigEntry(COMPARISON_OPERATOR.RANGE, params, (updatedParams) =>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import type {
|
|||
TSingleSelectFilterFieldConfig,
|
||||
TSupportedFilterFieldConfigs,
|
||||
TSupportedOperators,
|
||||
TOperatorSpecificConfigs,
|
||||
} from "@plane/types";
|
||||
|
||||
/**
|
||||
|
|
@ -18,9 +19,7 @@ import type {
|
|||
* @param config - The filter config to create
|
||||
* @returns The created filter config
|
||||
*/
|
||||
export const createFilterConfig = <P extends TFilterProperty, V extends TFilterValue>(
|
||||
config: TFilterConfig<P, V>
|
||||
): TFilterConfig<P, V> => config;
|
||||
export const createFilterConfig = <P extends TFilterProperty>(config: TFilterConfig<P>): TFilterConfig<P> => config;
|
||||
|
||||
/**
|
||||
* Base parameters for filter type config factory functions.
|
||||
|
|
@ -56,16 +55,20 @@ export type TCreateDateFilterParams = TCreateFilterConfigParams & IFilterIconCon
|
|||
/**
|
||||
* Helper to create an operator entry for the supported operators map.
|
||||
* This ensures consistency between the operator key and the operator passed to the config function.
|
||||
* Returns a type compatible with TOperatorSpecificConfigs so Map constructor accepts union types.
|
||||
* @param operator - The operator to use as both key and parameter
|
||||
* @param createParams - The base filter configuration parameters
|
||||
* @param configFn - Function that creates the operator config using base configuration
|
||||
* @returns A tuple of operator and its config
|
||||
* @returns A tuple of operator and its config, typed to be compatible with operator configs map
|
||||
*/
|
||||
export const createOperatorConfigEntry = <T, P extends TCreateFilterConfigParams>(
|
||||
export const createOperatorConfigEntry = <
|
||||
T extends TOperatorSpecificConfigs[keyof TOperatorSpecificConfigs],
|
||||
P extends TCreateFilterConfigParams,
|
||||
>(
|
||||
operator: TSupportedOperators,
|
||||
createParams: P,
|
||||
configFn: (updatedParams: P) => T
|
||||
): [TSupportedOperators, T] => [
|
||||
): [TSupportedOperators, TOperatorSpecificConfigs[keyof TOperatorSpecificConfigs]] => [
|
||||
operator,
|
||||
configFn({ isOperatorEnabled: createParams.allowedOperators.has(operator), ...createParams }),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export const getCycleMultiSelectConfig = (params: TCreateCycleFilterParams, sing
|
|||
export const getCycleFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateCycleFilterParams> =>
|
||||
(params: TCreateCycleFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Cycle",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { createFilterConfig, getSupportedDateOperators } from "../../../rich-fil
|
|||
export const getStartDateFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Start date",
|
||||
...params,
|
||||
|
|
@ -33,7 +33,7 @@ export const getStartDateFilterConfig =
|
|||
export const getTargetDateFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Target date",
|
||||
...params,
|
||||
|
|
@ -51,7 +51,7 @@ export const getTargetDateFilterConfig =
|
|||
export const getCreatedAtFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Created at",
|
||||
...params,
|
||||
|
|
@ -69,7 +69,7 @@ export const getCreatedAtFilterConfig =
|
|||
export const getUpdatedAtFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateDateFilterParams> =>
|
||||
(params: TCreateDateFilterParams) =>
|
||||
createFilterConfig<P, Date>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Updated at",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export const getLabelMultiSelectConfig = (params: TCreateLabelFilterParams, sing
|
|||
export const getLabelFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateLabelFilterParams> =>
|
||||
(params: TCreateLabelFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Label",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export const getModuleMultiSelectConfig = (params: TCreateModuleFilterParams) =>
|
|||
export const getModuleFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateModuleFilterParams> =>
|
||||
(params: TCreateModuleFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Module",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ export const getPriorityMultiSelectConfig = (
|
|||
export const getPriorityFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreatePriorityFilterParams> =>
|
||||
(params: TCreatePriorityFilterParams) =>
|
||||
createFilterConfig<P, TIssuePriorities>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Priority",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import { createFilterConfig, createOperatorConfigEntry, getProjectMultiSelectCon
|
|||
export const getProjectFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateProjectFilterParams> =>
|
||||
(params: TCreateProjectFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Projects",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import {
|
|||
|
||||
// ------------ Date filter ------------
|
||||
|
||||
export const getSupportedDateOperators = (params: TCreateDateFilterParams): TOperatorConfigMap<Date> =>
|
||||
export const getSupportedDateOperators = (params: TCreateDateFilterParams): TOperatorConfigMap =>
|
||||
new Map([
|
||||
createOperatorConfigEntry(EQUALITY_OPERATOR.EXACT, params, (updatedParams) => getDatePickerConfig(updatedParams)),
|
||||
createOperatorConfigEntry(COMPARISON_OPERATOR.RANGE, params, (updatedParams) =>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export const getStateGroupMultiSelectConfig = (
|
|||
export const getStateGroupFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateStateGroupFilterParams> =>
|
||||
(params: TCreateStateGroupFilterParams) =>
|
||||
createFilterConfig<P, TStateGroups>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "State Group",
|
||||
...params,
|
||||
|
|
@ -102,7 +102,7 @@ export const getStateMultiSelectConfig = (params: TCreateStateFilterParams, sing
|
|||
export const getStateFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateStateFilterParams> =>
|
||||
(params: TCreateStateFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "State",
|
||||
...params,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export type TCreateAssigneeFilterParams = TCreateUserFilterParams;
|
|||
export const getAssigneeFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateAssigneeFilterParams> =>
|
||||
(params: TCreateAssigneeFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Assignees",
|
||||
...params,
|
||||
|
|
@ -49,7 +49,7 @@ export type TCreateMentionFilterParams = TCreateUserFilterParams;
|
|||
export const getMentionFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateMentionFilterParams> =>
|
||||
(params: TCreateMentionFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Mentions",
|
||||
...params,
|
||||
|
|
@ -77,7 +77,7 @@ export type TCreateCreatedByFilterParams = TCreateUserFilterParams;
|
|||
export const getCreatedByFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateCreatedByFilterParams> =>
|
||||
(params: TCreateCreatedByFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Created by",
|
||||
...params,
|
||||
|
|
@ -105,7 +105,7 @@ export type TCreateSubscriberFilterParams = TCreateUserFilterParams;
|
|||
export const getSubscriberFilterConfig =
|
||||
<P extends TFilterProperty>(key: P): TCreateFilterConfig<P, TCreateSubscriberFilterParams> =>
|
||||
(params: TCreateSubscriberFilterParams) =>
|
||||
createFilterConfig<P, string>({
|
||||
createFilterConfig<P>({
|
||||
id: key,
|
||||
label: "Subscriber",
|
||||
...params,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue