@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,1267 @@
|
|
|
1
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
+
import { useIntl, FormattedMessage } from 'react-intl';
|
|
3
|
+
import { useParams, useHistory, useLocation } from 'react-router-dom';
|
|
4
|
+
import { useStripes } from '@folio/stripes/core';
|
|
5
|
+
import {
|
|
6
|
+
Avatar,
|
|
7
|
+
Button,
|
|
8
|
+
Headline,
|
|
9
|
+
Icon,
|
|
10
|
+
KeyValue,
|
|
11
|
+
Pane,
|
|
12
|
+
PaneHeader,
|
|
13
|
+
AccordionSet,
|
|
14
|
+
Accordion,
|
|
15
|
+
ExpandAllButton,
|
|
16
|
+
Label,
|
|
17
|
+
MetaSection,
|
|
18
|
+
MessageBanner,
|
|
19
|
+
Row,
|
|
20
|
+
Col,
|
|
21
|
+
LoadingPane,
|
|
22
|
+
List,
|
|
23
|
+
} from '@folio/stripes/components';
|
|
24
|
+
import ProfilePicture from './helpers/ProfilePicture/ProfilePicture.js';
|
|
25
|
+
import GetDetails from './GetDetails';
|
|
26
|
+
import GetName from './GetName';
|
|
27
|
+
import GetNameCreatedBy from './GetNameCreatedBy';
|
|
28
|
+
import identifyCurrentTrespassDocs from './helpers/identifyCurrentTrespassDocs';
|
|
29
|
+
import GetLocationsInService from '../../settings/GetLocationsInService';
|
|
30
|
+
import GetIncidentTypesDetails from '../../settings/GetIncidentTypesDetails';
|
|
31
|
+
import ModalViewMedia from './ModalViewMedia';
|
|
32
|
+
import GetMedia from './GetMedia';
|
|
33
|
+
import Thumbnail from './Thumbnail';
|
|
34
|
+
import ThumbnailSkeleton from './ThumbnailSkeleton';
|
|
35
|
+
import ModalCustomWitness from './ModalCustomWitness';
|
|
36
|
+
// used for rendering instance values where only the date is considered:
|
|
37
|
+
import convertDateIgnoringTZ from './helpers/convertDateIgnoringTZ';
|
|
38
|
+
// convert for UI presentation:
|
|
39
|
+
import convertUTCISOToPrettyDate from './helpers/convertUTCISOToPrettyDate';
|
|
40
|
+
// convert for UI presentation:
|
|
41
|
+
import convertUTCISOToLocalePrettyTime from './helpers/convertUTCISOToLocalePrettyTime';
|
|
42
|
+
import sortTrespassDocuments from './helpers/sortTrespassDocuments.js';
|
|
43
|
+
import GetTrespassReasons from '../../settings/GetTrespassReasons';
|
|
44
|
+
import LinkedIncident from './LinkedIncident.js';
|
|
45
|
+
import { useIncidents } from '../../contexts/IncidentContext';
|
|
46
|
+
|
|
47
|
+
const DetailsPane = ({
|
|
48
|
+
...props
|
|
49
|
+
}) => {
|
|
50
|
+
const stripes = useStripes();
|
|
51
|
+
const { id } = useParams();
|
|
52
|
+
const history = useHistory();
|
|
53
|
+
const location = useLocation();
|
|
54
|
+
const intl = useIntl();
|
|
55
|
+
const {
|
|
56
|
+
singleIncident, setSingleIncident,
|
|
57
|
+
closeDetailsPane,
|
|
58
|
+
openEditPane,
|
|
59
|
+
openLoadingDetails,
|
|
60
|
+
isLoadingDetails,
|
|
61
|
+
isModalViewImage,
|
|
62
|
+
openModalViewImage,
|
|
63
|
+
mode,
|
|
64
|
+
incidentTypesList,
|
|
65
|
+
locationsInService,
|
|
66
|
+
isImageArrayLoading,
|
|
67
|
+
openImageSkeleton, // set isImageArrayLoading to true
|
|
68
|
+
closeImageSkeleton, // set isImageArrayLoading to false
|
|
69
|
+
openModalCustomWitness,
|
|
70
|
+
documentError,
|
|
71
|
+
documentErrorMessage,
|
|
72
|
+
clearDocumentError,
|
|
73
|
+
trespassReasons
|
|
74
|
+
} = useIncidents();
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (id) {
|
|
78
|
+
setSingleIncident({})
|
|
79
|
+
openLoadingDetails();
|
|
80
|
+
}
|
|
81
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
82
|
+
}, [id]);
|
|
83
|
+
|
|
84
|
+
const {
|
|
85
|
+
incidentLocation = '',
|
|
86
|
+
subLocation = '',
|
|
87
|
+
dateTimeOfIncident = '',
|
|
88
|
+
isApproximateTime = false,
|
|
89
|
+
incidentWitnesses = [],
|
|
90
|
+
detailedDescriptionOfIncident = '',
|
|
91
|
+
customers = [],
|
|
92
|
+
incidentTypes = [],
|
|
93
|
+
attachments = [],
|
|
94
|
+
createdBy = {},
|
|
95
|
+
metadata = {},
|
|
96
|
+
staffSuppressed = Boolean,
|
|
97
|
+
linkedToSummary = []
|
|
98
|
+
} = singleIncident;
|
|
99
|
+
|
|
100
|
+
// console.log("singleIncident --> ", JSON.stringify(singleIncident, null, 2))
|
|
101
|
+
|
|
102
|
+
const hasViewProfilePicturePerm = stripes.hasPerm('ui-users.profile-pictures.view');
|
|
103
|
+
const [incTypeTitles, setIncTypeTitles] = useState([]);
|
|
104
|
+
const [locName, setLocName] = useState('');
|
|
105
|
+
const [modalViewImageData, setModalViewImageData] = useState({});
|
|
106
|
+
const [mediaSrc, setMediaSrc] = useState({});
|
|
107
|
+
const [mediaArray, setMediaArray] = useState([]);
|
|
108
|
+
const [loadingStatus, setLoadingStatus] = useState({});
|
|
109
|
+
const [documents, setDocuments] = useState([]);
|
|
110
|
+
const [mostCurrentTrespassDocIds, setMostCurrentTrespassDocIds] = useState([]);
|
|
111
|
+
const [associatedKeyCustArray, setAssociatedKeyCustArray] = useState([]);
|
|
112
|
+
const [associatedKeyWitArray, setAssociatedKeyWitArray] = useState([]);
|
|
113
|
+
const [customersForRender, setCustomersForRender] = useState([]);
|
|
114
|
+
const [witnessesForRender, setWitnessesForRender] = useState([]);
|
|
115
|
+
const [createdById, setCreatedById] = useState('');
|
|
116
|
+
const [updatedById, setUpdatedById] = useState('');
|
|
117
|
+
const [readyCreatedByInUI, setReadyCreatedByinUI] = useState(null);
|
|
118
|
+
const [custWitViewObj, setCustWitViewObj] = useState({});
|
|
119
|
+
const [missingUsers, setMissingUsers] = useState([]);
|
|
120
|
+
const [createdByForRender, setCreatedByForRender] = useState({
|
|
121
|
+
id: '',
|
|
122
|
+
barcode: '',
|
|
123
|
+
firstName: '',
|
|
124
|
+
lastName: ''
|
|
125
|
+
}); // leveraged for both record 'createdBy' key and MetaSection 'createdBy'
|
|
126
|
+
const [updatedByForRender, setUpdatedByForRender] = useState({
|
|
127
|
+
id: '',
|
|
128
|
+
barcode: '',
|
|
129
|
+
firstName: '',
|
|
130
|
+
lastName: ''
|
|
131
|
+
}); // leveraged for MetaSection 'lastUpdatedBy'
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (customers) {
|
|
135
|
+
const readyDataCustomers = customers.map((dataObj) => {
|
|
136
|
+
// handle names if not registered
|
|
137
|
+
if(!dataObj.registered) {
|
|
138
|
+
return {
|
|
139
|
+
...dataObj,
|
|
140
|
+
associatedFirstName: dataObj.firstName,
|
|
141
|
+
associatedLastName: dataObj.lastName,
|
|
142
|
+
profilePicLinkOrUUID: '' // Not registered, couldn't have profile pic
|
|
143
|
+
}
|
|
144
|
+
// handle if registered and associatedKeyCustArray has values to work with
|
|
145
|
+
} else if (dataObj.registered
|
|
146
|
+
&& associatedKeyCustArray
|
|
147
|
+
&& associatedKeyCustArray.length > 0) {
|
|
148
|
+
const matchingCust = associatedKeyCustArray.find(
|
|
149
|
+
(cust) => cust.id === dataObj.id
|
|
150
|
+
);
|
|
151
|
+
if (matchingCust) {
|
|
152
|
+
// return a matched customer with associated names
|
|
153
|
+
return {
|
|
154
|
+
...dataObj,
|
|
155
|
+
associatedFirstName: matchingCust.firstName,
|
|
156
|
+
associatedLastName: matchingCust.lastName,
|
|
157
|
+
profilePicLinkOrUUID: matchingCust.profilePicLinkOrUUID
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
// otherwise return obj
|
|
162
|
+
return dataObj;
|
|
163
|
+
});
|
|
164
|
+
setCustomersForRender(readyDataCustomers)
|
|
165
|
+
};
|
|
166
|
+
}, [customers, associatedKeyCustArray])
|
|
167
|
+
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
if(associatedKeyWitArray && associatedKeyWitArray.length > 0) {
|
|
170
|
+
const readyDataWitnesses = incidentWitnesses.map((dataObj) => {
|
|
171
|
+
const matchingWit = associatedKeyWitArray.find(
|
|
172
|
+
(wit) => wit.id === dataObj.id
|
|
173
|
+
);
|
|
174
|
+
if(matchingWit) {
|
|
175
|
+
return {
|
|
176
|
+
...dataObj,
|
|
177
|
+
associatedFirstName: matchingWit.firstName,
|
|
178
|
+
associatedLastName: matchingWit.lastName
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return dataObj;
|
|
182
|
+
});
|
|
183
|
+
setWitnessesForRender(readyDataWitnesses)
|
|
184
|
+
}
|
|
185
|
+
}, [incidentWitnesses, associatedKeyWitArray]);
|
|
186
|
+
|
|
187
|
+
const associatedKeyPlaceSigned = (value) => {
|
|
188
|
+
// value is expected to tbe the id associated w/ locationInService obj
|
|
189
|
+
const locObject = locationsInService.find(loc => loc.id === value)
|
|
190
|
+
// return the obj's location (which is the pretty name)
|
|
191
|
+
return locObject ? locObject.location : '';
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
useEffect(() => {
|
|
195
|
+
if(createdBy && createdBy.id !== '') {
|
|
196
|
+
setCreatedById(createdBy.id)
|
|
197
|
+
}
|
|
198
|
+
}, [createdBy]);
|
|
199
|
+
|
|
200
|
+
useEffect(() => {
|
|
201
|
+
if(metadata && 'updatedByUserId' in metadata && metadata.updatedByUserId !== '') {
|
|
202
|
+
setUpdatedById(metadata.updatedByUserId)
|
|
203
|
+
}
|
|
204
|
+
}, [metadata]);
|
|
205
|
+
|
|
206
|
+
useEffect(() => {
|
|
207
|
+
if(attachments && attachments.length > 0) {
|
|
208
|
+
const docs = attachments.filter((att) => att.contentType.startsWith('application'));
|
|
209
|
+
setDocuments(docs);
|
|
210
|
+
|
|
211
|
+
const medias = attachments.filter((att) => att.contentType.startsWith('image') || att.contentType.startsWith('video'));
|
|
212
|
+
setMediaArray(medias);
|
|
213
|
+
|
|
214
|
+
const newLoadingStatus = medias.reduce((acc, att) => ({
|
|
215
|
+
...acc,
|
|
216
|
+
[att.id]: true // start all media as loading true
|
|
217
|
+
}), {});
|
|
218
|
+
setLoadingStatus(newLoadingStatus);
|
|
219
|
+
|
|
220
|
+
openImageSkeleton();
|
|
221
|
+
} else {
|
|
222
|
+
setDocuments([]);
|
|
223
|
+
setMediaArray([]);
|
|
224
|
+
setMediaSrc({});
|
|
225
|
+
setLoadingStatus({});
|
|
226
|
+
closeImageSkeleton();
|
|
227
|
+
}
|
|
228
|
+
}, [attachments]);
|
|
229
|
+
|
|
230
|
+
const sortedDocuments = useMemo(() => sortTrespassDocuments(documents, mostCurrentTrespassDocIds), [documents, mostCurrentTrespassDocIds])
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
const handleMediaUrl = (mediaUrl, attachmentId) => {
|
|
234
|
+
setMediaSrc(prev => ({ ...prev, [attachmentId]: mediaUrl }));
|
|
235
|
+
setLoadingStatus(prev => ({ ...prev, [attachmentId]: false }));
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
const allImagesLoaded = Object.values(loadingStatus).every(status => !status);
|
|
240
|
+
if (allImagesLoaded) {
|
|
241
|
+
closeImageSkeleton();
|
|
242
|
+
|
|
243
|
+
}
|
|
244
|
+
}, [loadingStatus, closeImageSkeleton]);
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
useEffect(() => {
|
|
248
|
+
if (documents && documents.length > 0) {
|
|
249
|
+
const startStr = 'trespass-';
|
|
250
|
+
const current = identifyCurrentTrespassDocs(documents, startStr);
|
|
251
|
+
setMostCurrentTrespassDocIds(current);
|
|
252
|
+
}
|
|
253
|
+
}, [documents]);
|
|
254
|
+
|
|
255
|
+
const thumbnailStyle = { width: '100px', height: 'auto', objectFit: 'cover'};
|
|
256
|
+
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
if(singleIncident && singleIncident.incidentLocation) {
|
|
259
|
+
const locObject = locationsInService.find(loc => loc.id === singleIncident.incidentLocation);
|
|
260
|
+
const name = locObject && locObject.location ? locObject.location : "unknown"
|
|
261
|
+
setLocName(name)
|
|
262
|
+
}
|
|
263
|
+
}, [singleIncident, incidentLocation, locationsInService])
|
|
264
|
+
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
const ready = singleIncident?.incidentTypes?.length &&
|
|
267
|
+
incidentTypesList?.length;
|
|
268
|
+
if (!ready) {
|
|
269
|
+
setIncTypeTitles([]);
|
|
270
|
+
return
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const byId = new Map(
|
|
274
|
+
(incidentTypesList ?? []).map(t => [t.id, t])
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
const fullTypes = singleIncident.incidentTypes.map(({ id }) => {
|
|
278
|
+
const found = byId.get(id);
|
|
279
|
+
return found ?? {
|
|
280
|
+
id,
|
|
281
|
+
title: <FormattedMessage id="incident-type-not-found-fallback"
|
|
282
|
+
values={{ id }}/>,
|
|
283
|
+
description: ''
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
setIncTypeTitles(fullTypes);
|
|
288
|
+
}, [singleIncident, incidentTypesList]);
|
|
289
|
+
|
|
290
|
+
const incTypeFormatter = (item, index) => {
|
|
291
|
+
if (!item) {
|
|
292
|
+
return null;
|
|
293
|
+
};
|
|
294
|
+
return (
|
|
295
|
+
<li key={item.id ?? index}>
|
|
296
|
+
{item.title ? item.title : 'error'} {item.description ? item.description : ''}
|
|
297
|
+
</li>
|
|
298
|
+
)
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const handleMissingUsers = (userId) => {
|
|
302
|
+
setMissingUsers((prev) => {
|
|
303
|
+
return [ ...prev, userId]
|
|
304
|
+
})
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
const handleGetCustName = (userObj) => {
|
|
308
|
+
setAssociatedKeyCustArray((prevState) => {
|
|
309
|
+
return [...prevState, userObj]
|
|
310
|
+
})
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const handleGetWitnessName = (witObj) => {
|
|
314
|
+
setAssociatedKeyWitArray((prevState) => {
|
|
315
|
+
return [...prevState, witObj]
|
|
316
|
+
})
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const handleShowCustomWitModalAsDetails = (witObj) => {
|
|
320
|
+
setCustWitViewObj(witObj)
|
|
321
|
+
openModalCustomWitness()
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
const handleGetCreatedByName = (createdByNameObj) => {
|
|
325
|
+
if (createdByNameObj) {
|
|
326
|
+
setCreatedByForRender({
|
|
327
|
+
id: createdByNameObj.id,
|
|
328
|
+
barcode: createdByNameObj.barcode,
|
|
329
|
+
firstName: createdByNameObj.firstName,
|
|
330
|
+
lastName: createdByNameObj.lastName
|
|
331
|
+
})
|
|
332
|
+
} else {
|
|
333
|
+
setCreatedByForRender({
|
|
334
|
+
id: '',
|
|
335
|
+
barcode: '',
|
|
336
|
+
firstName: '',
|
|
337
|
+
lastName: ''
|
|
338
|
+
})
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
const handleGetUpdatedByName = (updatedByNameObj) => {
|
|
343
|
+
if (updatedByNameObj) {
|
|
344
|
+
setUpdatedByForRender({
|
|
345
|
+
id: updatedByNameObj.id,
|
|
346
|
+
barcode: updatedByNameObj.barcode,
|
|
347
|
+
firstName: updatedByNameObj.firstName,
|
|
348
|
+
lastName: updatedByNameObj.lastName
|
|
349
|
+
})
|
|
350
|
+
} else {
|
|
351
|
+
setUpdatedByForRender({
|
|
352
|
+
id: '',
|
|
353
|
+
barcode: '',
|
|
354
|
+
firstName: '',
|
|
355
|
+
lastName: ''
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
const witnessNames = witnessesForRender.map((wit) => {
|
|
361
|
+
const name = `${wit.associatedLastName}, ${wit.associatedFirstName}`;
|
|
362
|
+
return name;
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
const makeCreatedByLink = (createdByObject) => {
|
|
366
|
+
if (createdByObject.id && createdByObject.id !== '') {
|
|
367
|
+
return (
|
|
368
|
+
<a
|
|
369
|
+
href={`/users/preview/${createdByObject.id}`}
|
|
370
|
+
target="_blank"
|
|
371
|
+
aria-label="Link to created by in users application"
|
|
372
|
+
style={{
|
|
373
|
+
textDecoration: 'none',
|
|
374
|
+
color: 'rgb(0,0,238)',
|
|
375
|
+
fontWeight: 'bold',
|
|
376
|
+
}}
|
|
377
|
+
rel="noreferrer"
|
|
378
|
+
>
|
|
379
|
+
{`${createdByObject.lastName}, ${createdByObject.firstName}`}
|
|
380
|
+
</a>
|
|
381
|
+
)
|
|
382
|
+
} else {
|
|
383
|
+
return <Icon icon='spinner-ellipsis' size='small'></Icon>
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
if (createdByForRender) {
|
|
389
|
+
setReadyCreatedByinUI(makeCreatedByLink(createdByForRender));
|
|
390
|
+
}
|
|
391
|
+
}, [createdByForRender]) // on render
|
|
392
|
+
|
|
393
|
+
const witnessItemFormatter = (wit) => {
|
|
394
|
+
const isCustomWitness = wit.isCustom === true;
|
|
395
|
+
return (
|
|
396
|
+
<li key={wit.id}>
|
|
397
|
+
{isCustomWitness ? (
|
|
398
|
+
<>
|
|
399
|
+
{wit.lastName}, {wit.firstName}
|
|
400
|
+
<button
|
|
401
|
+
style={{ paddingLeft: '15px' }}
|
|
402
|
+
onClick={() => handleShowCustomWitModalAsDetails(wit)}
|
|
403
|
+
type="button"
|
|
404
|
+
>
|
|
405
|
+
<Icon icon="report" size="medium" />
|
|
406
|
+
<FormattedMessage id="view-details-custom-witness"/>
|
|
407
|
+
</button>
|
|
408
|
+
</>
|
|
409
|
+
) : <a
|
|
410
|
+
href={`/users/preview/${wit.id}`}
|
|
411
|
+
target="_blank"
|
|
412
|
+
aria-label="Link to created by in users application"
|
|
413
|
+
style={{
|
|
414
|
+
textDecoration: 'none',
|
|
415
|
+
color: 'rgb(0,0,238)',
|
|
416
|
+
fontWeight: 'bold',
|
|
417
|
+
}}
|
|
418
|
+
rel="noreferrer"
|
|
419
|
+
>
|
|
420
|
+
{`${wit.associatedLastName}, ${wit.associatedFirstName}`}
|
|
421
|
+
</a>
|
|
422
|
+
}
|
|
423
|
+
</li>
|
|
424
|
+
)
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
const style = {
|
|
428
|
+
display: 'block',
|
|
429
|
+
width: '50%',
|
|
430
|
+
marginTop: '10px',
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const handleDismissDetails = () => {
|
|
434
|
+
setCreatedByForRender({
|
|
435
|
+
id: '',
|
|
436
|
+
barcode: '',
|
|
437
|
+
firstName: '',
|
|
438
|
+
lastName: ''
|
|
439
|
+
});
|
|
440
|
+
setUpdatedByForRender({
|
|
441
|
+
id: '',
|
|
442
|
+
barcode: '',
|
|
443
|
+
firstName: '',
|
|
444
|
+
lastName: ''
|
|
445
|
+
});
|
|
446
|
+
setCreatedById('');
|
|
447
|
+
setUpdatedById('');
|
|
448
|
+
closeDetailsPane();
|
|
449
|
+
setSingleIncident({});
|
|
450
|
+
clearDocumentError();
|
|
451
|
+
setMissingUsers([]);
|
|
452
|
+
setMediaSrc({});
|
|
453
|
+
setMediaArray([]);
|
|
454
|
+
setLoadingStatus({});
|
|
455
|
+
|
|
456
|
+
setDocuments([]);
|
|
457
|
+
closeImageSkeleton();
|
|
458
|
+
|
|
459
|
+
const lastListRoute = sessionStorage.getItem('lastTrackListRoute');
|
|
460
|
+
|
|
461
|
+
if (mode === 'createMode') {
|
|
462
|
+
history.push(`/incidents?limit=20&offset=0`);
|
|
463
|
+
} else if (lastListRoute && lastListRoute.startsWith('/incidents')) {
|
|
464
|
+
sessionStorage.removeItem('lastTrackListRoute');
|
|
465
|
+
history.push(lastListRoute);
|
|
466
|
+
} else {
|
|
467
|
+
history.push(`/incidents?limit=20&offset=0`);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
const handleOpenEdit = (incidentId) => {
|
|
472
|
+
closeDetailsPane();
|
|
473
|
+
setAssociatedKeyCustArray([]);
|
|
474
|
+
setCustomersForRender([]);
|
|
475
|
+
setSingleIncident({});
|
|
476
|
+
setCreatedById('')
|
|
477
|
+
openEditPane();
|
|
478
|
+
clearDocumentError();
|
|
479
|
+
setMissingUsers([]);
|
|
480
|
+
setMediaSrc(null);
|
|
481
|
+
setMediaArray(null);
|
|
482
|
+
setLoadingStatus(null);
|
|
483
|
+
history.replace(`/incidents/${incidentId}/edit${location.search}`);
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
const handleImageClick = (imageObj) => {
|
|
487
|
+
setModalViewImageData(imageObj)
|
|
488
|
+
openModalViewImage();
|
|
489
|
+
};
|
|
490
|
+
|
|
491
|
+
const createMarkup = (content) => {
|
|
492
|
+
return {__html: content}
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const witnessesListLabel = intl.formatMessage(
|
|
496
|
+
{ id: `witnesses-list-label` },
|
|
497
|
+
{ count: witnessNames.length,
|
|
498
|
+
bold: (chunks) => (
|
|
499
|
+
<strong style={{ color: '#A12A2A' }}>{chunks}</strong>
|
|
500
|
+
)
|
|
501
|
+
}
|
|
502
|
+
);
|
|
503
|
+
|
|
504
|
+
const incidentTypesListLabel = intl.formatMessage(
|
|
505
|
+
{ id: `incident-types-list-label` },
|
|
506
|
+
{ count: incTypeTitles.length }
|
|
507
|
+
);
|
|
508
|
+
|
|
509
|
+
const getActionMenu = ({ onToggle }) => (
|
|
510
|
+
<>
|
|
511
|
+
<Button
|
|
512
|
+
buttonStyle="primary"
|
|
513
|
+
style={style}
|
|
514
|
+
onClick={() => handleOpenEdit(id)}
|
|
515
|
+
>
|
|
516
|
+
<FormattedMessage id="edit-button" />
|
|
517
|
+
</Button>
|
|
518
|
+
</>
|
|
519
|
+
);
|
|
520
|
+
|
|
521
|
+
const actionMenu = stripes.hasPerm('ui-security-incident.edit')
|
|
522
|
+
? getActionMenu
|
|
523
|
+
: undefined;
|
|
524
|
+
|
|
525
|
+
const trById = useMemo(
|
|
526
|
+
() => new Map(
|
|
527
|
+
(trespassReasons ?? []).map(tr => [tr.id, tr])
|
|
528
|
+
), [trespassReasons]);
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
const itemsFormatterExclusionList = (item) => {
|
|
532
|
+
const found = trById.get(item.id);
|
|
533
|
+
// item.reason is persisted fallback clear text
|
|
534
|
+
return <li key={item} style={{ marginLeft: '10px' }}>{found?.reason ?? item.reason}</li>;
|
|
535
|
+
};
|
|
536
|
+
|
|
537
|
+
return (
|
|
538
|
+
<>
|
|
539
|
+
{id &&
|
|
540
|
+
<GetDetails id={id}
|
|
541
|
+
/>}
|
|
542
|
+
|
|
543
|
+
{customers.map((cust) => {
|
|
544
|
+
// if customer is not registered (not in /Users db) then skip that cust object and return null (handled in useEffect instead)
|
|
545
|
+
if (!cust.registered) {
|
|
546
|
+
return null;
|
|
547
|
+
};
|
|
548
|
+
return (
|
|
549
|
+
<GetName
|
|
550
|
+
key={cust.id}
|
|
551
|
+
uuid={cust.id}
|
|
552
|
+
handleGetCustName={handleGetCustName}
|
|
553
|
+
handleMissingUsers={handleMissingUsers}
|
|
554
|
+
context='customer'/>
|
|
555
|
+
);
|
|
556
|
+
})}
|
|
557
|
+
|
|
558
|
+
{incidentWitnesses.map((wit) => (
|
|
559
|
+
<GetName
|
|
560
|
+
isCustomWitness={wit.isCustom === true ? wit : null}
|
|
561
|
+
key={wit.id}
|
|
562
|
+
uuid={wit.id}
|
|
563
|
+
handleGetWitnessName={handleGetWitnessName}
|
|
564
|
+
handleMissingUsers={handleMissingUsers}
|
|
565
|
+
context="witness"
|
|
566
|
+
/>
|
|
567
|
+
))}
|
|
568
|
+
|
|
569
|
+
{updatedById && updatedById !== '' && (
|
|
570
|
+
<GetName
|
|
571
|
+
uuid={updatedById}
|
|
572
|
+
handleGetUpdatedByName={handleGetUpdatedByName}
|
|
573
|
+
handleMissingUsers={handleMissingUsers}
|
|
574
|
+
context="updatedBy"
|
|
575
|
+
/>
|
|
576
|
+
)}
|
|
577
|
+
|
|
578
|
+
{createdById && createdById !== '' && (
|
|
579
|
+
<GetNameCreatedBy
|
|
580
|
+
uuid={createdById}
|
|
581
|
+
handleGetCreatedByName={handleGetCreatedByName}
|
|
582
|
+
handleMissingUsers={handleMissingUsers}
|
|
583
|
+
/>
|
|
584
|
+
)}
|
|
585
|
+
|
|
586
|
+
{isLoadingDetails || singleIncident?.id !== id ? (
|
|
587
|
+
<LoadingPane
|
|
588
|
+
defaultWidth="fill"
|
|
589
|
+
paneTitle={
|
|
590
|
+
<FormattedMessage id="details-pane.loading-pane-paneTitle" />
|
|
591
|
+
}
|
|
592
|
+
/>
|
|
593
|
+
) : (
|
|
594
|
+
<Pane
|
|
595
|
+
key={id}
|
|
596
|
+
paneTitle={<FormattedMessage id="details-pane.paneTitle" />}
|
|
597
|
+
defaultWidth="fill"
|
|
598
|
+
{...props}
|
|
599
|
+
renderHeader={(renderProps) => (
|
|
600
|
+
<PaneHeader
|
|
601
|
+
{...renderProps}
|
|
602
|
+
dismissible
|
|
603
|
+
onClose={handleDismissDetails}
|
|
604
|
+
paneTitle={<FormattedMessage id="details-pane.pane-header-paneTitle" />}
|
|
605
|
+
actionMenu={actionMenu}
|
|
606
|
+
/>
|
|
607
|
+
)}>
|
|
608
|
+
{custWitViewObj && Object.keys(custWitViewObj).length > 0 && (
|
|
609
|
+
<ModalCustomWitness
|
|
610
|
+
custWitViewObj={custWitViewObj}
|
|
611
|
+
/>
|
|
612
|
+
)}
|
|
613
|
+
{isModalViewImage &&
|
|
614
|
+
modalViewImageData &&
|
|
615
|
+
<ModalViewMedia
|
|
616
|
+
modalViewImageData={modalViewImageData}
|
|
617
|
+
/>
|
|
618
|
+
}
|
|
619
|
+
<GetIncidentTypesDetails context='incidents'/>
|
|
620
|
+
<GetLocationsInService />
|
|
621
|
+
<GetTrespassReasons />
|
|
622
|
+
|
|
623
|
+
{/* if 404 for any /Users request get associated key for name, render MessageBanner with message and those unfound uuid(s) */}
|
|
624
|
+
<Row>
|
|
625
|
+
<Col xs={12}>
|
|
626
|
+
<div>
|
|
627
|
+
<MessageBanner
|
|
628
|
+
dismissible
|
|
629
|
+
type="error"
|
|
630
|
+
show={missingUsers.length > 0}
|
|
631
|
+
>
|
|
632
|
+
{<FormattedMessage
|
|
633
|
+
id="message-banner.error-missing-users-404"
|
|
634
|
+
values={{ ids: missingUsers.join(', ') }}
|
|
635
|
+
/>}
|
|
636
|
+
</MessageBanner>
|
|
637
|
+
</div>
|
|
638
|
+
</Col>
|
|
639
|
+
</Row>
|
|
640
|
+
|
|
641
|
+
{/* if documentError render MessageBanner for documentErrorMessage */}
|
|
642
|
+
<Row>
|
|
643
|
+
<Col xs={12}>
|
|
644
|
+
<div>
|
|
645
|
+
<MessageBanner
|
|
646
|
+
dismissible
|
|
647
|
+
onExit={() => clearDocumentError()}
|
|
648
|
+
type="error"
|
|
649
|
+
show={documentError}
|
|
650
|
+
>
|
|
651
|
+
{<FormattedMessage
|
|
652
|
+
id="details-pane.error-generate-trespass-doc"
|
|
653
|
+
values={{ documentErrorMessage }}
|
|
654
|
+
/>}
|
|
655
|
+
</MessageBanner>
|
|
656
|
+
</div>
|
|
657
|
+
</Col>
|
|
658
|
+
</Row>
|
|
659
|
+
|
|
660
|
+
<AccordionSet>
|
|
661
|
+
<ExpandAllButton />
|
|
662
|
+
<MetaSection
|
|
663
|
+
headingLevel={4}
|
|
664
|
+
useAccordion
|
|
665
|
+
showUserLink
|
|
666
|
+
createdDate={metadata.createdDate || null}
|
|
667
|
+
lastUpdatedDate={metadata.updatedDate || null}
|
|
668
|
+
createdBy={{
|
|
669
|
+
id: metadata.createdByUserId,
|
|
670
|
+
personal: {
|
|
671
|
+
firstName: createdByForRender.firstName,
|
|
672
|
+
lastName: createdByForRender.lastName
|
|
673
|
+
}
|
|
674
|
+
}}
|
|
675
|
+
lastUpdatedBy={{
|
|
676
|
+
id: metadata.updatedByUserId,
|
|
677
|
+
personal: {
|
|
678
|
+
firstName: updatedByForRender.firstName,
|
|
679
|
+
lastName: updatedByForRender.lastName,
|
|
680
|
+
}
|
|
681
|
+
}}
|
|
682
|
+
/>
|
|
683
|
+
|
|
684
|
+
{staffSuppressed && staffSuppressed === true ? (
|
|
685
|
+
<div style={{ display: 'inline-block' }}>
|
|
686
|
+
<Icon size='small' icon='exclamation-circle' status='warn'>
|
|
687
|
+
</Icon>
|
|
688
|
+
<span style={{ marginLeft: '0.5rem' }}>
|
|
689
|
+
<FormattedMessage id="details-pane.staff-suppressed" />
|
|
690
|
+
</span>
|
|
691
|
+
</div>
|
|
692
|
+
) : (
|
|
693
|
+
null
|
|
694
|
+
)}
|
|
695
|
+
|
|
696
|
+
<Accordion label={<FormattedMessage id="accordion-label-media" />}>
|
|
697
|
+
<div>
|
|
698
|
+
{mediaArray?.map((attachment) => (
|
|
699
|
+
<GetMedia
|
|
700
|
+
context='thumbnail'
|
|
701
|
+
contentType={attachment.contentType}
|
|
702
|
+
key={attachment.id}
|
|
703
|
+
id={id}
|
|
704
|
+
imageId={attachment.id}
|
|
705
|
+
mediaHandler={(mediaUrl) => handleMediaUrl(mediaUrl, attachment.id)}
|
|
706
|
+
/>
|
|
707
|
+
))}
|
|
708
|
+
</div>
|
|
709
|
+
|
|
710
|
+
<Row style={{ margin: '25px' }}>
|
|
711
|
+
<Col xs={1} style={{ visibility: 'hidden' }}></Col>
|
|
712
|
+
{mediaArray?.slice(0, 5).map((attachment) => (
|
|
713
|
+
<Col xs={2} key={attachment.id}>
|
|
714
|
+
{loadingStatus[attachment.id] && isImageArrayLoading ? <ThumbnailSkeleton />
|
|
715
|
+
: <Thumbnail
|
|
716
|
+
key={attachment.id}
|
|
717
|
+
context='details'
|
|
718
|
+
src={mediaSrc[attachment.id]}
|
|
719
|
+
alt={attachment.description}
|
|
720
|
+
imageDescription={attachment.description}
|
|
721
|
+
contentType={attachment.contentType}
|
|
722
|
+
style={thumbnailStyle}
|
|
723
|
+
handler={() => handleImageClick({
|
|
724
|
+
"id": id,
|
|
725
|
+
"imageId": attachment.id,
|
|
726
|
+
"key": attachment.id,
|
|
727
|
+
"alt": attachment.description,
|
|
728
|
+
"contentType": attachment.contentType,
|
|
729
|
+
"imageDescription": attachment.description
|
|
730
|
+
})}
|
|
731
|
+
/>
|
|
732
|
+
}
|
|
733
|
+
</Col>
|
|
734
|
+
))}
|
|
735
|
+
</Row>
|
|
736
|
+
<Row style={{ margin: '25px' }}>
|
|
737
|
+
<Col xs={1} style={{ visibility: 'hidden' }}></Col>
|
|
738
|
+
{mediaArray?.slice(5, 10).map((attachment) => (
|
|
739
|
+
<Col xs={2} key={attachment.id}>
|
|
740
|
+
{loadingStatus[attachment.id] && isImageArrayLoading ? <ThumbnailSkeleton />
|
|
741
|
+
: <Thumbnail
|
|
742
|
+
key={attachment.id}
|
|
743
|
+
context='details'
|
|
744
|
+
src={mediaSrc[attachment.id]}
|
|
745
|
+
alt={attachment.description}
|
|
746
|
+
imageDescription={attachment.description}
|
|
747
|
+
handler={() => handleImageClick({
|
|
748
|
+
"id": id,
|
|
749
|
+
"imageId": attachment.id,
|
|
750
|
+
"key": attachment.id,
|
|
751
|
+
"alt": attachment.description,
|
|
752
|
+
"contentType": attachment.contentType,
|
|
753
|
+
"imageDescription": attachment.description
|
|
754
|
+
})}
|
|
755
|
+
contentType={attachment.contentType}
|
|
756
|
+
style={thumbnailStyle}
|
|
757
|
+
/>
|
|
758
|
+
}
|
|
759
|
+
</Col>
|
|
760
|
+
))}
|
|
761
|
+
</Row>
|
|
762
|
+
</Accordion>
|
|
763
|
+
<Accordion
|
|
764
|
+
label={singleIncident && singleIncident.customerNa === true ? <FormattedMessage id="accordion-label-no-associated-customers"/>
|
|
765
|
+
: <FormattedMessage id="accordion-label-customers" />}
|
|
766
|
+
>
|
|
767
|
+
|
|
768
|
+
<div style={{ padding: '15px' }}>
|
|
769
|
+
<Row>
|
|
770
|
+
<Col xs={10}>
|
|
771
|
+
{customersForRender.map((cust) => {
|
|
772
|
+
// init if trespass and trespass has end date
|
|
773
|
+
const endDateOfTrespassISO = cust.trespass ? cust.trespass.endDateOfTrespass : null;
|
|
774
|
+
|
|
775
|
+
// make pretty for UI if end date iso exists
|
|
776
|
+
const endDateOfTrespassPretty = endDateOfTrespassISO ? convertDateIgnoringTZ(endDateOfTrespassISO) : null;
|
|
777
|
+
|
|
778
|
+
// init as new Date obj if end date iso exists (for comparison)
|
|
779
|
+
const endDateOfTrespass = endDateOfTrespassISO ? new Date(endDateOfTrespassISO) : null;
|
|
780
|
+
|
|
781
|
+
// compare for is expired else false
|
|
782
|
+
const isTrespassExpired = endDateOfTrespass ? endDateOfTrespass.getTime() < Date.now() : false;
|
|
783
|
+
|
|
784
|
+
const isTrespassed = !!cust.trespass;
|
|
785
|
+
const isDeclarationOfService = cust.trespass &&
|
|
786
|
+
cust.trespass.declarationOfService &&
|
|
787
|
+
Object.keys(cust.trespass.declarationOfService).length > 0;
|
|
788
|
+
|
|
789
|
+
// NOTE: via useEffect associated first and last names are set for un-registered customers with their incident report instance value
|
|
790
|
+
// whereas registered customers associated first and last names are set by current value of their /Users instance value
|
|
791
|
+
const { associatedFirstName, associatedLastName } = cust;
|
|
792
|
+
const notAvailable = intl.formatMessage({ id: "unknown-name-placeholder" });
|
|
793
|
+
const displayedFirstName = associatedFirstName === '' ? notAvailable : associatedFirstName;
|
|
794
|
+
const displayedLastName = associatedLastName === '' ? notAvailable : associatedLastName;
|
|
795
|
+
let keyedName = `${displayedLastName}, ${displayedFirstName}`;
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
let trespassStatus = ''
|
|
799
|
+
if (isTrespassed) {
|
|
800
|
+
if (!isTrespassExpired) {
|
|
801
|
+
trespassStatus = (<FormattedMessage
|
|
802
|
+
id="details-pane.trespass-active-until"
|
|
803
|
+
values={{ date: endDateOfTrespassPretty}}/>)
|
|
804
|
+
} else {
|
|
805
|
+
trespassStatus = (<FormattedMessage
|
|
806
|
+
id="details-pane.trespass-expired"
|
|
807
|
+
values={{ date: endDateOfTrespassPretty}}/>)
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
const isKnown = cust.registered === true;
|
|
811
|
+
|
|
812
|
+
return (
|
|
813
|
+
<Accordion
|
|
814
|
+
key={cust.id}
|
|
815
|
+
label={!isKnown ? <>
|
|
816
|
+
{keyedName}
|
|
817
|
+
<span
|
|
818
|
+
style={{
|
|
819
|
+
marginLeft: '10px',
|
|
820
|
+
marginRight: '10px'
|
|
821
|
+
}}
|
|
822
|
+
>
|
|
823
|
+
{trespassStatus}
|
|
824
|
+
</span>
|
|
825
|
+
{isTrespassed && !isTrespassExpired && (
|
|
826
|
+
<span style={{
|
|
827
|
+
marginLeft: '10px',
|
|
828
|
+
marginRight: '10px',
|
|
829
|
+
color: 'red'}}>
|
|
830
|
+
<Icon icon='times-circle-solid' size='small'></Icon>
|
|
831
|
+
</span>
|
|
832
|
+
)}
|
|
833
|
+
</> : <>
|
|
834
|
+
<a
|
|
835
|
+
href={`/users/preview/${cust.id}`}
|
|
836
|
+
target="_blank"
|
|
837
|
+
aria-label="Link to customer in users application"
|
|
838
|
+
style={{
|
|
839
|
+
textDecoration: 'none',
|
|
840
|
+
color: 'rgb(0,0,238)',
|
|
841
|
+
fontWeight: 'bold',
|
|
842
|
+
}}
|
|
843
|
+
rel="noreferrer"
|
|
844
|
+
>
|
|
845
|
+
{keyedName}
|
|
846
|
+
</a>
|
|
847
|
+
<span
|
|
848
|
+
style={{
|
|
849
|
+
marginLeft: '10px',
|
|
850
|
+
marginRight: '10px'
|
|
851
|
+
}}
|
|
852
|
+
>
|
|
853
|
+
{trespassStatus}
|
|
854
|
+
</span>
|
|
855
|
+
{isTrespassed && !isTrespassExpired && (
|
|
856
|
+
<span style={{
|
|
857
|
+
marginLeft: '10px',
|
|
858
|
+
marginRight: '10px',
|
|
859
|
+
color: 'red'}}>
|
|
860
|
+
<Icon icon='times-circle-solid' size='small'></Icon>
|
|
861
|
+
</span>
|
|
862
|
+
)}
|
|
863
|
+
</>}>
|
|
864
|
+
|
|
865
|
+
<Row style={{ marginTop: '15px' }}>
|
|
866
|
+
<Col xs={4}>
|
|
867
|
+
<Headline size="medium" tag="h2">
|
|
868
|
+
{cust.description ? (<FormattedMessage id="details-pane.customersForRender-cust-description" />) : (<FormattedMessage id="details-pane.customersForRender-no-cust-description" />)}
|
|
869
|
+
</Headline>
|
|
870
|
+
{cust.description ? (
|
|
871
|
+
<div
|
|
872
|
+
dangerouslySetInnerHTML={createMarkup(cust.description)}>
|
|
873
|
+
</div>)
|
|
874
|
+
: null
|
|
875
|
+
}
|
|
876
|
+
</Col>
|
|
877
|
+
|
|
878
|
+
{hasViewProfilePicturePerm && (
|
|
879
|
+
<Col xs={6}>
|
|
880
|
+
<KeyValue
|
|
881
|
+
label={<FormattedMessage id="ui-users.information.profilePicture" />}
|
|
882
|
+
value={
|
|
883
|
+
<ProfilePicture
|
|
884
|
+
profilePictureLink={cust.profilePicLinkOrUUID}
|
|
885
|
+
/>}
|
|
886
|
+
/>
|
|
887
|
+
</Col>
|
|
888
|
+
)}
|
|
889
|
+
</Row>
|
|
890
|
+
|
|
891
|
+
<Row style={{ marginTop: '15px' }}>
|
|
892
|
+
<Col xs={4}>
|
|
893
|
+
<Headline size="medium" tag="h2">
|
|
894
|
+
{cust.details && Object.values(cust.details).some(value => value !== '' && value !== null) ? (<FormattedMessage id="details-pane.customersForRender-identity-details" />) : (<FormattedMessage id="details-pane.customersForRender-no-identity-details" />) }
|
|
895
|
+
</Headline>
|
|
896
|
+
</Col>
|
|
897
|
+
</Row>
|
|
898
|
+
|
|
899
|
+
{cust.details && Object.values(cust.details).some(value => value !== '' && value !== null) ? (
|
|
900
|
+
<>
|
|
901
|
+
<Row>
|
|
902
|
+
<Col xs={2}>
|
|
903
|
+
<Headline size="medium" tag="h2">
|
|
904
|
+
<FormattedMessage id="modal-view-customer-details.headline-sex" />
|
|
905
|
+
</Headline>
|
|
906
|
+
<p>
|
|
907
|
+
{cust.details && cust.details.sex ? cust.details.sex : '-'}
|
|
908
|
+
</p>
|
|
909
|
+
</Col>
|
|
910
|
+
|
|
911
|
+
<Col xs={2}>
|
|
912
|
+
<Headline size="medium" tag="h2">
|
|
913
|
+
<FormattedMessage id="modal-view-customer-details.headline-race" />
|
|
914
|
+
</Headline>
|
|
915
|
+
<p>
|
|
916
|
+
{cust.details && cust.details.race ? cust.details.race : '-'}
|
|
917
|
+
</p>
|
|
918
|
+
</Col>
|
|
919
|
+
<Col xs={2}>
|
|
920
|
+
<Headline size="medium" tag="h2">
|
|
921
|
+
<FormattedMessage id="modal-view-customer-details.headline-height" />
|
|
922
|
+
</Headline>
|
|
923
|
+
<p>
|
|
924
|
+
{cust.details && cust.details.height
|
|
925
|
+
? cust.details.height
|
|
926
|
+
: '-'}
|
|
927
|
+
</p>
|
|
928
|
+
</Col>
|
|
929
|
+
</Row>
|
|
930
|
+
|
|
931
|
+
<Row style={{ marginTop: '10px' }}>
|
|
932
|
+
<Col xs={2}>
|
|
933
|
+
<Headline size="medium" tag="h2">
|
|
934
|
+
<FormattedMessage id="modal-view-customer-details.headline-weight" />
|
|
935
|
+
</Headline>
|
|
936
|
+
<p>
|
|
937
|
+
{cust.details && cust.details.weight
|
|
938
|
+
? cust.details.weight
|
|
939
|
+
: '-'}
|
|
940
|
+
</p>
|
|
941
|
+
</Col>
|
|
942
|
+
<Col xs={2}>
|
|
943
|
+
<Headline size="medium" tag="h2">
|
|
944
|
+
<FormattedMessage id="modal-view-customer-details.headline-hair" />
|
|
945
|
+
</Headline>
|
|
946
|
+
<p>
|
|
947
|
+
{cust.details && cust.details.hair ? cust.details.hair : '-'}
|
|
948
|
+
</p>
|
|
949
|
+
|
|
950
|
+
</Col>
|
|
951
|
+
<Col xs={2}>
|
|
952
|
+
<Headline size="medium" tag="h2">
|
|
953
|
+
<FormattedMessage id="modal-view-customer-details.headline-eyes" />
|
|
954
|
+
</Headline>
|
|
955
|
+
<p>
|
|
956
|
+
{cust.details && cust.details.eyes ? cust.details.eyes : '-'}
|
|
957
|
+
</p>
|
|
958
|
+
</Col>
|
|
959
|
+
<Col xs={2}>
|
|
960
|
+
<Headline size="medium" tag="h2">
|
|
961
|
+
<FormattedMessage id="modal-view-customer-details.headline-date-of-birth" />
|
|
962
|
+
</Headline>
|
|
963
|
+
<p>
|
|
964
|
+
{cust.details && cust.details.dateOfBirth ? convertDateIgnoringTZ(cust.details.dateOfBirth) : '-'}
|
|
965
|
+
</p>
|
|
966
|
+
</Col>
|
|
967
|
+
</Row>
|
|
968
|
+
</>
|
|
969
|
+
)
|
|
970
|
+
: null
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
{/* TRESPASS DETAILS */}
|
|
974
|
+
<Row style={{ marginTop: '15px' }}>
|
|
975
|
+
<Col xs={4}>
|
|
976
|
+
<Headline size="medium" tag="h2">
|
|
977
|
+
{cust.trespass && Object.values(cust.trespass).some(value => value !== '' && value !== null) ? (<FormattedMessage id="details-pane.customersForRender-trespass-details" />) : (<FormattedMessage id="details-pane.customersForRender-no-trespass-details" />) }
|
|
978
|
+
</Headline>
|
|
979
|
+
</Col>
|
|
980
|
+
</Row>
|
|
981
|
+
{isTrespassed ? (
|
|
982
|
+
<>
|
|
983
|
+
<Row style={{ marginLeft: ' 15px' }}>
|
|
984
|
+
<Col xs={4}>
|
|
985
|
+
<Headline size="medium" tag="h3">
|
|
986
|
+
<FormattedMessage id="modal-view-trespass.headline-exclusion-based-on" />
|
|
987
|
+
</Headline>
|
|
988
|
+
<List
|
|
989
|
+
label={
|
|
990
|
+
<FormattedMessage id="modal-view-trespass.headline-exclusion-based-on" />
|
|
991
|
+
}
|
|
992
|
+
listStyle="bullets"
|
|
993
|
+
items={cust.trespass.exclusionOrTrespassBasedOn}
|
|
994
|
+
itemFormatter={itemsFormatterExclusionList}
|
|
995
|
+
isEmptyMessage="-"
|
|
996
|
+
/>
|
|
997
|
+
</Col>
|
|
998
|
+
</Row>
|
|
999
|
+
</>)
|
|
1000
|
+
: null}
|
|
1001
|
+
|
|
1002
|
+
{/* DECLARATION OF SERVICE DETAILS */}
|
|
1003
|
+
<Row style={{ marginTop: '15px' }}>
|
|
1004
|
+
<Col xs={4}>
|
|
1005
|
+
<Headline size="medium" tag="h2">
|
|
1006
|
+
{isDeclarationOfService ? (<FormattedMessage id="details-pane.customersForRender-declaration-of-service" />) : !isTrespassed ? null : (<FormattedMessage id="details-pane.customersForRender-no-declaration-of-service" />) }
|
|
1007
|
+
</Headline>
|
|
1008
|
+
</Col>
|
|
1009
|
+
</Row>
|
|
1010
|
+
|
|
1011
|
+
{isDeclarationOfService ? <Row style={{ marginTop: '15px', marginBottom: '30px'}}>
|
|
1012
|
+
<Col xs={2}>
|
|
1013
|
+
<Headline size="medium" tag="h3">
|
|
1014
|
+
<FormattedMessage id="modal-view-trespass.headline-date-served" />
|
|
1015
|
+
</Headline>
|
|
1016
|
+
<p>
|
|
1017
|
+
{cust.trespass.declarationOfService
|
|
1018
|
+
? convertDateIgnoringTZ(cust.trespass.declarationOfService.date) : '-'}
|
|
1019
|
+
</p>
|
|
1020
|
+
</Col>
|
|
1021
|
+
<Col xs={2}>
|
|
1022
|
+
<Headline size="medium" tag="h3">
|
|
1023
|
+
<FormattedMessage id="modal-view-trespass.headline-place-signed" />
|
|
1024
|
+
</Headline>
|
|
1025
|
+
<p>
|
|
1026
|
+
{cust.trespass.declarationOfService
|
|
1027
|
+
? associatedKeyPlaceSigned(cust.trespass.declarationOfService.placeSigned)
|
|
1028
|
+
: '-'}
|
|
1029
|
+
</p>
|
|
1030
|
+
</Col>
|
|
1031
|
+
<Col xs={2}>
|
|
1032
|
+
<Headline size="medium" tag="h3">
|
|
1033
|
+
<FormattedMessage id="modal-view-trespass.headline-title" />
|
|
1034
|
+
</Headline>
|
|
1035
|
+
<p>
|
|
1036
|
+
{cust.trespass.declarationOfService
|
|
1037
|
+
? cust.trespass.declarationOfService.title
|
|
1038
|
+
: '-'}
|
|
1039
|
+
</p>
|
|
1040
|
+
</Col>
|
|
1041
|
+
<Col xs={2}>
|
|
1042
|
+
<Headline size="medium" tag="h3">
|
|
1043
|
+
<FormattedMessage id="modal-view-trespass.headline-signed" />
|
|
1044
|
+
</Headline>
|
|
1045
|
+
<p>
|
|
1046
|
+
{cust.trespass.declarationOfService && cust.trespass.declarationOfService.signature ? (<FormattedMessage id="details-pane.customersForRender-declaration-of-service-signature-yes"/>) : '-'}
|
|
1047
|
+
</p>
|
|
1048
|
+
</Col>
|
|
1049
|
+
</Row> : null
|
|
1050
|
+
}
|
|
1051
|
+
</Accordion>);
|
|
1052
|
+
})}
|
|
1053
|
+
</Col>
|
|
1054
|
+
</Row>
|
|
1055
|
+
</div>
|
|
1056
|
+
</Accordion>
|
|
1057
|
+
|
|
1058
|
+
|
|
1059
|
+
<Accordion label={<FormattedMessage id="details-pane.accordion-label.incident-details"/>}>
|
|
1060
|
+
<Row>
|
|
1061
|
+
<Col xs={3}>
|
|
1062
|
+
<Label
|
|
1063
|
+
style={{ marginTop: '5px' }}
|
|
1064
|
+
size="medium"
|
|
1065
|
+
tag="h2"
|
|
1066
|
+
id="incident-location-label"
|
|
1067
|
+
>
|
|
1068
|
+
<FormattedMessage id="details-pane.incident-location" />
|
|
1069
|
+
</Label>
|
|
1070
|
+
<Col>
|
|
1071
|
+
<p aria-labelledby="incident-location-label">
|
|
1072
|
+
{locName}
|
|
1073
|
+
</p>
|
|
1074
|
+
</Col>
|
|
1075
|
+
</Col>
|
|
1076
|
+
|
|
1077
|
+
{subLocation !== '' ? (
|
|
1078
|
+
<Col xs={3}>
|
|
1079
|
+
<Label
|
|
1080
|
+
style={{ marginTop: '5px' }}
|
|
1081
|
+
size="medium"
|
|
1082
|
+
tag="h2"
|
|
1083
|
+
id="incident-sub-location-label"
|
|
1084
|
+
>
|
|
1085
|
+
<FormattedMessage id="details-pane.sub-location" />
|
|
1086
|
+
</Label>
|
|
1087
|
+
<Col>
|
|
1088
|
+
<p aria-labelledby="incident-sub-location-label">
|
|
1089
|
+
{subLocation}
|
|
1090
|
+
</p>
|
|
1091
|
+
</Col>
|
|
1092
|
+
</Col>
|
|
1093
|
+
) : null}
|
|
1094
|
+
</Row>
|
|
1095
|
+
|
|
1096
|
+
<Row>
|
|
1097
|
+
<Col xs={3}>
|
|
1098
|
+
<Label
|
|
1099
|
+
style={{ marginTop: '5px' }}
|
|
1100
|
+
size="medium"
|
|
1101
|
+
tag="h2"
|
|
1102
|
+
id="date-of-incident-label"
|
|
1103
|
+
>
|
|
1104
|
+
<FormattedMessage id="details-pane.date-of-incident" />
|
|
1105
|
+
</Label>
|
|
1106
|
+
<Col>
|
|
1107
|
+
<p aria-labelledby="date-of-incident-label">
|
|
1108
|
+
{convertUTCISOToPrettyDate(dateTimeOfIncident) || (<FormattedMessage id="not-available"/>)}
|
|
1109
|
+
</p>
|
|
1110
|
+
</Col>
|
|
1111
|
+
</Col>
|
|
1112
|
+
|
|
1113
|
+
<Col xs={3}>
|
|
1114
|
+
<Label
|
|
1115
|
+
style={{ marginTop: '5px' }}
|
|
1116
|
+
size="medium"
|
|
1117
|
+
tag="h2"
|
|
1118
|
+
id="time-of-incident-label"
|
|
1119
|
+
>
|
|
1120
|
+
<FormattedMessage id="details-pane.time-of-incident" />
|
|
1121
|
+
</Label>
|
|
1122
|
+
<Col>
|
|
1123
|
+
<p aria-labelledby="time-of-incident-label">
|
|
1124
|
+
{isApproximateTime ?
|
|
1125
|
+
(<>
|
|
1126
|
+
<FormattedMessage id="isApproximateTime" defaultMessage="Approximately" /> {convertUTCISOToLocalePrettyTime(dateTimeOfIncident)}</>
|
|
1127
|
+
)
|
|
1128
|
+
:
|
|
1129
|
+
(convertUTCISOToLocalePrettyTime(dateTimeOfIncident))
|
|
1130
|
+
}
|
|
1131
|
+
</p>
|
|
1132
|
+
</Col>
|
|
1133
|
+
</Col>
|
|
1134
|
+
</Row>
|
|
1135
|
+
|
|
1136
|
+
<Row style={{ marginTop: '25px' }}>
|
|
1137
|
+
<Col xs={6}>
|
|
1138
|
+
<Label style={{ marginTop: '5px' }} size="medium" tag="h2">
|
|
1139
|
+
<FormattedMessage
|
|
1140
|
+
id="witnesses-list-label"
|
|
1141
|
+
values={{
|
|
1142
|
+
count: witnessNames.length,
|
|
1143
|
+
bold: (chunks) => <strong>{chunks}</strong>,
|
|
1144
|
+
}}
|
|
1145
|
+
/>
|
|
1146
|
+
</Label>
|
|
1147
|
+
<List
|
|
1148
|
+
aria-labelledby="witnesses-list-label"
|
|
1149
|
+
label={witnessesListLabel}
|
|
1150
|
+
listStyle="bullets"
|
|
1151
|
+
items={witnessesForRender}
|
|
1152
|
+
itemFormatter={witnessItemFormatter}
|
|
1153
|
+
/>
|
|
1154
|
+
</Col>
|
|
1155
|
+
</Row>
|
|
1156
|
+
|
|
1157
|
+
<Row style={{ marginTop: '25px' }}>
|
|
1158
|
+
<Col xs={2}>
|
|
1159
|
+
<KeyValue
|
|
1160
|
+
label={linkedToSummary.length > 0 ? <FormattedMessage id="linked-incidents-label"/> : <FormattedMessage id="linked-incidents-empty-label"/>}
|
|
1161
|
+
value={linkedToSummary.length > 0 ? (
|
|
1162
|
+
<div style={{ display: 'grid', rowGap: '10px' }}>
|
|
1163
|
+
{linkedToSummary.map((ltS) => (
|
|
1164
|
+
<LinkedIncident
|
|
1165
|
+
key={ltS.id}
|
|
1166
|
+
summaryObj={ltS}
|
|
1167
|
+
renderContext='details'
|
|
1168
|
+
/>
|
|
1169
|
+
))}
|
|
1170
|
+
</div>
|
|
1171
|
+
) : null
|
|
1172
|
+
}
|
|
1173
|
+
/>
|
|
1174
|
+
</Col>
|
|
1175
|
+
</Row>
|
|
1176
|
+
|
|
1177
|
+
<Row style={{ marginTop: '13px' }}>
|
|
1178
|
+
<Col xs={8}>
|
|
1179
|
+
<Label style={{ marginTop: '5px' }} size="medium" tag="h2">
|
|
1180
|
+
{incidentTypesListLabel}
|
|
1181
|
+
</Label>
|
|
1182
|
+
<List
|
|
1183
|
+
listStyle="bullets"
|
|
1184
|
+
label={incidentTypesListLabel}
|
|
1185
|
+
items={incTypeTitles}
|
|
1186
|
+
itemFormatter={incTypeFormatter}
|
|
1187
|
+
/>
|
|
1188
|
+
</Col>
|
|
1189
|
+
</Row>
|
|
1190
|
+
|
|
1191
|
+
<Row>
|
|
1192
|
+
<Col xs={6}>
|
|
1193
|
+
<Label style={{ marginTop: '5px' }} size="medium" tag="h2">
|
|
1194
|
+
<FormattedMessage id="details-pane.incident-description" />
|
|
1195
|
+
</Label>
|
|
1196
|
+
<Col>
|
|
1197
|
+
<div
|
|
1198
|
+
dangerouslySetInnerHTML={createMarkup(detailedDescriptionOfIncident)}>
|
|
1199
|
+
</div>
|
|
1200
|
+
</Col>
|
|
1201
|
+
</Col>
|
|
1202
|
+
</Row>
|
|
1203
|
+
|
|
1204
|
+
<Row style={{ marginTop: '15px' }}>
|
|
1205
|
+
<Col xs={6}>
|
|
1206
|
+
<Label
|
|
1207
|
+
style={{ marginTop: '5px' }}
|
|
1208
|
+
size="medium"
|
|
1209
|
+
tag="h2"
|
|
1210
|
+
id="created-by-label"
|
|
1211
|
+
>
|
|
1212
|
+
<FormattedMessage id="details-pane.created-by" />
|
|
1213
|
+
</Label>
|
|
1214
|
+
{readyCreatedByInUI}
|
|
1215
|
+
</Col>
|
|
1216
|
+
</Row>
|
|
1217
|
+
</Accordion>
|
|
1218
|
+
|
|
1219
|
+
<Accordion
|
|
1220
|
+
label={<FormattedMessage id="accordion-label-documents" />}
|
|
1221
|
+
>
|
|
1222
|
+
{/* This div does not render visible UI. Maps documents for GetMedia connected component */}
|
|
1223
|
+
<div>
|
|
1224
|
+
{documents?.map((doc) => (
|
|
1225
|
+
<GetMedia
|
|
1226
|
+
context='document'
|
|
1227
|
+
key={doc.id}
|
|
1228
|
+
id={id}
|
|
1229
|
+
imageId={doc.id}
|
|
1230
|
+
mediaHandler={(mediaUrl) => handleMediaUrl(mediaUrl, doc.id)}
|
|
1231
|
+
/>
|
|
1232
|
+
))}
|
|
1233
|
+
</div>
|
|
1234
|
+
|
|
1235
|
+
{/* This sorts and maps document buttons. The most recent documents are placed at the visual top of list with a clock icon to identify the most current trespass document(s). */}
|
|
1236
|
+
<div>
|
|
1237
|
+
{sortedDocuments.map((doc) => {
|
|
1238
|
+
const isMostCurrent = mostCurrentTrespassDocIds.includes(doc.id);
|
|
1239
|
+
|
|
1240
|
+
return (
|
|
1241
|
+
<Row xs={2} style={{ marginLeft: '15px' }} key={doc.id}>
|
|
1242
|
+
<Button
|
|
1243
|
+
allowAnchorClick={true}
|
|
1244
|
+
href={mediaSrc[doc.id]}
|
|
1245
|
+
target='_blank'
|
|
1246
|
+
style={{ marginTop: '15px' }}
|
|
1247
|
+
>
|
|
1248
|
+
{doc.description}
|
|
1249
|
+
</Button>
|
|
1250
|
+
{isMostCurrent && (
|
|
1251
|
+
<span style={{ marginLeft: '8px', marginTop: '20px' }}>
|
|
1252
|
+
<Icon icon='clock' size='small' />
|
|
1253
|
+
</span>
|
|
1254
|
+
)}
|
|
1255
|
+
</Row>
|
|
1256
|
+
);
|
|
1257
|
+
})}
|
|
1258
|
+
</div>
|
|
1259
|
+
</Accordion>
|
|
1260
|
+
</AccordionSet>
|
|
1261
|
+
</Pane>
|
|
1262
|
+
)}
|
|
1263
|
+
</>
|
|
1264
|
+
);
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1267
|
+
export default DetailsPane;
|