Projekt

Obecné

Profil

Stáhnout (6.02 KB) Statistiky
| Větev: | Tag: | Revize:
1
import { Fragment, FunctionComponent, useEffect, useState } from 'react'
2
import { CatalogItemDto } from '../../swagger/data-contracts'
3
import { PathVariant } from './buildPathVariants'
4
import TextPath from 'react-leaflet-textpath'
5
import { Marker, Popup } from 'react-leaflet'
6
import {
7
    Checkbox,
8
    FormControlLabel,
9
    Paper,
10
    Stack,
11
    Typography,
12
} from '@mui/material'
13
import { formatHtmlStringToReactDom } from '../../utils/formatting/HtmlUtils'
14
import { DialogCatalogItemDetail as CatalogItemDetailDialog } from '../Catalog/CatalogItemDetail'
15
import { useDispatch, useSelector } from 'react-redux'
16
import { RootState } from '../redux/store'
17

    
18
// CatalogItemDto wrapper to keep track whether the item is active or not
19
class DisplayableMapPoint {
20
    constructor(
21
        public readonly catalogItem: CatalogItemDto,
22
        public active: boolean = true
23
    ) {}
24
}
25

    
26
export interface MapPathProps {
27
    pathVariant: PathVariant // aka CatalogItemDto[]
28
    idx: number // index of path in the list
29
}
30

    
31
// Blue
32
export const primaryPathColor = '#346eeb'
33

    
34
// Grey
35
export const secondaryPathColor = '#878e9c'
36

    
37
// Map path component
38
const MapPath: FunctionComponent<MapPathProps> = ({ idx, pathVariant }) => {
39
    // List of all map points that belong to the path
40
    const pathVariants = useSelector(
41
        (state: RootState) => state.trackingTool.pathVariants
42
    )
43
    const [mapPoints, setMapPoints] = useState<DisplayableMapPoint[]>([])
44
    const dispatch = useDispatch()
45

    
46
    // Set of all active paths
47
    const activePaths = useSelector(
48
        (state: RootState) => state.trackingTool.activePaths
49
    )
50
    // Index of the primary path
51
    const primaryPathIdx = useSelector(
52
        (state: RootState) => state.trackingTool.primaryPathIdx
53
    )
54

    
55
    // Whether the path is active or not
56
    const [active, setActive] = useState(false)
57
    useEffect(() => {
58
        setActive(activePaths.has(idx))
59
    }, [activePaths, idx])
60

    
61
    const getActiveMapPoints = () => mapPoints.filter((item) => item.active)
62

    
63
    // Refresh the list of map points if it has changed
64
    useEffect(() => {
65
        if (!pathVariants || pathVariants.length <= idx) {
66
            return
67
        }
68
        setMapPoints(
69
            [...pathVariants[idx]]
70
                .filter((item) => item.latitude && item.longitude)
71
                .map((item) => new DisplayableMapPoint(item))
72
        )
73
    }, [pathVariants, idx])
74

    
75
    // Builds all edges of the path
76
    const buildEdges = () => {
77
        const activeMapPoints = getActiveMapPoints()
78
        if (activeMapPoints.length < 2) {
79
            return null
80
        }
81

    
82
        // Create path edges
83
        const edges: any[] = []
84
        for (let i = 0; i < activeMapPoints.length - 1; i += 1) {
85
            edges.push(
86
                <TextPath
87
                    positions={[
88
                        [
89
                            activeMapPoints[i].catalogItem.latitude,
90
                            activeMapPoints[i].catalogItem.longitude,
91
                        ],
92
                        [
93
                            activeMapPoints[i + 1].catalogItem.latitude,
94
                            activeMapPoints[i + 1].catalogItem.longitude,
95
                        ],
96
                    ]}
97
                    text="►"
98
                    attributes={{
99
                        'font-size': 25,
100
                        // Set to primaryPathColor if primary index in the tracking tool is equal to this index
101
                        fill:
102
                            primaryPathIdx === idx
103
                                ? primaryPathColor
104
                                : secondaryPathColor,
105
                    }}
106
                    onClick={() => {
107
                        dispatch(setPrimaryIdx(idx))
108
                    }}
109
                    repeat
110
                    center
111
                    weight={9}
112
                />
113
            )
114
        }
115

    
116
        // Return the path
117
        return edges
118
    }
119

    
120
    /**
121
     * Creates a list of all vertices in the path
122
     */
123
    const buildVertices = () => {
124
        return mapPoints.map((mapPoint, idx) => (
125
            <Marker
126
                key={idx}
127
                position={[
128
                    mapPoint.catalogItem.latitude as number,
129
                    mapPoint.catalogItem.longitude as number,
130
                ]}
131
            >
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
                                    mapPoint.catalogItem.name as string
142
                                )}
143
                            </Typography>
144
                            <FormControlLabel
145
                                control={
146
                                    <Checkbox
147
                                        checked={mapPoint.active}
148
                                        onChange={() => {
149
                                            mapPoint.active = !mapPoint.active
150
                                            setMapPoints([...mapPoints])
151
                                        }}
152
                                    />
153
                                }
154
                                labelPlacement="end"
155
                                label="Active"
156
                            />
157
                            <CatalogItemDetailDialog
158
                                itemId={mapPoint.catalogItem.id ?? ''}
159
                            />
160
                        </Stack>
161
                    </Fragment>
162
                </Popup>
163
            </Marker>
164
        ))
165
    }
166

    
167
    return (
168
        <Fragment>
169
            {active && (
170
                <Fragment>
171
                    {buildVertices()}
172
                    {buildEdges()}
173
                </Fragment>
174
            )}
175
        </Fragment>
176
    )
177
}
178

    
179
export default MapPath
180
function setPrimaryIdx(idx: number): any {
181
    throw new Error('Function not implemented.')
182
}
(2-2/8)