Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 14588cb6

Přidáno uživatelem Václav Honzík před téměř 3 roky(ů)

  • ID 14588cb653e6b7358e0e641cc2b8d45dc27b5cf8
  • Rodič fc8a530f

fixed keys and indices

re #9741

Zobrazit rozdíly:

frontend/src/features/Reusables/SingleFileSelectionForm.tsx
9 9
    onFileSelected: (event: any) => void
10 10
    formik: any
11 11
    onClearSelectedFile: () => void
12
    loading?: boolean
12 13
}
13 14

  
14 15
const SingleFileSelectionForm: FunctionComponent<
15 16
    SingleFileSelectionFormProps
16
> = ({ filename, onFileSelected, formik, onClearSelectedFile }) => {
17
> = ({ filename, onFileSelected, formik, onClearSelectedFile, loading }) => {
17 18
    return (
18 19
        <form onSubmit={formik.handleSubmit}>
19 20
            {!filename ? (
......
76 77
                            type="submit"
77 78
                            variant="contained"
78 79
                            startIcon={<SendIcon />}
80
                            disabled={loading}
79 81
                        >
80 82
                            Submit
81 83
                        </Button>
frontend/src/features/TrackingTool/Controls/DragDropCtxWrapper.tsx
32 32
                            <MapPointDraggableListItem
33 33
                                list={items}
34 34
                                idx={index}
35
                                key={item.id}
35
                                key={item.reactId}
36 36
                            />
37 37
                        ))}
38 38
                        {provided.placeholder}
frontend/src/features/TrackingTool/Controls/MapPointDraggableList.tsx
1 1
import { Paper } from '@mui/material'
2
import { useCallback } from 'react'
2
import { Fragment, useCallback } from 'react'
3 3
import { DropResult } from 'react-beautiful-dnd'
4 4
import { useDispatch, useSelector } from 'react-redux'
5 5
import { RootState } from '../../redux/store'
6
import { moveMarkerToDestination } from '../trackingToolSlice'
6
import { changeMarkerIdx } from '../trackingToolSlice'
7 7
import DragDropCtxWrapper from './DragDropCtxWrapper'
8 8

  
9 9
const MapPointDraggableList = () => {
......
18 18
            }
19 19

  
20 20
            dispatch(
21
                moveMarkerToDestination({
21
                changeMarkerIdx({
22 22
                    source: source.index,
23 23
                    destination: destination.index,
24 24
                })
......
28 28
    )
29 29

  
30 30
    return (
31
        <Paper variant="outlined">
32
            <DragDropCtxWrapper items={path ?? []} onDragEnd={onDragEnd} />
33
        </Paper>
31
        <Fragment>
32
            {path && (
33
                <Paper variant="outlined">
34
                    <DragDropCtxWrapper
35
                        items={path ?? []}
36
                        onDragEnd={onDragEnd}
37
                    />
38
                </Paper>
39
            )}
40
        </Fragment>
34 41
    )
35 42
}
36 43

  
frontend/src/features/TrackingTool/Controls/MapPointDraggableListItem.tsx
8 8
import { Draggable } from 'react-beautiful-dnd'
9 9
import {
10 10
    getMapPointSemanticColor,
11
    isMapPointDisplayable,
11 12
    MapPointType,
12 13
    PathVariant,
13 14
} from '../trackingToolUtils'
14 15
import { CatalogItemDto } from '../../../swagger/data-contracts'
15 16
import { useDispatch } from 'react-redux'
16
import { removeMapMarker, updateMapMarker } from '../trackingToolSlice'
17
import {
18
    removeMapMarker,
19
    updateMapPoint,
20
    updateMapPointAtIndex,
21
} from '../trackingToolSlice'
17 22
import { useMemo } from 'react'
18 23
import DragHandleIcon from '@mui/icons-material/DragHandle'
19 24
import VisibilityIcon from '@mui/icons-material/Visibility'
......
27 32
    idx: number
28 33
}
29 34

  
35
// function Item({ provided, item, isDragging }) {
36
//     return (
37
//       <div style={{ paddingBottom: '8px' }}>
38
//         <div
39
//           {...provided.draggableProps}
40
//           {...provided.dragHandleProps}
41
//           ref={provided.innerRef}
42
//           style={provided.draggableProps.style}
43
//           className={`item ${isDragging ? 'is-dragging' : ''}`}
44
//         >
45
//           {item.text}
46
//         </div>
47
//       </div>
48
//     )
49
//   }
50

  
51
//   const HeightPreservingItem = ({ children, ...props }) => {
52
//     const [size, setSize] = useState(0)
53
//     const knownSize = props['data-known-size']
54
//     useEffect(() => {
55
//       setSize((prevSize) => {
56
//         return knownSize == 0 ? prevSize : knownSize
57
//       })
58
//     }, [knownSize])
59
//     return (
60
//       <div
61
//         {...props}
62
//         className="height-preserving-container"
63
//         // check styling in the style tag below
64
//         style={{ '--child-height': `${size}px`, }}
65
//       >
66
//         {children}
67
//       </div>
68
//     )
69
//   }
70

  
30 71
const getFormattedLocationOrEmpty = (catalogItem: CatalogItemDto) => {
31 72
    if (!catalogItem || !catalogItem.latitude || !catalogItem.longitude) {
32 73
        return 'Location unavailable'
......
52 93
                //     } as MapPoint,
53 94
                //     id: item.id,
54 95
                // })
55
                updateMapMarker({
96
                updateMapPointAtIndex({
56 97
                    ...item,
57 98
                    addToPath: !item?.addToPath,
58 99
                    idx,
......
69 110
                //     } as MapPoint,
70 111
                //     id: item.id,
71 112
                // })
72
                updateMapMarker({
113
                updateMapPoint({
73 114
                    ...item,
74 115
                    hidden: !item?.hidden,
75 116
                    idx,
......
89 130
        return (
90 131
            item && (
91 132
                <Draggable
92
                    key={`${item.id}`}
93
                    draggableId={`${item.id}`}
133
                    key={`${item.reactId}`}
134
                    draggableId={`${item.reactId}`}
94 135
                    index={idx}
95 136
                >
96 137
                    {(provided, snapshot) => (
......
124 165
                                    <DeleteForeverIcon />
125 166
                                </IconButton>
126 167
                            )}
127
                            <IconButton sx={{ mr: 1 }} onClick={toggleHidden}>
128
                                {item.hidden ? (
129
                                    <VisibilityOffIcon />
130
                                ) : (
131
                                    <VisibilityIcon />
132
                                )}
133
                            </IconButton>
168
                            {isMapPointDisplayable(item) ? (
169
                                <IconButton
170
                                    sx={{ mr: 1 }}
171
                                    onClick={toggleHidden}
172
                                >
173
                                    {item.hidden ? (
174
                                        <VisibilityOffIcon />
175
                                    ) : (
176
                                        <VisibilityIcon />
177
                                    )}
178
                                </IconButton>
179
                            ) : null}
134 180
                            <IconButton
135 181
                                sx={{ mr: 1 }}
136 182
                                onClick={toggleAddToPath}
frontend/src/features/TrackingTool/Controls/ProcessedTextDisplay.tsx
12 12
    return (
13 13
        <Fragment>
14 14
            {pathDto && (
15
                <Card variant="outlined" sx={{ maxHeight: '50vh' }}>
15
                <Card variant="outlined" sx={{ maxHeight: '50vh', overflow: 'auto' }}>
16 16
                    <CardContent>
17 17
                        <Stack direction="column">
18 18
                            <Typography
frontend/src/features/TrackingTool/Map/Map.tsx
7 7
import { buildTheme } from '../../Theme/ThemeWrapper'
8 8
import RightClickPopupMenu from '../Import/ImportContextMenu'
9 9
import MapPath from './MapPath'
10
import L, { Map as LeafletMap } from 'leaflet'
11
import {  } from 'leaflet.fullscreen'
10
import { Map as LeafletMap } from 'leaflet'
12 11

  
13 12
const mapTheme = buildTheme('light')
14 13

  
frontend/src/features/TrackingTool/Map/MapPath.tsx
3 3
import { RootState } from '../../redux/store'
4 4
import { MapPoint, isMapPointDisplayable } from '../trackingToolUtils'
5 5
import TextPath from 'react-leaflet-textpath'
6
import { updateMapMarker } from '../trackingToolSlice'
6
import { updateMapPoint } from '../trackingToolSlice'
7 7
import MapMarker from './MapMarker'
8 8
import { LatLngTuple } from 'leaflet'
9 9
import { Popup, Tooltip } from 'react-leaflet'
......
14 14
type EdgeElement = any
15 15
const MapPath = () => {
16 16
    const dispatch = useDispatch()
17

  
18
    // Displayed path contains all map points
17 19
    const path = useSelector(
18 20
        (state: RootState) => state.trackingTool.displayedPath
19 21
    )
......
47 49
            setEdges([])
48 50
            return
49 51
        }
52
        console.log('rerender')
50 53

  
51
        // Build edges
54
        // Keep track of already built edges so we do not render excessive amount of them
55
        // We can use a simple hack where we concatenate id of both and check if it is already in the set
56
        const existingPaths = new Set<string>()
52 57
        const edges = []
53 58
        for (let i = 0; i < activeMapPoints.length - 1; i += 1) {
59
            const edgeId = `${activeMapPoints[i].id}${
60
                activeMapPoints[i + 1].id
61
            }`
62
            if (existingPaths.has(edgeId)) {
63
                continue
64
            }
65
            existingPaths.add(edgeId)
54 66
            const [start, end] = [
55 67
                activeMapPoints[i].catalogItem,
56 68
                activeMapPoints[i + 1].catalogItem,
57 69
            ]
58 70
            edges.push(
59 71
                <TextPath
60
                    key={`${activeMapPoints[i].id}-${
61
                        activeMapPoints[i + 1].id
62
                    }`}
72
                    key={edgeId}
63 73
                    positions={[
64 74
                        [start.latitude, start.longitude],
65 75
                        [end.latitude, end.longitude],
66 76
                    ]}
67 77
                    text="►"
68 78
                    attributes={{
69
                        'font-size': 19,
79
                        'font-size': 17,
70 80
                        fill: pathColor,
71 81
                    }}
72 82
                    repeat
......
82 92
    const [vertices, setVertices] = useState<JSX.Element[]>([])
83 93
    useEffect(() => {
84 94
        // Iterate over all displayable map points and map them to MapMarker
95
        const uniqueMapPoints = new Set<string>()
85 96
        setVertices(
86
            displayableMapPoints.map((item) => (
87
                <MapMarker
88
                    key={item.id}
89
                    position={[
90
                        item.catalogItem.latitude as number,
91
                        item.catalogItem.longitude as number,
92
                    ]}
93
                    mapPoint={item}
94
                    updatePositionCallbackFn={(position: LatLngTuple) => {
95
                        dispatch(
96
                            updateMapMarker({
97
                                ...item,
98
                                catalogItem: {
99
                                    ...item.catalogItem,
100
                                    latitude: position[0],
101
                                    longitude: position[1],
102
                                },
103
                            })
104
                        )
105
                    }}
106
                >
107
                    <Fragment>
108
                        <Tooltip>
109
                            {/* <Typography> */}
110
                            {item.catalogItem.name ?? ''}
111
                            {/* </Typography> */}
112
                        </Tooltip>
113
                        <Popup>
114
                            <Fragment>
115
                                <Stack direction="column" sx={{ m: 0 }}>
116
                                    <Typography
117
                                        variant="h6"
118
                                        fontWeight="bold"
119
                                        fontSize={16}
120
                                    >
121
                                        {formatHtmlStringToReactDom(
122
                                            item.catalogItem.name as string
123
                                        )}
124
                                    </Typography>
125
                                    <FormControlLabel
126
                                        control={
127
                                            <Checkbox
128
                                                checked={item.addToPath}
129
                                                onChange={() => {
130
                                                    dispatch(
131
                                                        updateMapMarker({
132
                                                            ...item,
133
                                                            addToPath:
134
                                                                !item.addToPath,
135
                                                        })
136
                                                    )
137
                                                }}
138
                                            />
139
                                        }
140
                                        labelPlacement="end"
141
                                        label="Active"
142
                                    />
143
                                    <CatalogItemDetailDialog
144
                                        itemId={item.catalogItem.id ?? ''}
145
                                    />
146
                                </Stack>
147
                            </Fragment>
148
                        </Popup>
149
                    </Fragment>
150
                </MapMarker>
151
            ))
97
            displayableMapPoints
98
                .filter((mapPoint) => {
99
                    if (uniqueMapPoints.has(mapPoint.id)) {
100
                        return false
101
                    }
102
                    uniqueMapPoints.add(mapPoint.id)
103
                    return true
104
                })
105
                .map((item) => (
106
                    <MapMarker
107
                        key={item.id}
108
                        position={[
109
                            item.catalogItem.latitude as number,
110
                            item.catalogItem.longitude as number,
111
                        ]}
112
                        mapPoint={item}
113
                        updatePositionCallbackFn={(position: LatLngTuple) => {
114
                            dispatch(
115
                                updateMapPoint({
116
                                    ...item,
117
                                    catalogItem: {
118
                                        ...item.catalogItem,
119
                                        latitude: position[0],
120
                                        longitude: position[1],
121
                                    },
122
                                })
123
                            )
124
                        }}
125
                    >
126
                        <Fragment>
127
                            <Tooltip>
128
                                {/* <Typography> */}
129
                                {item.catalogItem.name ?? ''}
130
                                {/* </Typography> */}
131
                            </Tooltip>
132
                            <Popup>
133
                                <Fragment>
134
                                    <Stack direction="column" sx={{ m: 0 }}>
135
                                        <Typography
136
                                            variant="h6"
137
                                            fontWeight="bold"
138
                                            fontSize={16}
139
                                        >
140
                                            {formatHtmlStringToReactDom(
141
                                                item.catalogItem.name as string
142
                                            )}
143
                                        </Typography>
144
                                        <FormControlLabel
145
                                            control={
146
                                                <Checkbox
147
                                                    checked={item.addToPath}
148
                                                    onChange={() => {
149
                                                        dispatch(
150
                                                            updateMapPoint({
151
                                                                ...item,
152
                                                                addToPath:
153
                                                                    !item.addToPath,
154
                                                            })
155
                                                        )
156
                                                    }}
157
                                                />
158
                                            }
159
                                            labelPlacement="end"
160
                                            label="Active"
161
                                        />
162
                                        <CatalogItemDetailDialog
163
                                            itemId={item.catalogItem.id ?? ''}
164
                                        />
165
                                    </Stack>
166
                                </Fragment>
167
                            </Popup>
168
                        </Fragment>
169
                    </MapMarker>
170
                ))
152 171
        )
153 172
    }, [dispatch, displayableMapPoints])
154 173

  
frontend/src/features/TrackingTool/Map/mapUtils.ts
35 35
        variant.map(
36 36
            (catalogItem, idx) => (
37 37
                {
38
                    id: generateUuid(),
38
                    id: '',
39 39
                    idx,
40
                    reactId: generateUuid(),
40 41
                    addToPath: !!catalogItem.latitude && !!catalogItem.longitude,
41 42
                    catalogItem,
42 43
                    type: mapPointType,
frontend/src/features/TrackingTool/TrackingTool.tsx
128 128
                </Grid>
129 129
                <Grid container sx={{ mt: 1, mb: 20 }} spacing={1}>
130 130
                    <Grid item xs={12} md={6}>
131
                        {/* <MapPointDraggableList /> */}
131
                        <MapPointDraggableList />
132 132
                    </Grid>
133 133
                    <Grid item xs={12} md={6}>
134 134
                        <ProcessedTextDisplay />
frontend/src/features/TrackingTool/Upload/FileUpload.tsx
1 1
import {
2
    Button,
3 2
    DialogContent,
4 3
    DialogTitle,
5
    Link,
6
    Stack,
7
    Typography,
8 4
} from '@mui/material'
9 5
import { useFormik } from 'formik'
10
import { Fragment, useState } from 'react'
6
import { useState } from 'react'
11 7
import * as yup from 'yup'
12
import axiosInstance from '../../../api/api'
13 8
import ButtonOpenableDialog from '../../Reusables/ButtonOpenableDialog'
14
import { useDispatch } from 'react-redux'
9
import { useDispatch, useSelector } from 'react-redux'
15 10
import { sendTextForProcessing } from '../trackingToolThunks'
16 11
import SingleFileSelectionForm from '../../Reusables/SingleFileSelectionForm'
17 12
import AttachFileIcon from '@mui/icons-material/AttachFile'
18
import TextSnippetIcon from '@mui/icons-material/TextSnippet'
13
import { RootState } from '../../redux/store'
19 14

  
20 15
interface UploadValues {
21 16
    file?: File
......
34 29
        file: yup.mixed().required('File is required'),
35 30
    })
36 31

  
32
    const loading = useSelector(
33
        (state: RootState) => state.trackingTool.isLoading
34
    )
35

  
37 36
    const formik = useFormik({
38 37
        initialValues,
39 38
        validationSchema,
......
88 87
                    onClearSelectedFile={onClearSelectedFile}
89 88
                    filename={filename}
90 89
                    formik={formik}
90
                    loading={loading}
91 91
                />
92 92
            </DialogContent>
93 93
        </ButtonOpenableDialog>
frontend/src/features/TrackingTool/trackingToolSlice.ts
1 1
import { createSlice } from '@reduxjs/toolkit'
2 2
import mapConfig from '../../config/mapConfig'
3 3
import { PathDto } from '../../swagger/data-contracts'
4
import generateUuid from '../../utils/id/uuidGenerator'
4 5
import buildPathVariants from './Map/mapUtils'
5 6
import TrackingToolState from './trackingToolState'
6 7
import { sendTextForProcessing } from './trackingToolThunks'
7
import { calculateMapCenter, MapPoint, PathVariant } from './trackingToolUtils'
8
import { calculateMapCenter, MapPoint, PathVariant, setMapPointIds } from './trackingToolUtils'
8 9

  
9 10
const initialState: TrackingToolState = {
10 11
    isLoading: false,
......
18 19
    initialState,
19 20
    reducers: {
20 21
        consumeErr: (state: TrackingToolState) => ({ ...state, lastErr: undefined, }),
21
        setSelectedPathIdx: (state: TrackingToolState, action: { payload: number }) => ({ ...state, selectedPathIdx: action.payload, }),
22
        resetDialogApiCallSuccess: (state: TrackingToolState) => ({ ...state, dialogApiCallSuccess: false, }),
22
        setSelectedPathIdx: (state: TrackingToolState, action: { payload: number }) =>
23
            ({ ...state, selectedPathIdx: action.payload, }),
24
        resetDialogApiCallSuccess: (state: TrackingToolState) =>
25
            ({ ...state, dialogApiCallSuccess: false, }),
23 26
        // Updates currently displayed path
24
        updateDisplayedPath: (state: TrackingToolState, action: { payload: PathVariant }) => ({ ...state, displayedPath: action.payload, }),
25
        // Updates map marker
26
        updateMapMarker: (state: TrackingToolState, action: { payload: MapPoint }) => {
27
        updateDisplayedPath: (state: TrackingToolState, action: { payload: PathVariant }) =>
28
            ({ ...state, displayedPath: action.payload, }),
29
        updateMapPointAtIndex: (state: TrackingToolState, action: { payload: MapPoint }) => {
27 30
            const newPath = [...state.displayedPath ?? []]
28 31
            if (newPath.length <= action.payload.idx) {
29 32
                return state // do nothing if there is no path
......
35 38
                displayedPath: newPath,
36 39
            }
37 40
        },
41
        // Updates map marker
42
        updateMapPoint: (state: TrackingToolState, action: { payload: MapPoint }) => {
43
            const newPath = [...state.displayedPath ?? []]
44
            return {
45
                ...state,
46
                displayedPath: newPath.map((point, _) => point.id === action.payload.id ? {...action.payload, idx: point.idx} : point)
47
            }
48
        },
38 49
        // Removes map marker from currently used path
39 50
        removeMapMarker: (state: TrackingToolState, action: { payload: { id: string, idx: number } }) => {
40 51
            const newPath = [...state.displayedPath ?? []]
......
47 58
                displayedPath: [...newPath.slice(0, action.payload.idx), ...newPath.slice(action.payload.idx + 1)],
48 59
            }
49 60
        },
50
        // Moves map marker in the path array
51
        moveMarkerToDestination: (state: TrackingToolState, action: { payload: { destination: number, source: number } }) => {
61
        // Changes marker index
62
        changeMarkerIdx: (state: TrackingToolState, action: { payload: { destination: number, source: number } }) => {
52 63
            const { destination, source } = action.payload
53 64
            const newPath = [...state.displayedPath ?? []]
54 65
            if (newPath.length <= source
......
74 85

  
75 86
            const newPath = [...state.displayedPath ?? []]
76 87
            const existingIds = new Set(newPath.map(item => item.id ?? ''))
77

  
78 88
            const newItems: MapPoint[] = []
79 89
            jsonPath.forEach(item => {
80 90
                if (!existingIds.has(item.id ?? '')) {
......
85 95
            newItems.forEach(item => {
86 96
                item.addToPath = !state.pathVariants || state.pathVariants.length === 0
87 97
                item.idx = newPath.length
98
                const uuid = generateUuid()
99
                item.reactId = uuid
100
                item.id = item.catalogItem.id ? item.catalogItem.id : uuid
88 101
                newPath.push(item)
89 102
            })
90 103

  
......
106 119

  
107 120
            // We will always have displayedPath defined if this function is called
108 121
            pathVariants.splice(previousIdx, 0, [...state.displayedPath ?? []])
109
            const newPath = pathVariants.splice(newIdx, 1)[0]
122
            const newPath = setMapPointIds(pathVariants.splice(newIdx, 1)[0])
110 123
            return {
111 124
                ...state,
112 125
                displayedPath: newPath,
......
114 127
                pathVariants,
115 128
            }
116 129
        },
117
        moveToNextPathVariant: (state: TrackingToolState) => {
118
            const currentPathIdx = state.displayedPathIdx
119
            const pathVariants = [...state.pathVariants ?? []]
120

  
121
            // Since we take out the selected path index the displayedPathIdx will serve as
122
            // index of the next element
123
            if (currentPathIdx >= pathVariants.length) {
124
                return state // do nothing if the displayed path is also the last one
125
            }
126

  
127
            // Else get the next path variant
128
            const newPath = [...pathVariants[currentPathIdx]]
129
            const previousPath = [...state.displayedPath ?? []]
130

  
131
            // And replace the displayed path with the new one
132
            return {
133
                ...state,
134
                displayedPath: newPath,
135
                displayedPathIdx: currentPathIdx + 1,
136
                pathVariants: [
137
                    ...pathVariants.slice(0, currentPathIdx),
138
                    previousPath,
139
                    ...pathVariants.slice(currentPathIdx + 1),
140
                ]
141
            }
142
        },
143
        moveToPreviousPathVariant: (state: TrackingToolState) => {
144
            const currentPathIdx = state.displayedPathIdx
145
            const pathVariants = [...state.pathVariants ?? []]
146

  
147
            const previousPathIdx = currentPathIdx - 1
148
            if (previousPathIdx < 0) {
149
                return state // do nothing if the displayed path is the first one
150
            }
151

  
152
            // Else get the previous path variant
153
            const newPath = [...pathVariants[previousPathIdx]]
154
            const previousPath = [...state.displayedPath ?? []]
155

  
156
            return {
157
                ...state,
158
                displayedPath: newPath,
159
                displayedPathIdx: previousPathIdx,
160
                pathVariants: [
161
                    ...pathVariants.slice(0, previousPathIdx),
162
                    previousPath,
163
                    ...pathVariants.slice(previousPathIdx + 1),
164
                ]
165
            }
166
        }
167 130
    },
168 131
    extraReducers: (builder) => {
169 132
        builder.addCase(sendTextForProcessing.fulfilled, (state, action) => {
170 133
            const pathDto: PathDto = action.payload
171 134
            const pathVariants = buildPathVariants(pathDto)
172
            const selectedPath = pathVariants.length > 0 ? pathVariants[0] : undefined
135
            const selectedPath = pathVariants.length > 0 ? setMapPointIds(pathVariants[0]) : undefined
173 136
            pathVariants.splice(0, 1) // remove the selected path so that we do not have to update it here
174 137
            if (!selectedPath) {
175 138
                return {
......
220 183
    setSelectedPathIdx,
221 184
    resetDialogApiCallSuccess,
222 185
    updateDisplayedPath,
223
    updateMapMarker,
186
    updateMapPoint,
224 187
    removeMapMarker,
225
    moveMarkerToDestination,
188
    changeMarkerIdx,
226 189
    clear,
227 190
    mergeWithCurrentPath,
228 191
    setDisplayedPathIdx,
192
    updateMapPointAtIndex
229 193
} = trackingToolSlice.actions
230 194

  
231 195
const trackingToolReducer = trackingToolSlice.reducer
frontend/src/features/TrackingTool/trackingToolUtils.ts
1 1

  
2 2
import L, { LatLngTuple, PointExpression } from 'leaflet'
3 3
import { CatalogItemDto } from '../../swagger/data-contracts'
4
import generateUuid from '../../utils/id/uuidGenerator'
4 5

  
5 6
// For more comprehensive code alias CatalogItemDto[] as path variant
6 7
export type PathVariant = MapPoint[]
......
14 15

  
15 16
// Represents a point on the map - wrapper for CatalogItemDto to make it easier to work with
16 17
export interface MapPoint {
17
    id: string // unique id for react
18
    id: string // unique id to identify the point on the map
19
    reactId: string // unique id to identify item in React - e.g. rendering in a list
18 20
    idx: number,
19 21
    addToPath: boolean, // whether to add the point to the path
20 22
    catalogItem: CatalogItemDto,
......
65 67
    [MapPointType.FromCoordinates]: createMapMarkerSvg('#21972D'),
66 68
}
67 69

  
68
const iconAnchor = [25, 25] as PointExpression
69
const iconSize = [40, 40] as PointExpression
70
const iconAnchor = [22, 22] as PointExpression
71
const iconSize = [35, 35] as PointExpression
70 72

  
71 73
const mapMarkers = {
72 74
    [MapPointType.LocalCatalog]: L.icon({
......
104 106
            .map((item) => item.catalogItem.longitude ?? 0)
105 107
            .reduce((a, b) => a + b, 0) / displayableItems.length,
106 108
    ]
107
}
109
}
110

  
111
export const setMapPointIds = (pathVariant: PathVariant): PathVariant => pathVariant.map(mapPoint => {
112
    // Get identifier - either catalog item identifier is used or generate a new UUID if the point does not have uuid
113
    // - e.g. is not from the catalog
114
    mapPoint.id = mapPoint.catalogItem.id ? mapPoint.catalogItem.id : generateUuid()
115
    return mapPoint
116
})

Také k dispozici: Unified diff