Skip to content

Commit e455ab8

Browse files
committed
Merged PR 22348: Grouping, Aggregations, Rewrite to SSRM
2 parents 8266396 + 7e86fd0 commit e455ab8

File tree

181 files changed

+7023
-6448
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+7023
-6448
lines changed

package-lock.json

Lines changed: 263 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,28 @@
7474
"@ag-grid-community/core": "^31.3.2",
7575
"@ag-grid-community/react": "^31.3.2",
7676
"@ag-grid-community/styles": "^31.3.2",
77+
"@ag-grid-enterprise/clipboard": "31.3.2",
7778
"@ag-grid-enterprise/core": "31.3.2",
7879
"@ag-grid-enterprise/row-grouping": "31.3.2",
80+
"@ag-grid-enterprise/server-side-row-model": "31.3.2",
7981
"@fluentui/react-migration-v8-v9": "^9.6.20",
8082
"color": "^4.2.3",
8183
"dayjs": "^1.11.10",
84+
"debounce": "^2.2.0",
8285
"external-svg-loader": "^1.7.1",
8386
"fast-deep-equal": "^3.1.3",
87+
"hotkeys-js": "^3.13.15",
8488
"humanize-duration": "^3.32.0",
8589
"liquidjs": "^9.43.0",
8690
"merge-anything": "^5.1.7",
8791
"numeral": "^2.0.6",
8892
"use-debounce": "^10.0.1",
89-
"validator": "^13.11.9",
90-
"@talxis/client-libraries": "^1.2506.4"
93+
"validator": "^13.11.9"
9194
},
9295
"peerDependencies": {
9396
"@fluentui/react": "<=8.121.5",
94-
"@talxis/react-components": "^1.2503.4",
97+
"@talxis/react-components": "1.2505.2",
98+
"@talxis/client-libraries": "1.2512.2",
9599
"react": "^16.8.6 || ^17.0.2",
96100
"react-dom": "^16.8.6 || ^17.0.2"
97101
}

