Skip to content

Commit c56dde1

Browse files
committed
WIP
1 parent 0ce3dc7 commit c56dde1

File tree

23 files changed

+402
-131
lines changed

23 files changed

+402
-131
lines changed

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

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -301,20 +301,34 @@
301301
<enumerationValue key="both">Both</enumerationValue>
302302
</enumerationValues>
303303
</property>
304-
<property key="dynamicPageSize" type="attribute" required="false">
305-
<caption>Dynamic page size attribute</caption>
306-
<description>Optional attribute to set the page size dynamically. The attribute requires Integer type.</description>
307-
<attributeTypes>
308-
<attributeType name="Integer" />
309-
</attributeTypes>
310-
</property>
311304
<property key="loadMoreButtonCaption" type="textTemplate" required="false">
312305
<caption>Load more caption</caption>
313306
<description />
314307
<translations>
315308
<translation lang="en_US">Load More</translation>
316309
</translations>
317310
</property>
311+
<property key="dynamicPageSize" type="attribute" required="false">
312+
<caption>Dynamic page size attribute</caption>
313+
<description>Attribute to set the page size dynamically.</description>
314+
<attributeTypes>
315+
<attributeType name="Integer" />
316+
</attributeTypes>
317+
</property>
318+
<property key="dynamicPage" type="attribute" required="false">
319+
<caption>Dynamic page attribute</caption>
320+
<description>Attribute to set the page dynamically.</description>
321+
<attributeTypes>
322+
<attributeType name="Integer" />
323+
</attributeTypes>
324+
</property>
325+
<property key="totalCountValue" type="attribute" required="false">
326+
<caption>Total count</caption>
327+
<description>Attribute to store current total count</description>
328+
<attributeTypes>
329+
<attributeType name="Integer" />
330+
</attributeTypes>
331+
</property>
318332
</propertyGroup>
319333
<propertyGroup caption="Appearance">
320334
<property key="showEmptyPlaceholder" type="enumeration" defaultValue="none">

