;
+ name: string;
+}
+
+type Component = (props: P) => React.ReactElement;
+
+export function withLinkedEnumStore
(Cmp: Component
): Component
{
+ function ProviderHost(props: P & { provider: StoreProvider; channel: string }): React.ReactElement {
+ useSetup(() => props.provider);
+ return ;
+ }
+
+ return function FilterAPIProvider(props) {
+ const api = useEnumStoreProvider(props);
+
+ if (api.hasError) {
+ return {api.error.message};
+ }
+
+ return ;
+ };
+}
+
+function useEnumStoreProvider(props: RequiredProps): Result<{ provider: StoreProvider; channel: string }, APIError> {
+ const filterAPI = useFilterAPI();
+ return useConst(() => {
+ if (filterAPI.hasError) {
+ return error(filterAPI.error);
+ }
+
+ return value({
+ provider: new EnumStoreProvider(filterAPI.value, {
+ attributes: [props.attr],
+ dataKey: props.name
+ }),
+ channel: filterAPI.value.parentChannelName
+ });
+ });
+}
diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx
new file mode 100644
index 0000000000..319d7e48e5
--- /dev/null
+++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx
@@ -0,0 +1,90 @@
+import { useEffect, createElement } from "react";
+import { Alert } from "@mendix/widget-plugin-component-kit/Alert";
+import { RefFilterStore } from "@mendix/widget-plugin-dropdown-filter/stores/RefFilterStore";
+import { FilterAPI, useFilterAPI } from "@mendix/widget-plugin-filtering/context";
+import { BaseStoreProvider } from "@mendix/widget-plugin-filtering/custom-filter-api/BaseStoreProvider";
+import { DerivedPropsGate } from "@mendix/widget-plugin-mobx-kit/props-gate";
+import { GateProvider } from "@mendix/widget-plugin-mobx-kit/GateProvider";
+import { useConst } from "@mendix/widget-plugin-mobx-kit/react/useConst";
+import { ListValue, ListAttributeValue, AssociationMetaData } from "mendix";
+import { DatagridDropdownFilterContainerProps } from "../../typings/DatagridDropdownFilterProps";
+import { useSetup } from "@mendix/widget-plugin-mobx-kit/react/useSetup";
+import { RefFilterAPI } from "../components/typings";
+
+type WidgetProps = Pick;
+
+export interface RequiredProps {
+ name: string;
+ refEntity: AssociationMetaData;
+ refOptions: ListValue;
+ refCaption: ListAttributeValue;
+ searchAttrId: ListAttributeValue["id"];
+}
+
+type Component = (props: P) => React.ReactElement;
+
+export function withLinkedRefStore
(Cmp: Component
): Component
{
+ function StoreProvider(props: P & { filterAPI: FilterAPI }): React.ReactElement {
+ const gate = useGate(props);
+ const provider = useSetup(() => new RefStoreProvider(props.filterAPI, gate));
+ return ;
+ }
+ return function FilterAPIProvider(props) {
+ const api = useFilterAPI();
+
+ if (api.hasError) {
+ return {api.error.message};
+ }
+
+ return ;
+ };
+}
+
+function mapProps(props: WidgetProps): RequiredProps {
+ if (!props.refEntity) {
+ throw new Error("RefFilterStoreProvider: refEntity is required");
+ }
+
+ if (!props.refOptions) {
+ throw new Error("RefFilterStoreProvider: refOptions is required");
+ }
+
+ if (!props.refCaption) {
+ throw new Error("RefFilterStoreProvider: refCaption is required");
+ }
+ return {
+ name: props.name,
+ refEntity: props.refEntity,
+ refOptions: props.refOptions,
+ refCaption: props.refCaption,
+ searchAttrId: props.refCaption.id
+ };
+}
+
+function useGate(props: WidgetProps): DerivedPropsGate {
+ const gp = useConst(() => new GateProvider(mapProps(props)));
+ useEffect(() => {
+ gp.setProps(mapProps(props));
+ });
+ return gp.gate;
+}
+
+class RefStoreProvider extends BaseStoreProvider {
+ protected _store: RefFilterStore;
+ protected filterAPI: FilterAPI;
+ readonly dataKey: string;
+
+ constructor(filterAPI: FilterAPI, gate: DerivedPropsGate) {
+ super();
+ this.filterAPI = filterAPI;
+ this.dataKey = gate.props.name;
+ this._store = new RefFilterStore({
+ gate,
+ initCond: this.findInitFilter(filterAPI.sharedInitFilter, this.dataKey)
+ });
+ }
+
+ get store(): RefFilterStore {
+ return this._store;
+ }
+}
diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withParentProvidedEnumStore.tsx b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withParentProvidedEnumStore.tsx
new file mode 100644
index 0000000000..d6cec1c09d
--- /dev/null
+++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withParentProvidedEnumStore.tsx
@@ -0,0 +1,48 @@
+import { Alert } from "@mendix/widget-plugin-component-kit/Alert";
+import { useRef, createElement } from "react";
+import { useFilterAPI } from "@mendix/widget-plugin-filtering/context";
+import { APIError, EMISSINGSTORE, EStoreTypeMisMatch } from "@mendix/widget-plugin-filtering/errors";
+import { Result, error, value } from "@mendix/widget-plugin-filtering/result-meta";
+import { EnumFilterAPI } from "../components/typings";
+
+export function withParentProvidedEnumStore(
+ Component: (props: P & EnumFilterAPI) => React.ReactElement
+): (props: P) => React.ReactElement {
+ return function FilterAPIProvider(props: P): React.ReactElement {
+ const api = useEnumFilterAPI();
+ if (api.hasError) {
+ return {api.error.message};
+ }
+
+ return (
+
+ );
+ };
+}
+
+function useEnumFilterAPI(): Result {
+ const ctx = useFilterAPI();
+ const slctAPI = useRef();
+
+ if (ctx.hasError) {
+ return error(ctx.error);
+ }
+
+ const api = ctx.value;
+
+ if (api.provider.hasError) {
+ return error(api.provider.error);
+ }
+
+ const store = api.provider.value.type === "direct" ? api.provider.value.store : null;
+
+ if (store === null) {
+ return error(EMISSINGSTORE);
+ }
+
+ if (store.storeType !== "select") {
+ return error(EStoreTypeMisMatch("dropdown filter", store.arg1.type));
+ }
+
+ return value((slctAPI.current ??= { filterStore: store, parentChannelName: api.parentChannelName }));
+}
diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withSelectFilterAPI.tsx b/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withSelectFilterAPI.tsx
deleted file mode 100644
index f8f6a74f88..0000000000
--- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withSelectFilterAPI.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Alert } from "@mendix/widget-plugin-component-kit/Alert";
-import { Select_FilterAPIv2, useSelectFilterAPI } from "@mendix/widget-plugin-filtering/helpers/useSelectFilterAPI";
-import { createElement } from "react";
-
-export { Select_FilterAPIv2 };
-
-export function withSelectFilterAPI(
- Component: (props: P & Select_FilterAPIv2) => React.ReactElement
-): (props: P) => React.ReactElement {
- return function FilterAPIProvider(props: P): React.ReactElement {
- const api = useSelectFilterAPI(props);
- if (api.hasError) {
- return {api.error.message};
- }
-
- return (
-
- );
- };
-}
diff --git a/packages/pluggableWidgets/datagrid-dropdown-filter-web/typings/DatagridDropdownFilterProps.d.ts b/packages/pluggableWidgets/datagrid-dropdown-filter-web/typings/DatagridDropdownFilterProps.d.ts
index c1c4cd5e41..a443bd6589 100644
--- a/packages/pluggableWidgets/datagrid-dropdown-filter-web/typings/DatagridDropdownFilterProps.d.ts
+++ b/packages/pluggableWidgets/datagrid-dropdown-filter-web/typings/DatagridDropdownFilterProps.d.ts
@@ -4,7 +4,11 @@
* @author Mendix Widgets Framework Team
*/
import { CSSProperties } from "react";
-import { ActionValue, DynamicValue, EditableValue } from "mendix";
+import { ActionValue, AssociationMetaData, AttributeMetaData, DynamicValue, EditableValue, ListValue, ListAttributeValue } from "mendix";
+
+export type BaseTypeEnum = "attr" | "ref";
+
+export type AttrChoiceEnum = "auto" | "linked";
export interface FilterOptionsType {
caption: DynamicValue;
@@ -25,9 +29,16 @@ export interface DatagridDropdownFilterContainerProps {
class: string;
style?: CSSProperties;
tabIndex?: number;
+ baseType: BaseTypeEnum;
+ attrChoice: AttrChoiceEnum;
+ attr: AttributeMetaData;
auto: boolean;
- defaultValue?: DynamicValue;
filterOptions: FilterOptionsType[];
+ refEntity: AssociationMetaData;
+ refOptions?: ListValue;
+ refCaption?: ListAttributeValue;
+ fetchOptionsLazy: boolean;
+ defaultValue?: DynamicValue;
filterable: boolean;
multiSelect: boolean;
emptyOptionCaption?: DynamicValue;
@@ -50,9 +61,16 @@ export interface DatagridDropdownFilterPreviewProps {
readOnly: boolean;
renderMode: "design" | "xray" | "structure";
translate: (text: string) => string;
+ baseType: BaseTypeEnum;
+ attrChoice: AttrChoiceEnum;
+ attr: string;
auto: boolean;
- defaultValue: string;
filterOptions: FilterOptionsPreviewType[];
+ refEntity: string;
+ refOptions: {} | { caption: string } | { type: string } | null;
+ refCaption: string;
+ fetchOptionsLazy: boolean;
+ defaultValue: string;
filterable: boolean;
multiSelect: boolean;
emptyOptionCaption: string;
diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts
index bdf7464d68..21e05df9e6 100644
--- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts
+++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts
@@ -74,21 +74,6 @@ export function getProperties(
"hidable"
]);
}
-
- if (!column.filterAssociation) {
- hideNestedPropertiesIn(defaultProperties, values, "columns", index, [
- "filterAssociationOptions",
- "filterAssociationOptionLabel",
- "fetchOptionsLazy",
- "filterCaptionType",
- "filterAssociationOptionLabelAttr"
- ]);
- }
- if (column.filterCaptionType === "attribute") {
- hidePropertyIn(defaultProperties, values, "columns", index, "filterAssociationOptionLabel");
- } else {
- hidePropertyIn(defaultProperties, values, "columns", index, "filterAssociationOptionLabelAttr");
- }
});
if (values.pagination === "buttons") {
hidePropertyIn(defaultProperties, values, "showNumberOfRows");
@@ -209,11 +194,6 @@ export const getPreview = (
draggable: false,
dynamicText: "Dynamic text",
filter: { widgetCount: 0, renderer: () => null },
- filterAssociation: "",
- filterAssociationOptionLabel: "",
- filterAssociationOptionLabelAttr: "",
- filterAssociationOptions: {},
- filterCaptionType: "attribute",
header: "Column",
hidable: "no",
resizable: false,
@@ -227,8 +207,7 @@ export const getPreview = (
minWidth: "auto",
minWidthLimit: 100,
allowEventPropagation: true,
- exportValue: "",
- fetchOptionsLazy: true
+ exportValue: ""
}
];
const columns = rowLayout({
diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx
index 1bef235a15..ba1df3f098 100644
--- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx
+++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.editorPreview.tsx
@@ -35,11 +35,7 @@ const initColumns: ColumnsPreviewType[] = [
draggable: false,
dynamicText: "Dynamic Text",
filter: { renderer: () => , widgetCount: 0 },
- filterAssociation: "",
- filterAssociationOptionLabel: "",
- filterAssociationOptionLabelAttr: "",
- filterAssociationOptions: {},
- filterCaptionType: "expression",
+
header: "Column",
hidable: "no",
resizable: false,
@@ -53,8 +49,7 @@ const initColumns: ColumnsPreviewType[] = [
minWidth: "auto",
minWidthLimit: 100,
allowEventPropagation: true,
- exportValue: "",
- fetchOptionsLazy: true
+ exportValue: ""
}
];
diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.tsx b/packages/pluggableWidgets/datagrid-web/src/Datagrid.tsx
index 0178fe3ea8..018b3a94d4 100644
--- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.tsx
+++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.tsx
@@ -82,7 +82,7 @@ const Container = observer((props: Props): ReactElement => {
headerTitle={props.filterSectionTitle?.value}
headerContent={
props.filtersPlaceholder && (
-
+
{props.filtersPlaceholder}
)
diff --git a/packages/pluggableWidgets/datagrid-web/src/Datagrid.xml b/packages/pluggableWidgets/datagrid-web/src/Datagrid.xml
index 3f00e78f9c..92e6bd9e90 100644
--- a/packages/pluggableWidgets/datagrid-web/src/Datagrid.xml
+++ b/packages/pluggableWidgets/datagrid-web/src/Datagrid.xml
@@ -121,44 +121,6 @@