@spokane-folio/security-incident 1.0.28

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 (188) hide show
  1. package/.eslintrc +32 -0
  2. package/.github/workflows/CODEOWNERS +8 -0
  3. package/.github/workflows/pr-validation.yml +44 -0
  4. package/.github/workflows/release.yml +64 -0
  5. package/.prettierrc +6 -0
  6. package/.stripesclirc +4 -0
  7. package/CHANGELOG.md +8 -0
  8. package/CONTRIBUTING.md +4 -0
  9. package/LICENSE +201 -0
  10. package/README.md +16 -0
  11. package/administrator-documentation/roles-and-permissions.md +65 -0
  12. package/administrator-documentation/track-settings-admin-guide-sketch.md +192 -0
  13. package/administrator-documentation/using-the-application.md +192 -0
  14. package/icons/app.png +0 -0
  15. package/icons/app.svg +1 -0
  16. package/icons/playButton.png +0 -0
  17. package/icons/profilePicThumbnail.png +0 -0
  18. package/jest.config.js +10 -0
  19. package/module-descriptor.json +75 -0
  20. package/output/service-worker.js +0 -0
  21. package/package.json +146 -0
  22. package/src/components/incidents/ColumnChooser.js +37 -0
  23. package/src/components/incidents/CreateMedia.js +132 -0
  24. package/src/components/incidents/CreatePane.js +1215 -0
  25. package/src/components/incidents/CreatePane.test.js +138 -0
  26. package/src/components/incidents/CreateReport.js +102 -0
  27. package/src/components/incidents/DetailsPane.js +1267 -0
  28. package/src/components/incidents/DetailsPane.test.js +150 -0
  29. package/src/components/incidents/EditPane.js +2334 -0
  30. package/src/components/incidents/EditPane.test.js +187 -0
  31. package/src/components/incidents/GetDetails.js +55 -0
  32. package/src/components/incidents/GetListDQLinkIncident.js +81 -0
  33. package/src/components/incidents/GetListDynamicQuery.js +66 -0
  34. package/src/components/incidents/GetLocations.js +57 -0
  35. package/src/components/incidents/GetMedia.js +98 -0
  36. package/src/components/incidents/GetName.js +111 -0
  37. package/src/components/incidents/GetNameCreatedBy.js +94 -0
  38. package/src/components/incidents/GetOrgLocaleSettings.js +61 -0
  39. package/src/components/incidents/GetPatronGroups.js +52 -0
  40. package/src/components/incidents/GetSelf.js +65 -0
  41. package/src/components/incidents/GetSummary.js +110 -0
  42. package/src/components/incidents/IncidentTypeCard.js +53 -0
  43. package/src/components/incidents/IncidentTypeCard.test.js +133 -0
  44. package/src/components/incidents/IncidentsPaneset.js +810 -0
  45. package/src/components/incidents/IncidentsPaneset.test.js +128 -0
  46. package/src/components/incidents/LinkedIncident.js +86 -0
  47. package/src/components/incidents/ModalAddMedia.js +262 -0
  48. package/src/components/incidents/ModalAddMedia.test.js +97 -0
  49. package/src/components/incidents/ModalAttentionDecOfService.js +111 -0
  50. package/src/components/incidents/ModalCustomWitness.js +469 -0
  51. package/src/components/incidents/ModalCustomWitness.test.js +147 -0
  52. package/src/components/incidents/ModalCustomerDetails.js +480 -0
  53. package/src/components/incidents/ModalCustomerDetails.test.js +116 -0
  54. package/src/components/incidents/ModalDescribeCustomer.js +361 -0
  55. package/src/components/incidents/ModalDescribeCustomer.test.js +156 -0
  56. package/src/components/incidents/ModalDirtyFormWarn.js +62 -0
  57. package/src/components/incidents/ModalLinkIncident.js +1213 -0
  58. package/src/components/incidents/ModalLinkIncidentStyle.css +32 -0
  59. package/src/components/incidents/ModalSelectIncidentTypes.js +178 -0
  60. package/src/components/incidents/ModalSelectIncidentTypes.test.js +273 -0
  61. package/src/components/incidents/ModalSelectKnownCustomer.js +395 -0
  62. package/src/components/incidents/ModalSelectWitness.js +406 -0
  63. package/src/components/incidents/ModalSelectWitness.test.js +308 -0
  64. package/src/components/incidents/ModalStyle.css +44 -0
  65. package/src/components/incidents/ModalTrespass.js +741 -0
  66. package/src/components/incidents/ModalViewCustomerDetails.js +241 -0
  67. package/src/components/incidents/ModalViewMedia.js +86 -0
  68. package/src/components/incidents/ModalViewTrespass.js +210 -0
  69. package/src/components/incidents/ResultsPane.js +437 -0
  70. package/src/components/incidents/ResultsPane.test.js +120 -0
  71. package/src/components/incidents/SearchCustomerOrWitness.js +108 -0
  72. package/src/components/incidents/Thumbnail.js +72 -0
  73. package/src/components/incidents/ThumbnailMarkRemoval.js +38 -0
  74. package/src/components/incidents/ThumbnailSkeleton.js +30 -0
  75. package/src/components/incidents/ThumbnailStyles.js +49 -0
  76. package/src/components/incidents/ThumbnailTempPreSave.js +71 -0
  77. package/src/components/incidents/UpdateReport.js +84 -0
  78. package/src/components/incidents/__snapshots__/CreatePane.test.js.snap +3 -0
  79. package/src/components/incidents/__snapshots__/DetailsPane.test.js.snap +3 -0
  80. package/src/components/incidents/__snapshots__/EditPane.test.js.snap +3 -0
  81. package/src/components/incidents/__snapshots__/IncidentTypeCard.test.js.snap +3 -0
  82. package/src/components/incidents/__snapshots__/IncidentsPaneset.test.js.snap +3 -0
  83. package/src/components/incidents/__snapshots__/ModalAddMedia.test.js.snap +3 -0
  84. package/src/components/incidents/__snapshots__/ModalCustomerDetails.test.js.snap +3 -0
  85. package/src/components/incidents/__snapshots__/ModalSelectWitness.test.js.snap +3 -0
  86. package/src/components/incidents/__snapshots__/ResultsPane.test.js.snap +3 -0
  87. package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.css +5 -0
  88. package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.js +51 -0
  89. package/src/components/incidents/helpers/ProfilePicture/isAValidURL.js +3 -0
  90. package/src/components/incidents/helpers/ProfilePicture/useProfilePicture.js +127 -0
  91. package/src/components/incidents/helpers/buildQueryString.js +28 -0
  92. package/src/components/incidents/helpers/cleanFormValues.js +53 -0
  93. package/src/components/incidents/helpers/computeEditedCustomers.js +124 -0
  94. package/src/components/incidents/helpers/convertDateIgnoringTZ.js +8 -0
  95. package/src/components/incidents/helpers/convertUTCISOToLocalePrettyTime.js +15 -0
  96. package/src/components/incidents/helpers/convertUTCISOToPrettyDate.js +19 -0
  97. package/src/components/incidents/helpers/decodeParamsToForm.js +20 -0
  98. package/src/components/incidents/helpers/deepNormalizeForComparison.js +39 -0
  99. package/src/components/incidents/helpers/extractFilterString.js +12 -0
  100. package/src/components/incidents/helpers/formatDateAndTimeToUTCISO.js +14 -0
  101. package/src/components/incidents/helpers/formatDateToUTCISO.js +14 -0
  102. package/src/components/incidents/helpers/formatTimeToUTCISO.js +28 -0
  103. package/src/components/incidents/helpers/getCurrentTime.js +20 -0
  104. package/src/components/incidents/helpers/getTodayDate.js +12 -0
  105. package/src/components/incidents/helpers/handlebarsHelpers.js +148 -0
  106. package/src/components/incidents/helpers/hasFormChangedAtCreate.js +50 -0
  107. package/src/components/incidents/helpers/hasTopLevelChangeAffectedDeclaration.js +90 -0
  108. package/src/components/incidents/helpers/hasTopLevelFormChanged.js +111 -0
  109. package/src/components/incidents/helpers/identifyCurrentTrespassDocs.js +109 -0
  110. package/src/components/incidents/helpers/isSameHtml.js +13 -0
  111. package/src/components/incidents/helpers/isValidDateFormat.js +14 -0
  112. package/src/components/incidents/helpers/isValidTimeInput.js +11 -0
  113. package/src/components/incidents/helpers/isValidUTCTimeFormat.js +14 -0
  114. package/src/components/incidents/helpers/parseMMDDYYYY.js +7 -0
  115. package/src/components/incidents/helpers/parseQueryString.js +16 -0
  116. package/src/components/incidents/helpers/sortTrespassDocuments.js +44 -0
  117. package/src/components/incidents/helpers/stripHTML.js +11 -0
  118. package/src/components/incidents/helpers/trespassDocUtils.js +197 -0
  119. package/src/components/incidents/helpers/validateTrespassDetails.js +37 -0
  120. package/src/components/incidents/usePersistedColModalLink.js +70 -0
  121. package/src/components/incidents/usePersistedColumns.js +70 -0
  122. package/src/components/incidents/usePersistedSort.js +23 -0
  123. package/src/components/incidents/usePersistedSortModalLink.js +23 -0
  124. package/src/contexts/IncidentContext.js +433 -0
  125. package/src/index.js +61 -0
  126. package/src/routes/Application.js +13 -0
  127. package/src/settings/GetIncidentCategories.js +56 -0
  128. package/src/settings/GetIncidentTypesDetails.js +88 -0
  129. package/src/settings/GetIncidentTypesIds.js +74 -0
  130. package/src/settings/GetLocationsInService.js +54 -0
  131. package/src/settings/GetSingleCustomLocationDetails.js +60 -0
  132. package/src/settings/GetSingleIncidentTypeDetails.js +60 -0
  133. package/src/settings/GetTrespassReasons.js +67 -0
  134. package/src/settings/GetTrespassTemplates.js +51 -0
  135. package/src/settings/IncidentCategoriesPane.js +285 -0
  136. package/src/settings/IncidentCategoriesPane.test.js +229 -0
  137. package/src/settings/IncidentTypeDetailsPane.js +215 -0
  138. package/src/settings/IncidentTypeDetailsPane.test.js +220 -0
  139. package/src/settings/IncidentTypeEditPane.js +211 -0
  140. package/src/settings/IncidentTypeEditPane.test.js +170 -0
  141. package/src/settings/IncidentTypesPaneset.js +167 -0
  142. package/src/settings/IncidentTypesPaneset.test.js +124 -0
  143. package/src/settings/LocationInServiceEditPane.js +320 -0
  144. package/src/settings/LocationsPaneset.js +415 -0
  145. package/src/settings/LocationsPaneset.test.js +106 -0
  146. package/src/settings/ModalDeleteCategory.js +47 -0
  147. package/src/settings/ModalDeleteIncidentType.js +49 -0
  148. package/src/settings/ModalDeleteLocationInService.js +49 -0
  149. package/src/settings/ModalDeleteTrespassReason.js +49 -0
  150. package/src/settings/ModalPreviewTrespassDoc.js +65 -0
  151. package/src/settings/ModalTrespassDocTokens.js +83 -0
  152. package/src/settings/NewIncidentTypePane.js +182 -0
  153. package/src/settings/PutIncidentType.js +60 -0
  154. package/src/settings/PutLocationsInService.js +52 -0
  155. package/src/settings/PutTrespassReasons.js +61 -0
  156. package/src/settings/PutTrespassTemplate.js +50 -0
  157. package/src/settings/TrespassDoc.css +17 -0
  158. package/src/settings/TrespassDocDetailsPane.js +215 -0
  159. package/src/settings/TrespassDocEditPane.js +538 -0
  160. package/src/settings/TrespassDocPaneset.js +581 -0
  161. package/src/settings/TrespassReasonDetailsPane.js +171 -0
  162. package/src/settings/TrespassReasonEditPane.js +221 -0
  163. package/src/settings/TrespassReasonsPaneset.js +282 -0
  164. package/src/settings/__snapshots__/IncidentCategoriesPane.test.js.snap +3 -0
  165. package/src/settings/__snapshots__/IncidentTypeDetailsPane.test.js.snap +3 -0
  166. package/src/settings/__snapshots__/IncidentTypeEditPane.test.js.snap +3 -0
  167. package/src/settings/__snapshots__/IncidentTypesPaneset.test.js.snap +3 -0
  168. package/src/settings/__snapshots__/LocationsPaneset.test.js.snap +3 -0
  169. package/src/settings/data/exampleJSON.json +92 -0
  170. package/src/settings/data/templateTokens.js +396 -0
  171. package/src/settings/helpers/alphabetize.js +18 -0
  172. package/src/settings/helpers/getCategoryTitleById.js +13 -0
  173. package/src/settings/helpers/makeId.js +15 -0
  174. package/src/settings/index.js +48 -0
  175. package/stripes.config.js +10 -0
  176. package/test/jest/__mock__/index.js +8 -0
  177. package/test/jest/__mock__/intl.mock.js +27 -0
  178. package/test/jest/__mock__/stripes.mock.js +26 -0
  179. package/test/jest/__mock__/stripesComponents.mock.js +151 -0
  180. package/test/jest/__mock__/stripesConfig.mock.js +1 -0
  181. package/test/jest/__mock__/stripesCore.mock.js +9 -0
  182. package/test/jest/__mock__/stripesIcon.mock.js +5 -0
  183. package/test/jest/__mock__/stripesSmartComponents.mock.js +7 -0
  184. package/test/jest/__mock__/stripesUtils.mock.js +3 -0
  185. package/test/jest/eslintrc.js +12 -0
  186. package/test/jest/setupFiles.js +5 -0
  187. package/translations/ui-security-incident/en_US.json +542 -0
  188. package/ui-module-acceptance-criteria.md +34 -0