packages/pluggableWidgets/datagrid-web/src/components/GridBody.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
useDatagridConfig,
66
useItemCount,
77
useLoaderViewModel,
8-
usePaginationService,
8+
usePaginationVM,
99
useVisibleColumnsCount
1010
} from "../model/hooks/injection-hooks";
1111
import { useBodyScroll } from "../model/hooks/useBodyScroll";
@@ -31,7 +31,7 @@ export const GridBody = observer(function GridBody(props: PropsWithChildren): Re
3131

3232
const ContentGuard = observer(function ContentGuard(props: PropsWithChildren): ReactNode {
3333
const loaderVM = useLoaderViewModel();
34-
const { pageSize } = usePaginationService();
34+
const { pageSize } = usePaginationVM();
3535
const config = useDatagridConfig();
3636
const columnsCount = useVisibleColumnsCount().get();
3737
const itemCount = useItemCount().get();

packages/pluggableWidgets/datagrid-web/src/components/Pagination.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { Pagination as PaginationComponent } from "@mendix/widget-plugin-grid/components/Pagination";
22
import { observer } from "mobx-react-lite";
33
import { ReactNode } from "react";
4-
import { usePaginationService } from "../model/hooks/injection-hooks";
4+
import { usePaginationVM } from "../model/hooks/injection-hooks";
55

66
export const Pagination = observer(function Pagination(): ReactNode {
7-
const paging = usePaginationService();
7+
const paging = usePaginationVM();
88

99
if (!paging.paginationVisible) return null;
1010

packages/pluggableWidgets/datagrid-web/src/components/WidgetFooter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import { observer } from "mobx-react-lite";
33
import { ReactElement } from "react";
44
import { SelectionCounter } from "../features/selection-counter/SelectionCounter";
55
import { useSelectionCounterViewModel } from "../features/selection-counter/injection-hooks";
6-
import { useDatagridConfig, usePaginationService, useTexts } from "../model/hooks/injection-hooks";
6+
import { useDatagridConfig, usePaginationVM, useTexts } from "../model/hooks/injection-hooks";
77
import { Pagination } from "./Pagination";
88

99
export const WidgetFooter = observer(function WidgetFooter(): ReactElement {
1010
const config = useDatagridConfig();
11-
const paging = usePaginationService();
11+
const paging = usePaginationVM();
1212
const { loadMoreButtonCaption } = useTexts();
1313
const selectionCounterVM = useSelectionCounterViewModel();
1414

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { ComputedAtom, disposeBatch, SetupComponent, SetupComponentHost } from "@mendix/widget-plugin-mobx-kit/main";
2+
import { autorun, reaction } from "mobx";
3+
import { GridPageControl } from "./GridPageControl";
4+
5+
export class DynamicPaginationFeature implements SetupComponent {
6+
id = "DynamicPaginationFeature";
7+
constructor(
8+
host: SetupComponentHost,
9+
private config: { dynamicPageSizeEnabled: boolean; dynamicPageEnabled: boolean },
10+
private dynamicPage: ComputedAtom<number>,
11+
private dynamicPageSize: ComputedAtom<number>,
12+
private totalCount: ComputedAtom<number>,
13+
private service: GridPageControl
14+
) {
15+
host.add(this);
16+
}
17+
18+
setup(): () => void {
19+
const [add, disposeAll] = disposeBatch();
20+
21+
if (this.config.dynamicPageSizeEnabled) {
22+
add(
23+
reaction(
24+
() => this.dynamicPageSize.get(),
25+
pageSize => {
26+
if (pageSize < 0) return;
27+
this.service.setPageSize(pageSize);
28+
},
29+
{ delay: 250 }
30+
)
31+
);
32+
}
33+
34+
if (this.config.dynamicPageEnabled) {
35+
add(
36+
reaction(
37+
() => this.dynamicPage.get(),
38+
page => {
39+
if (page < 0) return;
40+
// FIXMIE: The service uses 1-based paging
41+
this.service.setPage(page + 1);
42+
},
43+
{ delay: 250 }
44+
)
45+
);
46+
add(
47+
autorun(() => {
48+
this.service.setTotalCount(this.totalCount.get());
49+
})
50+
);
51+
}
52+
53+
return disposeAll;
54+
}
55+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface GridPageControl {
2+
setPage(page: number): void;
3+
setPageSize(pageSize: number): void;
4+
setTotalCount(totalCount: number): void;
5+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { SetPageAction, SetPageSizeAction } from "@mendix/widget-plugin-grid/main";
2+
import { DerivedPropsGate } from "@mendix/widget-plugin-mobx-kit/main";
3+
import { Big } from "big.js";
4+
import { EditableValue } from "mendix";
5+
import { GridPageControl } from "./GridPageControl";
6+
7+
export class PageControlService implements GridPageControl {
8+
constructor(
9+
private gate: DerivedPropsGate<{
10+
totalCountValue?: EditableValue<Big>;
11+
}>,
12+
private setPageSizeAction: SetPageSizeAction,
13+
private setPageAction: SetPageAction
14+
) {}
15+
16+
setPageSize(pageSize: number): void {
17+
this.setPageSizeAction(pageSize);
18+
}
19+
20+
setPage(page: number): void {
21+
this.setPageAction(page);
22+
}
23+
24+
setTotalCount(count: number): void {
25+
const value = this.gate.props.totalCountValue;
26+
if (!value || value.readOnly) return;
27+
value.setValue(new Big(count));
28+
}
29+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { QueryService, SetPageAction } from "@mendix/widget-plugin-grid/main";
2+
import { ComputedAtom } from "@mendix/widget-plugin-mobx-kit/main";
3+
import { computed, makeObservable } from "mobx";
4+
import { PaginationEnum, ShowPagingButtonsEnum } from "../../../typings/DatagridProps";
5+
import { PaginationConfig } from "./pagination.config";
6+
7+
export class PaginationViewModel {
8+
readonly pagination: PaginationEnum;
9+
readonly showPagingButtons: ShowPagingButtonsEnum;
10+
11+
constructor(
12+
private config: PaginationConfig,
13+
private query: QueryService,
14+
private currentPageAtom: ComputedAtom<number>,
15+
private pageSizeAtom: ComputedAtom<number>,
16+
private setPageAction: SetPageAction
17+
) {
18+
this.pagination = config.pagination;
19+
this.showPagingButtons = config.showPagingButtons;
20+
21+
makeObservable(this, {
22+
pageSize: computed,
23+
currentPage: computed,
24+
paginationVisible: computed,
25+
hasMoreItems: computed,
26+
totalCount: computed
27+
});
28+
}
29+
30+
get pageSize(): number {
31+
return this.pageSizeAtom.get();
32+
}
33+
34+
get currentPage(): number {
35+
return this.currentPageAtom.get();
36+
}
37+
38+
get paginationVisible(): boolean {
39+
switch (this.config.paginationKind) {
40+
case "buttons.always":
41+
return true;
42+
case "buttons.auto": {
43+
const { totalCount = -1 } = this.query;
44+
return totalCount > this.query.limit;
45+
}
46+
default:
47+
return this.config.showNumberOfRows;
48+
}
49+
}
50+
51+
get hasMoreItems(): boolean {
52+
return this.query.hasMoreItems;
53+
}
54+
55+
get totalCount(): number | undefined {
56+
return this.query.totalCount;
57+
}
58+
59+
setPage: SetPageAction = value => {
60+
this.setPageAction(value);
61+
};
62+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { PaginationEnum, ShowPagingButtonsEnum } from "../../../typings/DatagridProps";
2+
import { MainGateProps } from "../../../typings/MainGateProps";
3+
4+
export interface PaginationConfig {
5+
pagination: PaginationEnum;
6+
paginationKind: PaginationKind;
7+
showPagingButtons: ShowPagingButtonsEnum;
8+
showNumberOfRows: boolean;
9+
pageSize: number;
10+
isLimitBased: boolean;
11+
dynamicPageSizeEnabled: boolean;
12+
dynamicPageEnabled: boolean;
13+
}
14+
15+
export type PaginationKind = `${PaginationEnum}.${ShowPagingButtonsEnum}`;
16+
17+
export function paginationConfig(props: MainGateProps): PaginationConfig {
18+
const config: PaginationConfig = {
19+
pagination: props.pagination,
20+
showPagingButtons: props.showPagingButtons,
21+
showNumberOfRows: props.showNumberOfRows,
22+
pageSize: props.pageSize,
23+
isLimitBased: isLimitBased(props),
24+
paginationKind: `${props.pagination}.${props.showPagingButtons}`,
25+
dynamicPageSizeEnabled: props.dynamicPageSize !== undefined,
26+
dynamicPageEnabled: props.dynamicPage !== undefined
27+
};
28+
29+
return Object.freeze(config);
30+
}
31+
32+
function isLimitBased(props: MainGateProps): boolean {
33+
return props.pagination === "virtualScrolling" || props.pagination === "loadMore";
34+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { boundPage, boundPageSize } from "@mendix/widget-plugin-grid/main";
2+
import { ComputedAtom, DerivedPropsGate } from "@mendix/widget-plugin-mobx-kit/main";
3+
4+
/** Atom for the dynamic page index provided by the widget's props. */
5+
export function dynamicPageAtom(gate: DerivedPropsGate<{ dynamicPage?: { value?: Big } }>): ComputedAtom<number> {
6+
return boundPage(() => gate.props.dynamicPage?.value?.toNumber() ?? -1);
7+
}
8+
9+
/** Atom for the dynamic page size. */
10+
export function dynamicPageSizeAtom(
11+
gate: DerivedPropsGate<{ dynamicPageSize?: { value?: Big } }>
12+
): ComputedAtom<number> {
13+
return boundPageSize(() => gate.props.dynamicPageSize?.value?.toNumber() ?? -1);
14+
}

0 commit comments

Comments
 (0)