Skip to content

Commit a799e34

Browse files
committed
feat: add select all service
1 parent 3dfaca3 commit a799e34

File tree

16 files changed

+563
-304
lines changed

16 files changed

+563
-304
lines changed

packages/pluggableWidgets/datagrid-web/src/Datagrid.depsContainer.ts

Lines changed: 70 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import { CombinedFilter, CombinedFilterConfig } from "@mendix/widget-plugin-filt
33
import { CustomFilterHost } from "@mendix/widget-plugin-filtering/stores/generic/CustomFilterHost";
44
import {
55
DatasourceService,
6+
ProgressService,
67
QueryService,
7-
RefreshController,
8-
SelectionCounterViewModel
8+
SelectAllService,
9+
SelectionCounterViewModel,
10+
TaskProgressService
911
} from "@mendix/widget-plugin-grid/main";
1012
import { ClosableGateProvider } from "@mendix/widget-plugin-mobx-kit/ClosableGateProvider";
1113
import { GateProvider } from "@mendix/widget-plugin-mobx-kit/GateProvider";
@@ -14,13 +16,12 @@ import { useConst } from "@mendix/widget-plugin-mobx-kit/react/useConst";
1416
import { useSetup } from "@mendix/widget-plugin-mobx-kit/react/useSetup";
1517

1618
import { generateUUID } from "@mendix/widget-plugin-platform/framework/generate-uuid";
17-
import { Container, injected, token } from "brandi";
19+
import { Container, DependencyModule, injected, token } from "brandi";
1820
import { useEffect } from "react";
1921
import { DatagridContainerProps, SelectionCounterPositionEnum } from "../typings/DatagridProps";
2022
import { DatasourceParamsController } from "./controllers/DatasourceParamsController";
2123
import { DerivedLoaderController, DerivedLoaderControllerConfig } from "./controllers/DerivedLoaderController";
2224
import { PaginationConfig, PaginationController } from "./controllers/PaginationController";
23-
import { ProgressStore } from "./features/data-export/ProgressStore";
2425
import { ColumnGroupStore } from "./helpers/state/ColumnGroupStore";
2526
import { GridBasicData } from "./helpers/state/GridBasicData";
2627
import { GridPersonalizationStore } from "./helpers/state/GridPersonalizationStore";
@@ -46,16 +47,13 @@ type MainGateProps = Pick<
4647
| "clearSelectionButtonLabel"
4748
>;
4849

