1
- import Link from '@admin/components/Link' ;
2
1
import ButtonLink from '@admin/components/ButtonLink' ;
2
+ import Link from '@admin/components/Link' ;
3
+ import ApiDataSetAutoMappedTable from '@admin/pages/release/data/components/ApiDataSetAutoMappedTable' ;
4
+ import ApiDataSetDeletedLocationGroupsTable from '@admin/pages/release/data/components/ApiDataSetDeletedLocationGroupsTable' ;
5
+ import ApiDataSetLocationCode from '@admin/pages/release/data/components/ApiDataSetLocationCode' ;
6
+ import ApiDataSetMappableTable from '@admin/pages/release/data/components/ApiDataSetMappableTable' ;
7
+ import ApiDataSetNewItemsTable from '@admin/pages/release/data/components/ApiDataSetNewItemsTable' ;
8
+ import ApiDataSetNewLocationGroupsTable from '@admin/pages/release/data/components/ApiDataSetNewLocationGroupsTable' ;
9
+ import { PendingMappingUpdate } from '@admin/pages/release/data/types/apiDataSetMappings' ;
3
10
import getApiDataSetLocationMappings , {
4
11
AutoMappedLocation ,
5
12
LocationCandidateWithKey ,
6
13
MappableLocation ,
7
14
} from '@admin/pages/release/data/utils/getApiDataSetLocationMappings' ;
8
- import ApiDataSetMappableTable from '@admin/pages/release/data/components/ApiDataSetMappableTable' ;
9
- import ApiDataSetNewItemsTable from '@admin/pages/release/data/components/ApiDataSetNewItemsTable' ;
10
- import ApiDataSetAutoMappedTable from '@admin/pages/release/data/components/ApiDataSetAutoMappedTable' ;
11
- import ApiDataSetLocationCode from '@admin/pages/release/data/components/ApiDataSetLocationCode' ;
12
- import { PendingMappingUpdate } from '@admin/pages/release/data/types/apiDataSetMappings' ;
13
15
import getUnmappedLocationErrors from '@admin/pages/release/data/utils/getUnmappedLocationErrors' ;
14
- import getApiDataSetLocationCodes from '@admin/pages/release/data/utils/getApiDataSetLocationCodes' ;
16
+ import apiDataSetQueries from '@admin/queries/apiDataSetQueries' ;
17
+ import apiDataSetVersionQueries from '@admin/queries/apiDataSetVersionQueries' ;
15
18
import {
16
19
releaseApiDataSetDetailsRoute ,
17
20
ReleaseDataSetRouteParams ,
18
21
} from '@admin/routes/releaseRoutes' ;
19
- import apiDataSetVersionQueries from '@admin/queries/apiDataSetVersionQueries' ;
20
- import apiDataSetQueries from '@admin/queries/apiDataSetQueries' ;
21
22
import apiDataSetVersionService , {
22
23
LocationCandidate ,
23
24
} from '@admin/services/apiDataSetVersionService' ;
24
- import Tag from '@common/components/Tag' ;
25
- import LoadingSpinner from '@common/components/LoadingSpinner' ;
26
25
import Accordion from '@common/components/Accordion' ;
27
26
import AccordionSection from '@common/components/AccordionSection' ;
28
- import PageNav , { NavItem } from '@common/components/PageNav ' ;
27
+ import LoadingSpinner from '@common/components/LoadingSpinner ' ;
29
28
import NotificationBanner from '@common/components/NotificationBanner' ;
29
+ import PageNav , { NavItem } from '@common/components/PageNav' ;
30
30
import SummaryListItem from '@common/components/SummaryListItem' ;
31
+ import Tag from '@common/components/Tag' ;
32
+ import useDebouncedCallback from '@common/hooks/useDebouncedCallback' ;
31
33
import locationLevelsMap , {
32
34
LocationLevelKey ,
33
35
} from '@common/utils/locationLevelsMap' ;
34
- import useDebouncedCallback from '@common/hooks/useDebouncedCallback' ;
35
36
import typedKeys from '@common/utils/object/typedKeys' ;
36
37
import { useQuery } from '@tanstack/react-query' ;
38
+ import compact from 'lodash/compact' ;
39
+ import omit from 'lodash/omit' ;
37
40
import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
38
41
import { generatePath , useParams } from 'react-router-dom' ;
39
- import omit from 'lodash/omit' ;
40
- import compact from 'lodash/compact' ;
41
42
import { useImmer } from 'use-immer' ;
42
43
43
44
// Fields to omit from mapping diff.
@@ -56,6 +57,14 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
56
57
const [ mappableLocations , updateMappableLocations ] = useImmer <
57
58
Partial < Record < LocationLevelKey , MappableLocation [ ] > >
58
59
> ( { } ) ;
60
+
61
+ const [ newLocationGroups , updateNewLocationGroups ] = useImmer <
62
+ Partial < Record < LocationLevelKey , LocationCandidate [ ] > >
63
+ > ( { } ) ;
64
+ const [ deletedLocationGroups , updateDeletedLocationGroups ] = useImmer <
65
+ Partial < Record < LocationLevelKey , LocationCandidate [ ] > >
66
+ > ( { } ) ;
67
+
59
68
const [ pendingUpdates , setPendingUpdates ] = useState < PendingMappingUpdate [ ] > (
60
69
[ ] ,
61
70
) ;
@@ -77,14 +86,20 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
77
86
useEffect ( ( ) => {
78
87
if ( locationsMapping ) {
79
88
const mappings = getApiDataSetLocationMappings ( locationsMapping ) ;
89
+
80
90
updateAutoMappedLocations ( mappings . autoMappedLocations ) ;
81
91
updateNewLocations ( mappings . newLocations ) ;
82
92
updateMappableLocations ( mappings . mappableLocations ) ;
93
+
94
+ updateNewLocationGroups ( mappings . newLocationGroups ) ;
95
+ updateDeletedLocationGroups ( mappings . deletedLocationGroups ) ;
83
96
}
84
97
} , [
85
98
locationsMapping ,
86
99
updateAutoMappedLocations ,
100
+ updateDeletedLocationGroups ,
87
101
updateMappableLocations ,
102
+ updateNewLocationGroups ,
88
103
updateNewLocations ,
89
104
] ) ;
90
105
@@ -100,11 +115,27 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
100
115
101
116
const navItems : NavItem [ ] = useMemo ( ( ) => {
102
117
return [
118
+ ...( Object . keys ( deletedLocationGroups ) . length > 0
119
+ ? [
120
+ {
121
+ id : 'deleted-location-groups' ,
122
+ text : 'Location groups not found in new data set' ,
123
+ } ,
124
+ ]
125
+ : [ ] ) ,
103
126
{
104
127
id : 'mappable-locations' ,
105
- text : 'Locations not found in the new data set' ,
128
+ text : 'Locations not found in new data set' ,
106
129
subNavItems : getSubNavItems ( mappableLocations , 'mappable' ) ,
107
130
} ,
131
+ ...( Object . keys ( newLocationGroups ) . length > 0
132
+ ? [
133
+ {
134
+ id : 'new-location-groups' ,
135
+ text : 'New location groups' ,
136
+ } ,
137
+ ]
138
+ : [ ] ) ,
108
139
{
109
140
id : 'new-locations' ,
110
141
text : 'New locations' ,
@@ -116,7 +147,13 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
116
147
subNavItems : getSubNavItems ( autoMappedLocations , 'auto-mapped' ) ,
117
148
} ,
118
149
] ;
119
- } , [ autoMappedLocations , mappableLocations , newLocations ] ) ;
150
+ } , [
151
+ autoMappedLocations ,
152
+ deletedLocationGroups ,
153
+ mappableLocations ,
154
+ newLocationGroups ,
155
+ newLocations ,
156
+ ] ) ;
120
157
121
158
const updateMappingState = useCallback (
122
159
( updates : PendingMappingUpdate [ ] ) => {
@@ -259,6 +296,7 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
259
296
< LoadingSpinner loading = { isLoadingDataSet || isLoadingMapping } >
260
297
< div className = "govuk-grid-row" >
261
298
< PageNav items = { navItems } />
299
+
262
300
< div className = "govuk-grid-column-three-quarters" >
263
301
< span className = "govuk-caption-l" > Map locations</ span >
264
302
< h2 > { dataSet ?. title } </ h2 >
@@ -286,8 +324,23 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
286
324
show as new locations in the API data set.
287
325
</ p >
288
326
327
+ { Object . keys ( deletedLocationGroups ) . length > 0 && (
328
+ < >
329
+ < h3 className = "govuk-heading-l" id = "deleted-location-groups" >
330
+ { `Location groups not found in new data set (${
331
+ Object . keys ( deletedLocationGroups ) . length
332
+ } ) `}
333
+ < Tag colour = "grey" > No action required</ Tag >
334
+ </ h3 >
335
+
336
+ < ApiDataSetDeletedLocationGroupsTable
337
+ locationGroups = { deletedLocationGroups }
338
+ />
339
+ </ >
340
+ ) }
341
+
289
342
< h3 className = "govuk-heading-l" id = "unmapped-locations" >
290
- Locations not found in the new data set
343
+ Locations not found in new data set
291
344
</ h3 >
292
345
293
346
{ typedKeys ( mappableLocations ) . length > 0 ? (
@@ -300,9 +353,9 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
300
353
return (
301
354
< ApiDataSetMappableTable
302
355
key = { level }
303
- candidateHint = { candidate =>
304
- getApiDataSetLocationCodes ( candidate )
305
- }
356
+ candidateHint = { candidate => (
357
+ < ApiDataSetLocationCode location = { candidate } />
358
+ ) }
306
359
candidateIsMajorMapping = { ( candidate , mapping ) => {
307
360
return Object . entries (
308
361
omit ( mapping . source , omittedDiffingFields ) ,
@@ -346,6 +399,24 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
346
399
< p > No locations.</ p >
347
400
) }
348
401
402
+ { Object . keys ( newLocationGroups ) . length > 0 && (
403
+ < >
404
+ < h3
405
+ className = "govuk-heading-l govuk-!-margin-top-8"
406
+ id = "new-location-groups"
407
+ >
408
+ { `New location groups (${
409
+ Object . keys ( deletedLocationGroups ) . length
410
+ } ) `}
411
+ < Tag colour = "grey" > No action required</ Tag >
412
+ </ h3 >
413
+
414
+ < ApiDataSetNewLocationGroupsTable
415
+ locationGroups = { newLocationGroups }
416
+ />
417
+ </ >
418
+ ) }
419
+
349
420
< h3
350
421
className = "govuk-heading-l govuk-!-margin-top-8"
351
422
id = "new-locations"
@@ -419,9 +490,9 @@ export default function ReleaseApiDataSetLocationsMappingPage() {
419
490
key = { level }
420
491
>
421
492
< ApiDataSetAutoMappedTable
422
- candidateHint = { candidate =>
423
- getApiDataSetLocationCodes ( candidate )
424
- }
493
+ candidateHint = { candidate => (
494
+ < ApiDataSetLocationCode location = { candidate } />
495
+ ) }
425
496
groupKey = { level }
426
497
groupLabel = { groupLabel }
427
498
itemLabel = "location"
0 commit comments