|
| 1 | +import { FilterAPI, WidgetFilterAPI } from "@mendix/widget-plugin-filtering/context"; |
| 2 | +import { CombinedFilter, CombinedFilterConfig } from "@mendix/widget-plugin-filtering/stores/generic/CombinedFilter"; |
| 3 | +import { CustomFilterHost } from "@mendix/widget-plugin-filtering/stores/generic/CustomFilterHost"; |
| 4 | +import { DatasourceController } from "@mendix/widget-plugin-grid/query/DatasourceController"; |
| 5 | +import { QueryController } from "@mendix/widget-plugin-grid/query/query-controller"; |
| 6 | +import { RefreshController } from "@mendix/widget-plugin-grid/query/RefreshController"; |
| 7 | +import { SelectionCountStore } from "@mendix/widget-plugin-grid/selection/stores/SelectionCountStore"; |
| 8 | +import { ClosableGateProvider } from "@mendix/widget-plugin-mobx-kit/ClosableGateProvider"; |
| 9 | +import { GateProvider } from "@mendix/widget-plugin-mobx-kit/GateProvider"; |
| 10 | +import { DerivedPropsGate } from "@mendix/widget-plugin-mobx-kit/props-gate"; |
| 11 | +import { useConst } from "@mendix/widget-plugin-mobx-kit/react/useConst"; |
| 12 | +import { useSetup } from "@mendix/widget-plugin-mobx-kit/react/useSetup"; |
| 13 | +import { ReactiveControllerHost } from "@mendix/widget-plugin-mobx-kit/reactive-controller"; |
| 14 | +import { generateUUID } from "@mendix/widget-plugin-platform/framework/generate-uuid"; |
| 15 | +import { Container, injected, token } from "brandi"; |
| 16 | +import { useEffect } from "react"; |
| 17 | +import { DatagridContainerProps } from "../typings/DatagridProps"; |
| 18 | +import { DatasourceParamsController } from "./controllers/DatasourceParamsController"; |
| 19 | +import { DerivedLoaderController, DerivedLoaderControllerConfig } from "./controllers/DerivedLoaderController"; |
| 20 | +import { PaginationConfig, PaginationController } from "./controllers/PaginationController"; |
| 21 | +import { ProgressStore } from "./features/data-export/ProgressStore"; |
| 22 | +import { ColumnGroupStore } from "./helpers/state/ColumnGroupStore"; |
| 23 | +import { GridBasicData } from "./helpers/state/GridBasicData"; |
| 24 | +import { GridPersonalizationStore } from "./helpers/state/GridPersonalizationStore"; |
| 25 | +import { DatagridSetupService } from "./services/DatagridSetupService"; |
| 26 | +import { StaticInfo } from "./typings/static-info"; |
| 27 | + |
| 28 | +/** Type to declare props available through main gait. */ |
| 29 | +type MainGateProps = Pick< |
| 30 | + DatagridContainerProps, |
| 31 | + | "name" |
| 32 | + | "datasource" |
| 33 | + | "refreshInterval" |
| 34 | + | "refreshIndicator" |
| 35 | + | "itemSelection" |
| 36 | + | "columns" |
| 37 | + | "configurationStorageType" |
| 38 | + | "storeFiltersInPersonalization" |
| 39 | + | "configurationAttribute" |
| 40 | + | "pageSize" |
| 41 | + | "pagination" |
| 42 | + | "showPagingButtons" |
| 43 | + | "showNumberOfRows" |
| 44 | + | "clearSelectionButtonLabel" |
| 45 | +>; |
| 46 | + |
| 47 | +/** Tokens to resolve dependencies from the container. */ |
| 48 | +const TOKENS = { |
| 49 | + basicDate: token<GridBasicData>("GridBasicData"), |
| 50 | + columnsStore: token<ColumnGroupStore>("ColumnGroupStore"), |
| 51 | + combinedFilter: token<CombinedFilter>("CombinedFilter"), |
| 52 | + combinedFilterConfig: token<CombinedFilterConfig>("CombinedFilterKey"), |
| 53 | + exportProgressService: token<ProgressStore>("ExportProgressService"), |
| 54 | + filterAPI: token<FilterAPI>("FilterAPI"), |
| 55 | + filterHost: token<CustomFilterHost>("FilterHost"), |
| 56 | + loaderViewModel: token<DerivedLoaderController>("DatagridLoaderViewModel"), |
| 57 | + loaderConfig: token<DerivedLoaderControllerConfig>("DatagridLoaderConfig"), |
| 58 | + mainGate: token<DerivedPropsGate<MainGateProps>>("MainGateForProps"), |
| 59 | + paginationService: token<PaginationController>("PaginationService"), |
| 60 | + paginationConfig: token<PaginationConfig>("PaginationConfig"), |
| 61 | + paramsService: token<DatasourceParamsController>("DatagridParamsService"), |
| 62 | + parentChannelName: token<string>("parentChannelName"), |
| 63 | + personalizationService: token<GridPersonalizationStore>("GridPersonalizationStore"), |
| 64 | + query: token<QueryController>("QueryService"), |
| 65 | + refreshService: token<RefreshController>("DatagridRefreshService"), |
| 66 | + refreshInterval: token<number>("refreshInterval"), |
| 67 | + selectionCounter: token<SelectionCountStore>("SelectionCountStore"), |
| 68 | + setupService: token<ReactiveControllerHost>("DatagridSetupHost"), |
| 69 | + staticInfo: token<StaticInfo>("StaticInfo") |
| 70 | +}; |
| 71 | + |
| 72 | +/** Root Datagrid container that resolve and inject dependencies. */ |
| 73 | +export const rootContainer = new Container(); |
| 74 | + |
| 75 | +// Class bindings, must be unique per container. |
| 76 | +rootContainer.bind(TOKENS.columnsStore).toInstance(ColumnGroupStore).inContainerScope(); |
| 77 | +rootContainer.bind(TOKENS.combinedFilter).toInstance(CombinedFilter).inContainerScope(); |
| 78 | +rootContainer.bind(TOKENS.exportProgressService).toInstance(ProgressStore).inContainerScope(); |
| 79 | +rootContainer.bind(TOKENS.filterAPI).toInstance(WidgetFilterAPI).inContainerScope(); |
| 80 | +rootContainer.bind(TOKENS.filterHost).toInstance(CustomFilterHost).inContainerScope(); |
| 81 | +rootContainer.bind(TOKENS.query).toInstance(DatasourceController).inContainerScope(); |
| 82 | +rootContainer.bind(TOKENS.refreshService).toInstance(RefreshController).inContainerScope(); |
| 83 | +rootContainer.bind(TOKENS.setupService).toInstance(DatagridSetupService).inContainerScope(); |
| 84 | +rootContainer.bind(TOKENS.paramsService).toInstance(DatasourceParamsController).inContainerScope(); |
| 85 | +rootContainer |
| 86 | + .bind(TOKENS.parentChannelName) |
| 87 | + .toInstance(() => `datagrid/${generateUUID()}`) |
| 88 | + .inContainerScope(); |
| 89 | + |
| 90 | +// Inject dependencies |
| 91 | +injected(SelectionCountStore, TOKENS.mainGate); |
| 92 | +injected(DatasourceController, TOKENS.setupService, TOKENS.mainGate); |
| 93 | +injected(WidgetFilterAPI, TOKENS.parentChannelName, TOKENS.filterHost); |
| 94 | +injected(ColumnGroupStore, TOKENS.mainGate, TOKENS.staticInfo, TOKENS.filterHost); |
| 95 | +injected(DerivedLoaderController, TOKENS.query, TOKENS.exportProgressService, TOKENS.columnsStore, TOKENS.loaderConfig); |
| 96 | +injected(RefreshController, TOKENS.setupService, TOKENS.query, TOKENS.refreshInterval.optional); |
| 97 | +injected(DatasourceParamsController, TOKENS.setupService, TOKENS.query, TOKENS.combinedFilter, TOKENS.columnsStore); |
| 98 | + |
| 99 | +/** Create new container that inherit bindings from root container. */ |
| 100 | +export function createContainer(): Container { |
| 101 | + return new Container().extend(rootContainer); |
| 102 | +} |
| 103 | + |
| 104 | +export function useDatagridDepsContainer(props: DatagridContainerProps): Container { |
| 105 | + const [container, mainGateProvider] = useConst( |
| 106 | + /** Function to clone container and setup prop dependant bindings. */ |
| 107 | + function init(): [Container, GateProvider<MainGateProps>] { |
| 108 | + const container = createContainer(); |
| 109 | + const exportProgress = container.get(TOKENS.exportProgressService); |
| 110 | + const gateProvider = new ClosableGateProvider<MainGateProps>(props, () => exportProgress.exporting); |
| 111 | + |
| 112 | + // Bind main gate |
| 113 | + container.bind(TOKENS.mainGate).toConstant(gateProvider.gate); |
| 114 | + |
| 115 | + // Bind static info |
| 116 | + container.bind(TOKENS.staticInfo).toConstant({ |
| 117 | + name: props.name, |
| 118 | + filtersChannelName: container.get(TOKENS.parentChannelName) |
| 119 | + }); |
| 120 | + |
| 121 | + container.bind(TOKENS.refreshInterval).toConstant(props.refreshInterval * 1000); |
| 122 | + |
| 123 | + // Bind combined filter config |
| 124 | + container.bind(TOKENS.combinedFilterConfig).toConstant({ |
| 125 | + stableKey: props.name, |
| 126 | + inputs: [container.get(TOKENS.filterHost), container.get(TOKENS.columnsStore)] |
| 127 | + }); |
| 128 | + |
| 129 | + // Bind loader config |
| 130 | + container.bind(TOKENS.loaderConfig).toConstant({ |
| 131 | + showSilentRefresh: props.refreshInterval > 1, |
| 132 | + refreshIndicator: props.refreshIndicator |
| 133 | + }); |
| 134 | + |
| 135 | + // Bind pagination config |
| 136 | + container.bind(TOKENS.paginationConfig).toConstant({ |
| 137 | + pagination: props.pagination, |
| 138 | + showPagingButtons: props.showPagingButtons, |
| 139 | + showNumberOfRows: props.showNumberOfRows, |
| 140 | + pageSize: props.pageSize |
| 141 | + }); |
| 142 | + |
| 143 | + // Create internal services |
| 144 | + container.get(TOKENS.refreshService); |
| 145 | + container.get(TOKENS.paramsService); |
| 146 | + |
| 147 | + // Hydrate filters from props |
| 148 | + container.get(TOKENS.combinedFilter).hydrate(props.datasource.filter); |
| 149 | + |
| 150 | + return [container, gateProvider]; |
| 151 | + } |
| 152 | + ); |
| 153 | + |
| 154 | + // Run setup hooks on mount |
| 155 | + useSetup(() => container.get(TOKENS.setupService)); |
| 156 | + |
| 157 | + // Push props through the main gate |
| 158 | + useEffect(() => mainGateProvider.setProps(props)); |
| 159 | + |
| 160 | + return container; |
| 161 | +} |
0 commit comments