@talxis/base-controls 1.2406.2 → 1.2406.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/examples/Currency/package.json +1 -1
  2. package/examples/DateTime/package.json +1 -1
  3. package/examples/Decimal/package.json +1 -1
  4. package/examples/Duration/package.json +1 -1
  5. package/examples/Grid/package.json +1 -1
  6. package/examples/Lookup/package.json +1 -1
  7. package/examples/MultiSelectOptionSet/package.json +1 -1
  8. package/examples/OptionSet/package.json +1 -1
  9. package/examples/TwoOptions/package.json +1 -1
  10. package/package.json +1 -1
  11. package/.env +0 -1
  12. package/.eslintrc +0 -117
  13. package/.npmgitignore +0 -9
  14. package/.vscode/settings.json +0 -3
  15. package/.yalcignore +0 -2
  16. package/azure-pipelines.yml +0 -44
  17. package/examples/Currency/package-lock.json +0 -15900
  18. package/examples/Currency/tsconfig.json +0 -7
  19. package/examples/DateTime/package-lock.json +0 -15900
  20. package/examples/DateTime/tsconfig.json +0 -7
  21. package/examples/Decimal/package-lock.json +0 -15900
  22. package/examples/Decimal/tsconfig.json +0 -7
  23. package/examples/Duration/package-lock.json +0 -15900
  24. package/examples/Duration/tsconfig.json +0 -7
  25. package/examples/Grid/package-lock.json +0 -15901
  26. package/examples/Grid/tsconfig.json +0 -7
  27. package/examples/Lookup/package-lock.json +0 -15900
  28. package/examples/Lookup/tsconfig.json +0 -8
  29. package/examples/MultiSelectOptionSet/package-lock.json +0 -15900
  30. package/examples/MultiSelectOptionSet/tsconfig.json +0 -7
  31. package/examples/OptionSet/package-lock.json +0 -15900
  32. package/examples/OptionSet/tsconfig.json +0 -7
  33. package/examples/TwoOptions/package-lock.json +0 -15900
  34. package/examples/TwoOptions/tsconfig.json +0 -7
  35. package/public/index.html +0 -43
  36. package/public/manifest.json +0 -25
  37. package/rollup.config.js +0 -44
  38. package/src/components/DateTime/DateTime.tsx +0 -97
  39. package/src/components/DateTime/components/Calendar.tsx +0 -80
  40. package/src/components/DateTime/hooks/useDateTime.ts +0 -144
  41. package/src/components/DateTime/index.ts +0 -2
  42. package/src/components/DateTime/interfaces.ts +0 -22
  43. package/src/components/DateTime/styles.ts +0 -37
  44. package/src/components/DateTime/translations.ts +0 -18
  45. package/src/components/Decimal/Decimal.tsx +0 -120
  46. package/src/components/Decimal/index.ts +0 -2
  47. package/src/components/Decimal/interfaces.ts +0 -20
  48. package/src/components/Duration/Duration.tsx +0 -143
  49. package/src/components/Duration/index.ts +0 -2
  50. package/src/components/Duration/interfaces.ts +0 -22
  51. package/src/components/Duration/translations.ts +0 -30
  52. package/src/components/Grid/Grid.tsx +0 -24
  53. package/src/components/Grid/core/components/AgGrid/AgGrid.tsx +0 -206
  54. package/src/components/Grid/core/components/AgGrid/components/EmptyRecordsOverlay/EmptyRecords.tsx +0 -16
  55. package/src/components/Grid/core/components/AgGrid/components/EmptyRecordsOverlay/styles.ts +0 -20
  56. package/src/components/Grid/core/components/AgGrid/components/LoadingOverlay/LoadingOverlay.tsx +0 -7
  57. package/src/components/Grid/core/components/AgGrid/controllers/useAgGridController.ts +0 -68
  58. package/src/components/Grid/core/components/AgGrid/model/AgGrid.ts +0 -100
  59. package/src/components/Grid/core/components/AgGrid/styles.ts +0 -72
  60. package/src/components/Grid/core/components/Cell/Commands/Commands.tsx +0 -32
  61. package/src/components/Grid/core/components/Cell/Commands/Icon.tsx +0 -17
  62. package/src/components/Grid/core/components/Cell/Commands/styles.ts +0 -21
  63. package/src/components/Grid/core/components/Cell/Commands/useCommands.tsx +0 -53
  64. package/src/components/Grid/core/components/Cell/EditableCell/EditableCell.tsx +0 -140
  65. package/src/components/Grid/core/components/Cell/ReadOnlyCell/ReadOnlyCell.tsx +0 -176
  66. package/src/components/Grid/core/components/Cell/ReadOnlyCell/ReadOnlyOptionSet/ReadOnlyOptionSet.tsx +0 -67
  67. package/src/components/Grid/core/components/Cell/ReadOnlyCell/ReadOnlyOptionSet/styles.ts +0 -24
  68. package/src/components/Grid/core/components/Cell/ReadOnlyCell/styles.ts +0 -56
  69. package/src/components/Grid/core/components/ColumnHeader/ColumnHeader.tsx +0 -71
  70. package/src/components/Grid/core/components/ColumnHeader/components/GlobalCheckbox/GlobalCheckbox.tsx +0 -31
  71. package/src/components/Grid/core/components/ColumnHeader/components/GlobalCheckbox/styles.ts +0 -16
  72. package/src/components/Grid/core/components/ColumnHeader/styles.ts +0 -40
  73. package/src/components/Grid/core/components/Component/Component.tsx +0 -59
  74. package/src/components/Grid/core/components/Component/controller/useComponentController.ts +0 -39
  75. package/src/components/Grid/core/components/Component/model/Component.ts +0 -251
  76. package/src/components/Grid/core/components/Dialog/Constants.tsx +0 -8
  77. package/src/components/Grid/core/components/Dialog/Styles.tsx +0 -61
  78. package/src/components/Grid/core/components/Dialog/index.tsx +0 -22
  79. package/src/components/Grid/core/components/Dialog/interfaces/index.d.ts +0 -7
  80. package/src/components/Grid/core/components/Save/Save.tsx +0 -74
  81. package/src/components/Grid/core/components/Save/components/ChangeEditor/ChangeEditor.tsx +0 -63
  82. package/src/components/Grid/core/components/Save/components/ChangeEditor/components/RecordGrids/RecordGrids.tsx +0 -153
  83. package/src/components/Grid/core/components/Save/components/ChangeEditor/components/RecordGrids/styles.ts +0 -52
  84. package/src/components/Grid/core/components/Save/components/ChangeEditor/styles.ts +0 -34
  85. package/src/components/Grid/core/components/Save/hooks/useSave.ts +0 -59
  86. package/src/components/Grid/core/components/Save/styles.ts +0 -41
  87. package/src/components/Grid/core/controllers/useGridController.ts +0 -46
  88. package/src/components/Grid/core/enums/ConditionOperator.ts +0 -46
  89. package/src/components/Grid/core/enums/DataType.ts +0 -25
  90. package/src/components/Grid/core/hooks/useGridInstance.ts +0 -7
  91. package/src/components/Grid/core/hooks/useRefreshCallback.ts +0 -20
  92. package/src/components/Grid/core/hooks/useRerender.ts +0 -15
  93. package/src/components/Grid/core/interfaces/IGridColumn.ts +0 -19
  94. package/src/components/Grid/core/interfaces/IGridContext.ts +0 -7
  95. package/src/components/Grid/core/model/Grid.ts +0 -250
  96. package/src/components/Grid/core/model/GridDependency.ts +0 -34
  97. package/src/components/Grid/core/model/Metadata.ts +0 -20
  98. package/src/components/Grid/core/services/RecordUpdateService/controllers/useRecordUpdateServiceController.ts +0 -36
  99. package/src/components/Grid/core/services/RecordUpdateService/model/RecordUpdateService.ts +0 -222
  100. package/src/components/Grid/filtering/components/FilterCallout/FilterCallout.tsx +0 -83
  101. package/src/components/Grid/filtering/components/FilterCallout/components/ConditionOperator/ConditionOperator.tsx +0 -66
  102. package/src/components/Grid/filtering/components/FilterCallout/components/ConditionValue/ConditionValue.tsx +0 -48
  103. package/src/components/Grid/filtering/components/FilterCallout/components/ConditionValue/model/ConditionComponentValue.ts +0 -120
  104. package/src/components/Grid/filtering/components/FilterCallout/styles.ts +0 -37
  105. package/src/components/Grid/filtering/constants.ts +0 -48
  106. package/src/components/Grid/filtering/controller/useColumnFilterConditionController.ts +0 -63
  107. package/src/components/Grid/filtering/model/Condition.ts +0 -309
  108. package/src/components/Grid/filtering/model/Filtering.ts +0 -78
  109. package/src/components/Grid/filtering/utils/FilteringUtilts.ts +0 -190
  110. package/src/components/Grid/interfaces.ts +0 -109
  111. package/src/components/Grid/paging/components/Paging/Paging.tsx +0 -76
  112. package/src/components/Grid/paging/components/Paging/styles.ts +0 -38
  113. package/src/components/Grid/paging/controllers/usePagingController.ts +0 -34
  114. package/src/components/Grid/paging/model/Paging.ts +0 -49
  115. package/src/components/Grid/selection/controllers/useSelectionController.ts +0 -25
  116. package/src/components/Grid/selection/model/Selection.ts +0 -60
  117. package/src/components/Grid/sorting/Sorting.ts +0 -30
  118. package/src/components/Grid/sorting/components/SortingContextualMenu/SortingContextualMenu.tsx +0 -126
  119. package/src/components/Grid/sorting/components/SortingContextualMenu/styles.ts +0 -12
  120. package/src/components/Grid/sorting/controllers/useColumnSortingController.ts +0 -26
  121. package/src/components/Grid/translations.ts +0 -80
  122. package/src/components/Grid/validation/controllers/useRecordValidationController.ts +0 -31
  123. package/src/components/Grid/validation/model/ColumnValidation.ts +0 -81
  124. package/src/components/Lookup/Lookup.tsx +0 -199
  125. package/src/components/Lookup/components/RecordCreator.tsx +0 -53
  126. package/src/components/Lookup/components/TargetSelector.tsx +0 -43
  127. package/src/components/Lookup/hooks/useFetchXml.ts +0 -31
  128. package/src/components/Lookup/hooks/useLoadedEntities.ts +0 -23
  129. package/src/components/Lookup/hooks/useLookup.ts +0 -126
  130. package/src/components/Lookup/index.ts +0 -2
  131. package/src/components/Lookup/interfaces.ts +0 -45
  132. package/src/components/Lookup/lib.ts +0 -3110
  133. package/src/components/Lookup/styles.ts +0 -106
  134. package/src/components/Lookup/translations.ts +0 -28
  135. package/src/components/MultiSelectOptionSet/MultiSelectOptionSet.tsx +0 -83
  136. package/src/components/MultiSelectOptionSet/index.ts +0 -2
  137. package/src/components/MultiSelectOptionSet/interfaces.ts +0 -14
  138. package/src/components/OptionSet/OptionSet.tsx +0 -67
  139. package/src/components/OptionSet/index.ts +0 -2
  140. package/src/components/OptionSet/interfaces.ts +0 -17
  141. package/src/components/TextField/TextField.tsx +0 -58
  142. package/src/components/TextField/hooks/useTextField.ts +0 -42
  143. package/src/components/TextField/index.ts +0 -2
  144. package/src/components/TextField/interfaces.ts +0 -20
  145. package/src/components/TwoOptions/TwoOptions.tsx +0 -43
  146. package/src/components/TwoOptions/index.ts +0 -2
  147. package/src/components/TwoOptions/interfaces.ts +0 -17
  148. package/src/hooks/index.ts +0 -1
  149. package/src/hooks/useComponent.ts +0 -83
  150. package/src/hooks/useFocusIn.ts +0 -23
  151. package/src/hooks/useInputBasedComponent.ts +0 -71
  152. package/src/hooks/useMouseOver.ts +0 -23
  153. package/src/index.tsx +0 -12
  154. package/src/interfaces/context.ts +0 -21
  155. package/src/interfaces/index.ts +0 -12
  156. package/src/interfaces/parameters.ts +0 -26
  157. package/src/interfaces/property.ts +0 -111
  158. package/src/sandbox/index.tsx +0 -137
  159. package/src/sandbox/mock/Context.ts +0 -18
  160. package/src/sandbox/mock/Formatting.ts +0 -186
  161. package/src/sandbox/mock/Mode.ts +0 -25
  162. package/src/sandbox/mock/UserSettings.ts +0 -31
  163. package/src/sandbox/mock/Utility.ts +0 -14
  164. package/src/sandbox/shared/durationList.tsx +0 -24
  165. package/src/sandbox/shared/multiSelectOptionList.tsx +0 -5
  166. package/src/sandbox/shared/optionList.tsx +0 -5
  167. package/src/stories/Introduction.stories.mdx +0 -122
  168. package/src/stories/assets/code-brackets.svg +0 -1
  169. package/src/stories/assets/colors.svg +0 -1
  170. package/src/stories/assets/comments.svg +0 -1
  171. package/src/stories/assets/direction.svg +0 -1
  172. package/src/stories/assets/flow.svg +0 -1
  173. package/src/stories/assets/plugin.svg +0 -1
  174. package/src/stories/assets/repo.svg +0 -1
  175. package/src/stories/assets/stackalt.svg +0 -1
  176. package/src/types/index.ts +0 -3
  177. package/src/utils/NumeralPCF.ts +0 -62
  178. package/tsconfig.json +0 -28
