@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,81 +0,0 @@
1
- import isNumeric from "validator/lib/isNumeric";
2
- import isEmail from "validator/lib/isEmail";
3
- import isURL from "validator/lib/isURL";
4
- import dayjs from "dayjs";
5
- import { DataType } from "../../core/enums/DataType";
6
- import { IGridColumn } from "../../core/interfaces/IGridColumn";
7
- import { GridDependency } from "../../core/model/GridDependency";
8
- import { Grid } from "../../core/model/Grid";
9
-
10
- export class ColumnValidation extends GridDependency {
11
- private _column: IGridColumn;
12
- private _forceNullCheck: boolean;
13
-
14
- constructor(grid: Grid, column: IGridColumn, forceNullCheck?: boolean) {
15
- super(grid);
16
- this._column = column;
17
- this._forceNullCheck = forceNullCheck ?? false;
18
- }
19
- public validate(value: any): [boolean, string] {
20
- const isNull = this._isNull(value);
21
- if((this._column.isRequired || this._forceNullCheck)) {
22
- if(isNull) {
23
- return [false, this._labels["validation-input-value"]()]
24
- }
25
- }
26
- //can be null
27
- else if(isNull) {
28
- return [true, ""]
29
- }
30
- switch (this._column.dataType) {
31
- case DataType.WHOLE_NONE:
32
- case DataType.DECIMAL:
33
- {
34
- value = `${value}`;
35
- if (!isNumeric(value)) {
36
- return [false, 'Invalid input!'];
37
- }
38
- break;
39
- }
40
- case DataType.SINGLE_LINE_EMAIL: {
41
- value = `${value}`;
42
- if (!isEmail(value)) {
43
- return [false, this._labels["validation-email"]()]
44
- }
45
- break;
46
- }
47
- case DataType.SINGLE_LINE_URL: {
48
- value = `${value}`;
49
- if (!isURL(value)) {
50
- return [false, this._labels["validation-url"]()]
51
- }
52
- break;
53
- }
54
- case DataType.DATE_AND_TIME_DATE_AND_TIME:
55
- case DataType.DATE_AND_TIME_DATE_ONLY: {
56
- const date = dayjs(value);
57
- if(!date.isValid()) {
58
- return [false, this._labels["validation-date"]()]
59
- }
60
- break;
61
- }
62
- default: {
63
- if(!value) {
64
- return [false, this._labels["validation-input-value"]()]
65
- }
66
- }
67
- }
68
- return [true, ""];
69
- }
70
- private _isNull(value: any) {
71
- if(!value) {
72
- return true;
73
- }
74
- if(value?.length === 0) {
75
- return true;
76
- }
77
- }
78
- private get _labels() {
79
- return this._grid.labels;
80
- }
81
- }
@@ -1,199 +0,0 @@
1
-
2
- import { ILookup } from "./interfaces";
3
- import { useLookup } from "./hooks/useLookup";
4
- import React, { useEffect, useRef } from 'react';
5
- import { useTheme } from "@fluentui/react";
6
- import { IItemProps, TagPicker } from "@talxis/react-components/dist/components/TagPicker";
7
- import { TargetSelector } from "./components/TargetSelector";
8
- import { useMouseOver } from "../../hooks/useMouseOver";
9
- import { getLookupStyles } from "./styles";
10
- import { IBasePicker } from "@fluentui/react/lib/components/pickers/BasePicker.types";
11
- import { ITag } from "@fluentui/react/lib/components/pickers/TagPicker/TagPicker.types";
12
- import { RecordCreator } from "./components/RecordCreator";
13
- import { useFocusIn } from "../../hooks/useFocusIn";
14
-
15
- export const Lookup = (props: ILookup) => {
16
- const context = props.context;
17
- const ref = useRef<HTMLDivElement>(null);
18
- const componentRef = useRef<IBasePicker<ITag>>(null);
19
- const itemLimit = props.parameters.MultipleEnabled?.raw === true ? Infinity : 1
20
- const theme = useTheme();
21
- const styles = getLookupStyles(theme, context.mode.allocatedHeight, itemLimit === 1);
22
- const [value, entities, labels, records, selectEntity, getSearchResults] = useLookup(props);
23
- const mouseOver = useMouseOver(ref);
24
- const isFocused = useFocusIn(ref);
25
- const firstRenderRef = useRef(true);
26
- const shouldFocusRef = useRef(false);
27
-
28
-
29
- useEffect(() => {
30
- if (firstRenderRef.current) {
31
- firstRenderRef.current = false;
32
- return;
33
- }
34
- //@ts-ignore
35
- if (componentRef.current.state.suggestionsVisible) {
36
- //if the suggestions callout is open and the selected target changes, refresh the results
37
- forceSearch();
38
- }
39
- }, [entities])
40
-
41
- useEffect(() => {
42
- const onKeyPress = (ev: KeyboardEvent) => {
43
- if (ev.key === 'Backspace') {
44
- const picker = ref.current?.querySelector('[class*="TALXIS__tag-picker__root"]');
45
- if ((document.activeElement === picker) && value.length === 1) {
46
- records.select(undefined);
47
- setTimeout(() => {
48
- componentRef.current?.focusInput()
49
- }, 200)
50
- }
51
- }
52
- }
53
- document.addEventListener('keydown', onKeyPress)
54
-
55
- return () => {
56
- document.removeEventListener('keydown', onKeyPress);
57
- }
58
- }, [value]);
59
-
60
- useEffect(() => {
61
- if(props.parameters.AutoFocus?.raw === true) {
62
- focus();
63
- }
64
- }, []);
65
-
66
- const focus = () => {
67
- if(componentRef.current?.items?.length === itemLimit) {
68
- //@ts-ignore
69
- ref.current?.querySelector('[class*="TALXIS__tag-picker__root"]').focus();
70
- return;
71
- }
72
- componentRef.current?.focusInput();
73
- }
74
-
75
- const forceSearch = async () => {
76
- //@ts-ignore - We need to use internal methods to show and fill the suggestions on entity change
77
- componentRef.current.suggestionStore.updateSuggestions([]);
78
- //@ts-ignore - ^^same as above
79
- componentRef.current.setState({
80
- suggestionsVisible: true,
81
- suggestionsLoading: true,
82
- });
83
- //@ts-ignore - ^^same as above
84
- const results = await onResolveSuggestions(componentRef.current.input.current.value)
85
- //@ts-ignore - ^^same as above
86
- componentRef.current.updateSuggestionsList(results);
87
- //@ts-ignore - ^^same above
88
- componentRef.current.setState({
89
- isMostRecentlyUsedVisible: false,
90
- suggestionsVisible: true,
91
- moreSuggestionsAvailable: false,
92
- });
93
- }
94
-
95
- const isComponentActive = () => {
96
- return mouseOver || isFocused;
97
- }
98
-
99
- const onResolveSuggestions = async (filter: string, selectedItems?: IItemProps[] | undefined): Promise<IItemProps[]> => {
100
- //TODO: onResolveSuggestions gets called when the record gets selected resulting in unnecessary call
101
- const results = await getSearchResults(filter);
102
- const suggestions: IItemProps[] = [];
103
- for(const result of results) {
104
- if(selectedItems?.find(x => x.key === result.id)) {
105
- continue;
106
- }
107
- const metadata = await entities.find(x => x.entityName === result.entityType)?.metadata;
108
- suggestions.push({
109
- key: result.id,
110
- text: result.name || labels.noName(),
111
- secondaryText: metadata?.DisplayName,
112
- 'data-entity': result.entityType
113
- })
114
- }
115
- return suggestions;
116
- }
117
- return (
118
- <div className={styles.root} ref={ref}>
119
- <TagPicker
120
- componentRef={componentRef}
121
- resolveDelay={200}
122
- stackItems={itemLimit === 1}
123
- pickerCalloutProps={{
124
- className: styles.suggestions,
125
- }}
126
- pickerSuggestionsProps={{
127
- loadingText: labels.searching(),
128
- noResultsFoundText: labels.noRecordsFound(),
129
- //@ts-ignore
130
- suggestionsHeaderText: <>
131
- {props.parameters.IsInlineNewEnabled?.raw !== false &&
132
- <RecordCreator labels={labels} entities={entities} onCreateRecord={records.create} />
133
- }
134
- {props.parameters.value.attributes.Targets.length > 1 &&
135
- <TargetSelector labels={labels} entities={entities} onEntitySelected={(entityName) => {
136
- selectEntity(entityName);
137
-
138
- }} />
139
- }
140
- </>
141
- }}
142
- transparent={!isComponentActive() && itemLimit === 1}
143
- onChange={(items) => {
144
- records.select(items?.map(item => {
145
- return {
146
- entityType: item['data-entity'],
147
- id: item.key,
148
- name: item.text
149
- }
150
- }))
151
- }}
152
- searchBtnProps={{
153
- iconProps: {
154
- iconName: 'Search'
155
- }
156
- }}
157
- selectedItems={value.map(lookup => {
158
- return {
159
- key: lookup.id,
160
- text: lookup.name || labels.noName(),
161
- 'data-entity': lookup.entityType,
162
- 'data-navigation-enabled': props.parameters.EnableNavigation?.raw !== false,
163
- onClick: () => {
164
- if (props.parameters.EnableNavigation?.raw === false) {
165
- return;
166
- }
167
- context.navigation.openForm({
168
- entityName: lookup.entityType,
169
- entityId: lookup.id
170
- })
171
- },
172
-
173
- deleteButtonProps: isComponentActive() || itemLimit > 1 ? {
174
- key: 'delete',
175
- iconProps: {
176
- iconName: 'ChromeClose',
177
- styles: {
178
- root: {
179
- fontSize: 12,
180
- width: 16,
181
- color: `${theme.palette.black} !important`
182
- }
183
- }
184
- },
185
- onClick: () => {
186
- shouldFocusRef.current = false;
187
- records.deselect(lookup);
188
- setTimeout(() => {
189
- focus()
190
- }, 200)
191
- }
192
- } : undefined
193
- }
194
- })}
195
- itemLimit={itemLimit}
196
- onResolveSuggestions={onResolveSuggestions} />
197
- </div>
198
- )
199
- };
@@ -1,53 +0,0 @@
1
-
2
- //@ts-nocheck - typescript
3
- import { ContextualMenuItemType, IContextualMenuItem, useTheme } from "@fluentui/react";
4
- import { CommandBarButton } from "@fluentui/react/lib/components/Button/CommandBarButton/CommandBarButton";
5
- import { IEntity, ILookupTranslations } from "../interfaces";
6
- import { getLookupStyles } from "../styles";
7
- import { StringProps } from '../../../types';
8
- import { useLoadedEntities } from "../hooks/useLoadedEntities";
9
- import React from 'react';
10
-
11
- interface IRecordCreator {
12
- labels: Required<StringProps<ILookupTranslations>>,
13
- entities: IEntity[];
14
- onCreateRecord: (entityName: string) => void;
15
- }
16
-
17
- export const RecordCreator = (props: IRecordCreator) => {
18
- const {labels, entities, onCreateRecord} = {...props};
19
- const [loadedEntities] = useLoadedEntities(entities);
20
- const theme = useTheme();
21
- const styles = getLookupStyles(theme, 0)
22
- const selectedEntity = entities.find(x => x.selected);
23
-
24
- return (
25
- <CommandBarButton
26
- className={styles.createRecordBtn}
27
- iconProps={{
28
- iconName: 'Add'
29
- }}
30
- onClick={selectedEntity ? () => onCreateRecord(selectedEntity.entityName) : undefined}
31
- menuProps={!selectedEntity ? {
32
- calloutProps: {
33
- coverTarget: false
34
- },
35
- isBeakVisible: true,
36
- items: loadedEntities ? (() => {
37
- const items: IContextualMenuItem[] = [{
38
- key: 'header',
39
- itemType: ContextualMenuItemType.Header,
40
- text: 'Vyberte tabulku'
41
- }]
42
- return [...items, ...loadedEntities.map(entity => {
43
- return {
44
- key: entity.entityName,
45
- text: entity.metadata.DisplayName,
46
- onClick: () => onCreateRecord(entity.entityName)
47
- }
48
- })];
49
- })() : []
50
- }: undefined}
51
- text={labels.newRecord()} />
52
- )
53
- }
@@ -1,43 +0,0 @@
1
- import React from 'react';
2
- import { IEntity, ILookupTranslations } from '../interfaces';
3
- import { Text } from '@fluentui/react/lib/Text';
4
- import { Link, useTheme } from '@fluentui/react';
5
- import { getLookupStyles, getTargetSelectorStyles } from '../styles';
6
- import { StringProps } from '../../../types';
7
- import { useLoadedEntities } from '../hooks/useLoadedEntities';
8
-
9
- interface ITargetSelector {
10
- labels: Required<StringProps<ILookupTranslations>>,
11
- entities: IEntity[];
12
- onEntitySelected: (entityName: string | null) => void;
13
- }
14
-
15
-
16
- export const TargetSelector = (props: ITargetSelector) => {
17
- const { labels, entities, onEntitySelected } = { ...props };
18
- const [loadedEntities] = useLoadedEntities(entities);
19
- const theme = useTheme();
20
- const styles = getTargetSelectorStyles(theme);
21
-
22
- return (
23
- <div className={styles.targetSelector}>
24
- <Text variant='small'>{labels.resultsFrom()} </Text>
25
- <div className={styles.targetSelectorLinks}>
26
- <Link
27
- onClick={() => onEntitySelected(null)}
28
- className={styles.targetSelectorLink}
29
- data-selected={!entities.find(x => x.selected)}>All</Link>
30
- {loadedEntities &&
31
- <>
32
- {loadedEntities.map((entity) => {
33
- return <Link
34
- className={styles.targetSelectorLink}
35
- data-selected={entity.selected}
36
- onClick={() => onEntitySelected(entity.entityName)}>{entity.metadata.DisplayName}</Link>
37
- })}
38
- </>
39
- }
40
- </div>
41
- </div>
42
- )
43
- }
@@ -1,31 +0,0 @@
1
- import { useRef } from "react"
2
- import { IEntity } from "../interfaces";
3
- import { Sdk } from "../lib";
4
-
5
- export const useFetchXml = (context: ComponentFramework.Context<any>): [
6
- (viewId: string) => Promise<string>,
7
- (entity: IEntity, fetchXml: string, query: string) => Promise<string>
8
- ] => {
9
- const cachedFetchXml = useRef<{
10
- [viewId: string]: Promise<ComponentFramework.WebApi.Entity>
11
- }>({});
12
-
13
- const get = async (viewId: string): Promise<string> => {
14
- if (!cachedFetchXml.current[viewId]) {
15
- cachedFetchXml.current[viewId] = context.webAPI.retrieveRecord('savedquery', viewId, '?$select=fetchxml');
16
- }
17
- return (await cachedFetchXml.current[viewId]).fetchxml;
18
- }
19
- const applyLookupQuery = async (entity: IEntity, fetchXml: string, query: string): Promise<string> => {
20
- if (!query) {
21
- return fetchXml
22
- }
23
- const metadata = await entity.metadata;
24
- const xmlObject = Sdk.FetchXml.fetch.fromXml(fetchXml);
25
- xmlObject.entity.addFilter(new Sdk.FetchXml.filter(Sdk.FetchXml.FilterType.Or, [
26
- new Sdk.FetchXml.condition(metadata.PrimaryNameAttribute, Sdk.FetchXml.Operator.Like, [new Sdk.FetchXml.value(`%${query}%`)])
27
- ]))
28
- return xmlObject.toXml();
29
- }
30
- return [get, applyLookupQuery]
31
- }
@@ -1,23 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { IEntity, IMetadata } from "../interfaces";
3
-
4
- interface ILoadedEntity extends Omit<IEntity, 'metadata'> {
5
- metadata: IMetadata
6
- }
7
-
8
- export const useLoadedEntities = (entities: IEntity[]): [ILoadedEntity[] | null] => {
9
- const [loadedEntities, setLoadedEntities] = useState<ILoadedEntity[] | null>(null);
10
- useEffect(() => {
11
- (async () => {
12
- setLoadedEntities(await Promise.all(entities.map(async entity => {
13
- return {
14
- entityName: entity.entityName,
15
- selected: entity.selected,
16
- metadata: await entity.metadata
17
- }
18
- })))
19
- })();
20
- }, [entities]);
21
-
22
- return [loadedEntities]
23
- }
@@ -1,126 +0,0 @@
1
- import { useEffect, useState } from "react";
2
- import { useComponent } from "../../../hooks";
3
- import { StringProps } from "../../../types";
4
- import { IEntity, ILookup, ILookupTranslations } from "../interfaces";
5
- import { lookupTranslations } from "../translations";
6
- import { useFetchXml } from "./useFetchXml";
7
-
8
- export const useLookup = (props: ILookup): [
9
- ComponentFramework.LookupValue[],
10
- IEntity[],
11
- Required<StringProps<ILookupTranslations>>,
12
- {
13
- create: (entityName: string) => void,
14
- select: (record: ComponentFramework.LookupValue[] | undefined) => void,
15
- deselect: (record: ComponentFramework.LookupValue) => void,
16
- },
17
- (entityName: string | null) => void,
18
- (query: string) => Promise<ComponentFramework.LookupValue[]>
19
- ] => {
20
-
21
- const targets = props.parameters.value.attributes.Targets;
22
- const boundValue = props.parameters.value.raw;
23
- const context = props.context;
24
- const [labels, notifyOutputChanged] = useComponent('Lookup', props, lookupTranslations);
25
- const [getFetchXml, applyLookupQuery] = useFetchXml(context);
26
-
27
- const [entities, setEntities] = useState<IEntity[]>(() => {
28
- return targets.map(target => {
29
- return {
30
- entityName: target,
31
- selected: targets.length === 1 ? true : false,
32
- metadata: props.context.utils.getEntityMetadata(target, []) as any,
33
- }
34
- })
35
- });
36
-
37
- const selectedEntity = entities.find(x => x.selected);
38
-
39
- const selectEntity = (entityName: string | null) => {
40
- setEntities([...entities as IEntity[]].map(entity => {
41
- return {
42
- entityName: entity.entityName,
43
- metadata: entity.metadata,
44
- selected: entity.entityName === entityName
45
- }
46
- }))
47
- }
48
-
49
- const selectRecords = (records: ComponentFramework.LookupValue[] | undefined) => {
50
- notifyOutputChanged({
51
- value: records
52
- })
53
- }
54
- const getSearchFetchXml = async (entityName: string, query: string): Promise<string> => {
55
- const response = (await props.parameters.value.getAllViews(entityName)).find(x => x.isDefault);
56
- if (!response?.viewId) {
57
- throw new Error(`Entity ${entityName} does not have a default view id!`);
58
- }
59
- let fetchXml = response?.fetchXml
60
- if(!fetchXml) {
61
- fetchXml = await getFetchXml(response.viewId)
62
- }
63
- return applyLookupQuery(entities.find(x => x.entityName === entityName)!, fetchXml, query);
64
-
65
- }
66
- const getSearchResults = async (query: string): Promise<ComponentFramework.LookupValue[]> => {
67
- const fetchXmlMap = new Map<string, Promise<string>>();
68
- if(selectedEntity) {
69
- fetchXmlMap.set(selectedEntity.entityName, getSearchFetchXml(selectedEntity.entityName, query))
70
- }
71
- else {
72
- for (const entity of targets) {
73
- fetchXmlMap.set(entity, getSearchFetchXml(entity, query))
74
- }
75
- }
76
- await Promise.all(fetchXmlMap.values());
77
- const responsePromiseMap = new Map<string, Promise<ComponentFramework.WebApi.RetrieveMultipleResponse>>()
78
- for (const [entityName, fetchXml] of fetchXmlMap) {
79
- responsePromiseMap.set(entityName, context.webAPI.retrieveMultipleRecords(entityName, `?fetchXml=${encodeURIComponent((await fetchXml))}`))
80
- }
81
- await Promise.all(responsePromiseMap.values());
82
- const result: ComponentFramework.LookupValue[] = [];
83
- for (const [entityName, response] of responsePromiseMap) {
84
- for (const entity of (await response).entities) {
85
- const entityMetadata = await entities.find(x => x.entityName === entityName)!.metadata;
86
- result.push({
87
- entityType: entityName,
88
- id: entity[entityMetadata.PrimaryIdAttribute],
89
- name: entity[entityMetadata.PrimaryNameAttribute]
90
- });
91
- }
92
- }
93
- return result;
94
- }
95
-
96
- const createRecord = async (entityName: string) => {
97
- const result = await context.navigation.openForm({
98
- entityName: entityName,
99
- useQuickCreateForm: true
100
- });
101
- if (!result.savedEntityReference) {
102
- return;
103
- }
104
- notifyOutputChanged({
105
- value: result.savedEntityReference
106
- })
107
- }
108
-
109
- const deselectRecord = (record: ComponentFramework.LookupValue) => {
110
- const map = new Map<string, ComponentFramework.LookupValue>(boundValue.map(value => [value.id, value]));
111
- map.delete(record.id);
112
- notifyOutputChanged({
113
- value: [...map.values()]
114
- })
115
- }
116
-
117
- return [
118
- boundValue, entities, labels, {
119
- create: createRecord,
120
- deselect: deselectRecord,
121
- select: selectRecords
122
- },
123
- selectEntity,
124
- getSearchResults
125
- ];
126
- };
@@ -1,2 +0,0 @@
1
- export * from './Lookup';
2
- export * from './interfaces';
@@ -1,45 +0,0 @@
1
- import { ILookupProperty, ITwoOptionsProperty } from "../../interfaces";
2
- import { IComponent, IOutputs, ITranslations } from "../../interfaces/context";
3
- import { IBaseParameters } from "../../interfaces/parameters";
4
-
5
- export interface ILookup extends IComponent<ILookupParameters, ILookupOutputs, ILookupTranslations> {
6
- /**
7
- * If provided, the Lookup will use the returned values of this function to display search results.
8
- * @param {any} entityNames An array of entity names that he Lookup is currently targeting.
9
- * @param {any} query: User text input
10
- * @returns {any}
11
- */
12
- onSearch?: (entityNames: string[], query: string) => Promise<ComponentFramework.LookupValue[]>
13
- }
14
-
15
- export interface ILookupParameters extends IBaseParameters {
16
- IsInlineNewEnabled?: ITwoOptionsProperty;
17
- MultipleEnabled?: ITwoOptionsProperty;
18
- EnableNavigation?: ITwoOptionsProperty;
19
- value: ILookupProperty;
20
- }
21
-
22
- export interface ILookupOutputs extends IOutputs {
23
- value?: ComponentFramework.LookupValue[]
24
- }
25
-
26
- export interface ILookupTranslations extends ITranslations {
27
- search: {[LCID: number]: string};
28
- newRecord: {[LCID: number]: string};
29
- searching: {[LCID: number]: string};
30
- noRecordsFound: {[LCID: number]: string};
31
- resultsFrom: {[LCID: number]: string};
32
- noName: {[LCID: number]: string};
33
- }
34
-
35
- export interface IMetadata extends ComponentFramework.PropertyHelper.EntityMetadata {
36
- DisplayName: string;
37
- PrimaryNameAttribute: string;
38
- PrimaryIdAttribute: string;
39
- }
40
-
41
- export interface IEntity {
42
- entityName: string;
43
- selected: boolean;
44
- metadata: Promise<IMetadata>
45
- }