commit c0b66eaf6f728487ba834c933e96948485c51d93
Author: Vaclav Honzik <vaclavhonzik98@gmail.com>
Date:   Thu May 19 19:10:19 2022 +0200

    map icon colors start
    
    re #9741

diff --git a/frontend/src/features/Reusables/ButtonOpenableDialog.tsx b/frontend/src/features/Reusables/ButtonOpenableDialog.tsx
index 10294d9..0970631 100644
--- a/frontend/src/features/Reusables/ButtonOpenableDialog.tsx
+++ b/frontend/src/features/Reusables/ButtonOpenableDialog.tsx
@@ -10,12 +10,13 @@ export interface ButtonOpenableDialogProps {
     buttonVariant: 'text' | 'outlined' | 'contained' // the variant of the button that opens the dialog
     children: ReactNode // the content of the dialog
     maxWidth?: 'xs' | 'sm' | 'md' | 'lg' // the max width of the dialog
-    open: boolean,
+    open: boolean
     setOpen: (open: boolean) => void
     size?: 'small' | 'medium' | 'large'
+    startIcon?: ReactNode // the icon to the left of the button
+    endIcon?: ReactNode // the icon to the right of the button
 }
 
-
 // Generic dialog that can be opened by a button and closed by clicking on the backdrop.
 const ButtonOpenableDialog: FunctionComponent<ButtonOpenableDialogProps> = ({
     onOpenCallback,
@@ -27,9 +28,10 @@ const ButtonOpenableDialog: FunctionComponent<ButtonOpenableDialogProps> = ({
     maxWidth,
     open,
     setOpen,
-    size
+    size,
+    startIcon,
+    endIcon,
 }) => {
-
     // Change maxWidth to large if its undefined
     maxWidth = maxWidth ?? 'lg'
 
@@ -55,15 +57,12 @@ const ButtonOpenableDialog: FunctionComponent<ButtonOpenableDialogProps> = ({
                 color={buttonColor}
                 variant={buttonVariant}
                 size={size ?? 'medium'}
+                startIcon={startIcon}
+                endIcon={endIcon}
             >
                 {buttonText}
             </Button>
-            <Dialog
-                fullWidth
-                open={open}
-                onClose={onClose}
-                maxWidth={maxWidth}
-            >
+            <Dialog fullWidth open={open} onClose={onClose} maxWidth={maxWidth}>
                 {children}
             </Dialog>
         </Fragment>
diff --git a/frontend/src/features/TrackingTool/DraggableList/DraggableList.tsx b/frontend/src/features/TrackingTool/DraggableList/DraggableList.tsx
deleted file mode 100644
index 9a4e08d..0000000
--- a/frontend/src/features/TrackingTool/DraggableList/DraggableList.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { memo } from 'react'
-import {
-    DragDropContext,
-    Droppable,
-    OnDragEndResponder,
-} from 'react-beautiful-dnd'
-import { MapPoint } from '../Map/pathUtils'
-import DraggableListItem from './DraggableListItem'
-
-export interface DraggableListProps {
-    items: MapPoint[]
-    onDragEnd: OnDragEndResponder
-}
-
-window.addEventListener('error', (e) => {
-    if (
-        e.message ===
-            'ResizeObserver loop completed with undelivered notifications.' ||
-        e.message === 'ResizeObserver loop limit exceeded'
-    ) {
-        e.stopImmediatePropagation()
-    }
-})
-
-const DraggableList = memo(({ items, onDragEnd }: DraggableListProps) => {
-    return (
-        <DragDropContext onDragEnd={onDragEnd}>
-            <Droppable droppableId="droppable-list">
-                {(provided) => (
-                    <div ref={provided.innerRef} {...provided.droppableProps}>
-                        {items.map((item, index) => (
-                            <DraggableListItem
-                                list={items}
-                                idx={index}
-                                key={item.id}
-                            />
-                        ))}
-                        {provided.placeholder}
-                    </div>
-                )}
-            </Droppable>
-        </DragDropContext>
-    )
-})
-
-export default DraggableList
diff --git a/frontend/src/features/TrackingTool/DraggableList/DraggableListItem.tsx b/frontend/src/features/TrackingTool/DraggableList/DraggableListItem.tsx
deleted file mode 100644
index f779f4b..0000000
--- a/frontend/src/features/TrackingTool/DraggableList/DraggableListItem.tsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import {
-    Checkbox,
-    FormControlLabel,
-    IconButton,
-    ListItem,
-    ListItemAvatar,
-    ListItemText,
-} from '@mui/material'
-import { Draggable } from 'react-beautiful-dnd'
-import { MapPoint, PathVariant } from '../Map/pathUtils'
-import { CatalogItemDto } from '../../../swagger/data-contracts'
-import { useDispatch } from 'react-redux'
-import { updateMapMarkerWithId } from '../trackingToolSlice'
-import { useMemo } from 'react'
-import DragHandleIcon from '@mui/icons-material/DragHandle'
-import VisibilityIcon from '@mui/icons-material/Visibility'
-import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'
-import AddRoadIcon from '@mui/icons-material/AddRoad'
-import RemoveRoadIcon from '@mui/icons-material/RemoveRoad'
-
-export type DraggableListItemProps = {
-    list: PathVariant
-    idx: number
-}
-
-const getFormattedLocationOrEmpty = (catalogItem: CatalogItemDto) => {
-    if (!catalogItem || !catalogItem.latitude || !catalogItem.longitude) {
-        return 'Location unavailable'
-    }
-
-    return `${catalogItem.latitude.toFixed(
-        3
-    )}°, ${catalogItem.longitude.toFixed(3)}°`
-}
-
-const DraggableListItem = ({ list, idx }: DraggableListItemProps) => {
-    const item = list[idx]
-    const dispatch = useDispatch()
-
-    // useMemo to prevent unnecessary re-renders which will make the list jumpy
-    return useMemo(() => {
-        const toggleAddToPath = () => {
-            dispatch(
-                updateMapMarkerWithId({
-                    item: {
-                        ...item,
-                        addToPath: !item?.addToPath,
-                    } as MapPoint,
-                    id: item.id,
-                })
-            )
-        }
-
-        const toggleHidden = () => {
-            dispatch(
-                updateMapMarkerWithId({
-                    item: {
-                        ...item,
-                        hidden: !item?.hidden,
-                    } as MapPoint,
-                    id: item.id,
-                })
-            )
-        }
-
-        return (
-            <Draggable
-                key={`${item.id}`}
-                draggableId={`${item.id}`}
-                index={idx}
-            >
-                {(provided, snapshot) => (
-                    <ListItem
-                        ref={provided.innerRef}
-                        {...provided.draggableProps}
-                        {...provided.dragHandleProps}
-                    >
-                        <ListItemAvatar>
-                            <DragHandleIcon />
-                        </ListItemAvatar>
-                        <ListItemText
-                            primary={item.catalogItem.name ?? 'Unknown name'}
-                            secondary={getFormattedLocationOrEmpty(
-                                item.catalogItem
-                            )}
-                        />
-                        <IconButton sx={{ mr: 1 }} onClick={toggleHidden}>
-                            {item.hidden ? (
-                                <VisibilityOffIcon />
-                            ) : (
-                                <VisibilityIcon />
-                            )}
-                        </IconButton>
-                        <IconButton sx={{ mr: 1 }} onClick={toggleAddToPath}>
-                            {item.addToPath ? (
-                                <AddRoadIcon />
-                            ) : (
-                                <RemoveRoadIcon />
-                            )}
-                        </IconButton>
-                        {/* <FormControlLabel
-                            control={
-                                <Checkbox
-                                    checked={item.addToPath}
-                                    onChange={toggleAddToPath}
-                                />
-                            }
-                            label="Add to path"
-                        /> */}
-                    </ListItem>
-                )}
-            </Draggable>
-        )
-    }, [item, idx, dispatch])
-}
-
-export default DraggableListItem
diff --git a/frontend/src/features/TrackingTool/DraggableList/DraggableMarkerList.tsx b/frontend/src/features/TrackingTool/DraggableList/DraggableMarkerList.tsx
deleted file mode 100644
index 6bd7685..0000000
--- a/frontend/src/features/TrackingTool/DraggableList/DraggableMarkerList.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { Paper } from '@mui/material'
-import { useEffect, useState, useCallback } from 'react'
-import { DropResult } from 'react-beautiful-dnd'
-import { useDispatch, useSelector } from 'react-redux'
-import { RootState } from '../../redux/store'
-import { moveMarkerToDestination } from '../trackingToolSlice'
-import { PathVariant } from '../Map/pathUtils'
-import DraggableList from './DraggableList'
-
-const DraggableMarkerList = () => {
-    const dispatch = useDispatch()
-
-    // List of all paths
-    const paths = useSelector(
-        (state: RootState) => state.trackingTool.pathVariants
-    )
-
-    // Primary path index - i.e. the selected path
-    const primaryPathIdx = useSelector(
-        (state: RootState) => state.trackingTool.primaryPathIdx
-    )
-
-    // Selected path as local state
-    const [path, setPath] = useState<PathVariant | undefined>()
-
-    // Set localstate path whenever it changes in the store
-    useEffect(() => {
-        if (!paths || paths.length < primaryPathIdx) {
-            setPath(undefined)
-            return
-        }
-
-        setPath(paths[primaryPathIdx])
-    }, [paths, primaryPathIdx])
-
-    const onDragEnd = useCallback(({ destination, source }: DropResult) => {
-        if (!destination || !source || destination.index === source.index) {
-            return
-        }
-
-        dispatch(
-            moveMarkerToDestination({
-                source: source.index,
-                destination: destination.index,
-            })
-        )
-    }, [dispatch])
-
-    return (
-        <Paper variant="outlined">
-            <DraggableList items={path ?? []} onDragEnd={onDragEnd} />
-        </Paper>
-    )
-}
-
-export default DraggableMarkerList
diff --git a/frontend/src/features/TrackingTool/Import/AddFromCoordinatesDialog.tsx b/frontend/src/features/TrackingTool/Import/AddFromCoordinatesDialog.tsx
index 82a5393..b9d29d0 100644
--- a/frontend/src/features/TrackingTool/Import/AddFromCoordinatesDialog.tsx
+++ b/frontend/src/features/TrackingTool/Import/AddFromCoordinatesDialog.tsx
@@ -14,7 +14,7 @@ import ButtonOpenableDialog from '../../Reusables/ButtonOpenableDialog'
 import * as yup from 'yup'
 import { useDispatch } from 'react-redux'
 import { mergeWithCurrentPath } from '../trackingToolSlice'
-import { MapPointType, PathVariant } from '../Map/pathUtils'
+import { MapPointType, PathVariant } from '../trackingToolUtils'
 import generateUuid from '../../../utils/id/uuidGenerator'
 import { useFormik } from 'formik'
 import ContextMenuDialogProps from './contextMenuDialogProps'
@@ -46,21 +46,20 @@ const AddFromCoordinatesDialog: FunctionComponent<ContextMenuDialogProps> = ({
             name: yup.string().required('Name is required'),
         }),
         onSubmit: (values: AddCatalogItemFromCoords) => {
-            dispatch(
-                mergeWithCurrentPath([
-                    {
-                        id: generateUuid(),
-                        idx: -1,
-                        addToPath: false,
-                        type: MapPointType.FromCoordinates,
-                        catalogItem: {
-                            name: values.name,
-                            latitude: values.latitude,
-                            longitude: values.longitude,
-                        },
-                    },
-                ] as PathVariant)
-            )
+            const item = {
+                id: generateUuid(),
+                idx: -1,
+                addToPath: false,
+                type: MapPointType.FromCoordinates,
+                catalogItem: {
+                    name: values.name,
+                    latitude: values.latitude,
+                    longitude: values.longitude,
+                },
+            }
+            console.log(`Creating item: ${JSON.stringify(item)}`)
+            dispatch(mergeWithCurrentPath([item] as PathVariant))
+            onClose()
         },
     })
 
@@ -133,7 +132,11 @@ const AddFromCoordinatesDialog: FunctionComponent<ContextMenuDialogProps> = ({
                                     md={3}
                                     justifyContent="flex-end"
                                 >
-                                    <Button variant="contained" type="submit" color="primary">
+                                    <Button
+                                        variant="contained"
+                                        type="submit"
+                                        color="primary"
+                                    >
                                         Import
                                     </Button>
                                 </Grid>
diff --git a/frontend/src/features/TrackingTool/Import/ImportContextMenu.tsx b/frontend/src/features/TrackingTool/Import/ImportContextMenu.tsx
index 2f6a79f..ea1ffe2 100644
--- a/frontend/src/features/TrackingTool/Import/ImportContextMenu.tsx
+++ b/frontend/src/features/TrackingTool/Import/ImportContextMenu.tsx
@@ -1,36 +1,24 @@
 import { LeafletMouseEvent } from 'leaflet'
 import { Fragment, useCallback, useState } from 'react'
-import { Popup, useMap, useMapEvents } from 'react-leaflet'
-
-import * as React from 'react'
-import Divider from '@mui/material/Divider'
-import Paper from '@mui/material/Paper'
-import MenuList from '@mui/material/MenuList'
-import MenuItem from '@mui/material/MenuItem'
-import ListItemText from '@mui/material/ListItemText'
-import ListItemIcon from '@mui/material/ListItemIcon'
+import { Popup, useMapEvents } from 'react-leaflet'
 import Typography from '@mui/material/Typography'
-import ContentCut from '@mui/icons-material/ContentCut'
-import ContentCopy from '@mui/icons-material/ContentCopy'
-import ContentPaste from '@mui/icons-material/ContentPaste'
-import Cloud from '@mui/icons-material/Cloud'
-import { Button, Stack, ThemeProvider } from '@mui/material'
+import {  Stack } from '@mui/material'
 import AddFromCoordinatesDialog from './AddFromCoordinatesDialog'
 import { useSelector } from 'react-redux'
 import { RootState } from '../../redux/store'
-import { buildTheme } from '../../Theme/ThemeWrapper'
 import ImportLocationDialog from './ImportLocationDialog'
+import { PathDto } from '../../../swagger/data-contracts'
 
 const RightClickPopupMenu = () => {
     const [open, setOpen] = useState(false)
     const [latLng, setLatLng] = useState<[number, number]>([0, 0])
-
-    const paletteMode = useSelector(
-        (state: RootState) => state.theme.paletteMode
-    )
+    const pathDto = useSelector((state: RootState) => state.trackingTool.pathDto)
 
     useMapEvents({
         contextmenu: (e: LeafletMouseEvent) => {
+            if (!pathDto) {
+                return
+            }
             setLatLng([e.latlng.lat, e.latlng.lng])
             setOpen(true)
         },
diff --git a/frontend/src/features/TrackingTool/Import/ImportLocationDialog.tsx b/frontend/src/features/TrackingTool/Import/ImportLocationDialog.tsx
index bb596d4..7d86452 100644
--- a/frontend/src/features/TrackingTool/Import/ImportLocationDialog.tsx
+++ b/frontend/src/features/TrackingTool/Import/ImportLocationDialog.tsx
@@ -25,12 +25,11 @@ const importTypes = {
     websiteCatalogs: 'Website Catalogs',
 }
 
-
 const externalCatalogs = {
-    'PLEIADES': 'Pleiades',
-    'GEONAMES': 'Geonames',
-    'CIGS': 'CIGS',
-    'ANE': 'ANE'
+    PLEIADES: 'Pleiades',
+    GEONAMES: 'Geonames',
+    CIGS: 'CIGS',
+    ANE: 'ANE',
 }
 
 interface ImportData {
@@ -56,8 +55,6 @@ const ImportLocationDialog: FunctionComponent<ContextMenuDialogProps> = ({
             if (importType === 'localCatalog') {
                 values.externalCatalogType = undefined
             }
-
-
         },
     })
 
@@ -98,15 +95,13 @@ const ImportLocationDialog: FunctionComponent<ContextMenuDialogProps> = ({
             <ThemeWrapper>
                 <Paper>
                     <DialogTitle>
-                    <Stack
+                        <Stack
                             direction="row"
                             justifyContent="space-between"
                             alignItems="center"
                             spacing={1}
                         >
-                            <Fragment>
-                                Import Locations
-                            </Fragment>
+                            <Fragment>Import Locations</Fragment>
                             <IconButton onClick={onClose}>
                                 <CloseIcon />
                             </IconButton>
@@ -153,7 +148,11 @@ const ImportLocationDialog: FunctionComponent<ContextMenuDialogProps> = ({
                                 md={3}
                                 justifyContent="flex-end"
                             >
-                                <Button variant="contained" type="submit" color="primary">
+                                <Button
+                                    variant="contained"
+                                    type="submit"
+                                    color="primary"
+                                >
                                     Import
                                 </Button>
                             </Grid>
@@ -174,22 +173,20 @@ const ImportLocationDialog: FunctionComponent<ContextMenuDialogProps> = ({
                                             name="externalCatalogType"
                                             value={
                                                 formik.values
-                                                    .externalCatalogType || "PLEIADES"
+                                                    .externalCatalogType ||
+                                                'PLEIADES'
                                             }
                                             onChange={formik.handleChange}
                                             label="Catalog Type"
                                             size="small"
                                         >
-                                            {Object.entries(externalCatalogs).map(
-                                                ([key, value], idx) => (
-                                                    <MenuItem
-                                                        key={key}
-                                                        value={key}
-                                                    >
-                                                        {value}
-                                                    </MenuItem>
-                                                )
-                                            )}
+                                            {Object.entries(
+                                                externalCatalogs
+                                            ).map(([key, value], idx) => (
+                                                <MenuItem key={key} value={key}>
+                                                    {value}
+                                                </MenuItem>
+                                            ))}
                                         </Select>
                                     </FormControl>
                                     <NameTextField />
diff --git a/frontend/src/features/TrackingTool/Map/MapMarker.tsx b/frontend/src/features/TrackingTool/Map/MapMarker.tsx
index db39848..9668421 100644
--- a/frontend/src/features/TrackingTool/Map/MapMarker.tsx
+++ b/frontend/src/features/TrackingTool/Map/MapMarker.tsx
@@ -1,10 +1,15 @@
-import { LatLngTuple, Marker as MarkerPOJO } from 'leaflet'
+import L, { LatLngTuple, Marker as MarkerPOJO } from 'leaflet'
 import { FunctionComponent, ReactNode, useMemo, useRef, useState } from 'react'
 import { Marker } from 'react-leaflet'
+import {
+    getMapPointIcon,
+    MapPoint,
+} from '../trackingToolUtils'
 
 export interface MapMarkerProps {
     position: LatLngTuple
     children?: ReactNode
+    mapPoint: MapPoint
     color?: 'external' | 'disabled' | 'localCatalog'
     updatePositionCallbackFn: (position: LatLngTuple) => void // Callback function to notify MapPath to rerender the path
 }
@@ -14,6 +19,7 @@ const MapMarker: FunctionComponent<MapMarkerProps> = ({
     position,
     children,
     updatePositionCallbackFn,
+    mapPoint,
 }) => {
     const [currentPosition, setCurrentPosition] = useState(position)
     const markerRef = useRef<MarkerPOJO | null>(null)
@@ -37,6 +43,7 @@ const MapMarker: FunctionComponent<MapMarkerProps> = ({
         <Marker
             draggable={true}
             position={currentPosition}
+            icon={getMapPointIcon(mapPoint)}
             eventHandlers={eventHandlers}
             ref={markerRef}
         >
diff --git a/frontend/src/features/TrackingTool/Map/MapPath.tsx b/frontend/src/features/TrackingTool/Map/MapPath.tsx
index a015048..87d91f8 100644
--- a/frontend/src/features/TrackingTool/Map/MapPath.tsx
+++ b/frontend/src/features/TrackingTool/Map/MapPath.tsx
@@ -1,7 +1,7 @@
 import { Fragment, FunctionComponent, useEffect, useState } from 'react'
 import { useDispatch, useSelector } from 'react-redux'
 import { RootState } from '../../redux/store'
-import { PathVariant, MapPoint, isMapPointDisplayable } from './pathUtils'
+import { PathVariant, MapPoint, isMapPointDisplayable } from '../trackingToolUtils'
 import TextPath from 'react-leaflet-textpath'
 import {
     setPrimaryIdx,
@@ -113,11 +113,12 @@ const MapPath: FunctionComponent<MapPathProps> = ({ idx }) => {
         setVertices(
             displayableMapPoints.map((item) => (
                 <MapMarker
-                    key={`${item.catalogItem.id}`}
+                    key={item.id}
                     position={[
                         item.catalogItem.latitude as number,
                         item.catalogItem.longitude as number,
                     ]}
+                    mapPoint={item}
                     updatePositionCallbackFn={(position: LatLngTuple) => {
                         dispatch(
                             updateMapMarkerWithId({
diff --git a/frontend/src/features/TrackingTool/Map/pathUtils.ts b/frontend/src/features/TrackingTool/Map/pathUtils.ts
index 9989fbd..ff5617c 100644
--- a/frontend/src/features/TrackingTool/Map/pathUtils.ts
+++ b/frontend/src/features/TrackingTool/Map/pathUtils.ts
@@ -1,30 +1,7 @@
-// Business logic for tracking tool
-
 import { CatalogItemDto, PathDto } from '../../../swagger/data-contracts'
 import generateUuid from '../../../utils/id/uuidGenerator'
+import { MapPoint, MapPointType, PathVariant } from '../trackingToolUtils'
 
-// For more comprehensive code alias CatalogItemDto[] as path variant
-export type PathVariant = MapPoint[]
-
-export enum MapPointType {
-    LocalCatalog, // Fetched from local catalog
-    ExternalCatalog, // Fetched from external catalog
-    GeoJson, // From GeoJSON file
-    FromCoordinates, // From coordinates
-}
-
-// Represents a point on the map - wrapper for CatalogItemDto to make it easier to work with
-export interface MapPoint {
-    id: string // unique id for react
-    idx: number,
-    addToPath: boolean, // whether to add the point to the path
-    catalogItem: CatalogItemDto,
-    type: MapPointType
-    hidden?: boolean // if true the point will not be displayed on the map
-}
-
-export const isMapPointDisplayable = (mapPoint: MapPoint): boolean =>
-    !!mapPoint.catalogItem.latitude && !!mapPoint.catalogItem.longitude && !mapPoint.hidden
 
 /**
  * Cartesian product of two arrays
diff --git a/frontend/src/features/TrackingTool/MapPointDraggableList/DragDropCtxWrapper.tsx b/frontend/src/features/TrackingTool/MapPointDraggableList/DragDropCtxWrapper.tsx
new file mode 100644
index 0000000..47cf397
--- /dev/null
+++ b/frontend/src/features/TrackingTool/MapPointDraggableList/DragDropCtxWrapper.tsx
@@ -0,0 +1,46 @@
+import { memo } from 'react'
+import {
+    DragDropContext,
+    Droppable,
+    OnDragEndResponder,
+} from 'react-beautiful-dnd'
+import { MapPoint } from '../trackingToolUtils'
+import MapPointDraggableListItem from './MapPointDraggableListItem'
+
+export interface DraggableListProps {
+    items: MapPoint[]
+    onDragEnd: OnDragEndResponder
+}
+
+window.addEventListener('error', (e) => {
+    if (
+        e.message ===
+            'ResizeObserver loop completed with undelivered notifications.' ||
+        e.message === 'ResizeObserver loop limit exceeded'
+    ) {
+        e.stopImmediatePropagation()
+    }
+})
+
+const DragDropCtxWrapper = memo(({ items, onDragEnd }: DraggableListProps) => {
+    return (
+        <DragDropContext onDragEnd={onDragEnd}>
+            <Droppable droppableId="droppable-list">
+                {(provided) => (
+                    <div ref={provided.innerRef} {...provided.droppableProps}>
+                        {items.map((item, index) => (
+                            <MapPointDraggableListItem
+                                list={items}
+                                idx={index}
+                                key={item.id}
+                            />
+                        ))}
+                        {provided.placeholder}
+                    </div>
+                )}
+            </Droppable>
+        </DragDropContext>
+    )
+})
+
+export default DragDropCtxWrapper
diff --git a/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableList.tsx b/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableList.tsx
new file mode 100644
index 0000000..e4bd339
--- /dev/null
+++ b/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableList.tsx
@@ -0,0 +1,56 @@
+import { Paper } from '@mui/material'
+import { useEffect, useState, useCallback } from 'react'
+import { DropResult } from 'react-beautiful-dnd'
+import { useDispatch, useSelector } from 'react-redux'
+import { RootState } from '../../redux/store'
+import { moveMarkerToDestination } from '../trackingToolSlice'
+import { PathVariant } from '../trackingToolUtils'
+import DragDropCtxWrapper from './DragDropCtxWrapper'
+
+const MapPointDraggableList = () => {
+    const dispatch = useDispatch()
+
+    // List of all paths
+    const paths = useSelector(
+        (state: RootState) => state.trackingTool.pathVariants
+    )
+
+    // Primary path index - i.e. the selected path
+    const primaryPathIdx = useSelector(
+        (state: RootState) => state.trackingTool.primaryPathIdx
+    )
+
+    // Selected path as local state
+    const [path, setPath] = useState<PathVariant | undefined>()
+
+    // Set localstate path whenever it changes in the store
+    useEffect(() => {
+        if (!paths || paths.length < primaryPathIdx) {
+            setPath(undefined)
+            return
+        }
+
+        setPath(paths[primaryPathIdx])
+    }, [paths, primaryPathIdx])
+
+    const onDragEnd = useCallback(({ destination, source }: DropResult) => {
+        if (!destination || !source || destination.index === source.index) {
+            return
+        }
+
+        dispatch(
+            moveMarkerToDestination({
+                source: source.index,
+                destination: destination.index,
+            })
+        )
+    }, [dispatch])
+
+    return (
+        <Paper variant="outlined">
+            <DragDropCtxWrapper items={path ?? []} onDragEnd={onDragEnd} />
+        </Paper>
+    )
+}
+
+export default MapPointDraggableList
diff --git a/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableListItem.tsx b/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableListItem.tsx
new file mode 100644
index 0000000..2e15420
--- /dev/null
+++ b/frontend/src/features/TrackingTool/MapPointDraggableList/MapPointDraggableListItem.tsx
@@ -0,0 +1,153 @@
+import {
+    IconButton,
+    ListItem,
+    ListItemAvatar,
+    ListItemText,
+    Typography,
+} from '@mui/material'
+import { Draggable } from 'react-beautiful-dnd'
+import { getMapPointSemanticColor as getMapPointSemanticColor, MapPoint, MapPointType, PathVariant } from '../trackingToolUtils'
+import { CatalogItemDto } from '../../../swagger/data-contracts'
+import { useDispatch } from 'react-redux'
+import { removeMapMarker, updateMapMarker } from '../trackingToolSlice'
+import { useMemo } from 'react'
+import DragHandleIcon from '@mui/icons-material/DragHandle'
+import VisibilityIcon from '@mui/icons-material/Visibility'
+import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'
+import AddRoadIcon from '@mui/icons-material/AddRoad'
+import RemoveRoadIcon from '@mui/icons-material/RemoveRoad'
+import DeleteForeverIcon from '@mui/icons-material/DeleteForever'
+
+export type DraggableListItemProps = {
+    list: PathVariant
+    idx: number
+}
+
+const getFormattedLocationOrEmpty = (catalogItem: CatalogItemDto) => {
+    if (!catalogItem || !catalogItem.latitude || !catalogItem.longitude) {
+        return 'Location unavailable'
+    }
+
+    return `${catalogItem.latitude.toFixed(
+        3
+    )}°, ${catalogItem.longitude.toFixed(3)}°`
+}
+
+const MapPointDraggableListItem = ({ list, idx }: DraggableListItemProps) => {
+    const item = list[idx]
+    const dispatch = useDispatch()
+
+    // useMemo to prevent unnecessary re-renders which will make the list jumpy
+    return useMemo(() => {
+        const toggleAddToPath = () => {
+            dispatch(
+                // updateMapMarkerWithId({
+                //     item: {
+                //         ...item,
+                //         addToPath: !item?.addToPath,
+                //     } as MapPoint,
+                //     id: item.id,
+                // })
+                updateMapMarker({
+                    ...item,
+                    addToPath: !item?.addToPath,
+                    idx,
+                })
+            )
+        }
+
+        const toggleHidden = () => {
+            dispatch(
+                // updateMapMarkerWithId({
+                //     item: {
+                //         ...item,
+                //         hidden: !item?.hidden,
+                //     } as MapPoint,
+                //     id: item.id,
+                // })
+                updateMapMarker({
+                    ...item,
+                    hidden: !item?.hidden,
+                    idx,
+                })
+            )
+        }
+
+        const deleteItem = () => {
+            dispatch(
+                removeMapMarker({
+                    ...item,
+                    idx,
+                })
+            )
+        }
+
+        return (
+            item && (
+                <Draggable
+                    key={`${item.id}`}
+                    draggableId={`${item.id}`}
+                    index={idx}
+                >
+                    {(provided, snapshot) => (
+                        <ListItem
+                            ref={provided.innerRef}
+                            {...provided.draggableProps}
+                            {...provided.dragHandleProps}
+                        >
+                            <ListItemAvatar>
+                                <DragHandleIcon />
+                            </ListItemAvatar>
+                            <ListItemText
+                                primary={
+                                    <Typography
+                                        style={{ color: getMapPointSemanticColor(item) }}
+                                    >
+                                        {item.catalogItem.name ??
+                                            'Unknown name'}
+                                    </Typography>
+                                }
+                                secondary={getFormattedLocationOrEmpty(
+                                    item.catalogItem
+                                )}
+                            />
+                            {item.type !== MapPointType.LocalCatalog && (
+                                <IconButton sx={{ mr: 1 }} onClick={deleteItem}>
+                                    <DeleteForeverIcon />
+                                </IconButton>
+                            )}
+                            <IconButton sx={{ mr: 1 }} onClick={toggleHidden}>
+                                {item.hidden ? (
+                                    <VisibilityOffIcon />
+                                ) : (
+                                    <VisibilityIcon />
+                                )}
+                            </IconButton>
+                            <IconButton
+                                sx={{ mr: 1 }}
+                                onClick={toggleAddToPath}
+                            >
+                                {item.addToPath ? (
+                                    <AddRoadIcon />
+                                ) : (
+                                    <RemoveRoadIcon />
+                                )}
+                            </IconButton>
+                            {/* <FormControlLabel
+                            control={
+                                <Checkbox
+                                    checked={item.addToPath}
+                                    onChange={toggleAddToPath}
+                                />
+                            }
+                            label="Add to path"
+                        /> */}
+                        </ListItem>
+                    )}
+                </Draggable>
+            )
+        )
+    }, [item, idx, dispatch])
+}
+
+export default MapPointDraggableListItem
diff --git a/frontend/src/features/TrackingTool/TrackingTool.tsx b/frontend/src/features/TrackingTool/TrackingTool.tsx
index 8fa34a0..8d0436a 100644
--- a/frontend/src/features/TrackingTool/TrackingTool.tsx
+++ b/frontend/src/features/TrackingTool/TrackingTool.tsx
@@ -23,9 +23,10 @@ import ClearIcon from '@mui/icons-material/Clear'
 import GeoJsonExportButton from './Upload/GeoJsonExportButton'
 import GeoJsonImportDialog from './Upload/GeoJsonImportDialog'
 import ProcessedTextDisplay from './ProcessedText/ProcessedTextDisplay'
-import DraggableMarkerList from './DraggableList/DraggableMarkerList'
+import MapPointDraggableList from './MapPointDraggableList/MapPointDraggableList'
 import RightClickPopupMenu from './Import/ImportContextMenu'
 import { buildTheme, getPalette } from '../Theme/ThemeWrapper'
+import AttachFileIcon from '@mui/icons-material/AttachFile'
 
 const mapTheme = buildTheme('light')
 
@@ -111,9 +112,11 @@ const TrackingTool = () => {
                                 <FileUpload />
                             </Fragment>
                         )}
-                        <GeoJsonImportDialog />
                         {pathVariants && pathVariants.length > 0 && (
-                            <GeoJsonExportButton />
+                            <Fragment>
+                                <GeoJsonImportDialog />
+                                <GeoJsonExportButton />
+                            </Fragment>
                         )}
                     </Stack>
 
@@ -163,7 +166,7 @@ const TrackingTool = () => {
                 </Grid>
                 <Grid container sx={{ mt: 1, mb: 20 }} spacing={1}>
                     <Grid item xs={12} md={6}>
-                        <DraggableMarkerList />
+                        <MapPointDraggableList />
                     </Grid>
                     <Grid item xs={12} md={6}>
                         <ProcessedTextDisplay />
diff --git a/frontend/src/features/TrackingTool/TrackingToolState.ts b/frontend/src/features/TrackingTool/TrackingToolState.ts
index 3ff4359..46cba4a 100644
--- a/frontend/src/features/TrackingTool/TrackingToolState.ts
+++ b/frontend/src/features/TrackingTool/TrackingToolState.ts
@@ -1,6 +1,6 @@
 import { LatLngTuple } from 'leaflet'
 import { PathDto } from '../../swagger/data-contracts'
-import { PathVariant } from './Map/pathUtils'
+import { PathVariant } from './trackingToolUtils'
 
 export default interface TrackingToolState {
     isLoading: boolean // whether the data is being loaded
diff --git a/frontend/src/features/TrackingTool/Upload/FileUpload.tsx b/frontend/src/features/TrackingTool/Upload/FileUpload.tsx
index 5f11cc4..a80b961 100644
--- a/frontend/src/features/TrackingTool/Upload/FileUpload.tsx
+++ b/frontend/src/features/TrackingTool/Upload/FileUpload.tsx
@@ -14,6 +14,8 @@ import ButtonOpenableDialog from '../../Reusables/ButtonOpenableDialog'
 import { useDispatch } from 'react-redux'
 import { sendTextForProcessing } from '../trackingToolThunks'
 import SingleFileSelectionForm from '../../Reusables/SingleFileSelectionForm'
+import AttachFileIcon from '@mui/icons-material/AttachFile'
+import TextSnippetIcon from '@mui/icons-material/TextSnippet'
 
 interface UploadValues {
     file?: File
@@ -77,6 +79,7 @@ const FileUpload = () => {
             maxWidth="xs"
             open={open}
             setOpen={setOpen}
+            startIcon={<AttachFileIcon />}
         >
             <DialogTitle>Upload New File</DialogTitle>
             <DialogContent>
diff --git a/frontend/src/features/TrackingTool/Upload/GeoJsonExportButton.tsx b/frontend/src/features/TrackingTool/Upload/GeoJsonExportButton.tsx
index 8076048..3ebdae9 100644
--- a/frontend/src/features/TrackingTool/Upload/GeoJsonExportButton.tsx
+++ b/frontend/src/features/TrackingTool/Upload/GeoJsonExportButton.tsx
@@ -2,8 +2,8 @@ import { Button } from '@mui/material'
 import { useEffect, useState } from 'react'
 import { useSelector } from 'react-redux'
 import { RootState } from '../../redux/store'
-import { isMapPointDisplayable, PathVariant } from '../Map/pathUtils'
-import { exportAsGeoJsonString } from './GeoJsonIo'
+import { isMapPointDisplayable, PathVariant } from '../trackingToolUtils'
+import { exportAsGeoJsonString } from './geoJsonIo'
 
 const GeoJsonExportButton = () => {
     const [path, setPath] = useState<PathVariant | undefined>(undefined)
diff --git a/frontend/src/features/TrackingTool/Upload/GeoJsonImportDialog.tsx b/frontend/src/features/TrackingTool/Upload/GeoJsonImportDialog.tsx
index f23ef8a..49d04ec 100644
--- a/frontend/src/features/TrackingTool/Upload/GeoJsonImportDialog.tsx
+++ b/frontend/src/features/TrackingTool/Upload/GeoJsonImportDialog.tsx
@@ -7,7 +7,7 @@ import * as yup from 'yup'
 import { showNotification } from '../../Notification/notificationSlice'
 import SingleFileSelectionForm from '../../Reusables/SingleFileSelectionForm'
 import { mergeWithCurrentPath } from '../trackingToolSlice'
-import { parseGeoJsonToPathVariant } from './GeoJsonIo'
+import { parseGeoJsonToPathVariant } from './geoJsonIo'
 
 const GeoJsonImportDialog = () => {
     const dispatch = useDispatch()
diff --git a/frontend/src/features/TrackingTool/Upload/GeoJsonIo.ts b/frontend/src/features/TrackingTool/Upload/GeoJsonIo.ts
index 646e68d..fab67f7 100644
--- a/frontend/src/features/TrackingTool/Upload/GeoJsonIo.ts
+++ b/frontend/src/features/TrackingTool/Upload/GeoJsonIo.ts
@@ -1,4 +1,4 @@
-import { isMapPointDisplayable, MapPoint, MapPointType, PathVariant } from '../Map/pathUtils'
+import { isMapPointDisplayable, MapPoint, MapPointType, PathVariant } from '../trackingToolUtils'
 import * as yup from 'yup'
 import generateUuid from '../../../utils/id/uuidGenerator'
 
diff --git a/frontend/src/features/TrackingTool/Upload/PlaintextUpload.tsx b/frontend/src/features/TrackingTool/Upload/PlaintextUpload.tsx
index 941132b..4ecd5c3 100644
--- a/frontend/src/features/TrackingTool/Upload/PlaintextUpload.tsx
+++ b/frontend/src/features/TrackingTool/Upload/PlaintextUpload.tsx
@@ -1,6 +1,5 @@
 import {
     Button,
-    Dialog,
     DialogContent,
     DialogTitle,
     Stack,
@@ -15,6 +14,8 @@ import { RootState } from '../../redux/store'
 import { sendTextForProcessing } from '../trackingToolThunks'
 import * as yup from 'yup'
 import { resetDialogApiCallSuccess } from '../trackingToolSlice'
+import ButtonOpenableDialog from '../../Reusables/ButtonOpenableDialog'
+import TextSnippetIcon from '@mui/icons-material/TextSnippet'
 
 const PlaintextUpload = () => {
     const loading = useSelector(
@@ -33,6 +34,7 @@ const PlaintextUpload = () => {
         text: yup.mixed().required('Text is required'),
     })
 
+    // Form control
     const formik = useFormik({
         initialValues: {
             text: '',
@@ -63,14 +65,15 @@ const PlaintextUpload = () => {
 
     return (
         <Fragment>
-            <Button variant="contained" onClick={() => setOpen(true)}>
-                Text
-            </Button>
-            <Dialog
+            <ButtonOpenableDialog
                 open={open}
-                fullWidth={true}
-                onClose={onCloseDialog}
+                setOpen={setOpen}
                 maxWidth="lg"
+                buttonColor="primary"
+                buttonVariant="contained"
+                buttonText="Text"
+                startIcon={<TextSnippetIcon />}
+                onCloseCallback={onCloseDialog}
             >
                 <DialogTitle>Plaintext Input</DialogTitle>
                 <DialogContent>
@@ -110,7 +113,7 @@ const PlaintextUpload = () => {
                         </Stack>
                     </form>
                 </DialogContent>
-            </Dialog>
+            </ButtonOpenableDialog>
         </Fragment>
     )
 }
diff --git a/frontend/src/features/TrackingTool/trackingToolSlice.ts b/frontend/src/features/TrackingTool/trackingToolSlice.ts
index 161c129..f3c4577 100644
--- a/frontend/src/features/TrackingTool/trackingToolSlice.ts
+++ b/frontend/src/features/TrackingTool/trackingToolSlice.ts
@@ -2,10 +2,11 @@ import { createSlice } from "@reduxjs/toolkit"
 import { LatLngTuple } from "leaflet"
 import mapConfig from "../../config/mapConfig"
 import { PathDto } from "../../swagger/data-contracts"
-import buildPathVariants, { isMapPointDisplayable, MapPoint, PathVariant } from "./Map/pathUtils"
+import buildPathVariants from "./Map/pathUtils"
+import  { isMapPointDisplayable, MapPoint, PathVariant } from "./trackingToolUtils"
 import { sendTextForProcessing } from "./trackingToolThunks"
 import storage from "redux-persist/lib/storage"
-import TrackingToolState from './TrackingToolState'
+import TrackingToolState from './trackingToolState'
 
 
 const defaultPathsPerPage = 5
@@ -103,6 +104,28 @@ export const trackingToolSlice = createSlice({
                 })
             }
         },
+        // Removes map marker based on its idx property
+        removeMapMarker: (state: TrackingToolState, action: { payload: { id: string, idx: number } }) => {
+            const item = action.payload
+            const idx = state.primaryPathIdx
+            if (!state.pathVariants || state.pathVariants.length <= idx) {
+                return state
+            }
+
+            return {
+                ...state,
+                pathVariants: state.pathVariants.map((pathVariant, i) => {
+                    if (i !== idx) {
+                        return [...pathVariant]
+                    }
+
+                    return [
+                        ...pathVariant.slice(0, item.idx),
+                        ...pathVariant.slice(item.idx + 1),
+                    ]
+                })
+            }
+        },
         moveMarkerToDestination: (state: TrackingToolState, action: { payload: { destination: number, source: number } }) => {
             const { destination, source } = action.payload
             if (!state.pathVariants || state.pathVariants.length === 0) {
@@ -154,7 +177,7 @@ export const trackingToolSlice = createSlice({
             // const itemsToReplace: MapPoint[] = []
             const itemsToAdd: MapPoint[] = []
             jsonPath.forEach((item) => {
-                if (!pathMap.has(item.catalogItem.id as string)) {
+                if (!pathMap.has(item.catalogItem.id ?? '')) {
                     itemsToAdd.push(item)
                     return
                 }
@@ -231,7 +254,8 @@ export const {
     updateMapMarker,
     mergeWithCurrentPath,
     moveMarkerToDestination,
-    updateMapMarkerWithId
+    updateMapMarkerWithId,
+    removeMapMarker,
 } = trackingToolSlice.actions
 const trackingToolReducer = trackingToolSlice.reducer
 export default trackingToolReducer
diff --git a/frontend/src/features/TrackingTool/trackingToolThunks.ts b/frontend/src/features/TrackingTool/trackingToolThunks.ts
index b5005ec..023b059 100644
--- a/frontend/src/features/TrackingTool/trackingToolThunks.ts
+++ b/frontend/src/features/TrackingTool/trackingToolThunks.ts
@@ -1,7 +1,7 @@
 import { createAsyncThunk } from '@reduxjs/toolkit'
 import axiosInstance from '../../api/api'
 import { RootState } from '../redux/store'
-import { MapPoint, PathVariant } from './Map/pathUtils'
+import { MapPoint, PathVariant } from './trackingToolUtils'
 
 export const sendTextForProcessing = createAsyncThunk(
     'trackingTool/sendTextForProcessing',
diff --git a/frontend/src/features/TrackingTool/trackingToolUtils.ts b/frontend/src/features/TrackingTool/trackingToolUtils.ts
new file mode 100644
index 0000000..b80baa7
--- /dev/null
+++ b/frontend/src/features/TrackingTool/trackingToolUtils.ts
@@ -0,0 +1,83 @@
+import L, { PointExpression } from 'leaflet'
+import { CatalogItemDto } from '../../swagger/data-contracts'
+import { mdiMapMarker } from '@mdi/js'
+
+// For more comprehensive code alias CatalogItemDto[] as path variant
+export type PathVariant = MapPoint[]
+
+export enum MapPointType {
+    LocalCatalog, // Fetched from local catalog
+    ExternalCatalog, // Fetched from external catalog
+    GeoJson, // From GeoJSON file
+    FromCoordinates, // From coordinates
+}
+
+// Represents a point on the map - wrapper for CatalogItemDto to make it easier to work with
+export interface MapPoint {
+    id: string // unique id for react
+    idx: number,
+    addToPath: boolean, // whether to add the point to the path
+    catalogItem: CatalogItemDto,
+    type: MapPointType
+    hidden?: boolean // if true the point will not be displayed on the map
+}
+
+export const isMapPointDisplayable = (mapPoint: MapPoint): boolean =>
+    !!mapPoint.catalogItem.latitude && !!mapPoint.catalogItem.longitude && !mapPoint.hidden
+
+/**
+ * Based on its type - either imported from local catalog, remote catalogs etc. each type has its own color to differentiate them
+ * @param item item to get color for
+ * @returns CSS color string
+ */
+export const getMapPointSemanticColor = (item: MapPoint) => {
+    switch (item.type) {
+        case MapPointType.LocalCatalog:
+            return 'inherit'
+        case MapPointType.FromCoordinates:
+            return '#21972D'
+        case MapPointType.ExternalCatalog:
+            return '#A72020'
+        case MapPointType.GeoJson:
+            return '#967520'
+    }
+}
+
+const createMapMarkerSvg = (color: string) => {
+    return `data:image/svg+xml;utf8, ${encodeURIComponent(`
+    <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="${color}">
+     <path d="M0 0h24v24H0z" fill="none" /><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
+     </svg>`)}`
+}
+
+const mapMarkerSvgs = {
+    [MapPointType.LocalCatalog]: createMapMarkerSvg('#285CAB'),
+    [MapPointType.ExternalCatalog]: createMapMarkerSvg('#A72020'),
+    [MapPointType.GeoJson]: createMapMarkerSvg('#967520'),
+    [MapPointType.FromCoordinates]: createMapMarkerSvg('#21972D'),
+}
+
+const iconAnchor = [32, 32] as PointExpression
+const iconSize = [42, 42] as PointExpression
+
+const mapMarkers = {
+    [MapPointType.LocalCatalog]: L.icon({
+        iconAnchor, iconSize,
+        iconUrl: mapMarkerSvgs[MapPointType.LocalCatalog],
+    }),
+    [MapPointType.ExternalCatalog]: L.icon({
+        iconAnchor, iconSize,
+        iconUrl: mapMarkerSvgs[MapPointType.ExternalCatalog],
+    }),
+
+    [MapPointType.GeoJson]: L.icon({
+        iconAnchor, iconSize,
+        iconUrl: mapMarkerSvgs[MapPointType.GeoJson],
+    }),
+    [MapPointType.FromCoordinates]: L.icon({
+        iconAnchor, iconSize,
+        iconUrl: mapMarkerSvgs[MapPointType.FromCoordinates],
+    }),
+}
+
+export const getMapPointIcon = (item: MapPoint): L.Icon => mapMarkers[item.type]
\ No newline at end of file