rollup.config.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const externalDeps = [
2626
'react',
2727
'react-dom',
2828
'react/jsx-runtime',
29+
'debounce',
2930
'use-debounce',
3031
'validator',
3132
'validator/es/lib/isURL',
@@ -35,11 +36,15 @@ const externalDeps = [
3536
'@ag-grid-community/client-side-row-model',
3637
"@ag-grid-enterprise/core",
3738
"@ag-grid-enterprise/row-grouping",
39+
"@ag-grid-enterprise/server-side-row-model",
40+
"@ag-grid-enterprise/menu",
41+
"@ag-grid-enterprise/clipboard",
3842
'@ag-grid-community/react',
3943
'@ag-grid-community/core',
4044
'@ag-grid-community/styles',
4145
'@ag-grid-community/styles/ag-grid.css',
42-
'@ag-grid-community/styles/ag-theme-balham.css'
46+
'@ag-grid-community/styles/ag-theme-balham.css',
47+
'hotkeys-js',
4348
]
4449

4550
export default [
Lines changed: 97 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,112 @@
1-
import { useMemo, useRef } from "react";
1+
import { useEffect, useMemo, useRef } from "react";
22
import { useControl } from "../../hooks";
33
import { ThemeProvider } from "@fluentui/react";
44
import { datasetControlTranslations } from "./translations";
5-
import { getDatasetControlStyles } from "./styles";
6-
import { IDatasetControl } from "./interfaces";
7-
import { QuickFind } from "./QuickFind/QuickFind";
85
import { useRerender } from "@talxis/react-components";
9-
import { Client } from "@talxis/client-libraries";
10-
import { DatasetPaging } from "./Paging";
11-
12-
const client = new Client();
6+
import { DatasetControlModel } from "./DatasetControlModel";
7+
import { ModelContext } from "./useModel";
8+
import { Pagination } from "./Pagination/Pagination";
9+
import { getDatasetControlStyles } from "./styles";
10+
import { Header } from "./Header/Header";
11+
import { useEventEmitter } from "../../hooks/useEventEmitter";
12+
import { IDataProviderEventListeners } from "@talxis/client-libraries";
13+
import { IDatasetControlProps } from "./interfaces";
14+
import { IDatasetControlEvents } from "../../utils/dataset-control";
1315

14-
export const DatasetControl = (props: IDatasetControl) => {
15-
const { labels, theme } = useControl('DatasetControl', props, datasetControlTranslations);
16-
const rerender = useRerender();
17-
const dataset = props.parameters.Grid;
18-
const injectedContextRef = useRef(props.context);
19-
const styles = useMemo(() => getDatasetControlStyles(theme, props.parameters.Height?.raw), []);
16+
export const DatasetControl = (props: IDatasetControlProps) => {
17+
const { labels, theme } = useControl('DatasetControl', {
18+
...props,
19+
context: props.onGetDatasetControlInstance().getPcfContext(),
20+
parameters: props.onGetDatasetControlInstance().getParameters(),
21+
}, datasetControlTranslations);
22+
23+
const propsRef = useRef<IDatasetControlProps>(props);
24+
propsRef.current = props;
25+
const datasetControl = propsRef.current.onGetDatasetControlInstance();
26+
const model = useMemo(() => new DatasetControlModel({
27+
datasetControl: datasetControl,
28+
getLabels: () => labels,
29+
}), []);
30+
useMemo(() => props.onGetDatasetControlInstance().init(), []);
2031
const onOverrideComponentProps = props.onOverrideComponentProps ?? ((props) => props);
21-
useMemo(() => {
22-
if (dataset.isVirtual() || !client.isTalxisPortal()) {
23-
dataset.setInterceptor('__onRequestRender', () => rerender());
24-
}
25-
}, []);
26-
27-
//we need to have a way to customize the init behavior from above
28-
const componentProps = onOverrideComponentProps({
29-
onDatasetInit: () => {
30-
if (dataset.isVirtual()) {
31-
dataset.paging.loadExactPage(dataset.paging.pageNumber);
32-
}
33-
},
34-
containerProps: {
35-
theme: theme,
36-
className: styles.datasetControlRoot,
37-
},
32+
const rerender = useRerender();
33+
const styles = useMemo(() => getDatasetControlStyles(datasetControl.getHeight()), [datasetControl.getHeight()]);
34+
const dataset = datasetControl.getDataset();
3835

39-
headerProps: {
40-
headerContainerProps: {
41-
className: styles.headerRoot
42-
},
43-
onRender: (renderQuickFind) => renderQuickFind(),
44-
onGetQuickFindProps: (props) => props
45-
},
46-
onRenderPagination: (props, renderPagination) => renderPagination(props)
47-
});
36+
useEventEmitter<IDataProviderEventListeners>(dataset, 'onNewDataLoaded', rerender);
37+
useEventEmitter<IDataProviderEventListeners>(dataset, 'onRenderRequested', rerender);
38+
useEventEmitter<IDataProviderEventListeners>(dataset, 'onBeforeNewDataLoaded', rerender);
4839

49-
useMemo(() => {
50-
//@ts-ignore - private property
51-
injectedContextRef.current = dataset._patchContext(props.context);
52-
}, [props.context]);
5340

54-
useMemo(() => {
55-
componentProps.onDatasetInit();
56-
}, []);
41+
const componentProps = onOverrideComponentProps({
42+
onRender: (props, defaultRender) => defaultRender(props),
43+
})
5744

58-
const isQuickFindEnabled = () => {
59-
if (dataset.isVirtual() && props.parameters.EnableQuickFind?.raw) {
60-
return true;
45+
const isFooterVisible = () => {
46+
switch (true) {
47+
case datasetControl.isPaginationVisible():
48+
case datasetControl.isRecordCountVisible():
49+
case datasetControl.isPageSizeSwitcherVisible():
50+
return true;
51+
default:
52+
return false;
6153
}
62-
return false;
6354
}
6455

56+
const isPaginationVisible = () => {
57+
return isFooterVisible();
58+
}
59+
60+
useEffect(() => {
61+
return () => {
62+
datasetControl.destroy();
63+
}
64+
}, []);
65+
66+
return <ModelContext.Provider value={model}>
67+
{componentProps.onRender({
68+
container: {
69+
theme: theme,
70+
className: styles.datasetControlRoot
71+
},
72+
onRenderHeader: (props, defaultRender) => defaultRender(props),
73+
onRenderFooter: (props, defaultRender) => defaultRender(props),
74+
onRenderControlContainer: (props, defaultRender) => defaultRender(props)
75+
}, (props) => {
76+
return <ThemeProvider {...props.container}>
77+
<Header onRenderHeader={props.onRenderHeader} />
78+
{props.onRenderControlContainer({
79+
controlContainerProps: {
80+
className: styles.controlContainer
81+
},
6582

66-
return (
67-
<ThemeProvider {...componentProps.containerProps}>
68-
{isQuickFindEnabled() &&
69-
<div {...componentProps.headerProps.headerContainerProps}>
70-
{componentProps.headerProps.onRender(() => {
71-
return <>
72-
{isQuickFindEnabled() &&
73-
<QuickFind
74-
dataset={dataset}
75-
labels={labels}
76-
theme={theme}
77-
onGetQuickFindComponentProps={(props) => componentProps.headerProps.onGetQuickFindProps(props)} />
78-
}
79-
</>
80-
})}
81-
</div>
82-
}
83-
{props.onGetControlComponent({ ...props, context: injectedContextRef.current })}
84-
{componentProps.onRenderPagination({
85-
context: injectedContextRef.current, parameters: {
86-
Dataset: dataset,
87-
EnablePagination: props.parameters.EnablePagination,
88-
EnablePageSizeSwitcher: props.parameters.EnablePageSizeSwitcher
89-
}
90-
}, (paginationProps) => <DatasetPaging {...paginationProps} />)}
91-
</ThemeProvider>
92-
)
83+
}, (props) => {
84+
const { onOverrideComponentProps, ...filteredProps } = propsRef.current;
85+
return <div {...props.controlContainerProps}>
86+
{propsRef.current.onGetControlComponent({
87+
...filteredProps,
88+
parameters: datasetControl.getParameters(),
89+
context: datasetControl.getPcfContext(),
90+
state: datasetControl.getState()
91+
})}
92+
</div>
93+
})}
94+
{props.onRenderFooter({
95+
footerContainerProps: {
96+
className: styles.footer
97+
},
98+
onRenderPagination: (props, defaultRender) => defaultRender(props)
99+
}, (props) => {
100+
if (!isFooterVisible()) {
101+
return <></>
102+
}
103+
return <div {...props.footerContainerProps}>
104+
{isPaginationVisible() &&
105+
<Pagination onRenderPagination={props.onRenderPagination} />
106+
}
107+
</div>
108+
})}
109+
</ThemeProvider>
110+
})}
111+
</ModelContext.Provider>
93112
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { IInternalDataProvider } from "@talxis/client-libraries";
2+
import { ITranslation } from "../../hooks";
3+
import { IDatasetControl } from "../../utils/dataset-control";
4+
import { datasetControlTranslations } from "./translations";
5+
6+
type Labels = Required<ITranslation<typeof datasetControlTranslations>>;
7+
8+
interface IDatasetControlModelOptions {
9+
datasetControl: IDatasetControl;
10+
getLabels: () => Labels;
11+
}
12+
13+
export class DatasetControlModel {
14+
private _options: IDatasetControlModelOptions;
15+
16+
constructor(options: IDatasetControlModelOptions) {
17+
this._options = options;
18+
this._registerInterceptors();
19+
}
20+
public getDatasetControl(): IDatasetControl {
21+
return this._options.datasetControl;
22+
}
23+
public getLabels(): Labels {
24+
return this._options.getLabels();
25+
}
26+
27+
//here due to translations, should be part of DatasetControl when we have translations settled
28+
private _registerInterceptors() {
29+
const dataset = this._options.datasetControl.getDataset()
30+
const dataProvider = dataset.getDataProvider() as IInternalDataProvider;
31+
dataProvider.setInterceptor('__unsavedChangesBlocker', (parameters, defaultAction) => {
32+
if (!dataProvider.isDirty()) {
33+
return defaultAction(parameters);
34+
}
35+
else if (window.confirm(this._options.getLabels()['saving-discard-all-confirmation']()) ) {
36+
//@ts-ignore
37+
dataProvider['_dirtyRecordIdsSet'].clear();
38+
//@ts-ignore
39+
dataProvider['_invalidRecordFieldIdsSet'].clear();
40+
return defaultAction(parameters);
41+
}
42+
})
43+
}
44+
45+
}

0 commit comments

Comments
 (0)