@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,171 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import { useParams } from 'react-router-dom';
|
|
4
|
+
import {
|
|
5
|
+
AccordionSet,
|
|
6
|
+
Accordion,
|
|
7
|
+
Button,
|
|
8
|
+
Col,
|
|
9
|
+
Dropdown,
|
|
10
|
+
DropdownMenu,
|
|
11
|
+
Headline,
|
|
12
|
+
KeyValue,
|
|
13
|
+
Label,
|
|
14
|
+
Pane,
|
|
15
|
+
PaneMenu,
|
|
16
|
+
Row,
|
|
17
|
+
} from '@folio/stripes/components';
|
|
18
|
+
import GetTrespassReasons from './GetTrespassReasons';
|
|
19
|
+
import { useIncidents } from '../contexts/IncidentContext';
|
|
20
|
+
import PutTrespassReasons from './PutTrespassReasons';
|
|
21
|
+
import ModalDeleteTrespassReason from './ModalDeleteTrespassReason';
|
|
22
|
+
|
|
23
|
+
const TrespassReasonDetailsPane = ({handleShowEdit, handleCloseDetails, ...props}, ) => {
|
|
24
|
+
const { id } = useParams();
|
|
25
|
+
const {
|
|
26
|
+
trespassReasons
|
|
27
|
+
} = useIncidents();
|
|
28
|
+
|
|
29
|
+
const [isClickDelete, setIsClickDelete] = useState(false);
|
|
30
|
+
const [toDeleteId, setToDeleteId] = useState(null);
|
|
31
|
+
const [formattedData, setFormattedData] = useState(null);
|
|
32
|
+
const [viewTrespassReason, setViewTrespassReason] = useState({
|
|
33
|
+
reason: '',
|
|
34
|
+
isDefault: false,
|
|
35
|
+
isSuppressed: false
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const singleTRbyId = trespassReasons.find(tr => tr.id === id);
|
|
40
|
+
// console.log("singleTRbyId --> ", JSON.stringify(singleTRbyId, null, 2))
|
|
41
|
+
if (singleTRbyId) {
|
|
42
|
+
setViewTrespassReason(singleTRbyId)
|
|
43
|
+
}
|
|
44
|
+
}, [id, trespassReasons])
|
|
45
|
+
|
|
46
|
+
const handleShowModal = (incidentTypeId) => {
|
|
47
|
+
setIsClickDelete(true);
|
|
48
|
+
setToDeleteId(incidentTypeId);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleCloseModal = () => {
|
|
52
|
+
setIsClickDelete(false);
|
|
53
|
+
setToDeleteId(null);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleDeleteSuccess = () => {
|
|
57
|
+
handleCloseModal();
|
|
58
|
+
handleCloseDetails();
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleDelete = () => {
|
|
62
|
+
if (toDeleteId) {
|
|
63
|
+
const updatedTrespassReasons = trespassReasons.filter((tr) => {
|
|
64
|
+
return tr.id !== toDeleteId;
|
|
65
|
+
});
|
|
66
|
+
const readyFormattedData = {
|
|
67
|
+
data: {
|
|
68
|
+
value: {
|
|
69
|
+
trespassReasons: updatedTrespassReasons
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
setFormattedData(readyFormattedData);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const lastMenu = (
|
|
78
|
+
<PaneMenu>
|
|
79
|
+
<Dropdown
|
|
80
|
+
label={<FormattedMessage id="dropdown-actions-button" />}
|
|
81
|
+
buttonProps={{ buttonStyle: 'primary' }}
|
|
82
|
+
style={{ marginTop: '8px' }}
|
|
83
|
+
>
|
|
84
|
+
<DropdownMenu>
|
|
85
|
+
<Button
|
|
86
|
+
style={{ marginTop: '10px' }}
|
|
87
|
+
buttonStyle="primary"
|
|
88
|
+
onClick={() => handleShowEdit(id)}
|
|
89
|
+
>
|
|
90
|
+
<FormattedMessage id="edit-button" />
|
|
91
|
+
</Button>
|
|
92
|
+
<Button
|
|
93
|
+
style={{ marginTop: '10px' }}
|
|
94
|
+
buttonStyle="warning"
|
|
95
|
+
onClick={() => handleShowModal(id)}
|
|
96
|
+
>
|
|
97
|
+
<FormattedMessage id="settings.incident-types.details-delete-button" />
|
|
98
|
+
</Button>
|
|
99
|
+
</DropdownMenu>
|
|
100
|
+
</Dropdown>
|
|
101
|
+
</PaneMenu>
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Pane
|
|
106
|
+
dismissible
|
|
107
|
+
onClose={handleCloseDetails}
|
|
108
|
+
defaultWidth="100%"
|
|
109
|
+
paneTitle={<FormattedMessage id="settings.trespass-reason-paneTitle"/>}
|
|
110
|
+
{...props}
|
|
111
|
+
lastMenu={lastMenu}>
|
|
112
|
+
|
|
113
|
+
<GetTrespassReasons />
|
|
114
|
+
|
|
115
|
+
{isClickDelete && (
|
|
116
|
+
<ModalDeleteTrespassReason
|
|
117
|
+
isOpen={isClickDelete}
|
|
118
|
+
onClose={handleCloseModal}
|
|
119
|
+
onConfirm={handleDelete}
|
|
120
|
+
/>
|
|
121
|
+
)}
|
|
122
|
+
|
|
123
|
+
{formattedData && (
|
|
124
|
+
<PutTrespassReasons
|
|
125
|
+
data={formattedData}
|
|
126
|
+
context='delete'
|
|
127
|
+
handleDeleteSuccess={handleDeleteSuccess}
|
|
128
|
+
/>
|
|
129
|
+
)}
|
|
130
|
+
|
|
131
|
+
<AccordionSet>
|
|
132
|
+
<Accordion label='Details'>
|
|
133
|
+
<Row>
|
|
134
|
+
<Col xs={6}>
|
|
135
|
+
<KeyValue
|
|
136
|
+
label={<FormattedMessage id="settings.trespass-reason-details-reason-label"/>}
|
|
137
|
+
value={viewTrespassReason.reason || ''}
|
|
138
|
+
/>
|
|
139
|
+
</Col>
|
|
140
|
+
</Row>
|
|
141
|
+
|
|
142
|
+
<Row>
|
|
143
|
+
<Col xs={6}>
|
|
144
|
+
<KeyValue
|
|
145
|
+
label={<FormattedMessage id="settings.trespass-reason-details-default-label"/>}
|
|
146
|
+
value={viewTrespassReason.isDefault ?
|
|
147
|
+
(<FormattedMessage id="settings.trespass-reason-details-yes"/>)
|
|
148
|
+
: (<FormattedMessage id="settings.trespass-reason-details-no"/>)
|
|
149
|
+
}
|
|
150
|
+
/>
|
|
151
|
+
</Col>
|
|
152
|
+
</Row>
|
|
153
|
+
|
|
154
|
+
<Row>
|
|
155
|
+
<Col xs={6}>
|
|
156
|
+
<KeyValue
|
|
157
|
+
label={ <FormattedMessage id="settings.trespass-reason-details-isSuppressed-label"/>}
|
|
158
|
+
value={viewTrespassReason.isSuppressed ?
|
|
159
|
+
(<FormattedMessage id="settings.trespass-reason-details-yes"/>)
|
|
160
|
+
: (<FormattedMessage id="settings.trespass-reason-details-no"/>)
|
|
161
|
+
}
|
|
162
|
+
/>
|
|
163
|
+
</Col>
|
|
164
|
+
</Row>
|
|
165
|
+
</Accordion>
|
|
166
|
+
</AccordionSet>
|
|
167
|
+
</Pane>
|
|
168
|
+
);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export default TrespassReasonDetailsPane;
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import { useParams } from 'react-router-dom';
|
|
4
|
+
import {
|
|
5
|
+
AccordionSet,
|
|
6
|
+
Accordion,
|
|
7
|
+
Button,
|
|
8
|
+
Checkbox,
|
|
9
|
+
Col,
|
|
10
|
+
LoadingPane,
|
|
11
|
+
Pane,
|
|
12
|
+
Row,
|
|
13
|
+
TextArea
|
|
14
|
+
} from '@folio/stripes/components';
|
|
15
|
+
import GetTrespassReasons from './GetTrespassReasons';
|
|
16
|
+
import PutTrespassReasons from './PutTrespassReasons';
|
|
17
|
+
import { useIncidents } from '../contexts/IncidentContext';
|
|
18
|
+
|
|
19
|
+
const TrespassReasonEditPane = ({handleCancelEdit, handleCloseEdit, ...props}) => {
|
|
20
|
+
const { id } = useParams();
|
|
21
|
+
const {
|
|
22
|
+
trespassReasons
|
|
23
|
+
} = useIncidents();
|
|
24
|
+
|
|
25
|
+
const [formattedTrespassReasons, setFormattedTrespassReasons] = useState(null);
|
|
26
|
+
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
|
|
27
|
+
const [trIsLoading, setTrIsLoading] = useState(false);
|
|
28
|
+
const [formData, setFormData] = useState({
|
|
29
|
+
id: '',
|
|
30
|
+
reason: '',
|
|
31
|
+
isDefault: false,
|
|
32
|
+
isSuppressed: false
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// useEffect(() => {
|
|
36
|
+
// console.log("formData --> ", JSON.stringify(formData, null, 2))
|
|
37
|
+
// }, [formData]);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (trespassReasons && trespassReasons.length > 0) {
|
|
41
|
+
const foundTR = trespassReasons.find((tr) => tr.id === id);
|
|
42
|
+
if (foundTR) {
|
|
43
|
+
setFormData({
|
|
44
|
+
id: foundTR.id,
|
|
45
|
+
reason: foundTR.reason || '',
|
|
46
|
+
...(foundTR.isDefault ? {isDefault: foundTR.isDefault} : {}),
|
|
47
|
+
...(foundTR.isSuppressed ? {isSuppressed: foundTR.isSuppressed} : {})
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
console.error(`trespass reason with id ${id} not found`);
|
|
51
|
+
setFormData({
|
|
52
|
+
id: '',
|
|
53
|
+
reason: '',
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
}, [id, trespassReasons]);
|
|
58
|
+
|
|
59
|
+
const handleChange = (event) => {
|
|
60
|
+
const { name, value } = event.target
|
|
61
|
+
if (name === 'isDefault') {
|
|
62
|
+
setFormData((prev) => ({
|
|
63
|
+
...prev,
|
|
64
|
+
[name]: event.target.checked
|
|
65
|
+
}));
|
|
66
|
+
} else if (name === 'isSuppressed') {
|
|
67
|
+
setFormData((prev) => ({
|
|
68
|
+
...prev,
|
|
69
|
+
[name]: event.target.checked
|
|
70
|
+
}))
|
|
71
|
+
} else {
|
|
72
|
+
setFormData((prev) => ({
|
|
73
|
+
...prev,
|
|
74
|
+
[name]: value
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const handleFinishEdit = () => {
|
|
80
|
+
setTrIsLoading(false);
|
|
81
|
+
handleCloseEdit(id);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const stripFalseFlags = (tr, keys = ['isDefault', 'isSuppressed']) => {
|
|
85
|
+
const out = { ...tr };
|
|
86
|
+
for (const k of keys) {
|
|
87
|
+
if (out[k] === false) delete out[k];
|
|
88
|
+
else if (out[k] === true) out[k] = true; // normalize to literal true
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const handleEditSaveAndClose = () => {
|
|
94
|
+
const newTR = {
|
|
95
|
+
id: formData.id,
|
|
96
|
+
reason: formData.reason,
|
|
97
|
+
isSuppressed: !!formData.isSuppressed,
|
|
98
|
+
isDefault: formData.isSuppressed ? false : !!formData.isDefault,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const upsertById = (list, item) => {
|
|
102
|
+
let found = false;
|
|
103
|
+
const replaced = list.map(tr => {
|
|
104
|
+
if (tr.id === item.id) {
|
|
105
|
+
found = true;
|
|
106
|
+
return { ...tr, ...item };
|
|
107
|
+
}
|
|
108
|
+
return tr;
|
|
109
|
+
});
|
|
110
|
+
return found ? replaced : [...replaced, item];
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
let next = upsertById(trespassReasons, newTR);
|
|
114
|
+
|
|
115
|
+
// no suppressed item can be default
|
|
116
|
+
next = next.map(tr => (tr.isSuppressed ? { ...tr, isDefault: false} : tr));
|
|
117
|
+
|
|
118
|
+
// ensure single isDefault (having a default is not required)
|
|
119
|
+
if (newTR.isDefault) {
|
|
120
|
+
next = next.map(tr => tr.id === newTR.id ? tr : { ...tr, isDefault: false }
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
// remove false flags (no persist isDefault: false, isSuppressed: false, only persist if true)
|
|
125
|
+
next = next.map(tr => stripFalseFlags(tr, ['isDefault', 'isSuppressed']));
|
|
126
|
+
|
|
127
|
+
const readyFormattedData = {
|
|
128
|
+
value: { trespassReasons: next }
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// console.log("ON SAVE, pre data key -> ", JSON.stringify(readyFormattedData, null, 2))
|
|
132
|
+
|
|
133
|
+
// triggers <PutTrespassReasons />
|
|
134
|
+
setFormattedTrespassReasons({ data: readyFormattedData })
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
useEffect(() => {
|
|
138
|
+
const isReasonNotEmpty = formData.reason && formData.reason.trim() !== '';
|
|
139
|
+
const isValid = isReasonNotEmpty;
|
|
140
|
+
setIsButtonDisabled(!isValid);
|
|
141
|
+
}, [formData]);
|
|
142
|
+
|
|
143
|
+
return (
|
|
144
|
+
<>
|
|
145
|
+
<GetTrespassReasons />
|
|
146
|
+
|
|
147
|
+
{formattedTrespassReasons &&
|
|
148
|
+
<PutTrespassReasons
|
|
149
|
+
data={formattedTrespassReasons}
|
|
150
|
+
handleFinishEdit={handleFinishEdit}
|
|
151
|
+
/>}
|
|
152
|
+
|
|
153
|
+
{trIsLoading ? (
|
|
154
|
+
<LoadingPane defaultWidth='100%'/>
|
|
155
|
+
) : (
|
|
156
|
+
<Pane
|
|
157
|
+
dismissible
|
|
158
|
+
onClose={() => handleCancelEdit(id)}
|
|
159
|
+
defaultWidth="100%"
|
|
160
|
+
paneTitle={<FormattedMessage
|
|
161
|
+
id="settings.trespass-reasons-paneTitle"/>
|
|
162
|
+
}
|
|
163
|
+
{...props}>
|
|
164
|
+
|
|
165
|
+
<AccordionSet>
|
|
166
|
+
<Accordion label={<FormattedMessage
|
|
167
|
+
id="details-pane.accordion-label.details"/>}
|
|
168
|
+
>
|
|
169
|
+
<Row>
|
|
170
|
+
<Col xs={8}>
|
|
171
|
+
<TextArea
|
|
172
|
+
required
|
|
173
|
+
label={<FormattedMessage id="settings.trespass-document-edit-textfield-reason-label"/>}
|
|
174
|
+
name='reason'
|
|
175
|
+
value={formData.reason}
|
|
176
|
+
onChange={handleChange}
|
|
177
|
+
/>
|
|
178
|
+
</Col>
|
|
179
|
+
</Row>
|
|
180
|
+
<Row>
|
|
181
|
+
<Col xs={6}>
|
|
182
|
+
<Checkbox
|
|
183
|
+
label={<FormattedMessage id="settings.trespass-document-edit-checkbox-default-label"/>}
|
|
184
|
+
name='isDefault'
|
|
185
|
+
checked={formData.isDefault}
|
|
186
|
+
onChange={handleChange}
|
|
187
|
+
/>
|
|
188
|
+
</Col>
|
|
189
|
+
</Row>
|
|
190
|
+
<Row>
|
|
191
|
+
<Col xs={6}>
|
|
192
|
+
<Checkbox
|
|
193
|
+
label={<FormattedMessage id="settings.trespass-document-edit-checkbox-suppress-label"/>}
|
|
194
|
+
name='isSuppressed'
|
|
195
|
+
checked={formData.isSuppressed}
|
|
196
|
+
onChange={handleChange}
|
|
197
|
+
/>
|
|
198
|
+
</Col>
|
|
199
|
+
</Row>
|
|
200
|
+
<Row style={{ marginTop: '20px', marginBottom: '25px'}}>
|
|
201
|
+
<Col xs={4}>
|
|
202
|
+
<Button
|
|
203
|
+
buttonStyle='primary'
|
|
204
|
+
disabled={isButtonDisabled}
|
|
205
|
+
onClick={handleEditSaveAndClose}
|
|
206
|
+
>
|
|
207
|
+
<FormattedMessage
|
|
208
|
+
id="save-and-close-button"
|
|
209
|
+
/>
|
|
210
|
+
</Button>
|
|
211
|
+
</Col>
|
|
212
|
+
</Row>
|
|
213
|
+
</Accordion>
|
|
214
|
+
</AccordionSet>
|
|
215
|
+
</Pane>
|
|
216
|
+
)}
|
|
217
|
+
</>
|
|
218
|
+
);
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
export default TrespassReasonEditPane;
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { useHistory, Switch, Route, useLocation } from 'react-router-dom';
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Checkbox,
|
|
8
|
+
Col,
|
|
9
|
+
Icon,
|
|
10
|
+
MultiColumnList,
|
|
11
|
+
Pane,
|
|
12
|
+
Paneset,
|
|
13
|
+
Row,
|
|
14
|
+
TextArea
|
|
15
|
+
} from '@folio/stripes/components';
|
|
16
|
+
import GetTrespassReasons from './GetTrespassReasons';
|
|
17
|
+
import PutTrespassReasons from './PutTrespassReasons';
|
|
18
|
+
import TrespassReasonDetailsPane from './TrespassReasonDetailsPane';
|
|
19
|
+
import TrespassReasonEditPane from './TrespassReasonEditPane';
|
|
20
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
21
|
+
import { useIncidents } from '../contexts/IncidentContext';
|
|
22
|
+
|
|
23
|
+
const TrespassReasonsPaneset = ({...props}) => {
|
|
24
|
+
const history = useHistory();
|
|
25
|
+
const { pathname } = useLocation();
|
|
26
|
+
const {
|
|
27
|
+
trespassReasons
|
|
28
|
+
} = useIncidents();
|
|
29
|
+
|
|
30
|
+
const [trespassReasonsList, setTrespassReasonsList] = useState([]);
|
|
31
|
+
const listRoute = '/settings/incidents/trespass-reasons';
|
|
32
|
+
const [reloadKey, setReloadKey] = useState(0);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (pathname === listRoute) {
|
|
35
|
+
setReloadKey(key => key + 1) // guarantee fresh GET
|
|
36
|
+
}
|
|
37
|
+
}, [pathname]);
|
|
38
|
+
const [isButtonDisabled, setIsButtonDisabled] = useState(false);
|
|
39
|
+
const [formattedTrespassReasons, setFormattedTrespassReasons] = useState(null);
|
|
40
|
+
const [formData, setFormData] = useState({
|
|
41
|
+
id: '',
|
|
42
|
+
reason: ''
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const sortTRlist = (trConfigList = []) => {
|
|
46
|
+
const collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
|
|
47
|
+
return [...trConfigList].sort((a, b) => {
|
|
48
|
+
const aStr = (a?.reason ?? '').trim();
|
|
49
|
+
const bStr = (b?.reason ?? '').trim();
|
|
50
|
+
return collator.compare(aStr, bStr);
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
const sortedTRlist = sortTRlist(trespassReasons);
|
|
56
|
+
// console.log("sortedTRlist --> ", JSON.stringify(sortedTRlist, null, 2))
|
|
57
|
+
setTrespassReasonsList(sortedTRlist)
|
|
58
|
+
}, [trespassReasons])
|
|
59
|
+
|
|
60
|
+
const handleChange = (event) => {
|
|
61
|
+
const { name, value } = event.target
|
|
62
|
+
if (name === 'isDefault') {
|
|
63
|
+
setFormData((prev) => ({
|
|
64
|
+
...prev,
|
|
65
|
+
[name]: event.target.checked
|
|
66
|
+
}));
|
|
67
|
+
} else {
|
|
68
|
+
setFormData((prev) => ({
|
|
69
|
+
...prev,
|
|
70
|
+
[name]: value
|
|
71
|
+
}));
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const resetForFreshFormInput = () => {
|
|
76
|
+
setFormData({
|
|
77
|
+
id: '',
|
|
78
|
+
reason: ''
|
|
79
|
+
})
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const makeTrespassReasonObject = () => {
|
|
83
|
+
return {
|
|
84
|
+
id: uuidv4(),
|
|
85
|
+
reason: formData.reason,
|
|
86
|
+
...(formData.isDefault ? { isDefault: true } : {})
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const handleSaveAndClose = () => {
|
|
91
|
+
const newTrespassReason = makeTrespassReasonObject();
|
|
92
|
+
let updatedTrespassReasonsList = [];
|
|
93
|
+
|
|
94
|
+
// handle can only be one TR w/ isDefault: true
|
|
95
|
+
if (newTrespassReason.isDefault) {
|
|
96
|
+
const removedPrevDefaultList = trespassReasons.map((tr) => {
|
|
97
|
+
const { isDefault, ...otherKeys } = tr;
|
|
98
|
+
return otherKeys;
|
|
99
|
+
});
|
|
100
|
+
updatedTrespassReasonsList = [...removedPrevDefaultList, newTrespassReason];
|
|
101
|
+
} else {
|
|
102
|
+
updatedTrespassReasonsList = [...trespassReasons, newTrespassReason]
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const readyFormattedData = {
|
|
106
|
+
value: {
|
|
107
|
+
trespassReasons: updatedTrespassReasonsList
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
setFormattedTrespassReasons({ data: readyFormattedData })
|
|
112
|
+
resetForFreshFormInput();
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const handleCloseDetails = () => {
|
|
116
|
+
history.push(`/settings/incidents/trespass-reasons`);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const handleShowDetails = (event, row) => {
|
|
120
|
+
const id = row.id
|
|
121
|
+
history.push(`/settings/incidents/trespass-reasons/${id}`);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const handleShowEdit = (reasonsId) => {
|
|
125
|
+
history.push(`/settings/incidents/trespass-reasons/${reasonsId}/edit`);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const handleCancelEdit = (reasonsId) => {
|
|
129
|
+
history.push(`/settings/incidents/trespass-reasons/${reasonsId}`);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const handleCloseEdit = (reasonsId) => {
|
|
133
|
+
history.push(`/settings/incidents/trespass-reasons/${reasonsId}`);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const getValidationResults = () => {
|
|
137
|
+
const isReasonNotEmpty = formData.reason && formData.reason.trim() !== '';
|
|
138
|
+
return isReasonNotEmpty
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
setIsButtonDisabled(!getValidationResults())
|
|
143
|
+
}, [formData]);
|
|
144
|
+
|
|
145
|
+
const columnWidths = {
|
|
146
|
+
reason: '275px',
|
|
147
|
+
isDefault: '80px'
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const formatter = {
|
|
151
|
+
reason: (item) => {
|
|
152
|
+
if (item.reason?.length > 48) {
|
|
153
|
+
return item.reason.slice(0, 72) + "...";
|
|
154
|
+
} else {
|
|
155
|
+
return item.reason;
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
isDefault: (item) => {
|
|
159
|
+
const isDefault = item.isDefault;
|
|
160
|
+
return isDefault ? <span style={{ color: 'green' }}>
|
|
161
|
+
<Icon icon='check-circle'></Icon>
|
|
162
|
+
</span>
|
|
163
|
+
: null
|
|
164
|
+
},
|
|
165
|
+
isSuppressed: (item) => {
|
|
166
|
+
const isSuppressed = item.isSuppressed;
|
|
167
|
+
return isSuppressed ? <span>
|
|
168
|
+
<Icon
|
|
169
|
+
size='small'
|
|
170
|
+
icon='exclamation-circle'
|
|
171
|
+
status='warn'>
|
|
172
|
+
</Icon>
|
|
173
|
+
</span>
|
|
174
|
+
: null
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Paneset>
|
|
180
|
+
<Pane
|
|
181
|
+
defaultWidth="fill"
|
|
182
|
+
paneTitle={<FormattedMessage
|
|
183
|
+
id="settings.trespass-reasons-paneTitle"/>
|
|
184
|
+
}
|
|
185
|
+
>
|
|
186
|
+
<GetTrespassReasons key={reloadKey} reloadKey={reloadKey}/>
|
|
187
|
+
|
|
188
|
+
{formattedTrespassReasons &&
|
|
189
|
+
<PutTrespassReasons
|
|
190
|
+
data={formattedTrespassReasons}
|
|
191
|
+
onSuccess={() => {
|
|
192
|
+
setFormattedTrespassReasons(null); // unmount this component
|
|
193
|
+
setReloadKey(key => key + 1); // force fresh GET
|
|
194
|
+
}}
|
|
195
|
+
/>}
|
|
196
|
+
|
|
197
|
+
<Row>
|
|
198
|
+
<Col xs={12}>
|
|
199
|
+
<MultiColumnList
|
|
200
|
+
contentData={trespassReasonsList ?? []}
|
|
201
|
+
visibleColumns={[
|
|
202
|
+
'reason',
|
|
203
|
+
'isDefault',
|
|
204
|
+
'isSuppressed'
|
|
205
|
+
]}
|
|
206
|
+
columnMapping={{
|
|
207
|
+
reason: <FormattedMessage id="settings.trespass-reasons.column-mapping-reason"/>,
|
|
208
|
+
isDefault: <FormattedMessage id="settings.trespass-reasons.column-mapping-default"/>,
|
|
209
|
+
isSuppressed: <FormattedMessage id="settings.trespass-reasons.column-mapping-isSuppressed"/>
|
|
210
|
+
}}
|
|
211
|
+
columnWidths={columnWidths}
|
|
212
|
+
formatter={formatter}
|
|
213
|
+
onRowClick={handleShowDetails}
|
|
214
|
+
/>
|
|
215
|
+
</Col>
|
|
216
|
+
</Row>
|
|
217
|
+
|
|
218
|
+
<Row style={{ marginTop: '45px' }}>
|
|
219
|
+
<Col xs={8}>
|
|
220
|
+
<TextArea
|
|
221
|
+
required
|
|
222
|
+
label={<FormattedMessage id="settings.trespass-reason-textarea-reason"/>}
|
|
223
|
+
name='reason'
|
|
224
|
+
value={formData.reason}
|
|
225
|
+
onChange={handleChange}
|
|
226
|
+
/>
|
|
227
|
+
</Col>
|
|
228
|
+
</Row>
|
|
229
|
+
|
|
230
|
+
<Row>
|
|
231
|
+
<Col xs={6}>
|
|
232
|
+
<Checkbox
|
|
233
|
+
label={<FormattedMessage id="settings.trespass-reason-checkbox-isDefault"/>}
|
|
234
|
+
name='isDefault'
|
|
235
|
+
checked={formData.isDefault}
|
|
236
|
+
onChange={handleChange}
|
|
237
|
+
/>
|
|
238
|
+
</Col>
|
|
239
|
+
</Row>
|
|
240
|
+
|
|
241
|
+
<Row style={{ marginTop: '20px', marginBottom: '25px'}}>
|
|
242
|
+
<Col xs={4}>
|
|
243
|
+
<Button
|
|
244
|
+
buttonStyle='primary'
|
|
245
|
+
disabled={isButtonDisabled}
|
|
246
|
+
onClick={handleSaveAndClose}
|
|
247
|
+
>
|
|
248
|
+
<FormattedMessage
|
|
249
|
+
id="save-and-close-button"
|
|
250
|
+
/>
|
|
251
|
+
</Button>
|
|
252
|
+
</Col>
|
|
253
|
+
</Row>
|
|
254
|
+
</Pane>
|
|
255
|
+
|
|
256
|
+
<Switch>
|
|
257
|
+
<Route
|
|
258
|
+
exact
|
|
259
|
+
path="/settings/incidents/trespass-reasons/:id"
|
|
260
|
+
render={(props) => (
|
|
261
|
+
<TrespassReasonDetailsPane
|
|
262
|
+
{...props}
|
|
263
|
+
handleCloseDetails={handleCloseDetails}
|
|
264
|
+
handleShowEdit={handleShowEdit}
|
|
265
|
+
/>
|
|
266
|
+
)}/>
|
|
267
|
+
<Route
|
|
268
|
+
exact
|
|
269
|
+
path="/settings/incidents/trespass-reasons/:id/edit"
|
|
270
|
+
render={(props) => (
|
|
271
|
+
<TrespassReasonEditPane
|
|
272
|
+
handleCancelEdit={handleCancelEdit}
|
|
273
|
+
handleCloseEdit={handleCloseEdit}
|
|
274
|
+
{...props}
|
|
275
|
+
/>
|
|
276
|
+
)}/>
|
|
277
|
+
</Switch>
|
|
278
|
+
</Paneset>
|
|
279
|
+
)
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
export default TrespassReasonsPaneset;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders without crashing (snapshot) 1`] = `"<div><div></div><div><div xs="10"><button><span>settings.categories-new-button</span></button></div></div><ul><li><div data-col="title">Behavior</div><div data-col="id"><div><div><button><span>edit-button</span></button><button><span>settings.categories-delete-button</span></button></div></div></div></li><li><div data-col="title">Property</div><div data-col="id"><div><div><button><span>edit-button</span></button><button><span>settings.categories-delete-button</span></button></div></div></div></li></ul><div>Mock GetIncidentCategories</div></div>"`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders without crashing (snapshot) 1`] = `"<div><div><div><div><div><button buttonstyle="primary" style="display: block; width: 50%; margin-top: 10px;"><span>edit-button</span></button><button buttonstyle="warning" style="display: block; width: 50%; margin-top: 10px;"><span>settings.incident-types.details-delete-button</span></button></div></div></div></div><div>Mock GetIncidentCategories</div><div>Mock GetSingleIncidentTypeDetails</div><div>Mock GetIncidentTypesDetails</div><div><div label="[object Object]"><div><div xs="8"><div><label style="margin-top: 5px;" tag="h2"><span>settings.incident-types.details.title-label</span></label><p>Type 1 - Disorderly</p></div></div></div><div><div xs="8"><div><label style="margin-top: 5px;" tag="h2"><span>settings.incident-types.details.category-label</span></label><p>Behavior</p></div></div></div><div><div xs="10"><label style="margin-top: 5px;" tag="h2"><span>settings.incident-types.details.description-label</span></label><p>Initial description</p></div></div></div><div label="[object Object]"></div></div></div>"`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders without crashing (snapshot) 1`] = `"<div><div panetitle="[object Object]"></div><div>Mock GetSingleIncidentTypeDetails</div><div>Mock GetIncidentCategories</div><div>Mock GetIncidentTypesDetails</div><div><div label="[object Object]"><div><div xs="8"><div><input required="" label="[object Object]" name="title" value="Type 1 - Disorderly"></div></div></div><div><div xs="4"><div><select required="" label="[object Object]" name="category_id" placeholder="Select a category" dataoptions="[object Object],[object Object]"></select></div></div></div><div><div xs="6"><textarea required="" label="[object Object]" name="description" style="width: 100%; height: 200px;">Initial description</textarea></div></div></div></div><div><button><span>cancel-button</span></button><button buttonstyle="primary"><span>save-and-close-button</span></button></div></div>"`;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`renders without crashing (snapshot) 1`] = `"<div><div panetitle="[object Object]" defaultwidth="fill"><div><div xs="10"><button buttonstyle="primary"><span>settings.incident-types-new-button</span></button></div></div><ul><li><li>Type 1 - Disorderly</li><li>Type 2 - Theft</li><li>Type 2.1 - Minor</li><li>Type 10 - Assault</li></li></ul></div><div>Mock GetIncidentTypesDetails</div><div></div></div>"`;
|