49-
/** Root Datagrid container that resolve and inject dependencies. */
50-
export const rootContainer = new Container();
51-
5250
/** Tokens to resolve dependencies from the container. */
5351
export const TOKENS = {
5452
basicDate: token<GridBasicData>("GridBasicData"),
5553
columnsStore: token<ColumnGroupStore>("ColumnGroupStore"),
5654
combinedFilter: token<CombinedFilter>("CombinedFilter"),
5755
combinedFilterConfig: token<CombinedFilterConfig>("CombinedFilterKey"),
58-
exportProgressService: token<ProgressStore>("ExportProgressService"),
56+
exportProgressService: token<TaskProgressService>("ExportProgressService"),
5957
filterAPI: token<FilterAPI>("FilterAPI"),
6058
filterHost: token<CustomFilterHost>("FilterHost"),
6159
loaderConfig: token<DerivedLoaderControllerConfig>("DatagridLoaderConfig"),
@@ -68,102 +66,120 @@ export const TOKENS = {
6866
personalizationService: token<GridPersonalizationStore>("GridPersonalizationStore"),
6967
query: token<QueryService>("QueryService"),
7068
refreshInterval: token<number>("refreshInterval"),
71-
refreshService: token<RefreshController>("DatagridRefreshService"),
7269
selectionCounter: token<SelectionCounterViewModel>("SelectionCounterViewModel"),
7370
selectionCounterPosition: token<SelectionCounterPositionEnum>("SelectionCounterPositionEnum"),
7471
setupService: token<SetupComponentHost>("DatagridSetupHost"),
75-
staticInfo: token<StaticInfo>("StaticInfo")
72+
staticInfo: token<StaticInfo>("StaticInfo"),
73+
selectAllProgressService: token<TaskProgressService>("SelectAllProgressService"),
74+
selectAllGate: token<DerivedPropsGate<SelectAllGateProps>>("SelectAllGateForProps"),
75+
selectAllQuery: token<QueryService>("SelectAllQueryService"),
76+
SelectAllService: token<SelectAllService>("SelectAllService")
7677
};
7778

79+
/** Deps injections */
80+
injected(ColumnGroupStore, TOKENS.setupService, TOKENS.mainGate, TOKENS.staticInfo, TOKENS.filterHost);
81+
injected(GridBasicData, TOKENS.mainGate);
82+
injected(CombinedFilter, TOKENS.setupService, TOKENS.combinedFilterConfig);
83+
injected(WidgetFilterAPI, TOKENS.parentChannelName, TOKENS.filterHost);
84+
injected(DatasourceParamsController, TOKENS.setupService, TOKENS.query, TOKENS.combinedFilter, TOKENS.columnsStore);
85+
injected(GridPersonalizationStore, TOKENS.setupService, TOKENS.mainGate, TOKENS.columnsStore, TOKENS.filterHost);
86+
injected(PaginationController, TOKENS.setupService, TOKENS.paginationConfig, TOKENS.query);
87+
injected(DatasourceService, TOKENS.setupService, TOKENS.mainGate, TOKENS.refreshInterval.optional);
88+
injected(DerivedLoaderController, TOKENS.query, TOKENS.exportProgressService, TOKENS.columnsStore, TOKENS.loaderConfig);
89+
injected(SelectionCounterViewModel, TOKENS.mainGate, TOKENS.selectionCounterPosition);
90+
injected(
91+
SelectAllService,
92+
TOKENS.setupService,
93+
TOKENS.selectAllGate,
94+
TOKENS.selectAllQuery,
95+
TOKENS.selectAllProgressService
96+
);
97+
7898
class DatagridContainer extends Container {
7999
constructor() {
80100
super();
81101

82102
// Column store
83103
this.bind(TOKENS.columnsStore).toInstance(ColumnGroupStore).inSingletonScope();
84-
injected(ColumnGroupStore, TOKENS.setupService, TOKENS.mainGate, TOKENS.staticInfo, TOKENS.filterHost);
85104

86105
// Basic data store
87106
this.bind(TOKENS.basicDate).toInstance(GridBasicData).inSingletonScope();
88-
injected(GridBasicData, TOKENS.mainGate);
89107

90108
// Combined filter
91109
this.bind(TOKENS.combinedFilter).toInstance(CombinedFilter).inSingletonScope();
92-
injected(CombinedFilter, TOKENS.setupService, TOKENS.combinedFilterConfig);
93110

94-
// Export progress store
95-
this.bind(TOKENS.exportProgressService).toInstance(ProgressStore).inSingletonScope();
111+
// Export progress
112+
this.bind(TOKENS.exportProgressService).toInstance(ProgressService).inSingletonScope();
113+
114+
// Select all progress
115+
this.bind(TOKENS.selectAllProgressService).toInstance(ProgressService).inSingletonScope();
96116

97117
// FilterAPI
98118
this.bind(TOKENS.filterAPI).toInstance(WidgetFilterAPI).inSingletonScope();
99-
injected(WidgetFilterAPI, TOKENS.parentChannelName, TOKENS.filterHost);
100119

101120
// Filter host
102121
this.bind(TOKENS.filterHost).toInstance(CustomFilterHost).inSingletonScope();
103122

104123
// Datasource params service
105124
this.bind(TOKENS.paramsService).toInstance(DatasourceParamsController).inSingletonScope();
106-
injected(
107-
DatasourceParamsController,
108-
TOKENS.setupService,
109-
TOKENS.query,
110-
TOKENS.combinedFilter,
111-
TOKENS.columnsStore
112-
);
113125

114126
// Personalization service
115127
this.bind(TOKENS.personalizationService).toInstance(GridPersonalizationStore).inSingletonScope();
116-
injected(
117-
GridPersonalizationStore,
118-
TOKENS.setupService,
119-
TOKENS.mainGate,
120-
TOKENS.columnsStore,
121-
TOKENS.filterHost
122-
);
123128

124129
// Query service
125130
this.bind(TOKENS.query).toInstance(DatasourceService).inSingletonScope();
126-
injected(DatasourceService, TOKENS.setupService, TOKENS.mainGate);
127131

128132
// Pagination service
129133
this.bind(TOKENS.paginationService).toInstance(PaginationController).inSingletonScope();
130-
injected(PaginationController, TOKENS.setupService, TOKENS.paginationConfig, TOKENS.query);
131-
132-
// Refresh service
133-
this.bind(TOKENS.refreshService).toInstance(RefreshController).inSingletonScope();
134-
injected(RefreshController, TOKENS.setupService, TOKENS.query, TOKENS.refreshInterval.optional);
135134

136135
// Setup service
137136
this.bind(TOKENS.setupService).toInstance(DatagridSetupService).inSingletonScope();
138137

139138
// Events channel for child widgets
140139
this.bind(TOKENS.parentChannelName)
141-
.toInstance(() => `datagrid/${generateUUID()}`)
140+
.toInstance(() => `Datagrid@${generateUUID()}`)
142141
.inSingletonScope();
143142

144143
// Loader view model
145144
this.bind(TOKENS.loaderViewModel).toInstance(DerivedLoaderController).inSingletonScope();
146-
injected(
147-
DerivedLoaderController,
148-
TOKENS.query,
149-
TOKENS.exportProgressService,
150-
TOKENS.columnsStore,
151-
TOKENS.loaderConfig
152-
);
153145

154146
// Selection counter view model
155147
this.bind(TOKENS.selectionCounter).toInstance(SelectionCounterViewModel).inSingletonScope();
156-
injected(SelectionCounterViewModel, TOKENS.mainGate, TOKENS.selectionCounterPosition);
148+
}
149+
}
150+
151+
type SelectAllGateProps = Pick<DatagridContainerProps, "itemSelection" | "datasource">;
152+
class SelectAllModule extends DependencyModule {
153+
selectAllGateProvider: GateProvider<SelectAllGateProps>;
154+
constructor(props: SelectAllGateProps) {
155+
super();
156+
this.selectAllGateProvider = new GateProvider<SelectAllGateProps>(props);
157+
// Bind gate
158+
this.bind(TOKENS.selectAllGate).toConstant(this.selectAllGateProvider.gate);
159+
// Bind query
160+
this.bind(TOKENS.selectAllQuery).toInstance(DatasourceService).inSingletonScope();
161+
// Bind progress
162+
this.bind(TOKENS.selectAllProgressService).toInstance(ProgressService).inSingletonScope();
163+
// Bind service
164+
this.bind(TOKENS.SelectAllService).toInstance(SelectAllService).inSingletonScope();
157165
}
158166
}
159167

160168
export function useDatagridDepsContainer(props: DatagridContainerProps): Container {
161-
const [container, mainGateProvider] = useConst(
169+
const [container, mainGateHost, selectAllGateHost] = useConst(
162170
/** Function to clone container and setup prop dependant bindings. */
163-
function init(): [Container, GateProvider<MainGateProps>] {
171+
function init(): [Container, GateProvider<MainGateProps>, GateProvider<SelectAllGateProps>] {
164172
const container = new DatagridContainer();
173+
const selectAllModule = new SelectAllModule(props);
174+
175+
container.use(TOKENS.selectAllProgressService).from(selectAllModule);
176+
container.use(TOKENS.SelectAllService).from(selectAllModule);
177+
165178
const exportProgress = container.get(TOKENS.exportProgressService);
166-
const gateProvider = new ClosableGateProvider<MainGateProps>(props, () => exportProgress.exporting);
179+
const selectAllProgress = container.get(TOKENS.selectAllProgressService);
180+
const gateProvider = new ClosableGateProvider<MainGateProps>(props, function isLocked() {
181+
return exportProgress.inProgress || selectAllProgress.inProgress;
182+
});
167183

168184
// Bind main gate
169185
container.bind(TOKENS.mainGate).toConstant(gateProvider.gate);
@@ -200,22 +216,24 @@ export function useDatagridDepsContainer(props: DatagridContainerProps): Contain
200216
container.bind(TOKENS.selectionCounterPosition).toConstant(props.selectionCounterPosition);
201217

202218
// Make sure essential services are created upfront
203-
container.get(TOKENS.refreshService);
204219
container.get(TOKENS.paramsService);
205220
container.get(TOKENS.paginationService);
206221

207222
// Hydrate filters from props
208223
container.get(TOKENS.combinedFilter).hydrate(props.datasource.filter);
209224

210-
return [container, gateProvider];
225+
return [container, gateProvider, selectAllModule.selectAllGateProvider];
211226
}
212227
);
213228

214229
// Run setup hooks on mount
215230
useSetup(() => container.get(TOKENS.setupService));
216231

217-
// Push props through the main gate
218-
useEffect(() => mainGateProvider.setProps(props));
232+
// Push props through the gates
233+
useEffect(() => {
234+
mainGateHost.setProps(props);
235+
selectAllGateHost.setProps(props);
236+
});
219237

220238
return container;
221239
}

packages/pluggableWidgets/datagrid-web/src/Datagrid.editorConfig.ts

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import {
33
hideNestedPropertiesIn,
44
hidePropertiesIn,
55
hidePropertyIn,
6-
Properties,
7-
transformGroupsIntoTabs
6+
Properties
87
} from "@mendix/pluggable-widgets-tools";
98
import {
109
container,
@@ -19,11 +18,7 @@ import {
1918

2019
import { ColumnsPreviewType, DatagridPreviewProps } from "../typings/DatagridProps";
2120

22-
export function getProperties(
23-
values: DatagridPreviewProps,
24-
defaultProperties: Properties,
25-
platform: "web" | "desktop"
26-
): Properties {
21+
export function getProperties(values: DatagridPreviewProps, defaultProperties: Properties): Properties {
2722
values.columns.forEach((column, index) => {
2823
if (column.showContentAs !== "attribute" && !column.sortable && !values.columnsFilterable) {
2924
hidePropertyIn(defaultProperties, values, "columns", index, "attribute");
@@ -65,15 +60,6 @@ export function getProperties(
6560
if (column.minWidth !== "manual") {
6661
hidePropertyIn(defaultProperties, values, "columns", index, "minWidthLimit");
6762
}
68-
if (!values.advanced && platform === "web") {
69-
hideNestedPropertiesIn(defaultProperties, values, "columns", index, [
70-
"columnClass",
71-
"sortable",
72-
"resizable",
73-
"draggable",
74-
"hidable"
75-
]);
76-
}
7763
});
7864

7965
if (values.pagination === "buttons") {
@@ -125,28 +111,6 @@ export function getProperties(
125111
"columns"
126112
);
127113

128-
if (platform === "web") {
129-
if (!values.advanced) {
130-
hidePropertiesIn(defaultProperties, values, [
131-
"pagination",
132-
"pagingPosition",
133-
"showEmptyPlaceholder",
134-
"rowClass",
135-
"columnsSortable",
136-
"columnsDraggable",
137-
"columnsResizable",
138-
"columnsHidable",
139-
"configurationAttribute",
140-
"onConfigurationChange",
141-
"filterSectionTitle"
142-
]);
143-
}
144-
145-
transformGroupsIntoTabs(defaultProperties);
146-
} else {
147-
hidePropertyIn(defaultProperties, values, "advanced");
148-
}
149-
150114
if (values.configurationStorageType === "localStorage") {
151115
hidePropertiesIn(defaultProperties, values, ["configurationAttribute", "onConfigurationChange"]);
152116
}
@@ -172,7 +136,7 @@ function hideSelectionProperties(defaultProperties: Properties, values: Datagrid
172136
if (itemSelection !== "Multi") {
173137
hidePropertiesIn(defaultProperties, values, [
174138
"keepSelection",
175-
"selectionCountPosition",
139+
"selectionCounterPosition",
176140
"clearSelectionButtonLabel"
177141
]);
178142
}

packages/pluggableWidgets/datagrid-web/src/Datagrid.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const DatagridRoot = observer((props: DatagridContainerProps): ReactElement => {
3333
const loaderVM = useLoaderViewModel();
3434
const items = gate.props.datasource.items ?? [];
3535

36-
const [, abortExport] = useDataExport(props, columnsStore, exportProgress);
36+
const [abortExport] = useDataExport(props, columnsStore, exportProgress);
3737

3838
const selectionHelper = useSelectionHelper(
3939
props.itemSelection,
@@ -119,7 +119,7 @@ const DatagridRoot = observer((props: DatagridContainerProps): ReactElement => {
119119
rowClass={useCallback((value: any) => props.rowClass?.get(value)?.value ?? "", [props.rowClass])}
120120
setPage={paginationService.setPage}
121121
styles={props.style}
122-
exporting={exportProgress.exporting}
122+
exporting={exportProgress.inProgress}
123123
processedRows={exportProgress.loaded}
124124
visibleColumns={columnsStore.visibleColumns}
125125
availableColumns={columnsStore.availableColumns}

0 commit comments

Comments
 (0)