@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.
- package/.eslintrc +32 -0
- package/.github/workflows/CODEOWNERS +8 -0
- package/.github/workflows/pr-validation.yml +44 -0
- package/.github/workflows/release.yml +64 -0
- package/.prettierrc +6 -0
- package/.stripesclirc +4 -0
- package/CHANGELOG.md +8 -0
- package/CONTRIBUTING.md +4 -0
- package/LICENSE +201 -0
- package/README.md +16 -0
- package/administrator-documentation/roles-and-permissions.md +65 -0
- package/administrator-documentation/track-settings-admin-guide-sketch.md +192 -0
- package/administrator-documentation/using-the-application.md +192 -0
- package/icons/app.png +0 -0
- package/icons/app.svg +1 -0
- package/icons/playButton.png +0 -0
- package/icons/profilePicThumbnail.png +0 -0
- package/jest.config.js +10 -0
- package/module-descriptor.json +75 -0
- package/output/service-worker.js +0 -0
- package/package.json +146 -0
- package/src/components/incidents/ColumnChooser.js +37 -0
- package/src/components/incidents/CreateMedia.js +132 -0
- package/src/components/incidents/CreatePane.js +1215 -0
- package/src/components/incidents/CreatePane.test.js +138 -0
- package/src/components/incidents/CreateReport.js +102 -0
- package/src/components/incidents/DetailsPane.js +1267 -0
- package/src/components/incidents/DetailsPane.test.js +150 -0
- package/src/components/incidents/EditPane.js +2334 -0
- package/src/components/incidents/EditPane.test.js +187 -0
- package/src/components/incidents/GetDetails.js +55 -0
- package/src/components/incidents/GetListDQLinkIncident.js +81 -0
- package/src/components/incidents/GetListDynamicQuery.js +66 -0
- package/src/components/incidents/GetLocations.js +57 -0
- package/src/components/incidents/GetMedia.js +98 -0
- package/src/components/incidents/GetName.js +111 -0
- package/src/components/incidents/GetNameCreatedBy.js +94 -0
- package/src/components/incidents/GetOrgLocaleSettings.js +61 -0
- package/src/components/incidents/GetPatronGroups.js +52 -0
- package/src/components/incidents/GetSelf.js +65 -0
- package/src/components/incidents/GetSummary.js +110 -0
- package/src/components/incidents/IncidentTypeCard.js +53 -0
- package/src/components/incidents/IncidentTypeCard.test.js +133 -0
- package/src/components/incidents/IncidentsPaneset.js +810 -0
- package/src/components/incidents/IncidentsPaneset.test.js +128 -0
- package/src/components/incidents/LinkedIncident.js +86 -0
- package/src/components/incidents/ModalAddMedia.js +262 -0
- package/src/components/incidents/ModalAddMedia.test.js +97 -0
- package/src/components/incidents/ModalAttentionDecOfService.js +111 -0
- package/src/components/incidents/ModalCustomWitness.js +469 -0
- package/src/components/incidents/ModalCustomWitness.test.js +147 -0
- package/src/components/incidents/ModalCustomerDetails.js +480 -0
- package/src/components/incidents/ModalCustomerDetails.test.js +116 -0
- package/src/components/incidents/ModalDescribeCustomer.js +361 -0
- package/src/components/incidents/ModalDescribeCustomer.test.js +156 -0
- package/src/components/incidents/ModalDirtyFormWarn.js +62 -0
- package/src/components/incidents/ModalLinkIncident.js +1213 -0
- package/src/components/incidents/ModalLinkIncidentStyle.css +32 -0
- package/src/components/incidents/ModalSelectIncidentTypes.js +178 -0
- package/src/components/incidents/ModalSelectIncidentTypes.test.js +273 -0
- package/src/components/incidents/ModalSelectKnownCustomer.js +395 -0
- package/src/components/incidents/ModalSelectWitness.js +406 -0
- package/src/components/incidents/ModalSelectWitness.test.js +308 -0
- package/src/components/incidents/ModalStyle.css +44 -0
- package/src/components/incidents/ModalTrespass.js +741 -0
- package/src/components/incidents/ModalViewCustomerDetails.js +241 -0
- package/src/components/incidents/ModalViewMedia.js +86 -0
- package/src/components/incidents/ModalViewTrespass.js +210 -0
- package/src/components/incidents/ResultsPane.js +437 -0
- package/src/components/incidents/ResultsPane.test.js +120 -0
- package/src/components/incidents/SearchCustomerOrWitness.js +108 -0
- package/src/components/incidents/Thumbnail.js +72 -0
- package/src/components/incidents/ThumbnailMarkRemoval.js +38 -0
- package/src/components/incidents/ThumbnailSkeleton.js +30 -0
- package/src/components/incidents/ThumbnailStyles.js +49 -0
- package/src/components/incidents/ThumbnailTempPreSave.js +71 -0
- package/src/components/incidents/UpdateReport.js +84 -0
- package/src/components/incidents/__snapshots__/CreatePane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/DetailsPane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/EditPane.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/IncidentTypeCard.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/IncidentsPaneset.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalAddMedia.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalCustomerDetails.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ModalSelectWitness.test.js.snap +3 -0
- package/src/components/incidents/__snapshots__/ResultsPane.test.js.snap +3 -0
- package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.css +5 -0
- package/src/components/incidents/helpers/ProfilePicture/ProfilePicture.js +51 -0
- package/src/components/incidents/helpers/ProfilePicture/isAValidURL.js +3 -0
- package/src/components/incidents/helpers/ProfilePicture/useProfilePicture.js +127 -0
- package/src/components/incidents/helpers/buildQueryString.js +28 -0
- package/src/components/incidents/helpers/cleanFormValues.js +53 -0
- package/src/components/incidents/helpers/computeEditedCustomers.js +124 -0
- package/src/components/incidents/helpers/convertDateIgnoringTZ.js +8 -0
- package/src/components/incidents/helpers/convertUTCISOToLocalePrettyTime.js +15 -0
- package/src/components/incidents/helpers/convertUTCISOToPrettyDate.js +19 -0
- package/src/components/incidents/helpers/decodeParamsToForm.js +20 -0
- package/src/components/incidents/helpers/deepNormalizeForComparison.js +39 -0
- package/src/components/incidents/helpers/extractFilterString.js +12 -0
- package/src/components/incidents/helpers/formatDateAndTimeToUTCISO.js +14 -0
- package/src/components/incidents/helpers/formatDateToUTCISO.js +14 -0
- package/src/components/incidents/helpers/formatTimeToUTCISO.js +28 -0
- package/src/components/incidents/helpers/getCurrentTime.js +20 -0
- package/src/components/incidents/helpers/getTodayDate.js +12 -0
- package/src/components/incidents/helpers/handlebarsHelpers.js +148 -0
- package/src/components/incidents/helpers/hasFormChangedAtCreate.js +50 -0
- package/src/components/incidents/helpers/hasTopLevelChangeAffectedDeclaration.js +90 -0
- package/src/components/incidents/helpers/hasTopLevelFormChanged.js +111 -0
- package/src/components/incidents/helpers/identifyCurrentTrespassDocs.js +109 -0
- package/src/components/incidents/helpers/isSameHtml.js +13 -0
- package/src/components/incidents/helpers/isValidDateFormat.js +14 -0
- package/src/components/incidents/helpers/isValidTimeInput.js +11 -0
- package/src/components/incidents/helpers/isValidUTCTimeFormat.js +14 -0
- package/src/components/incidents/helpers/parseMMDDYYYY.js +7 -0
- package/src/components/incidents/helpers/parseQueryString.js +16 -0
- package/src/components/incidents/helpers/sortTrespassDocuments.js +44 -0
- package/src/components/incidents/helpers/stripHTML.js +11 -0
- package/src/components/incidents/helpers/trespassDocUtils.js +197 -0
- package/src/components/incidents/helpers/validateTrespassDetails.js +37 -0
- package/src/components/incidents/usePersistedColModalLink.js +70 -0
- package/src/components/incidents/usePersistedColumns.js +70 -0
- package/src/components/incidents/usePersistedSort.js +23 -0
- package/src/components/incidents/usePersistedSortModalLink.js +23 -0
- package/src/contexts/IncidentContext.js +433 -0
- package/src/index.js +61 -0
- package/src/routes/Application.js +13 -0
- package/src/settings/GetIncidentCategories.js +56 -0
- package/src/settings/GetIncidentTypesDetails.js +88 -0
- package/src/settings/GetIncidentTypesIds.js +74 -0
- package/src/settings/GetLocationsInService.js +54 -0
- package/src/settings/GetSingleCustomLocationDetails.js +60 -0
- package/src/settings/GetSingleIncidentTypeDetails.js +60 -0
- package/src/settings/GetTrespassReasons.js +67 -0
- package/src/settings/GetTrespassTemplates.js +51 -0
- package/src/settings/IncidentCategoriesPane.js +285 -0
- package/src/settings/IncidentCategoriesPane.test.js +229 -0
- package/src/settings/IncidentTypeDetailsPane.js +215 -0
- package/src/settings/IncidentTypeDetailsPane.test.js +220 -0
- package/src/settings/IncidentTypeEditPane.js +211 -0
- package/src/settings/IncidentTypeEditPane.test.js +170 -0
- package/src/settings/IncidentTypesPaneset.js +167 -0
- package/src/settings/IncidentTypesPaneset.test.js +124 -0
- package/src/settings/LocationInServiceEditPane.js +320 -0
- package/src/settings/LocationsPaneset.js +415 -0
- package/src/settings/LocationsPaneset.test.js +106 -0
- package/src/settings/ModalDeleteCategory.js +47 -0
- package/src/settings/ModalDeleteIncidentType.js +49 -0
- package/src/settings/ModalDeleteLocationInService.js +49 -0
- package/src/settings/ModalDeleteTrespassReason.js +49 -0
- package/src/settings/ModalPreviewTrespassDoc.js +65 -0
- package/src/settings/ModalTrespassDocTokens.js +83 -0
- package/src/settings/NewIncidentTypePane.js +182 -0
- package/src/settings/PutIncidentType.js +60 -0
- package/src/settings/PutLocationsInService.js +52 -0
- package/src/settings/PutTrespassReasons.js +61 -0
- package/src/settings/PutTrespassTemplate.js +50 -0
- package/src/settings/TrespassDoc.css +17 -0
- package/src/settings/TrespassDocDetailsPane.js +215 -0
- package/src/settings/TrespassDocEditPane.js +538 -0
- package/src/settings/TrespassDocPaneset.js +581 -0
- package/src/settings/TrespassReasonDetailsPane.js +171 -0
- package/src/settings/TrespassReasonEditPane.js +221 -0
- package/src/settings/TrespassReasonsPaneset.js +282 -0
- package/src/settings/__snapshots__/IncidentCategoriesPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypeDetailsPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypeEditPane.test.js.snap +3 -0
- package/src/settings/__snapshots__/IncidentTypesPaneset.test.js.snap +3 -0
- package/src/settings/__snapshots__/LocationsPaneset.test.js.snap +3 -0
- package/src/settings/data/exampleJSON.json +92 -0
- package/src/settings/data/templateTokens.js +396 -0
- package/src/settings/helpers/alphabetize.js +18 -0
- package/src/settings/helpers/getCategoryTitleById.js +13 -0
- package/src/settings/helpers/makeId.js +15 -0
- package/src/settings/index.js +48 -0
- package/stripes.config.js +10 -0
- package/test/jest/__mock__/index.js +8 -0
- package/test/jest/__mock__/intl.mock.js +27 -0
- package/test/jest/__mock__/stripes.mock.js +26 -0
- package/test/jest/__mock__/stripesComponents.mock.js +151 -0
- package/test/jest/__mock__/stripesConfig.mock.js +1 -0
- package/test/jest/__mock__/stripesCore.mock.js +9 -0
- package/test/jest/__mock__/stripesIcon.mock.js +5 -0
- package/test/jest/__mock__/stripesSmartComponents.mock.js +7 -0
- package/test/jest/__mock__/stripesUtils.mock.js +3 -0
- package/test/jest/eslintrc.js +12 -0
- package/test/jest/setupFiles.js +5 -0
- package/translations/ui-security-incident/en_US.json +542 -0
- package/ui-module-acceptance-criteria.md +34 -0
|
@@ -0,0 +1,1213 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import { useIntl } from 'react-intl';
|
|
4
|
+
import {
|
|
5
|
+
Accordion,
|
|
6
|
+
AutoSuggest,
|
|
7
|
+
Checkbox,
|
|
8
|
+
Paneset,
|
|
9
|
+
Pane,
|
|
10
|
+
SearchField,
|
|
11
|
+
Button,
|
|
12
|
+
Headline,
|
|
13
|
+
Datepicker,
|
|
14
|
+
Row,
|
|
15
|
+
Col,
|
|
16
|
+
Icon,
|
|
17
|
+
TextField,
|
|
18
|
+
RadioButton,
|
|
19
|
+
Modal,
|
|
20
|
+
ModalFooter,
|
|
21
|
+
MultiColumnList,
|
|
22
|
+
PaneHeader,
|
|
23
|
+
LoadingPane,
|
|
24
|
+
} from '@folio/stripes/components';
|
|
25
|
+
import css from './ModalLinkIncidentStyle.css';
|
|
26
|
+
import GetLocationsInService from '../../settings/GetLocationsInService';
|
|
27
|
+
import GetListDQLinkIncident from './GetListDQLinkIncident';
|
|
28
|
+
import GetLocations from './GetLocations';
|
|
29
|
+
import GetIncidentTypesDetails from '../../settings/GetIncidentTypesDetails';
|
|
30
|
+
import buildQueryString from './helpers/buildQueryString.js';
|
|
31
|
+
import cleanFormValues from './helpers/cleanFormValues.js';
|
|
32
|
+
import GetOrgLocaleSettings from './GetOrgLocaleSettings.js';
|
|
33
|
+
import usePersistedSortModalLink from './usePersistedSortModalLink.js';
|
|
34
|
+
import convertUTCISOToPrettyDate from './helpers/convertUTCISOToPrettyDate';
|
|
35
|
+
import ColumnChooser from './ColumnChooser.js';
|
|
36
|
+
import usePersistedColModalLink from './usePersistedColModalLink.js';
|
|
37
|
+
import { useIncidents } from '../../contexts/IncidentContext';
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
const ModalLinkIncident = ({
|
|
41
|
+
handleCloseModalLinkIncident,
|
|
42
|
+
toggleRowChecked,
|
|
43
|
+
ids, // linkedTo ids (CreatePane passes selectedIds, EditPane passes allLinkedToArray)
|
|
44
|
+
setIds, // setter for ids (CreatePane passes setSelectedIds, EditPane passes setAllLinkedToArray)
|
|
45
|
+
...props
|
|
46
|
+
}) => {
|
|
47
|
+
const intl = useIntl();
|
|
48
|
+
const {
|
|
49
|
+
incidentTypesNamesIdsList,
|
|
50
|
+
locationsInService,
|
|
51
|
+
isLoadingSearch,
|
|
52
|
+
organizationTimezone,
|
|
53
|
+
} = useIncidents();
|
|
54
|
+
|
|
55
|
+
const {
|
|
56
|
+
sortColumn,
|
|
57
|
+
sortDirection,
|
|
58
|
+
setSortColumn,
|
|
59
|
+
setSortDirection
|
|
60
|
+
} = usePersistedSortModalLink();
|
|
61
|
+
|
|
62
|
+
const [limit, setLimit] = useState(20); //limit value for query params, load more
|
|
63
|
+
const [offset, setOffset] = useState(0);//offset value for query params, load more
|
|
64
|
+
const [appliedFilters, setAppliedFilters] = useState(null);
|
|
65
|
+
const [incidentsListForLink, setIncidentsListForLink] = useState([]); // data for MCL
|
|
66
|
+
const [totalResultsForLink, setTotalResultsForLink] = useState(0);
|
|
67
|
+
const [readyQuery, setReadyQuery] = useState(null) // local query string
|
|
68
|
+
const [locationInputValue, setLocationInputValue] = useState('');
|
|
69
|
+
const [locationsVisibleCount, setLocationsVisibleCount] = useState(5);
|
|
70
|
+
const [locationsHasExpanded, setLocationsHasExpanded] = useState(false);
|
|
71
|
+
const [incidentTypeInputValue, setIncidentTypeInputValue] = useState('');
|
|
72
|
+
const [incidentTypesVisibleCount, setIncidentTypesVisibleCount] = useState(5);
|
|
73
|
+
const [incTypesHasExpanded, setIncTypesHasExpanded] = useState(false);
|
|
74
|
+
const [resetKey, setResetKey] = useState(0);
|
|
75
|
+
const [disableCreatedByTextField, setDisableCreatedByTextField] = useState(false);
|
|
76
|
+
const [disableWitnessedByTextField, setDisableWitnessedByTextField] = useState(false);
|
|
77
|
+
const [formSearchParams, setFormSearchParams] = useState({
|
|
78
|
+
searchType: 'keyword', // type of search (e.g. 'keyword', 'name-or-barcode')
|
|
79
|
+
term: '', // user input of search term
|
|
80
|
+
locationValue: [], // location filter set via Checkbox
|
|
81
|
+
incidentTypeId: [], // incident type filter set via Checkbox
|
|
82
|
+
witnessedBy: '', // search by who witnessed/staff involved in incident
|
|
83
|
+
createdBy: '', // search by who created the incident
|
|
84
|
+
startDate: '', // filter by incident start date
|
|
85
|
+
endDate: '', // filter by incident end date
|
|
86
|
+
currentTrespass: false, // filter by has current trespass
|
|
87
|
+
expiredTrespass: false, // filter by has expired trespass
|
|
88
|
+
timezone: '', // gets set if query with date range (no UI)
|
|
89
|
+
// includeSuppressed: false, // default show non-suppressed
|
|
90
|
+
// notIncludeSuppressed: true
|
|
91
|
+
staffSuppress: 'non' // legal values 'non'(default), 'suppressed', 'all'
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const logSelection = (label, set, total) => {
|
|
95
|
+
const ids = [...set];
|
|
96
|
+
|
|
97
|
+
console.log(
|
|
98
|
+
`[${label}] ${ids.length}/${total} selected`,
|
|
99
|
+
ids.length === total ? 'ALL rows' : '',
|
|
100
|
+
ids.sort()
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// useEffect(() => {
|
|
105
|
+
// logSelection('effect', ids, incidentsListForLink.length);
|
|
106
|
+
// }, [ids]);
|
|
107
|
+
|
|
108
|
+
const buildLocalQuery = ({
|
|
109
|
+
filters,
|
|
110
|
+
limit,
|
|
111
|
+
offset,
|
|
112
|
+
sortColumn,
|
|
113
|
+
sortDirection,
|
|
114
|
+
organizationTimezone,
|
|
115
|
+
}) => {
|
|
116
|
+
const cleaned = cleanFormValues(
|
|
117
|
+
filters,
|
|
118
|
+
organizationTimezone,
|
|
119
|
+
Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// if there's no sortColumn, pass empty strings so back end ignores sort.
|
|
123
|
+
return buildQueryString(
|
|
124
|
+
{ ...cleaned, limit, offset },
|
|
125
|
+
sortColumn || '',
|
|
126
|
+
sortColumn ? sortDirection : '' // 'asc' | 'desc' or ''
|
|
127
|
+
);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
// Compare the *filter-only* canonical strings to avoid ref churn
|
|
132
|
+
const canonical = buildQueryString(
|
|
133
|
+
cleanFormValues(formSearchParams, organizationTimezone, Intl.DateTimeFormat().resolvedOptions().timeZone),
|
|
134
|
+
);
|
|
135
|
+
const canonicalApplied = appliedFilters
|
|
136
|
+
? buildQueryString(
|
|
137
|
+
cleanFormValues(appliedFilters, organizationTimezone, Intl.DateTimeFormat().resolvedOptions().timeZone),
|
|
138
|
+
)
|
|
139
|
+
: '';
|
|
140
|
+
|
|
141
|
+
if (canonical !== canonicalApplied) {
|
|
142
|
+
// new filters -> reset to page 1
|
|
143
|
+
const nextFilters = formSearchParams;
|
|
144
|
+
const nextOffset = 0;
|
|
145
|
+
|
|
146
|
+
setAppliedFilters(nextFilters);
|
|
147
|
+
setOffset(nextOffset);
|
|
148
|
+
|
|
149
|
+
const qs = buildLocalQuery({
|
|
150
|
+
filters: nextFilters,
|
|
151
|
+
limit,
|
|
152
|
+
offset: nextOffset,
|
|
153
|
+
sortColumn,
|
|
154
|
+
sortDirection,
|
|
155
|
+
organizationTimezone,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
setReadyQuery(qs);
|
|
159
|
+
}
|
|
160
|
+
// Only re-run when the toggled filter groups change:
|
|
161
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
162
|
+
}, [
|
|
163
|
+
formSearchParams.locationValue,
|
|
164
|
+
formSearchParams.incidentTypeId,
|
|
165
|
+
formSearchParams.currentTrespass,
|
|
166
|
+
formSearchParams.expiredTrespass,
|
|
167
|
+
formSearchParams.staffSuppress,
|
|
168
|
+
organizationTimezone,
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
const handleSubmit = (resetPaging = true, overrideForm = formSearchParams) => {
|
|
172
|
+
const nextFilters = overrideForm;
|
|
173
|
+
const nextOffset = resetPaging ? 0 : offset;
|
|
174
|
+
|
|
175
|
+
setAppliedFilters(nextFilters);
|
|
176
|
+
setOffset(nextOffset);
|
|
177
|
+
|
|
178
|
+
const qs = buildLocalQuery({
|
|
179
|
+
filters: nextFilters,
|
|
180
|
+
limit,
|
|
181
|
+
offset: nextOffset,
|
|
182
|
+
sortColumn,
|
|
183
|
+
sortDirection, // already 'asc' | 'desc'
|
|
184
|
+
organizationTimezone,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
setReadyQuery(qs);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const handleSort = (_e, { name }) => {
|
|
191
|
+
const nextCol = name;
|
|
192
|
+
const nextDir = name === sortColumn && sortDirection === 'asc' ? 'desc' : 'asc';
|
|
193
|
+
|
|
194
|
+
setSortColumn(nextCol);
|
|
195
|
+
setSortDirection(nextDir);
|
|
196
|
+
|
|
197
|
+
const baseFilters = appliedFilters || formSearchParams;
|
|
198
|
+
const nextOffset = 0;
|
|
199
|
+
setOffset(nextOffset);
|
|
200
|
+
|
|
201
|
+
const qs = buildLocalQuery({
|
|
202
|
+
filters: baseFilters,
|
|
203
|
+
limit,
|
|
204
|
+
offset: nextOffset,
|
|
205
|
+
sortColumn: nextCol,
|
|
206
|
+
sortDirection: nextDir,
|
|
207
|
+
organizationTimezone,
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
setReadyQuery(qs);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
const handleLoadMore = () => {
|
|
214
|
+
const nextOffset = incidentsListForLink.length; // append after current rows
|
|
215
|
+
setOffset(nextOffset);
|
|
216
|
+
|
|
217
|
+
const baseFilters = appliedFilters || formSearchParams;
|
|
218
|
+
|
|
219
|
+
const qs = buildLocalQuery({
|
|
220
|
+
filters: baseFilters,
|
|
221
|
+
limit,
|
|
222
|
+
offset: nextOffset,
|
|
223
|
+
sortColumn,
|
|
224
|
+
sortDirection,
|
|
225
|
+
organizationTimezone,
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
setReadyQuery(qs);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
const handleResetAll = () => {
|
|
233
|
+
const blankFilters = {
|
|
234
|
+
searchType: formSearchParams.searchType,
|
|
235
|
+
term: '',
|
|
236
|
+
locationValue: [],
|
|
237
|
+
incidentTypeId: [],
|
|
238
|
+
witnessedBy: '',
|
|
239
|
+
createdBy: '',
|
|
240
|
+
startDate: '',
|
|
241
|
+
endDate: '',
|
|
242
|
+
timezone: '',
|
|
243
|
+
currentTrespass: false,
|
|
244
|
+
expiredTrespass: false,
|
|
245
|
+
staffSuppress: 'non',
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// UI resets
|
|
249
|
+
setLocationInputValue('');
|
|
250
|
+
setIncidentTypeInputValue('');
|
|
251
|
+
setResetKey((k) => k + 1);
|
|
252
|
+
setSortColumn('');
|
|
253
|
+
setSortDirection('');
|
|
254
|
+
setFormSearchParams(blankFilters);
|
|
255
|
+
|
|
256
|
+
// Run a new baseline search (page 1)
|
|
257
|
+
// handleSubmit(true, blankFilters);
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
// produce canonical (sorted) string that contains only the filter params
|
|
261
|
+
// const buildFiltersOnlyQS = (source = formSearchParams) => {
|
|
262
|
+
// const cleaned = cleanFormValues(
|
|
263
|
+
// source,
|
|
264
|
+
// organizationTimezone,
|
|
265
|
+
// Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
266
|
+
// );
|
|
267
|
+
// // drop paging, always restart at the first page
|
|
268
|
+
// const { limit: _1, offset: _0, ...filters } = cleaned;
|
|
269
|
+
// return buildQueryString(filters) // "locationValue=..." etc
|
|
270
|
+
// };
|
|
271
|
+
|
|
272
|
+
const handleClearSearchField = () => {
|
|
273
|
+
setFormSearchParams((prev) => {
|
|
274
|
+
return {
|
|
275
|
+
...prev,
|
|
276
|
+
term: '',
|
|
277
|
+
};
|
|
278
|
+
});
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
const handleKeyDown = (event) => {
|
|
282
|
+
if (event.key === 'Enter') {
|
|
283
|
+
handleSubmit(true);
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const handleParamsValueChange = (event) => {
|
|
288
|
+
const { name, value } = event.target;
|
|
289
|
+
setFormSearchParams((prev) => ({
|
|
290
|
+
...prev,
|
|
291
|
+
[name]: value,
|
|
292
|
+
}));
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const handleIndexChange = (event) => {
|
|
296
|
+
if (event.target.value === 'created-by') {
|
|
297
|
+
setDisableCreatedByTextField(true);
|
|
298
|
+
} else {
|
|
299
|
+
setDisableCreatedByTextField(false);
|
|
300
|
+
};
|
|
301
|
+
if (event.target.value === 'witnessed-by') {
|
|
302
|
+
setDisableWitnessedByTextField(true);
|
|
303
|
+
} else {
|
|
304
|
+
setDisableWitnessedByTextField(false);
|
|
305
|
+
};
|
|
306
|
+
setFormSearchParams((prev) => ({
|
|
307
|
+
...prev,
|
|
308
|
+
searchType: event.target.value,
|
|
309
|
+
}));
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const handleCreatedByChange = (event) => {
|
|
313
|
+
const { value } = event.target;
|
|
314
|
+
setFormSearchParams((prev) => {
|
|
315
|
+
const newState = { ...prev };
|
|
316
|
+
if (value) {
|
|
317
|
+
newState.createdBy = value;
|
|
318
|
+
} else {
|
|
319
|
+
delete newState.createdBy;
|
|
320
|
+
}
|
|
321
|
+
return newState;
|
|
322
|
+
});
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const handleWitnessedByChange = (event) => {
|
|
326
|
+
const { value } = event.target;
|
|
327
|
+
setFormSearchParams((prev) => {
|
|
328
|
+
const newState = { ...prev };
|
|
329
|
+
if (value) {
|
|
330
|
+
newState.witnessedBy = value;
|
|
331
|
+
} else {
|
|
332
|
+
delete newState.witnessedBy;
|
|
333
|
+
}
|
|
334
|
+
return newState;
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const handleLocationFilterChange = (value) => {
|
|
339
|
+
setFormSearchParams((prevParams) => {
|
|
340
|
+
const currentLocations = prevParams.locationValue;
|
|
341
|
+
const isChecked = currentLocations.includes(value);
|
|
342
|
+
|
|
343
|
+
// add/remove value
|
|
344
|
+
const updatedLocations = isChecked
|
|
345
|
+
? currentLocations.filter((loc) => loc !== value)
|
|
346
|
+
: [...currentLocations, value];
|
|
347
|
+
|
|
348
|
+
return {
|
|
349
|
+
...prevParams,
|
|
350
|
+
locationValue: updatedLocations
|
|
351
|
+
};
|
|
352
|
+
});
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
const handleIncidentTypeFilterChange = (value) => {
|
|
356
|
+
setFormSearchParams((prevParams) => {
|
|
357
|
+
const currentIncTypeIds = prevParams.incidentTypeId;
|
|
358
|
+
const isChecked = currentIncTypeIds.includes(value);
|
|
359
|
+
|
|
360
|
+
// add/remove value
|
|
361
|
+
const updatedIncTypeIds = isChecked
|
|
362
|
+
? currentIncTypeIds.filter((loc) => loc !== value)
|
|
363
|
+
: [...currentIncTypeIds, value];
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
...prevParams,
|
|
367
|
+
incidentTypeId: updatedIncTypeIds
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const handleTrespassFilterChange = (value) => {
|
|
373
|
+
setFormSearchParams((prev) => {
|
|
374
|
+
const params = { ...prev };
|
|
375
|
+
if (value === 'none') {
|
|
376
|
+
delete params.currentTrespass;
|
|
377
|
+
delete params.expiredTrespass;
|
|
378
|
+
};
|
|
379
|
+
if (value === 'currentTrespass') {
|
|
380
|
+
params.currentTrespass = true;
|
|
381
|
+
delete params.expiredTrespass;
|
|
382
|
+
};
|
|
383
|
+
if (value === 'expiredTrespass') {
|
|
384
|
+
params.expiredTrespass = true;
|
|
385
|
+
delete params.currentTrespass;
|
|
386
|
+
};
|
|
387
|
+
return params;
|
|
388
|
+
});
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
const handleSuppressedFilterChange = (event) => {
|
|
392
|
+
const { value } = event.target;
|
|
393
|
+
// console.log("value --> ", value);
|
|
394
|
+
setFormSearchParams((prev) => ({
|
|
395
|
+
...prev,
|
|
396
|
+
staffSuppress: value
|
|
397
|
+
}));
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const customCameraSvg = (props) => (
|
|
401
|
+
<svg
|
|
402
|
+
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 32 32" {...props}>
|
|
403
|
+
<g clipPath="url(#a)">
|
|
404
|
+
<path fill="#fff" d="M0 0h24v24H0z"/><path stroke="#000" strokeLinecap="round" strokeLinejoin="round" d="M3 8a1 1 0 0 1 1-1h4.5l1-3h5l1 3H20a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V8Z"/>
|
|
405
|
+
<circle cx="12" cy="13" r="3" stroke="#000" strokeLinejoin="round"/>
|
|
406
|
+
</g>
|
|
407
|
+
<defs>
|
|
408
|
+
<clipPath id="a">
|
|
409
|
+
<path fill="#fff" d="M0 0h24v24H0z"/></clipPath>
|
|
410
|
+
</defs>
|
|
411
|
+
</svg>
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
const inlineIconStyle = {
|
|
415
|
+
display: 'inline-flex',
|
|
416
|
+
alignItems: 'center',
|
|
417
|
+
verticalAlign: 'middle',
|
|
418
|
+
lineHeight: '1.2',
|
|
419
|
+
gap: '4px',
|
|
420
|
+
marginLeft: '8px'
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const selectAllHeader = (
|
|
424
|
+
<Checkbox
|
|
425
|
+
aria-label={<FormattedMessage id="column-mapping.select-all-or-deselect-rows-aria-label" />}
|
|
426
|
+
checked={ids.size === incidentsListForLink.length}
|
|
427
|
+
indeterminate={
|
|
428
|
+
ids.size > 0 && ids.size < incidentsListForLink.length
|
|
429
|
+
}
|
|
430
|
+
onClick={(e) => {
|
|
431
|
+
e.stopPropagation();
|
|
432
|
+
ids.size === incidentsListForLink.length
|
|
433
|
+
? setIds(new Set())
|
|
434
|
+
: setIds(new Set(incidentsListForLink.map(r => r.id)));
|
|
435
|
+
}}
|
|
436
|
+
/>
|
|
437
|
+
);
|
|
438
|
+
|
|
439
|
+
const resultsFormatter = {
|
|
440
|
+
id: (item) => {
|
|
441
|
+
return (
|
|
442
|
+
<Checkbox
|
|
443
|
+
checked={ids.has(item.id)}
|
|
444
|
+
value={item.id}
|
|
445
|
+
onClick={(e) => {
|
|
446
|
+
e.stopPropagation();
|
|
447
|
+
toggleRowChecked(item.id)
|
|
448
|
+
}}
|
|
449
|
+
onKeyDown={(e) => {
|
|
450
|
+
if (e.key === ' ' || e.key === 'Enter') e.stopPropagation();
|
|
451
|
+
}}
|
|
452
|
+
/>
|
|
453
|
+
)
|
|
454
|
+
},
|
|
455
|
+
customers: (item) => {
|
|
456
|
+
const isStaffSuppressed = item.staffSuppressed && item.staffSuppressed === true;
|
|
457
|
+
// if report has attachments of image or video, returns true
|
|
458
|
+
const hasImageOrVideo = item.attachments?.some((att) => {
|
|
459
|
+
return att.contentType.startsWith('image/') || att.contentType.startsWith('video/') || false
|
|
460
|
+
});
|
|
461
|
+
// if report has non trespass related document, returns true
|
|
462
|
+
const hasNonTrespassPDF = item.attachments?.some((att) => att.contentType === 'application/pdf' && !att.id?.toLowerCase()?.includes('trespass')) || false;
|
|
463
|
+
|
|
464
|
+
const customerNameList = item.customers?.map((cust, index) => {
|
|
465
|
+
const nameLabel = cust.customerNameLabel;
|
|
466
|
+
const custDescSnippet = cust.customerDescSnippet;
|
|
467
|
+
const trespassServed =
|
|
468
|
+
cust.trespass && cust.trespass.declarationOfService;
|
|
469
|
+
const endDateOfTrespass = cust.trespass?.endDateOfTrespass ?? null;
|
|
470
|
+
const isTrespassExpired =
|
|
471
|
+
endDateOfTrespass && new Date(endDateOfTrespass) < Date.now();
|
|
472
|
+
|
|
473
|
+
return (
|
|
474
|
+
<li key={index}>
|
|
475
|
+
{nameLabel ? nameLabel : custDescSnippet}
|
|
476
|
+
|
|
477
|
+
{/* render green check for has been served 'in hand' */}
|
|
478
|
+
{trespassServed && !isTrespassExpired ? (
|
|
479
|
+
<span style={{
|
|
480
|
+
...inlineIconStyle,
|
|
481
|
+
color: 'green'
|
|
482
|
+
}}>
|
|
483
|
+
<Icon icon="check-circle"/>
|
|
484
|
+
</span>
|
|
485
|
+
) : (
|
|
486
|
+
null
|
|
487
|
+
)}
|
|
488
|
+
{/* render X if currently trespassed, else trespass expired */}
|
|
489
|
+
{cust.trespass && !isTrespassExpired ? (
|
|
490
|
+
<span style={{
|
|
491
|
+
...inlineIconStyle,
|
|
492
|
+
color: 'red'
|
|
493
|
+
}}>
|
|
494
|
+
<Icon
|
|
495
|
+
icon="times-circle-solid" />
|
|
496
|
+
{endDateOfTrespass ?
|
|
497
|
+
convertUTCISOToPrettyDate(endDateOfTrespass)
|
|
498
|
+
: <FormattedMessage id="results-pane.customers-formatter-trespass-no-end-date"/>}
|
|
499
|
+
</span>
|
|
500
|
+
) : cust.trespass && isTrespassExpired ? (
|
|
501
|
+
<span style={{ marginLeft: '10px' }}>
|
|
502
|
+
<FormattedMessage id="results-pane.customers-formatter-trespass-expired"/>
|
|
503
|
+
</span>
|
|
504
|
+
) : (
|
|
505
|
+
null
|
|
506
|
+
)}
|
|
507
|
+
{/* render icon if report has attachment(s) of image or video or non-trespass pdf*/}
|
|
508
|
+
{hasImageOrVideo || hasNonTrespassPDF ? (
|
|
509
|
+
<span style={{ ...inlineIconStyle, marginTop: '3px', }}>
|
|
510
|
+
<Icon
|
|
511
|
+
size='large'
|
|
512
|
+
iconClassName='cameraIcon'
|
|
513
|
+
icon={customCameraSvg}
|
|
514
|
+
aria-label='camera icon'
|
|
515
|
+
/>
|
|
516
|
+
</span>
|
|
517
|
+
) : (
|
|
518
|
+
null
|
|
519
|
+
)}
|
|
520
|
+
{isStaffSuppressed ? (
|
|
521
|
+
<span
|
|
522
|
+
style={{
|
|
523
|
+
display: 'inline-block',
|
|
524
|
+
marginBottom: '4px',
|
|
525
|
+
marginLeft: '3px',
|
|
526
|
+
verticalAlign: 'middle'
|
|
527
|
+
}}>
|
|
528
|
+
<Icon size='small' icon='exclamation-circle' status='warn'>
|
|
529
|
+
</Icon>
|
|
530
|
+
</span>)
|
|
531
|
+
: (
|
|
532
|
+
null
|
|
533
|
+
)}
|
|
534
|
+
</li>
|
|
535
|
+
);
|
|
536
|
+
});
|
|
537
|
+
return <ul style={{ margin: '0' }}>
|
|
538
|
+
{customerNameList?.length > 0 ?
|
|
539
|
+
customerNameList
|
|
540
|
+
: (
|
|
541
|
+
<li>
|
|
542
|
+
<FormattedMessage
|
|
543
|
+
id="results-pane.customers-formatter-no-associated-customers"
|
|
544
|
+
/>
|
|
545
|
+
{hasImageOrVideo || hasNonTrespassPDF ? (
|
|
546
|
+
<span style={{ ...inlineIconStyle, marginTop: '3px', }}>
|
|
547
|
+
<Icon
|
|
548
|
+
size='large'
|
|
549
|
+
iconClassName='cameraIcon'
|
|
550
|
+
icon={customCameraSvg}
|
|
551
|
+
aria-label='camera icon'
|
|
552
|
+
/>
|
|
553
|
+
</span>
|
|
554
|
+
) : (
|
|
555
|
+
null
|
|
556
|
+
)}
|
|
557
|
+
{isStaffSuppressed ? (
|
|
558
|
+
<span
|
|
559
|
+
style={{
|
|
560
|
+
display: 'inline-block',
|
|
561
|
+
marginBottom: '2px',
|
|
562
|
+
marginLeft: '3px',
|
|
563
|
+
verticalAlign: 'middle'
|
|
564
|
+
|
|
565
|
+
}}>
|
|
566
|
+
<Icon size='small' icon='exclamation-circle' status='warn'>
|
|
567
|
+
</Icon>
|
|
568
|
+
</span>)
|
|
569
|
+
: (
|
|
570
|
+
null
|
|
571
|
+
)}
|
|
572
|
+
</li>
|
|
573
|
+
)
|
|
574
|
+
}
|
|
575
|
+
</ul>;
|
|
576
|
+
},
|
|
577
|
+
incidentLocation: (item) => {
|
|
578
|
+
return item.incidentLocationLabel ? item.incidentLocationLabel : item.incidentLocation
|
|
579
|
+
},
|
|
580
|
+
dateOfIncident: (item) => {
|
|
581
|
+
const readableDate = convertUTCISOToPrettyDate(item.dateTimeOfIncident);
|
|
582
|
+
return readableDate;
|
|
583
|
+
},
|
|
584
|
+
endDateOfTrespass: (item) => {
|
|
585
|
+
const readableDate = item.convertUTCISOToPrettyDate(endDateOfTrespass);
|
|
586
|
+
return readableDate;
|
|
587
|
+
},
|
|
588
|
+
incidentTypes: (item) => {
|
|
589
|
+
const typeList = item.incidentTypesLabels.map((type, index) => (
|
|
590
|
+
<li key={index} style={{ listStyleType: 'none', padding: '5px 0' }}>
|
|
591
|
+
{type}
|
|
592
|
+
</li>
|
|
593
|
+
));
|
|
594
|
+
|
|
595
|
+
return <ul style={{ padding: '0', margin: '0' }}>{typeList}</ul>;
|
|
596
|
+
},
|
|
597
|
+
incidentWitnesses: (item) => {
|
|
598
|
+
const staffInvolvedNamesAssociatedKeys = item.incidentWitnesses?.map((wit) => {
|
|
599
|
+
const witnessNameLabel = wit.witnessNameLabel;
|
|
600
|
+
return (
|
|
601
|
+
<li key={wit.id} style={{ listStyleType: 'none', padding: '5px 0' }}>
|
|
602
|
+
{`${witnessNameLabel}`}
|
|
603
|
+
</li>
|
|
604
|
+
);
|
|
605
|
+
});
|
|
606
|
+
|
|
607
|
+
return <ul style={{ padding: '0', margin: '0' }}>
|
|
608
|
+
{staffInvolvedNamesAssociatedKeys}
|
|
609
|
+
</ul>
|
|
610
|
+
},
|
|
611
|
+
createdBy: (item) => {
|
|
612
|
+
return item.createdByLabel ? item.createdByLabel
|
|
613
|
+
: `${item.createdBy?.lastName}, ${item.createdBy?.firstName}`
|
|
614
|
+
},
|
|
615
|
+
trespassExpirationDates: (item) => {
|
|
616
|
+
const { customers = [] } = item;
|
|
617
|
+
|
|
618
|
+
if (customers.length === 0) {
|
|
619
|
+
return <FormattedMessage id="no-customers" />
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
const endDates = customers
|
|
623
|
+
.map(cust => cust.trespass?.endDateOfTrespass)
|
|
624
|
+
.filter(Boolean);
|
|
625
|
+
|
|
626
|
+
if (endDates.length === 0) {
|
|
627
|
+
return <FormattedMessage id="no-trespass" />;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return (
|
|
631
|
+
<ul style={{ paddingLeft: 20, margin: 0 }}>
|
|
632
|
+
{endDates.map((date, idx) => (
|
|
633
|
+
<li key={idx}>{convertUTCISOToPrettyDate(date)}</li>
|
|
634
|
+
))}
|
|
635
|
+
</ul>
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
const incidentTypesItems = useMemo(() => {
|
|
641
|
+
const formattedIncTypes = incidentTypesNamesIdsList
|
|
642
|
+
? incidentTypesNamesIdsList.map((incident) => ({
|
|
643
|
+
value: incident.id,
|
|
644
|
+
label: incident.title,
|
|
645
|
+
}))
|
|
646
|
+
: [{
|
|
647
|
+
value: '',
|
|
648
|
+
label: <FormattedMessage
|
|
649
|
+
id="search-pane.incTypesItems-label-no-loaded"
|
|
650
|
+
/>}];
|
|
651
|
+
return formattedIncTypes;
|
|
652
|
+
}, [incidentTypesNamesIdsList]);
|
|
653
|
+
|
|
654
|
+
const locationItems = useMemo(() => {
|
|
655
|
+
const formattedLocations = locationsInService
|
|
656
|
+
? locationsInService.map((loc) => ({
|
|
657
|
+
value: loc.id,
|
|
658
|
+
label: loc.location,
|
|
659
|
+
}))
|
|
660
|
+
: [{
|
|
661
|
+
value: '',
|
|
662
|
+
label: <FormattedMessage
|
|
663
|
+
id="search-pane.locationItems-label-no-loaded"
|
|
664
|
+
/>}];
|
|
665
|
+
return formattedLocations;
|
|
666
|
+
}, [locationsInService]);
|
|
667
|
+
|
|
668
|
+
|
|
669
|
+
// START locations help
|
|
670
|
+
const allFilteredLocations = locationItems.filter(item => item.label.toLowerCase().includes(locationInputValue.toLowerCase()));
|
|
671
|
+
const filteredLocations = allFilteredLocations.slice(0, locationsVisibleCount);
|
|
672
|
+
const handleMoreLocationsClick = () => {
|
|
673
|
+
setLocationsVisibleCount((prevCount) => {
|
|
674
|
+
return Math.min(prevCount + 5, allFilteredLocations.length)
|
|
675
|
+
});
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const loadMoreLocations = () => {
|
|
679
|
+
handleMoreLocationsClick();
|
|
680
|
+
if (!locationsHasExpanded) {
|
|
681
|
+
setLocationsHasExpanded(true);
|
|
682
|
+
};
|
|
683
|
+
};
|
|
684
|
+
|
|
685
|
+
const locationsContainerStyle = {
|
|
686
|
+
maxHeight: locationsHasExpanded ? '175px' : '125px',
|
|
687
|
+
overflowX: 'clip',
|
|
688
|
+
overflowY: 'auto',
|
|
689
|
+
marginTop: '8px'
|
|
690
|
+
};
|
|
691
|
+
// END locations help
|
|
692
|
+
|
|
693
|
+
// START incident types help
|
|
694
|
+
const allFilteredIncidentTypes = incidentTypesItems.filter(item => item.label.toLowerCase().includes(incidentTypeInputValue.toLowerCase()));
|
|
695
|
+
const filteredIncidentTypes = allFilteredIncidentTypes.slice(0, incidentTypesVisibleCount);
|
|
696
|
+
const handleMoreIncidentTypesClick = () => {
|
|
697
|
+
setIncidentTypesVisibleCount((prevCount) => {
|
|
698
|
+
return Math.min(prevCount + 5, allFilteredIncidentTypes.length)
|
|
699
|
+
});
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
const loadMoreIncTypes = () => {
|
|
703
|
+
handleMoreIncidentTypesClick();
|
|
704
|
+
if (!incTypesHasExpanded) {
|
|
705
|
+
setIncTypesHasExpanded(true);
|
|
706
|
+
};
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
const incTypesContainerStyle = {
|
|
710
|
+
maxHeight: incTypesHasExpanded ? '175px' : '125px',
|
|
711
|
+
overflowX: 'clip',
|
|
712
|
+
overflowY: 'auto',
|
|
713
|
+
marginTop: '8px'
|
|
714
|
+
};
|
|
715
|
+
// END incident types help
|
|
716
|
+
|
|
717
|
+
const searchableIndexes = [
|
|
718
|
+
{
|
|
719
|
+
label: intl.formatMessage({
|
|
720
|
+
id: "search-pane.searchableIndex-label-keyword"
|
|
721
|
+
}),
|
|
722
|
+
value: 'keyword'
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
label: intl.formatMessage({
|
|
726
|
+
id: "search-pane.searchableIndex-label-name-or-barcode"
|
|
727
|
+
}),
|
|
728
|
+
value: 'name-or-barcode'
|
|
729
|
+
},
|
|
730
|
+
{
|
|
731
|
+
label: intl.formatMessage({
|
|
732
|
+
id: "search-pane.searchableIndex-label-customer-desc"
|
|
733
|
+
}),
|
|
734
|
+
value: 'customer-desc'
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
label: intl.formatMessage({
|
|
738
|
+
id: "search-pane.searchableIndex-label-witnessed-by"
|
|
739
|
+
}),
|
|
740
|
+
value: 'witnessed-by'
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
label: intl.formatMessage({
|
|
744
|
+
id: "search-pane.searchableIndex-label-created-by"
|
|
745
|
+
}),
|
|
746
|
+
value: 'created-by'
|
|
747
|
+
}
|
|
748
|
+
];
|
|
749
|
+
|
|
750
|
+
const columnWidths = {
|
|
751
|
+
customers: '375px',
|
|
752
|
+
incidentLocation: '175px',
|
|
753
|
+
dateOfIncident: '110px',
|
|
754
|
+
incidentTypes: '175px'
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
const resultCount = intl.formatMessage(
|
|
758
|
+
{ id: `results-pane.paneSubTitle` },
|
|
759
|
+
{ count: totalResultsForLink }
|
|
760
|
+
);
|
|
761
|
+
|
|
762
|
+
const fixedColumns = ['id', 'customers'];
|
|
763
|
+
const toggleableColumns = useMemo(() => [
|
|
764
|
+
'incidentLocation',
|
|
765
|
+
'dateOfIncident',
|
|
766
|
+
'incidentTypes',
|
|
767
|
+
'incidentWitnesses',
|
|
768
|
+
'createdBy',
|
|
769
|
+
'trespassExpirationDates'
|
|
770
|
+
], []);
|
|
771
|
+
const allColumns = [...fixedColumns, ...toggleableColumns];
|
|
772
|
+
const sortableFields = [...allColumns];
|
|
773
|
+
const columnLabels = {
|
|
774
|
+
customers: <FormattedMessage id="column-mapping.name" />,
|
|
775
|
+
incidentLocation: <FormattedMessage id="column-mapping.incidentLocation" />,
|
|
776
|
+
dateOfIncident: <FormattedMessage id="column-mapping.dateOfIncident" />,
|
|
777
|
+
incidentTypes: <FormattedMessage id="column-mapping.incidentTypes" />,
|
|
778
|
+
incidentWitnesses: <FormattedMessage id="column-mapping.witnessedBy" />,
|
|
779
|
+
createdBy: <FormattedMessage id="column-mapping.createdBy" />,
|
|
780
|
+
trespassExpirationDates: <FormattedMessage id="column-mapping.trespassExpirationDates" />
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
const [visibleToggleable, toggleColumn] = usePersistedColModalLink(toggleableColumns);
|
|
784
|
+
|
|
785
|
+
const visibleColumns = [...fixedColumns, ...visibleToggleable];
|
|
786
|
+
|
|
787
|
+
const actionMenu = useCallback(({ onToggle }) => (
|
|
788
|
+
<div
|
|
789
|
+
onMouseDown={(e) => e.stopPropagation()}
|
|
790
|
+
onClick={(e) => e.stopPropagation()}
|
|
791
|
+
onKeyDown={(e) => e.stopPropagation()}
|
|
792
|
+
style={{ padding: '0.5rem 0.75rem', maxWidth: 320 }}
|
|
793
|
+
>
|
|
794
|
+
<ColumnChooser
|
|
795
|
+
possibleColumns={toggleableColumns}
|
|
796
|
+
visibleColumns={visibleToggleable}
|
|
797
|
+
toggleColumn={toggleColumn}
|
|
798
|
+
columnLabels={columnLabels}
|
|
799
|
+
/>
|
|
800
|
+
</div>
|
|
801
|
+
));
|
|
802
|
+
|
|
803
|
+
const renderHeader = (renderProps) => (
|
|
804
|
+
<PaneHeader
|
|
805
|
+
{...renderProps}
|
|
806
|
+
paneTitle={<FormattedMessage id="results-pane.paneTitle" />}
|
|
807
|
+
paneSub={resultCount}
|
|
808
|
+
actionMenu={actionMenu}
|
|
809
|
+
/>
|
|
810
|
+
);
|
|
811
|
+
|
|
812
|
+
const footer = (
|
|
813
|
+
<ModalFooter>
|
|
814
|
+
<Button
|
|
815
|
+
id="close-continue-button"
|
|
816
|
+
onClick={handleCloseModalLinkIncident}
|
|
817
|
+
buttonStyle="primary"
|
|
818
|
+
marginBottom0
|
|
819
|
+
>
|
|
820
|
+
<FormattedMessage id="close-continue-button" />
|
|
821
|
+
</Button>
|
|
822
|
+
</ModalFooter>
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
return (
|
|
826
|
+
<Modal
|
|
827
|
+
enforceFocus={false}
|
|
828
|
+
style={{
|
|
829
|
+
minHeight: '550px',
|
|
830
|
+
height: '80%', // allows modal to grow/shrink based on content
|
|
831
|
+
maxHeight: '600vh',
|
|
832
|
+
maxWidth: '600vw', // modal width responsive to viewport width
|
|
833
|
+
width: '70%' // modal width adjusts based on content and window size
|
|
834
|
+
}}
|
|
835
|
+
open
|
|
836
|
+
dismissible
|
|
837
|
+
closeOnBackgroundClick
|
|
838
|
+
label={<FormattedMessage id="search-pane.paneTitle" />}
|
|
839
|
+
size="large"
|
|
840
|
+
onClose={handleCloseModalLinkIncident}
|
|
841
|
+
footer={footer}
|
|
842
|
+
contentClass={css.modalContent}
|
|
843
|
+
>
|
|
844
|
+
<div className={css.modalBody}>
|
|
845
|
+
<Paneset style={{ height: '100%', flexGrow: 1 }}>
|
|
846
|
+
<Pane
|
|
847
|
+
paneTitle={<FormattedMessage id="search-pane.paneTitle" />}
|
|
848
|
+
defaultWidth="25%"
|
|
849
|
+
{...props}
|
|
850
|
+
>
|
|
851
|
+
<div className={css.leftPaneScroll}>
|
|
852
|
+
|
|
853
|
+
{readyQuery &&
|
|
854
|
+
<GetListDQLinkIncident
|
|
855
|
+
queryStringLinkIncident={readyQuery}
|
|
856
|
+
offset={offset}
|
|
857
|
+
setIncidentsListForLink={setIncidentsListForLink}
|
|
858
|
+
setTotalResultsForLink={setTotalResultsForLink}
|
|
859
|
+
/>}
|
|
860
|
+
|
|
861
|
+
<GetIncidentTypesDetails
|
|
862
|
+
context='incidents'
|
|
863
|
+
/>
|
|
864
|
+
<GetLocationsInService />
|
|
865
|
+
<GetLocations />
|
|
866
|
+
<GetOrgLocaleSettings />
|
|
867
|
+
|
|
868
|
+
<Row style={{ marginTop: '35px' }}>
|
|
869
|
+
<Col xs={10}>
|
|
870
|
+
<Headline
|
|
871
|
+
size="large"
|
|
872
|
+
margin="medium"
|
|
873
|
+
tag="h2"
|
|
874
|
+
id="searchField-label"
|
|
875
|
+
>
|
|
876
|
+
<FormattedMessage id="search-pane.searchField-h2-label" />
|
|
877
|
+
</Headline>
|
|
878
|
+
</Col>
|
|
879
|
+
</Row>
|
|
880
|
+
|
|
881
|
+
<Row>
|
|
882
|
+
<Col xs={12}>
|
|
883
|
+
<SearchField
|
|
884
|
+
aria-labelledby="searchField-label"
|
|
885
|
+
key={resetKey}
|
|
886
|
+
onChange={handleParamsValueChange}
|
|
887
|
+
name="term"
|
|
888
|
+
value={formSearchParams.term}
|
|
889
|
+
searchableIndexes={searchableIndexes}
|
|
890
|
+
onChangeIndex={handleIndexChange}
|
|
891
|
+
onClear={handleClearSearchField}
|
|
892
|
+
onKeyDown={handleKeyDown}
|
|
893
|
+
/>
|
|
894
|
+
|
|
895
|
+
<Row style={{ marginTop: '45px' }}>
|
|
896
|
+
<Col xs={10}>
|
|
897
|
+
<Headline size="large" margin="medium" tag="h2">
|
|
898
|
+
<FormattedMessage id="search-pane.filters-h2-label" />
|
|
899
|
+
</Headline>
|
|
900
|
+
</Col>
|
|
901
|
+
</Row>
|
|
902
|
+
|
|
903
|
+
<Accordion label={
|
|
904
|
+
<FormattedMessage id="search-pane.accordion-label-location" />
|
|
905
|
+
}>
|
|
906
|
+
<Row>
|
|
907
|
+
<Col xs={10}>
|
|
908
|
+
<AutoSuggest
|
|
909
|
+
value={locationInputValue}
|
|
910
|
+
items={[]}
|
|
911
|
+
onChange={setLocationInputValue}
|
|
912
|
+
menuStyle={{ display: 'none' }}
|
|
913
|
+
renderValue={(val) => val || ''} //render item in input field
|
|
914
|
+
/>
|
|
915
|
+
</Col>
|
|
916
|
+
</Row>
|
|
917
|
+
<Row>
|
|
918
|
+
<Col xs={12} style={{ marginLeft: '10px' }}>
|
|
919
|
+
<div style={locationsContainerStyle}>
|
|
920
|
+
{filteredLocations.map((item) => (
|
|
921
|
+
<Checkbox
|
|
922
|
+
key={item.value}
|
|
923
|
+
label={item.label}
|
|
924
|
+
value={item.value}
|
|
925
|
+
checked={formSearchParams.locationValue.includes(item.value)}
|
|
926
|
+
onChange={() => handleLocationFilterChange(item.value)}
|
|
927
|
+
/>
|
|
928
|
+
))}
|
|
929
|
+
</div>
|
|
930
|
+
<div style={{ marginTop: '2px' }}>
|
|
931
|
+
{locationsVisibleCount < allFilteredLocations.length && (
|
|
932
|
+
<Button
|
|
933
|
+
onClick={loadMoreLocations}
|
|
934
|
+
>
|
|
935
|
+
<FormattedMessage id="more-button" />
|
|
936
|
+
</Button>
|
|
937
|
+
)}
|
|
938
|
+
</div>
|
|
939
|
+
</Col>
|
|
940
|
+
</Row>
|
|
941
|
+
</Accordion>
|
|
942
|
+
|
|
943
|
+
<Accordion label={
|
|
944
|
+
<FormattedMessage id="search-pane.accordion-label-incident-types" />
|
|
945
|
+
}>
|
|
946
|
+
<Row>
|
|
947
|
+
<Col xs={10}>
|
|
948
|
+
<AutoSuggest
|
|
949
|
+
value={incidentTypeInputValue}
|
|
950
|
+
items={[]}
|
|
951
|
+
onChange={setIncidentTypeInputValue}
|
|
952
|
+
menuStyle={{ display: 'none' }}
|
|
953
|
+
renderValue={(val) => val || ''} //render item in input field
|
|
954
|
+
/>
|
|
955
|
+
</Col>
|
|
956
|
+
</Row>
|
|
957
|
+
<Row>
|
|
958
|
+
<Col xs={12} style={{ marginLeft: '10px' }}>
|
|
959
|
+
<div style={incTypesContainerStyle}>
|
|
960
|
+
{filteredIncidentTypes.map((item) => (
|
|
961
|
+
<Checkbox
|
|
962
|
+
value={item.value}
|
|
963
|
+
key={item.value}
|
|
964
|
+
label={item.label}
|
|
965
|
+
checked={formSearchParams.incidentTypeId.includes(item.value)}
|
|
966
|
+
onChange={() => handleIncidentTypeFilterChange(item.value)}
|
|
967
|
+
/>
|
|
968
|
+
))}
|
|
969
|
+
</div>
|
|
970
|
+
<div style={{ marginTop: '2px' }}>
|
|
971
|
+
{incidentTypesVisibleCount < allFilteredIncidentTypes.length && (
|
|
972
|
+
<Button
|
|
973
|
+
onClick={loadMoreIncTypes}
|
|
974
|
+
>
|
|
975
|
+
<FormattedMessage id="more-button" />
|
|
976
|
+
</Button>
|
|
977
|
+
)}
|
|
978
|
+
</div>
|
|
979
|
+
</Col>
|
|
980
|
+
</Row>
|
|
981
|
+
</Accordion>
|
|
982
|
+
<hr/>
|
|
983
|
+
|
|
984
|
+
<Row style={{ marginTop: '25px'}}>
|
|
985
|
+
<Col xs={8}>
|
|
986
|
+
<TextField
|
|
987
|
+
disabled={disableWitnessedByTextField}
|
|
988
|
+
value={formSearchParams.witnessedBy || ''}
|
|
989
|
+
label={
|
|
990
|
+
<FormattedMessage id= "search-pane.witnessed-by-text-field-label"/>
|
|
991
|
+
}
|
|
992
|
+
onChange={handleWitnessedByChange}
|
|
993
|
+
/>
|
|
994
|
+
</Col>
|
|
995
|
+
</Row>
|
|
996
|
+
|
|
997
|
+
<Row>
|
|
998
|
+
<Col xs={8}>
|
|
999
|
+
<TextField
|
|
1000
|
+
disabled={disableCreatedByTextField}
|
|
1001
|
+
value={formSearchParams.createdBy || ''}
|
|
1002
|
+
label={
|
|
1003
|
+
<FormattedMessage id="search-pane.created-by-text-field-label" />
|
|
1004
|
+
}
|
|
1005
|
+
onChange={handleCreatedByChange}
|
|
1006
|
+
/>
|
|
1007
|
+
</Col>
|
|
1008
|
+
</Row>
|
|
1009
|
+
</Col>
|
|
1010
|
+
</Row>
|
|
1011
|
+
|
|
1012
|
+
<Row>
|
|
1013
|
+
<Col xs={10} style={{ marginTop: '12px' }}>
|
|
1014
|
+
<Datepicker
|
|
1015
|
+
label={
|
|
1016
|
+
<FormattedMessage id="search-pane.date-picker-from-label" />
|
|
1017
|
+
}
|
|
1018
|
+
name="startDate"
|
|
1019
|
+
value={formSearchParams.startDate || ''}
|
|
1020
|
+
onChange={handleParamsValueChange}
|
|
1021
|
+
/>
|
|
1022
|
+
<Datepicker
|
|
1023
|
+
label={<FormattedMessage id="search-pane.date-picker-to-label" />}
|
|
1024
|
+
name="endDate"
|
|
1025
|
+
value={formSearchParams.endDate || ''}
|
|
1026
|
+
onChange={handleParamsValueChange}
|
|
1027
|
+
/>
|
|
1028
|
+
</Col>
|
|
1029
|
+
</Row>
|
|
1030
|
+
|
|
1031
|
+
<Row>
|
|
1032
|
+
<Col xs={12}>
|
|
1033
|
+
<Headline size="large" tag="h2" style={{ marginTop: '15px'}}>
|
|
1034
|
+
<FormattedMessage id="search-pane.trespass-status-label" />
|
|
1035
|
+
</Headline>
|
|
1036
|
+
</Col>
|
|
1037
|
+
</Row>
|
|
1038
|
+
|
|
1039
|
+
<Row style={{ marginTop: '-15px'}}>
|
|
1040
|
+
<Col xs={12}>
|
|
1041
|
+
<RadioButton
|
|
1042
|
+
label={<FormattedMessage
|
|
1043
|
+
id="search-pane.radio-button-all-statuses-label"
|
|
1044
|
+
/>}
|
|
1045
|
+
checked={!formSearchParams.currentTrespass && !formSearchParams.expiredTrespass}
|
|
1046
|
+
onChange={() => handleTrespassFilterChange('none')}
|
|
1047
|
+
/>
|
|
1048
|
+
</Col>
|
|
1049
|
+
</Row>
|
|
1050
|
+
|
|
1051
|
+
<Row>
|
|
1052
|
+
<Col xs={12}>
|
|
1053
|
+
<RadioButton
|
|
1054
|
+
label={<FormattedMessage
|
|
1055
|
+
id="search-pane.radio-button-current-trespass-label"
|
|
1056
|
+
/>}
|
|
1057
|
+
checked={formSearchParams.currentTrespass === true}
|
|
1058
|
+
onChange={() => handleTrespassFilterChange('currentTrespass')}
|
|
1059
|
+
/>
|
|
1060
|
+
</Col>
|
|
1061
|
+
</Row>
|
|
1062
|
+
|
|
1063
|
+
<Row>
|
|
1064
|
+
<Col xs={12}>
|
|
1065
|
+
<RadioButton
|
|
1066
|
+
label={<FormattedMessage
|
|
1067
|
+
id="search-pane.radio-button-expired-trespass-label"
|
|
1068
|
+
/>}
|
|
1069
|
+
checked={formSearchParams.expiredTrespass === true}
|
|
1070
|
+
onChange={() => handleTrespassFilterChange('expiredTrespass')}
|
|
1071
|
+
/>
|
|
1072
|
+
</Col>
|
|
1073
|
+
</Row>
|
|
1074
|
+
|
|
1075
|
+
<Row style={{ marginTop: '20px' }}>
|
|
1076
|
+
<Col xs={12}>
|
|
1077
|
+
<Accordion
|
|
1078
|
+
closedByDefault
|
|
1079
|
+
label={<FormattedMessage
|
|
1080
|
+
id="search-pane.accordion-label-staff-suppressed"
|
|
1081
|
+
/>}>
|
|
1082
|
+
<Row>
|
|
1083
|
+
<Col xs={12}>
|
|
1084
|
+
<RadioButton
|
|
1085
|
+
name='staffSuppress'
|
|
1086
|
+
value='non'
|
|
1087
|
+
checked={formSearchParams.staffSuppress === 'non'}
|
|
1088
|
+
label={<FormattedMessage
|
|
1089
|
+
id="search-pane.radio-button-suppressed-non-label"
|
|
1090
|
+
/>}
|
|
1091
|
+
onChange={handleSuppressedFilterChange}
|
|
1092
|
+
/>
|
|
1093
|
+
</Col>
|
|
1094
|
+
</Row>
|
|
1095
|
+
<Row>
|
|
1096
|
+
<Col xs={12}>
|
|
1097
|
+
<RadioButton
|
|
1098
|
+
name='staffSuppress'
|
|
1099
|
+
value='suppressed'
|
|
1100
|
+
checked={formSearchParams.staffSuppress === 'suppressed'}
|
|
1101
|
+
label={<FormattedMessage
|
|
1102
|
+
id="search-pane.radio-button-suppressed-suppressed-label"
|
|
1103
|
+
/>}
|
|
1104
|
+
onChange={handleSuppressedFilterChange}
|
|
1105
|
+
/>
|
|
1106
|
+
</Col>
|
|
1107
|
+
</Row>
|
|
1108
|
+
<Row>
|
|
1109
|
+
<Col xs={12}>
|
|
1110
|
+
<RadioButton
|
|
1111
|
+
name='staffSuppress'
|
|
1112
|
+
value='all'
|
|
1113
|
+
checked={formSearchParams.staffSuppress === 'all'}
|
|
1114
|
+
label={<FormattedMessage
|
|
1115
|
+
id="search-pane.radio-button-suppressed-all-label"
|
|
1116
|
+
/>}
|
|
1117
|
+
onChange={handleSuppressedFilterChange}
|
|
1118
|
+
/>
|
|
1119
|
+
</Col>
|
|
1120
|
+
</Row>
|
|
1121
|
+
</Accordion>
|
|
1122
|
+
</Col>
|
|
1123
|
+
</Row>
|
|
1124
|
+
|
|
1125
|
+
<Row>
|
|
1126
|
+
<Col xs={12}>
|
|
1127
|
+
<Button
|
|
1128
|
+
fullWidth
|
|
1129
|
+
style={{ marginTop: '23px' }}
|
|
1130
|
+
buttonStyle="primary"
|
|
1131
|
+
onClick={() => handleSubmit(true)}
|
|
1132
|
+
>
|
|
1133
|
+
<FormattedMessage id="search-button" />
|
|
1134
|
+
</Button>
|
|
1135
|
+
</Col>
|
|
1136
|
+
</Row>
|
|
1137
|
+
|
|
1138
|
+
<Row>
|
|
1139
|
+
<Col xs={12}>
|
|
1140
|
+
<Button
|
|
1141
|
+
fullWidth
|
|
1142
|
+
style={{ backgroundColor: 'rgb(222, 221, 217)' }}
|
|
1143
|
+
buttonStyle="disabled"
|
|
1144
|
+
onClick={handleResetAll}
|
|
1145
|
+
>
|
|
1146
|
+
<Icon icon="times-circle-solid">
|
|
1147
|
+
<FormattedMessage id="search-pane.reset-all-button" />
|
|
1148
|
+
</Icon>
|
|
1149
|
+
</Button>
|
|
1150
|
+
</Col>
|
|
1151
|
+
</Row>
|
|
1152
|
+
</div>
|
|
1153
|
+
</Pane>
|
|
1154
|
+
|
|
1155
|
+
{ isLoadingSearch ? (
|
|
1156
|
+
<LoadingPane defaultWidth="fill" paneTitle="Loading results..." />
|
|
1157
|
+
) : <Pane
|
|
1158
|
+
paneTitle={<FormattedMessage id="results-pane.paneTitle"/>}
|
|
1159
|
+
id="results-pane"
|
|
1160
|
+
defaultWidth="75%"
|
|
1161
|
+
{...props}
|
|
1162
|
+
renderHeader={renderHeader}
|
|
1163
|
+
>
|
|
1164
|
+
|
|
1165
|
+
<div className={css.mclContainer}>
|
|
1166
|
+
<MultiColumnList
|
|
1167
|
+
autosize
|
|
1168
|
+
virtualize
|
|
1169
|
+
showSortIndicator
|
|
1170
|
+
sortableFields={sortableFields}
|
|
1171
|
+
onHeaderClick={handleSort}
|
|
1172
|
+
sortedColumn={sortColumn}
|
|
1173
|
+
sortDirection={sortDirection === 'desc' ? 'descending' : 'ascending'}
|
|
1174
|
+
contentData={incidentsListForLink}
|
|
1175
|
+
pageAmount={limit}
|
|
1176
|
+
totalCount={totalResultsForLink}
|
|
1177
|
+
pagingType='click'
|
|
1178
|
+
pagingOffset={incidentsListForLink.length}
|
|
1179
|
+
pagingCanGoNext={incidentsListForLink.length < totalResultsForLink}
|
|
1180
|
+
pagingCanGoPrevious={false}
|
|
1181
|
+
onNeedMoreData={() => handleLoadMore()}
|
|
1182
|
+
formatter={resultsFormatter}
|
|
1183
|
+
visibleColumns={visibleColumns}
|
|
1184
|
+
columnMapping={{
|
|
1185
|
+
id: selectAllHeader,
|
|
1186
|
+
customers: <FormattedMessage id="column-mapping.name" />,
|
|
1187
|
+
incidentLocation:
|
|
1188
|
+
<FormattedMessage id="column-mapping.incidentLocation" />
|
|
1189
|
+
,
|
|
1190
|
+
dateOfIncident:
|
|
1191
|
+
<FormattedMessage id="column-mapping.dateOfIncident" />
|
|
1192
|
+
,
|
|
1193
|
+
incidentTypes:
|
|
1194
|
+
<FormattedMessage id="column-mapping.incidentTypes" />
|
|
1195
|
+
,
|
|
1196
|
+
incidentWitnesses:
|
|
1197
|
+
<FormattedMessage id="column-mapping.witnessedBy" />,
|
|
1198
|
+
createdBy:
|
|
1199
|
+
<FormattedMessage id="column-mapping.createdBy" />,
|
|
1200
|
+
trespassExpirationDates:
|
|
1201
|
+
<FormattedMessage id="column-mapping.trespassExpirationDates" />,
|
|
1202
|
+
}}
|
|
1203
|
+
columnWidths={columnWidths}
|
|
1204
|
+
/>
|
|
1205
|
+
</div>
|
|
1206
|
+
</Pane>}
|
|
1207
|
+
</Paneset>
|
|
1208
|
+
</div>
|
|
1209
|
+
</Modal>
|
|
1210
|
+
);
|
|
1211
|
+
};
|
|
1212
|
+
|
|
1213
|
+
export default ModalLinkIncident;
|