Projekt

Obecné

Profil

Stáhnout (9.97 KB) Statistiky
| Větev: | Tag: | Revize:
1 de12c6be Vaclav Honzik
import { createSlice } from "@reduxjs/toolkit"
2
import { LatLngTuple } from "leaflet"
3
import mapConfig from "../../config/mapConfig"
4
import { PathDto } from "../../swagger/data-contracts"
5 c0b66eaf Vaclav Honzik
import buildPathVariants from "./Map/pathUtils"
6 26f9c9ff Vaclav Honzik
import { isMapPointDisplayable, MapPoint, PathVariant } from "./trackingToolUtils"
7 de12c6be Vaclav Honzik
import { sendTextForProcessing } from "./trackingToolThunks"
8
import storage from "redux-persist/lib/storage"
9 c0b66eaf Vaclav Honzik
import TrackingToolState from './trackingToolState'
10 8c57f958 Vaclav Honzik
11
12 81698b9a Vaclav Honzik
const defaultPathsPerPage = 5
13
14 8c57f958 Vaclav Honzik
const initialState: TrackingToolState = {
15
    isLoading: false,
16 de12c6be Vaclav Honzik
    mapCenter: [mapConfig.defaultCoordinates[0], mapConfig.defaultCoordinates[1]],
17 8c57f958 Vaclav Honzik
    primaryPathIdx: 0,
18
    dialogApiCallSuccess: true,
19 81698b9a Vaclav Honzik
    pathsPerPage: defaultPathsPerPage,
20
    currentPage: 0,
21 8c57f958 Vaclav Honzik
}
22
23 11fca75a Vaclav Honzik
const calculateMapCenter = (pathVariant: PathVariant): LatLngTuple | undefined => {
24 a7ae217f Vaclav Honzik
    const displayableItems = pathVariant.filter((item) => isMapPointDisplayable(item))
25 11fca75a Vaclav Honzik
    if (displayableItems.length === 0) {
26
        return undefined
27
    }
28
29
    return [
30
        displayableItems
31
            .map((item) => item.catalogItem.latitude ?? 0)
32
            .reduce((a, b) => a + b, 0) / displayableItems.length,
33
        displayableItems
34
            .map((item) => item.catalogItem.longitude ?? 0)
35
            .reduce((a, b) => a + b, 0) / displayableItems.length,
36
    ]
37
}
38 8c57f958 Vaclav Honzik
39 04fdedc6 Vaclav Honzik
const persistConfig = {
40 de12c6be Vaclav Honzik
    key: "auth",
41 04fdedc6 Vaclav Honzik
    storage, // localStorage for browsers
42
}
43
44 8c57f958 Vaclav Honzik
export const trackingToolSlice = createSlice({
45 de12c6be Vaclav Honzik
    name: "trackingTool",
46 8c57f958 Vaclav Honzik
    initialState,
47
    reducers: {
48 de12c6be Vaclav Honzik
        consumeErr: (state: TrackingToolState) => ({
49
            ...state,
50
            lastErr: undefined,
51
        }),
52 c0cf1dbc Vaclav Honzik
        setPrimaryIdx: (state: TrackingToolState, action: any) => ({
53 8c57f958 Vaclav Honzik
            ...state,
54
            primaryPathIdx: action.payload,
55
        }),
56 c0cf1dbc Vaclav Honzik
        resetDialogApiCallSuccess: (state: TrackingToolState) => ({
57 8c57f958 Vaclav Honzik
            ...state,
58
            dialogApiCallSuccess: false,
59
        }),
60 de12c6be Vaclav Honzik
        setPage: (state: TrackingToolState, action: { payload: number }) => ({
61 81698b9a Vaclav Honzik
            ...state,
62
            currentPage: action.payload,
63
        }),
64 26f9c9ff Vaclav Honzik
        updatePrimaryPath: (state: TrackingToolState, action: { payload: PathVariant }) => {
65
            const { primaryPathIdx } = state
66
            const path = action.payload
67
            const paths = [...state.pathVariants ?? []]
68
69
            if (paths.length <= primaryPathIdx) {
70
                return { ...state }
71
            }
72
73
            return {
74
                ...state,
75
                pathVariants: [
76
                    ...paths.slice(0, primaryPathIdx),
77
                    path,
78
                    ...paths.slice(primaryPathIdx + 1),
79
                ],
80
            }
81
        },
82 812b9f90 Vaclav Honzik
        // Updates map marker while ignoring its idx property
83
        updateMapMarkerWithId: (state: TrackingToolState, action: { payload: { id: string, item: MapPoint } }) => {
84
            const { item } = action.payload
85 26f9c9ff Vaclav Honzik
            const { primaryPathIdx } = state
86
            if (!state.pathVariants || state.pathVariants.length <= primaryPathIdx) {
87 812b9f90 Vaclav Honzik
                return state
88
            }
89
90 26f9c9ff Vaclav Honzik
            const mapMarkerIdx = state.pathVariants[primaryPathIdx].findIndex((item) => item.id === action.payload.id)
91 812b9f90 Vaclav Honzik
            if (mapMarkerIdx === -1) {
92
                return state
93
            }
94
95 26f9c9ff Vaclav Honzik
            const newPathVariant = [...state.pathVariants[primaryPathIdx]]
96 812b9f90 Vaclav Honzik
            newPathVariant[mapMarkerIdx] = item
97
            return {
98
                ...state,
99 26f9c9ff Vaclav Honzik
                pathVariants: [...state.pathVariants.slice(0, primaryPathIdx), newPathVariant, ...state.pathVariants.slice(primaryPathIdx + 1)],
100 812b9f90 Vaclav Honzik
            }
101
        },
102
        // Updates map marker based on its idx property
103 7d477849 Vaclav Honzik
        updateMapMarker: (state: TrackingToolState, action: { payload: MapPoint }) => {
104
            const item = action.payload
105 26f9c9ff Vaclav Honzik
            const { primaryPathIdx } = state
106
            if (!state.pathVariants || state.pathVariants.length <= primaryPathIdx) {
107 de12c6be Vaclav Honzik
                return state
108
            }
109
110
            return {
111
                ...state,
112
                pathVariants: state.pathVariants.map((pathVariant, i) => {
113 26f9c9ff Vaclav Honzik
                    if (i !== primaryPathIdx) {
114 de12c6be Vaclav Honzik
                        return [...pathVariant]
115
                    }
116
117
                    return [
118 7b864a5c Vaclav Honzik
                        ...pathVariant.slice(0, item.idx),
119
                        item,
120
                        ...pathVariant.slice(item.idx + 1),
121 de12c6be Vaclav Honzik
                    ]
122
                })
123
            }
124
        },
125 c0b66eaf Vaclav Honzik
        // Removes map marker based on its idx property
126
        removeMapMarker: (state: TrackingToolState, action: { payload: { id: string, idx: number } }) => {
127
            const item = action.payload
128
            const idx = state.primaryPathIdx
129
            if (!state.pathVariants || state.pathVariants.length <= idx) {
130
                return state
131
            }
132
133
            return {
134
                ...state,
135
                pathVariants: state.pathVariants.map((pathVariant, i) => {
136
                    if (i !== idx) {
137
                        return [...pathVariant]
138
                    }
139
140
                    return [
141
                        ...pathVariant.slice(0, item.idx),
142
                        ...pathVariant.slice(item.idx + 1),
143
                    ]
144
                })
145
            }
146
        },
147 7d477849 Vaclav Honzik
        moveMarkerToDestination: (state: TrackingToolState, action: { payload: { destination: number, source: number } }) => {
148 812b9f90 Vaclav Honzik
            const { destination, source } = action.payload
149
            if (!state.pathVariants || state.pathVariants.length === 0) {
150
                return state
151
            }
152
153
            return {
154
                ...state,
155
                pathVariants: state.pathVariants.map((pathVariant, i) => {
156
                    if (state.primaryPathIdx !== i) {
157
                        return [...pathVariant]
158
                    }
159
160
                    if (pathVariant.length <= destination || pathVariant.length <= source) {
161
                        return [...pathVariant]
162
                    }
163
164
                    // JS dark magic splice
165
                    const result = [...pathVariant]
166
                    const [removed] = result.splice(source, 1)
167
                    result.splice(destination, 0, removed)
168 7d477849 Vaclav Honzik
                    return result.map((item, idx) => ({ ...item, idx }))
169 812b9f90 Vaclav Honzik
                })
170
            }
171
        },
172 de12c6be Vaclav Honzik
        clear: () => ({ ...initialState }),
173 a7ae217f Vaclav Honzik
        mergeWithCurrentPath: (state: TrackingToolState, action: { payload: PathVariant }) => {
174
            const { payload: jsonPath } = action
175
            if (!jsonPath) {
176
                return { ...state }
177
            }
178
179
            const pathVariants = [...state.pathVariants ?? []]
180
            let primaryPathIdx = state.primaryPathIdx
181
            let currentPage = state.currentPage
182
183
            // If there are no path append a new array to the pathVariants array and set primaryIdx to 0
184
            if (pathVariants.length === 0) {
185
                primaryPathIdx = 0
186
                currentPage = 0
187
                pathVariants.push([])
188
            }
189
190
            // Get the path and create a map to check whether some point with the same id already exists
191
            const path = pathVariants[primaryPathIdx]
192
            const pathMap = new Map(path.map((item) => [item.catalogItem.id as string, item]))
193
194
            // Create an array of items to be replaced and items to be added to the end
195 812b9f90 Vaclav Honzik
            // const itemsToReplace: MapPoint[] = []
196 a7ae217f Vaclav Honzik
            const itemsToAdd: MapPoint[] = []
197
            jsonPath.forEach((item) => {
198 c0b66eaf Vaclav Honzik
                if (!pathMap.has(item.catalogItem.id ?? '')) {
199 a7ae217f Vaclav Honzik
                    itemsToAdd.push(item)
200
                    return
201
                }
202 812b9f90 Vaclav Honzik
203
                // const idx = pathMap.get(item.catalogItem.id as string)!.idx
204
                // item.idx = idx
205
                // itemsToReplace.push(item)
206 a7ae217f Vaclav Honzik
            })
207
208
            // Iterate over items to replace and replace them
209
            const newPath = [...path]
210 812b9f90 Vaclav Honzik
            // itemsToReplace.forEach((item) => {
211
            //     newPath[item.idx] = item
212
            // })
213 a7ae217f Vaclav Honzik
214
            // Add items to the end
215
            itemsToAdd.forEach((item) => {
216 f41a4cd3 Vaclav Honzik
                item.addToPath = !state.pathVariants || state.pathVariants.length === 0
217 a7ae217f Vaclav Honzik
                item.idx = newPath.length
218
                newPath.push(item)
219
            })
220
221
            // Return the new path
222
            return {
223
                ...state,
224
                pathVariants: [
225
                    ...pathVariants.slice(0, primaryPathIdx),
226
                    newPath,
227
                    ...pathVariants.slice(primaryPathIdx + 1),
228
                ],
229
                primaryPathIdx, // in case the list is empty
230
                currentPage, // in case the list is empty
231
            }
232
        }
233 8c57f958 Vaclav Honzik
    },
234
    extraReducers: (builder) => {
235
        builder.addCase(sendTextForProcessing.fulfilled, (state, action) => {
236 04fdedc6 Vaclav Honzik
            const pathDto: PathDto = action.payload
237
            const pathVariants = buildPathVariants(pathDto)
238 11fca75a Vaclav Honzik
239
            const mapCenter = calculateMapCenter(pathVariants[state.primaryPathIdx])
240 8c57f958 Vaclav Honzik
            return {
241
                ...state,
242
                pathVariants,
243 04fdedc6 Vaclav Honzik
                pathDto,
244 11fca75a Vaclav Honzik
                mapCenter: mapCenter ?? state.mapCenter,
245 8c57f958 Vaclav Honzik
                isLoading: false,
246
                dialogApiCallSuccess: true,
247 81698b9a Vaclav Honzik
                currentPage: 0,
248 8c57f958 Vaclav Honzik
            }
249
        })
250 b45d0300 Vaclav Honzik
        builder.addCase(sendTextForProcessing.rejected, (_, action) => ({
251 8c57f958 Vaclav Honzik
            ...initialState,
252 dd270a41 Vaclav Honzik
            lastError: action.error.message,
253 8c57f958 Vaclav Honzik
            isLoading: false,
254
            dialogApiCallSuccess: false,
255 81698b9a Vaclav Honzik
            currentPage: 0,
256 8c57f958 Vaclav Honzik
        }))
257
        builder.addCase(sendTextForProcessing.pending, (state) => {
258
            return {
259
                ...state,
260
                isLoading: true,
261
                dialogApiCallSuccess: false,
262
            }
263
        })
264
    },
265
})
266
267 812b9f90 Vaclav Honzik
export const {
268
    consumeErr,
269
    setPrimaryIdx,
270
    resetDialogApiCallSuccess,
271
    clear,
272
    updateMapMarker,
273
    mergeWithCurrentPath,
274 7d477849 Vaclav Honzik
    moveMarkerToDestination,
275 c0b66eaf Vaclav Honzik
    updateMapMarkerWithId,
276
    removeMapMarker,
277 26f9c9ff Vaclav Honzik
    updatePrimaryPath
278 812b9f90 Vaclav Honzik
} = trackingToolSlice.actions
279 8c57f958 Vaclav Honzik
const trackingToolReducer = trackingToolSlice.reducer
280
export default trackingToolReducer