@@ -0,0 +1,395 @@
1
+ import React, { useState } from 'react';
2
+ import { useIntl, FormattedMessage } from 'react-intl';
3
+ import { useStripes } from '@folio/stripes/core';
4
+ import {
5
+ Button,
6
+ Icon,
7
+ KeyValue,
8
+ LoadingPane,
9
+ Modal,
10
+ ModalFooter,
11
+ MultiColumnList,
12
+ Pane,
13
+ Paneset,
14
+ PaneHeader,
15
+ SearchField,
16
+ } from '@folio/stripes/components';
17
+ import css from './ModalStyle.css';
18
+ import { useIncidents } from '../../contexts/IncidentContext';
19
+ import ProfilePicture from './helpers/ProfilePicture/ProfilePicture.js';
20
+ import SearchCustomerOrWitness from './SearchCustomerOrWitness';
21
+
22
+ const ModalSelectKnownCustomer = ({
23
+ setFormData,
24
+ formData,
25
+ setRemovedCustomerIds,
26
+ removedCustomerIds,
27
+ context }) => {
28
+ const stripes = useStripes();
29
+ const intl = useIntl();
30
+ const [searchTerm, setSearchTerm] = useState('');
31
+ const [search, setSearch] = useState('');
32
+
33
+ const {
34
+ isModalSelectKnownCustOpen,
35
+ closeModalSelectKnownCust,
36
+ setCustomers,
37
+ customers, // response array
38
+ isLoadingSearch,
39
+ selectedCustomers,
40
+ setSelectedCustomers,
41
+ } = useIncidents();
42
+
43
+ const hasViewProfilePicturePerm = stripes.hasPerm('ui-users.profile-pictures.view');
44
+
45
+ if (!isModalSelectKnownCustOpen) {
46
+ return null;
47
+ }
48
+
49
+ let endOflistTotal = 0;
50
+
51
+ if (customers) {
52
+ endOflistTotal = customers.length;
53
+ }
54
+
55
+ const handleChange = (event) => {
56
+ const term = event.target.value;
57
+ setSearchTerm(term);
58
+ };
59
+
60
+ const handleSearchSubmit = () => {
61
+ setSearch(searchTerm.trim());
62
+ };
63
+
64
+ // toggle handler in context of edit
65
+ const handleToggleCustomer = (data) => {
66
+ const isInstanceCustomer = formData.customers.some(cust => cust.id === data.id);
67
+ const isRemovedCustomer = removedCustomerIds.includes(data.id);
68
+ // handle remove instance customer
69
+ if (isInstanceCustomer && !isRemovedCustomer) {
70
+ setFormData(prevFormData => ({
71
+ ...prevFormData,
72
+ customers: prevFormData.customers.filter(cust => cust.id !== data.id)
73
+ }));
74
+ setRemovedCustomerIds(prev => [...prev, data.id]); //mark as removed
75
+ return;
76
+ };
77
+ // handle adding / removing from selected customers
78
+ setSelectedCustomers((prevState) => {
79
+ console.log("setSelectedCustomers - prevState --> ", JSON.stringify(prevState, null, 2))
80
+ const index = prevState.findIndex((cust) => cust.id === data.id);
81
+ if (index > -1) {
82
+ // remove customer from selectedCustomers
83
+ return prevState.filter((cust) => cust.id !== data.id);
84
+ } else {
85
+ // add customer to selectedCustomers
86
+ return [...prevState, data];
87
+ }
88
+ });
89
+ // if customer previously removed,
90
+ // this treats selection as new selected customer
91
+ // and remove from removedCustomerIds
92
+ if(isRemovedCustomer) {
93
+ setRemovedCustomerIds(prev => prev.filter(id => id !== data.id));
94
+ };
95
+ // allow keyboard only users immediate access to the close button on select
96
+ document.getElementById('close-continue-button').focus();
97
+ };
98
+
99
+ // toggle handler in context of create
100
+ const handleToggleCustomerCreate = (data) => {
101
+ setSelectedCustomers((prevState) => {
102
+ const index = prevState.findIndex((cust) => cust.id === data.id);
103
+ if (index > -1) {
104
+ // remove customer from selectedCustomers
105
+ return prevState.filter((cust) => cust.id !== data.id);
106
+ } else {
107
+ // add customer to selectedCustomers
108
+ return [...prevState, data];
109
+ }
110
+ });
111
+ // allow keyboard only users immediate access to the close button on select
112
+ document.getElementById('close-continue-button').focus();
113
+ };
114
+
115
+
116
+ const handleSave = () => {
117
+ closeModalSelectKnownCust();
118
+ setCustomers([]);
119
+ setSearch('');
120
+ };
121
+
122
+ const handleDismissClose = () => {
123
+ closeModalSelectKnownCust();
124
+ setCustomers([]);
125
+ setSearch('');
126
+ };
127
+
128
+ const handleKeyDown = (event) => {
129
+ if (event.key === 'Enter') {
130
+ handleSearchSubmit();
131
+ }
132
+ };
133
+
134
+ // results formatter in context of edit
135
+ const resultsFormatter = {
136
+ active: (item) => {
137
+ const isActive = item.active === true;
138
+ return <p>{isActive ?
139
+ (<FormattedMessage id="modal-select-customer.resultsFormatter-active"/>)
140
+ :
141
+ (<FormattedMessage id="modal-select-customer.resultsFormatter-inactive"/>)}
142
+ </p>;
143
+ },
144
+ id: (item) => {
145
+ const isCustSelected = selectedCustomers.some(
146
+ (cust) => cust.id === item.id
147
+ );
148
+ const isInstanceCustomer = formData.customers.some(
149
+ (cust) => cust.id === item.id
150
+ );
151
+ const isRemovedCustomer = removedCustomerIds.includes(item.id);
152
+ const showCheckMark = (isCustSelected || isInstanceCustomer) && !isRemovedCustomer;
153
+ const buttonStyle = showCheckMark ? 'success' : 'primary';
154
+ const buttonText = showCheckMark ? <Icon icon="check-circle" /> : 'Add';
155
+ const custData = {
156
+ id: item.id,
157
+ lastName: item.lastName,
158
+ firstName: item.firstName,
159
+ barcode: item.barcode,
160
+ registered: true,
161
+ };
162
+ return (
163
+ <Button
164
+ onClick={() => handleToggleCustomer(custData)}
165
+ buttonStyle={buttonStyle}
166
+ >
167
+ {buttonText}
168
+ </Button>
169
+ );
170
+ },
171
+ name: (item) => {
172
+ if (item.middleName && item.middleName !== '') {
173
+ return `${item.lastName}, ${item.firstName} ${item.middleName}`;
174
+ } else {
175
+ return `${item.lastName}, ${item.firstName}`;
176
+ }
177
+ },
178
+ profilePicLinkOrUUID: (item) => {
179
+ return (
180
+ <div style={{
181
+ height: '100%',
182
+ width: '100%',
183
+ display: 'flex',
184
+ justifyContent: 'center', // horizontal
185
+ alignItems: 'center' // vertical
186
+ }}>
187
+ {/* fixed-size box to prevent overflow/shift */}
188
+ <div
189
+ style={{
190
+ width: 100,
191
+ height: 100,
192
+ display: 'flex',
193
+ alignItems: 'center',
194
+ justifyContent: 'center'
195
+ }}>
196
+ <ProfilePicture profilePictureLink={item.profilePicLinkOrUUID} />
197
+ </div>
198
+ </div>
199
+ )
200
+ }
201
+ };
202
+
203
+ // results formatter in context of create
204
+ const resultsFormatterCreate = {
205
+ active: (item) => {
206
+ return <p>{item.active ?
207
+ (<FormattedMessage id="modal-select-customer.resultsFormatter-active"/>)
208
+ :
209
+ (<FormattedMessage id="modal-select-customer.resultsFormatter-inactive"/>)}
210
+ </p>;
211
+ },
212
+ id: (item) => {
213
+ const isCustSelected = selectedCustomers.some(
214
+ (cust) => cust.id === item.id
215
+ );
216
+ const buttonStyle = isCustSelected ? 'success' : 'primary';
217
+ const buttonText = isCustSelected ? <Icon icon="check-circle" /> : 'Add';
218
+ const custData = {
219
+ id: item.id,
220
+ lastName: item.lastName,
221
+ firstName: item.firstName,
222
+ barcode: item.barcode,
223
+ registered: true,
224
+ };
225
+ return (
226
+ <Button
227
+ onClick={() => handleToggleCustomerCreate(custData)}
228
+ buttonStyle={buttonStyle}
229
+ >
230
+ {buttonText}
231
+ </Button>
232
+ );
233
+ },
234
+ name: (item) => {
235
+ if (item.middleName && item.middleName !== '') {
236
+ return `${item.lastName}, ${item.firstName} ${item.middleName}`;
237
+ } else {
238
+ return `${item.lastName}, ${item.firstName}`;
239
+ }
240
+ },
241
+ profilePicLinkOrUUID: (item) => {
242
+ return (
243
+ <div style={{
244
+ height: '100%',
245
+ width: '100%',
246
+ display: 'flex',
247
+ justifyContent: 'center', // horizontal
248
+ alignItems: 'center' // vertical
249
+ }}>
250
+ {/* fixed-size box to prevent overflow/shift */}
251
+ <div
252
+ style={{
253
+ width: 100,
254
+ height: 100,
255
+ display: 'flex',
256
+ alignItems: 'center',
257
+ justifyContent: 'center'
258
+ }}>
259
+ <ProfilePicture profilePictureLink={item.profilePicLinkOrUUID} />
260
+ </div>
261
+ </div>
262
+ )
263
+ }
264
+ };
265
+
266
+ const isFormDataPresent = () => {
267
+ const isTermValid = searchTerm && searchTerm.trim() !== '';
268
+ return isTermValid;
269
+ };
270
+
271
+ const resultCount = intl.formatMessage(
272
+ { id: `modal-select-customer.results-pane.paneSubTitle` },
273
+ { count: customers.length }
274
+ );
275
+
276
+ const renderHeader = (renderProps) => (
277
+ <PaneHeader
278
+ {...renderProps}
279
+ paneTitle={<FormattedMessage id="modal-select-customer.paneTitle" />}
280
+ paneSub={resultCount}
281
+ />
282
+ );
283
+
284
+ const footer = (
285
+ <ModalFooter>
286
+ <Button
287
+ id="close-continue-button"
288
+ onClick={handleSave}
289
+ buttonStyle="primary"
290
+ marginBottom0
291
+ >
292
+ <FormattedMessage id="close-continue-button" />
293
+ </Button>
294
+ <Button onClick={handleDismissClose}>
295
+ <FormattedMessage id="cancel-button" />
296
+ </Button>
297
+ </ModalFooter>
298
+ );
299
+
300
+ return (
301
+ <Modal
302
+ style={{
303
+ minHeight: '550px',
304
+ height: '80%', // allows modal to grow/shrink based on content
305
+ maxHeight: '300vh',
306
+ maxWidth: '400vw', // modal width responsive to viewport width
307
+ width: '70%' // modal width adjusts based on content and window size
308
+ }}
309
+ open
310
+ dismissible
311
+ closeOnBackgroundClick
312
+ label={<FormattedMessage id="modal-select-customer.paneTitle" />}
313
+ size="large"
314
+ onClose={handleDismissClose}
315
+ footer={footer}
316
+ contentClass={css.modalContent}
317
+ >
318
+ <div className={css.modalBody}>
319
+ {search && <SearchCustomerOrWitness term={search} />}
320
+
321
+ <Paneset style={{ height: '100%', flexGrow: 1 }}>
322
+ <Pane
323
+ paneTitle={
324
+ <FormattedMessage id="modal-select-customer.search-pane.paneTitle" />
325
+ }
326
+ defaultWidth="25%"
327
+ >
328
+ <SearchField
329
+ placeholder="Name or barcode"
330
+ value=""
331
+ onChange={handleChange}
332
+ onKeyDown={handleKeyDown}
333
+ />
334
+ <Button
335
+ disabled={!isFormDataPresent()}
336
+ onClick={handleSearchSubmit}
337
+ >
338
+ <FormattedMessage id="search-button" />
339
+ </Button>
340
+ </Pane>
341
+
342
+ {isLoadingSearch ? (
343
+ <LoadingPane
344
+ defaultWidth="fill"
345
+ paneTitle={
346
+ <FormattedMessage id="modal-select-customer.loading-pane-paneTitle" />
347
+ }
348
+ />
349
+ ) : (
350
+ <Pane
351
+ paneTitle={
352
+ <FormattedMessage id="modal-select-customer.results-pane-paneTitle" />
353
+ }
354
+ defaultWidth="75%"
355
+ style={{ overflowY: 'auto', flexGrow: 1 }}
356
+ renderHeader={renderHeader}
357
+ >
358
+ <div className={css.mclContainer}>
359
+ <MultiColumnList
360
+ autosize
361
+ virtualize
362
+ totalCount={endOflistTotal}
363
+ contentData={customers}
364
+ columnWidths={{ profilePicLinkOrUUID: '120px' }}
365
+ visibleColumns={hasViewProfilePicturePerm ? [
366
+ 'name',
367
+ 'active',
368
+ 'barcode',
369
+ 'profilePicLinkOrUUID',
370
+ 'id'
371
+ ] : [
372
+ 'name',
373
+ 'active',
374
+ 'barcode',
375
+ 'id'
376
+ ]}
377
+ columnMapping={{
378
+ name: <FormattedMessage id="column-mapping.name" />,
379
+ active: <FormattedMessage id="column-mapping.active" />,
380
+ barcode: <FormattedMessage id="column-mapping.barcode" />,
381
+ profilePicLinkOrUUID: <FormattedMessage id="column-mapping.profilePicture" />,
382
+ id: 'Add',
383
+ }}
384
+ formatter={context === 'edit' ? resultsFormatter : resultsFormatterCreate}
385
+ />
386
+ </div>
387
+ </Pane>
388
+ )}
389
+ </Paneset>
390
+ </div>
391
+ </Modal>
392
+ );
393
+ };
394
+
395
+ export default ModalSelectKnownCustomer;