@@ -1,143 +0,0 @@
1
- import { ComboBox } from '@talxis/react-components/dist/components/ComboBox';
2
- import React, { useEffect } from 'react';
3
- import { useInputBasedComponent } from '../../hooks/useInputBasedComponent';
4
- import { IDuration, IDurationOutputs, IDurationParameters, IDurationTranslations } from './interfaces';
5
- import { IComboBoxOption } from '@fluentui/react';
6
- import { durationOptions } from '../../sandbox/shared/durationList';
7
- import { UserSettings } from '../../sandbox/mock/UserSettings';
8
- import numeral from "numeral";
9
- import { NumeralPCF } from '../../utils/NumeralPCF';
10
- import { getDefaultDurationTranslations } from './translations';
11
-
12
- export const Duration = (props: IDuration) => {
13
- const parameters = props.parameters;
14
- const boundValue = parameters.value;
15
- const context = props.context;
16
- const humanizeDuration = require("humanize-duration");
17
- const formattingInfo = context.userSettings as UserSettings;
18
- const language = formattingInfo.locale;
19
- const numberFormatting = context.userSettings.numberFormattingInfo;
20
-
21
- const formatter = (value: number | null) => {
22
- //all duration formatting should happen here
23
- if (value === null) return null;
24
- const durationInMilliseconds = value * 60000;
25
- const units = value < 60 ? ['m'] : value >= 1440 ? ['d'] : ['h'];
26
- const options = {
27
- units: units,
28
- maxDecimalPoints: 2,
29
- language: language.slice(0, language.indexOf("-")),
30
- decimal: context.userSettings.numberFormattingInfo.numberDecimalSeparator,
31
- fallbacks: ["en"]
32
- };
33
- return humanizeDuration(durationInMilliseconds, options);
34
- };
35
-
36
- const valueExtractor = (str: string | null): number | undefined => {
37
- //extraction of number of minutes from formatted string should happen here
38
- // parsing because labels are string that represent array of strings
39
- const minuteLabels= JSON.parse(labels.minute());
40
- const minutesLabels= JSON.parse(labels.minutes());
41
- const hourLabels= JSON.parse(labels.hour());
42
- const hoursLabels= JSON.parse(labels.hours());
43
- const dayLabels= JSON.parse(labels.day());
44
- const daysLabels= JSON.parse(labels.days());
45
- const minuteRegex = new RegExp("^(" + minuteLabels.join('|') + ")\\s|\\s(" + minuteLabels.join('|') + ")$|^(" + minutesLabels.join('|') + ")\\s|\\s(" + minutesLabels.join('|') + ")$", "i");
46
- const hourRegex = new RegExp("^(" + hourLabels.join('|') + ")\\s|\\s(" + hourLabels.join('|') + ")$|^(" + hoursLabels.join('|') + ")\\s|\\s(" + hoursLabels.join('|') + ")$", "i");
47
- const dayRegex = new RegExp("^(" + dayLabels.join('|') + ")\\s|\\s(" + dayLabels.join('|') + ")$|^(" + daysLabels.join('|') + ")\\s|\\s(" + daysLabels.join('|') + ")$", "i");
48
-
49
- if (str && str.trim()) {
50
- let input = str.trim().toLowerCase();
51
- let unit = 'minute';
52
-
53
- if (minuteRegex.test(input)) {
54
- input = input.replace(minuteRegex, "").trim();
55
- } else if (hourRegex.test(input)) {
56
- input = input.replace(hourRegex, "").trim();
57
- unit = 'hour';
58
- } else if (dayRegex.test(input)) {
59
- input = input.replace(dayRegex, "").trim();
60
- unit = 'day';
61
- }
62
- const parsedNumber = parseNumber(input);
63
- if (parsedNumber && !isNaN(parsedNumber)) {
64
- return getDurationInMinutes(parsedNumber, unit);
65
- }
66
- return NaN;
67
- }
68
- return undefined;
69
- };
70
-
71
- const parseNumber = (input: string): number | undefined => {
72
- NumeralPCF.decimal(numberFormatting);
73
- return numeral(input).value() ?? undefined;
74
- };
75
-
76
- const getDurationInMinutes = (value: number, unit: string): number => {
77
- switch (unit) {
78
- case 'hour':
79
- return 60 * value;
80
- case 'day':
81
- return 60 * value * 24;
82
- case 'minute':
83
- default:
84
- return value;
85
- }
86
- };
87
-
88
- const presetOptions = (): IComboBoxOption[] => {
89
- const formattedOptions = durationOptions.map(option => ({
90
- key: option.Value.toString(),
91
- text: formatter(parseInt(option.Label)),
92
- }));
93
- return formattedOptions;
94
- };
95
-
96
- const comboBoxOptions: IComboBoxOption[] = presetOptions();
97
-
98
- const [value, labels, setValue, onNotifyOutputChanged] = useInputBasedComponent<string | null, IDurationParameters, IDurationOutputs, IDurationTranslations>('Duration', props, {
99
- formatter: formatter,
100
- valueExtractor: valueExtractor,
101
- defaultTranslations: getDefaultDurationTranslations(),
102
- });
103
-
104
- return (
105
- <ComboBox
106
- borderless={parameters.EnableBorder?.raw === false}
107
- options={comboBoxOptions}
108
- allowFreeInput={true}
109
- autoComplete='on'
110
- autofill={parameters.AutoFocus?.raw === true ? {
111
- autoFocus: true
112
- } : undefined}
113
- readOnly={context.mode.isControlDisabled}
114
- useComboBoxAsMenuWidth
115
- errorMessage={boundValue.errorMessage}
116
- text={value ?? ''}
117
- styles={{
118
- root: {
119
- height: context.mode.allocatedHeight || undefined,
120
- width: context.mode.allocatedWidth || undefined,
121
- display: 'flex',
122
- alignItems: 'center',
123
- },
124
- callout: {
125
- height: 300
126
- }
127
- }}
128
- onInputValueChange={(text) => {
129
- setValue(text ?? '');
130
- }}
131
- onBlur={(event) => {
132
- onNotifyOutputChanged({
133
- value: valueExtractor(value)
134
- });
135
- }}
136
- onChange={(e, value) => {
137
- onNotifyOutputChanged({
138
- value: valueExtractor(value?.text ?? '')
139
- });
140
- }}
141
- />
142
- );
143
- };
@@ -1,2 +0,0 @@
1
- export * from './Duration';
2
- export * from './interfaces';
@@ -1,22 +0,0 @@
1
- import { IWholeNumberProperty } from "../../interfaces";
2
- import { IComponent, IOutputs, ITranslations } from "../../interfaces/context";
3
- import { IBaseParameters } from "../../interfaces/parameters";
4
-
5
- export interface IDuration extends IComponent<IDurationParameters, IDurationOutputs, IDurationTranslations> {
6
- }
7
-
8
- export interface IDurationParameters extends IBaseParameters {
9
- value: IWholeNumberProperty;
10
- }
11
-
12
- export interface IDurationOutputs extends IOutputs {
13
- value?: number
14
- }
15
- export interface IDurationTranslations extends ITranslations {
16
- minute?: {[LCID: number]: string []}
17
- minutes?: {[LCID: number]: string[]}
18
- hour?: {[LCID: number]: string[]}
19
- hours?: {[LCID: number]: string[]}
20
- day?: {[LCID: number]: string[]}
21
- days?: {[LCID: number]: string[]}
22
- }
@@ -1,30 +0,0 @@
1
- import { IDurationTranslations } from "./interfaces";
2
-
3
- export const getDefaultDurationTranslations = (): Required<IDurationTranslations> => {
4
- return {
5
- minute: {
6
- 1029: ['min','minuta', 'minuty', 'minute', 'minutu', 'minutě', 'minutou', 'minuta', 'minuty', 'minute', 'minutu', 'minute', 'minutou'],
7
- 1033: ['min','minute']
8
- },
9
- minutes: {
10
- 1029: ['minuty', 'minut', 'minutám', 'minutách', 'minutami', 'minuty', 'minut', 'minutam', 'minutach', 'minutami'],
11
- 1033: ['minutes']
12
- },
13
- hour: {
14
- 1029: ['hod','hodina', 'hodiny', 'hodině', 'hodinu', 'hodinou', 'hodina', 'hodiny', 'hodine', 'hodinu', 'hodinou'],
15
- 1033: ['hour']
16
- },
17
- hours: {
18
- 1029: ['hodiny', 'hodin', 'hodinám', 'hodinách', 'hodinami', 'hodiny', 'hodin', 'hodinam', 'hodinach', 'hodinami'],
19
- 1033: ['hours']
20
- },
21
- day: {
22
- 1029: ['den', 'dne', 'dni', 'dnu', 'dnem', 'den', 'dne', 'dni', 'dnu', 'dnem'],
23
- 1033: ['day']
24
- },
25
- days: {
26
- 1029: ['dny', 'dnů', 'dnům', 'dnech', 'dny', 'dní', 'dny', 'dnu', 'dnom', 'dnech', 'dny', 'dni'],
27
- 1033: ['days']
28
- },
29
- };
30
- };
@@ -1,24 +0,0 @@
1
- import { createContext, useMemo } from "react";
2
- import { useComponent } from "../../hooks"
3
- import { IGridContext } from "./core/interfaces/IGridContext";
4
- import { Grid as GridModel } from "./core/model/Grid";
5
- import { IGrid } from "./interfaces";
6
- import { AgGrid } from './core/components/AgGrid/AgGrid';
7
- import React from 'react';
8
- import { gridTranslations } from './translations';
9
-
10
- export const GridContext = createContext<IGridContext>(null as any);
11
-
12
- export const Grid = (props: IGrid) => {
13
- const [labels, notifyOutputChanged] = useComponent('Grid', props, gridTranslations);
14
- const grid = useMemo(() => new GridModel(props, labels), []);
15
- grid.updateDependencies(props);
16
-
17
- return (
18
- <GridContext.Provider value={{
19
- gridInstance: grid
20
- }}>
21
- <AgGrid />
22
- </GridContext.Provider>
23
- )
24
- }
@@ -1,206 +0,0 @@
1
- import { AgGridReact } from '@ag-grid-community/react';
2
- import { MessageBar, MessageBarType, useTheme } from "@fluentui/react";
3
- import { ColumnApi, GridApi, GridState } from "@ag-grid-community/core";
4
- import { useEffect, useRef } from "react";
5
- import { useSelectionController } from "../../../selection/controllers/useSelectionController";
6
- import { useGridInstance } from "../../hooks/useGridInstance";
7
- import { getGridStyles } from "./styles";
8
- import React from 'react';
9
- import { useAgGridController } from "./controllers/useAgGridController";
10
- import { Paging } from "../../../paging/components/Paging/Paging";
11
- import { EmptyRecords } from "./components/EmptyRecordsOverlay/EmptyRecords";
12
- import { Save } from "../Save/Save";
13
- import { LoadingOverlay } from "./components/LoadingOverlay/LoadingOverlay";
14
- import { useStateValues } from '@talxis/react-components/dist/hooks';
15
- import { usePagingController } from '../../../paging/controllers/usePagingController';
16
- import { IUpdatedRecord } from '../../services/RecordUpdateService/model/RecordUpdateService';
17
-
18
- interface IAgGridState extends GridState {
19
- '__updatedRecords'?: IUpdatedRecord[]
20
- }
21
-
22
- export const AgGrid = () => {
23
- const grid = useGridInstance();
24
- const selection = useSelectionController();
25
- const gridApiRef = useRef<GridApi<ComponentFramework.PropertyHelper.DataSetApi.EntityRecord>>();
26
- const gridColumnApiRef = useRef<ColumnApi>();
27
- const containerRef = useRef<HTMLDivElement>(null);
28
- const theme = useTheme();
29
- //used for grid sizing - only the initial pageSize is relevant for this case
30
- let { agColumns, records, onGridReady } = useAgGridController(gridApiRef);
31
- const [stateValuesRef, getNewStateValues, setDefaultStateValues] = useStateValues<IAgGridState>(grid.state as IAgGridState);
32
- const pagingController = usePagingController();
33
- const pageSizeRef = useRef<number>(pagingController.pageSize);
34
- const firstRenderRef = useRef(true);
35
-
36
- useEffect(() => {
37
- const globalClickHandler = (e: MouseEvent) => {
38
- const hasAncestorWithClass = (element: HTMLElement, className: string): boolean => {
39
- let parent = element;
40
- while (!parent.classList.contains('ag-theme-balham')) {
41
- if (parent.classList.contains(className)) {
42
- return true;
43
- }
44
- if (parent.tagName === 'HTML') {
45
- return false;
46
- }
47
- parent = parent.parentElement!;
48
- if (!parent) {
49
- return true;
50
- }
51
- }
52
- return false;
53
- };
54
- try {
55
- if (!hasAncestorWithClass(e.target as HTMLElement, 'ag-cell')) {
56
- gridApiRef.current?.stopEditing();
57
- }
58
- }
59
- catch (err) {
60
- }
61
- }
62
- document.addEventListener('click', globalClickHandler)
63
- return () => {
64
- document.removeEventListener('click', globalClickHandler);
65
- if (!gridApiRef.current || grid.isNested) {
66
- return;
67
- }
68
- stateValuesRef.current.__updatedRecords = grid.recordUpdateService.updatedRecords;
69
- grid.pcfContext.mode.setControlState(getNewStateValues());
70
- }
71
- }, []);
72
-
73
- useEffect(() => {
74
- const onBeforeUnload = (ev: BeforeUnloadEvent) => {
75
- if(grid.recordUpdateService.isDirty) {
76
- ev.preventDefault();
77
- return 'Unsaved changes!'
78
- }
79
- }
80
- window.addEventListener('beforeunload', onBeforeUnload);
81
- return () => {
82
- window.removeEventListener('beforeunload', onBeforeUnload);
83
- }
84
- }, []);
85
-
86
- useEffect(() => {
87
- if (!gridApiRef.current) {
88
- return;
89
- }
90
- if (grid.loading) {
91
- gridApiRef.current.showLoadingOverlay();
92
- return;
93
- }
94
- gridApiRef.current.hideOverlay()
95
- }, [grid.loading]);
96
-
97
- useEffect(() => {
98
- if (firstRenderRef.current) {
99
- firstRenderRef.current = false;
100
- return;
101
- }
102
- gridApiRef.current?.ensureIndexVisible(0)
103
- }, [pagingController.pageNumber]);
104
-
105
-
106
-
107
- const getColumnsWidth = () => {
108
- let width = 0;
109
- for (const column of gridColumnApiRef.current!.getAllGridColumns()) {
110
- width = width + column.getActualWidth();
111
- }
112
- return width;
113
- }
114
-
115
- const getAvailableWidth = () => {
116
- const rootWrapper = containerRef.current?.querySelector('.ag-root-wrapper');
117
- return rootWrapper?.clientWidth ?? 0;
118
- }
119
-
120
- const sizeColumnsIfSpaceAvailable = () => {
121
- const totalWidth = getColumnsWidth();
122
- const availableWidth = getAvailableWidth();
123
- if (availableWidth > totalWidth) {
124
- gridApiRef.current!.sizeColumnsToFit();
125
- }
126
- }
127
-
128
- const getGridHeight = () => {
129
- if (pageSizeRef.current < grid.records.length) {
130
- return pageSizeRef.current;
131
- }
132
- return grid.records.length;
133
- }
134
-
135
- const styles = getGridStyles(theme, getGridHeight());
136
- return (
137
- <div ref={containerRef} className={`${styles.root} ag-theme-balham`}>
138
- {((grid.isEditable && grid.parameters.ChangeEditorMode?.raw !== 'edit') || grid.parameters.ChangeEditorMode?.raw === 'read') &&
139
- <Save />
140
- }
141
- {grid.error &&
142
- <MessageBar messageBarType={MessageBarType.error}>
143
- <span dangerouslySetInnerHTML={{
144
- __html: grid.errorMessage!
145
- }} />
146
- </MessageBar>
147
- }
148
- <AgGridReact
149
- animateRows
150
- rowBuffer={0}
151
- rowSelection={grid.selection.type}
152
- noRowsOverlayComponent={EmptyRecords}
153
- loadingOverlayComponent={LoadingOverlay}
154
- onRowSelected={(e) => {
155
- //prevent infinite loop since we are also setting the rows
156
- //when the selection comes from above
157
- if (e.source.includes('api')) {
158
- return;
159
- }
160
- selection.toggle(e.data!, e.node.isSelected()!)
161
- }}
162
- onCellDoubleClicked={(e) => {
163
- if (grid.isNavigationEnabled && !grid.isEditable) {
164
- grid.openDatasetItem(e.data!.getNamedReference())
165
- }
166
- }}
167
- onCellMouseOver={(e) => {
168
- if (e.colDef.colId === '__checkbox') {
169
- gridApiRef.current?.setSuppressRowClickSelection(true);
170
- }
171
- }}
172
- onCellMouseOut={(e) => {
173
- gridApiRef.current?.setSuppressRowClickSelection(false);
174
- }}
175
- getRowId={(params) => params.data.getRecordId()}
176
- onGridReady={(e) => {
177
- gridApiRef.current = e.api as any;
178
- gridColumnApiRef.current = e.columnApi;
179
- if (grid.loading) {
180
- gridApiRef.current?.showLoadingOverlay();
181
- }
182
- setDefaultStateValues({
183
- ...e.api.getState(),
184
- __updatedRecords: []
185
- });
186
- sizeColumnsIfSpaceAvailable();
187
- onGridReady();
188
- }}
189
- initialState={!grid.isNested ? stateValuesRef.current : undefined}
190
- onStateUpdated={(e) => {
191
- if (grid.isNested) {
192
- return;
193
- }
194
- stateValuesRef.current = e.state
195
- }}
196
- rowHeight={42}
197
- columnDefs={agColumns as any}
198
- rowData={records}
199
- >
200
- </AgGridReact>
201
- {grid.props.parameters.EnablePagination?.raw !== false &&
202
- <Paging />
203
- }
204
- </div>
205
- );
206
- }
@@ -1,16 +0,0 @@
1
- import React from 'react';
2
- import {Icon} from '@fluentui/react';
3
- import { useGridInstance } from '../../../../hooks/useGridInstance';
4
- import { Text } from '@fluentui/react/lib/Text';
5
- import { emptyRecordStyles } from './styles';
6
-
7
- export const EmptyRecords = () => {
8
- const labels = useGridInstance().labels;
9
-
10
- return (
11
- <div className={`${emptyRecordStyles.root} TALXIS__grid__empty-records`}>
12
- <Icon className={emptyRecordStyles.icon} iconName='SearchAndApps' />
13
- <Text>{labels.norecordsfound()}</Text>
14
- </div>
15
- )
16
- }
@@ -1,20 +0,0 @@
1
- import { mergeStyleSets } from "@fluentui/react";
2
-
3
- export const emptyRecordStyles = mergeStyleSets({
4
- root: {
5
- display: 'flex',
6
- flexDirection: 'column',
7
- gap: 10,
8
- alignItems: 'center',
9
- position: 'relative',
10
- top: 18
11
- },
12
- icon: {
13
- fontSize: 46
14
- },
15
- image: {
16
- 'img': {
17
- width: '100px'
18
- }
19
- }
20
- })
@@ -1,7 +0,0 @@
1
- import { SpinnerSize } from '@fluentui/react';
2
- import { Spinner } from '@fluentui/react/lib/components/Spinner/Spinner';
3
- import React from 'react';
4
-
5
- export const LoadingOverlay = () => {
6
- return <Spinner size={SpinnerSize.large} />
7
- }
@@ -1,68 +0,0 @@
1
- import { ColDef, GridApi } from "@ag-grid-community/core";
2
- import { useEffect, useMemo, useRef, useState } from "react";
3
- import { IEntityRecord } from "../../../../interfaces";
4
- import { useGridController } from "../../../controllers/useGridController"
5
- import { useGridInstance } from "../../../hooks/useGridInstance";
6
- import { EditableCell } from "../../Cell/EditableCell/EditableCell";
7
- import { ReadOnlyCell } from "../../Cell/ReadOnlyCell/ReadOnlyCell";
8
- import { ColumnHeader } from "../../ColumnHeader/ColumnHeader";
9
- import { GlobalCheckBox } from "../../ColumnHeader/components/GlobalCheckbox/GlobalCheckbox";
10
- import { AgGrid } from "../model/AgGrid";
11
- import { ModuleRegistry } from '@ag-grid-community/core';
12
- import { ClientSideRowModelModule } from '@ag-grid-community/client-side-row-model';
13
- import { useDebounce } from 'use-debounce';
14
- import "@ag-grid-community/styles/ag-grid.css";
15
- import "@ag-grid-community/styles/ag-theme-balham.css";
16
- ModuleRegistry.registerModules([ClientSideRowModelModule]);
17
-
18
- interface IAgGridController {
19
- agColumns: ColDef[],
20
- records: IEntityRecord[],
21
- onGridReady: () => void;
22
- }
23
-
24
- export const useAgGridController = (gridApiRef: React.MutableRefObject<GridApi<ComponentFramework.PropertyHelper.DataSetApi.EntityRecord> | undefined>): IAgGridController => {
25
- const grid = useGridInstance();
26
- const agGridReadyRef = useRef<boolean>(false);
27
- const agGrid = useMemo(() => new AgGrid(grid, gridApiRef), [])
28
- const { columns, records } = useGridController();
29
- const [agColumns, setAgColumns] = useState<ColDef[]>([]);
30
- //this is to prevent AgGrid from throwing errors in some rerender edge cases - https://github.com/ag-grid/ag-grid/issues/6013
31
- const [agRecords] = useDebounce(records, 0);
32
-
33
- useEffect(() => {
34
- if (!agGridReadyRef.current) {
35
- return;
36
- }
37
- agGrid.selectRows();
38
- }, [grid.dataset.getSelectedRecordIds().join('')]);
39
-
40
-
41
- const onGridReady = () => {
42
- agGridReadyRef.current = true;
43
- agGrid.selectRows();
44
- }
45
- useEffect(() => {
46
- if (columns.length === 0) {
47
- return;
48
- }
49
- const _agColumns = agGrid.columns;
50
- for (const agColumn of _agColumns) {
51
- agColumn.cellRenderer = ReadOnlyCell;
52
- agColumn.cellEditor = EditableCell;
53
- agColumn.headerComponent = ColumnHeader;
54
-
55
- if (agColumn.field === '__checkbox') {
56
- agColumn.lockPosition = 'left';
57
- agColumn.headerComponent = GlobalCheckBox
58
- }
59
- }
60
- setAgColumns(_agColumns);
61
- }, [columns]);
62
-
63
- return {
64
- agColumns: agColumns,
65
- records: agRecords,
66
- onGridReady: onGridReady
67
- }
68
- }
@@ -1,100 +0,0 @@
1
- import { ColDef, GridApi, IRowNode } from "@ag-grid-community/core";
2
- import { Grid } from "../../../model/Grid";
3
- import { GridDependency } from "../../../model/GridDependency";
4
- import { DataType } from "../../../enums/DataType";
5
- import { IGridColumn } from "../../../interfaces/IGridColumn";
6
-
7
- export class AgGrid extends GridDependency {
8
- private _gridApiRef: React.MutableRefObject<GridApi<ComponentFramework.PropertyHelper.DataSetApi.EntityRecord> | undefined>
9
-
10
- constructor(grid: Grid, gridApiRef: React.MutableRefObject<GridApi<ComponentFramework.PropertyHelper.DataSetApi.EntityRecord> | undefined>) {
11
- super(grid);
12
- this._gridApiRef = gridApiRef;
13
- }
14
- public get columns() {
15
- const agColumns: ColDef[] = [];
16
- for (const column of this._grid.columns) {
17
- const agColumn: ColDef = {
18
- colId: column.key,
19
- field: column.key,
20
- headerName: column.displayName,
21
- initialWidth: column.width,
22
- sortable: column.isSortable,
23
- editable: column.isEditable,
24
- resizable: column.isResizable,
25
- suppressMovable: this._grid.props.parameters.ChangeEditorMode ? true : undefined,
26
- autoHeaderHeight: true,
27
- suppressSizeToFit: column.key === '__checkbox',
28
- cellClass: this._getCellClassName(column),
29
- valueFormatter: (p) => {
30
- return p.data.getFormattedValue(column.key)
31
- },
32
- valueGetter: (p) => {
33
- return p.data.getValue(column.key)
34
- },
35
- cellRendererParams: {
36
- baseColumn: column
37
- },
38
- cellEditorParams: {
39
- baseColumn: column,
40
- },
41
- headerComponentParams: {
42
- baseColumn: column
43
- },
44
- suppressKeyboardEvent: (params) => {
45
- if (params.event.key !== 'Enter' || params.api.getEditingCells().length === 0) {
46
- return false;
47
- }
48
- switch (column.dataType) {
49
- case DataType.DATE_AND_TIME_DATE_AND_TIME:
50
- case DataType.DATE_AND_TIME_DATE_ONLY:
51
- case DataType.LOOKUP_OWNER:
52
- case DataType.LOOKUP_SIMPLE:
53
- case DataType.MULTI_SELECT_OPTIONSET:
54
- case DataType.OPTIONSET:
55
- case DataType.TWO_OPTIONS:
56
- case DataType.WHOLE_DURATION: {
57
- return true;
58
- }
59
- }
60
- return false;
61
- }
62
- }
63
- agColumns.push(agColumn)
64
- }
65
- return agColumns;
66
- }
67
- public selectRows() {
68
- if (!this._gridApi) {
69
- return;
70
- }
71
- const nodesToSelect: IRowNode[] = [];
72
- this._gridApi.deselectAll();
73
- this._gridApi.forEachNode((node: IRowNode) => {
74
- if (this._grid.dataset.getSelectedRecordIds().includes(node.data.getRecordId())) {
75
- nodesToSelect.push(node);
76
- }
77
- });
78
- this._gridApi.setNodesSelected({
79
- nodes: nodesToSelect,
80
- newValue: true
81
- });
82
- this._gridApi.refreshCells({
83
- columns: ['__checkbox'],
84
- force: true
85
- })
86
- }
87
- private get _gridApi() {
88
- return this._gridApiRef.current;
89
- }
90
- private _getCellClassName(column: IGridColumn) {
91
- switch (column.dataType) {
92
- case DataType.CURRENCY:
93
- case DataType.DECIMAL:
94
- case DataType.WHOLE_NONE: {
95
- return 'talxis-cell-align-right';
96
- }
97
- }
98
- return 'talxis-cell-align-left';
99
- }
100
- }