LocationMap.tsx 4.32 KB
Newer Older
Valeriy Panov's avatar
Valeriy Panov committed
1
import * as React from 'react';
Valeriy Panov's avatar
Valeriy Panov committed
2
import {withStyles} from 'material-ui/styles';
Valeriy Panov's avatar
Valeriy Panov committed
3
4
import Grid from 'material-ui/Grid';

Valeriy Panov's avatar
Valeriy Panov committed
5
import {isNumeric} from 'utilities';
6
import { Location, IGeoPoint } from 'model/location.model';
Valeriy Panov's avatar
Valeriy Panov committed
7
8
9
10
11
12
13

let Map;
let Marker;
let TileLayer;

interface ILocationMapProps extends React.ClassAttributes<any> {
    classes: any;
Valeriy Panov's avatar
Valeriy Panov committed
14
    locations: Location[];
Valeriy Panov's avatar
Valeriy Panov committed
15
16
17
18
19
20
21
22
23
24
25
26
}

const styles = (theme) => ({
    leafletContainer: {
        width: '100%',
        height: '300px',
    },
    locationIcon: {
        marginLeft: '20px',
        marginRight: '4px',
        width: '20px',
        height: '20px',
Valeriy Panov's avatar
Valeriy Panov committed
27
        position: 'relative' as 'relative',
Valeriy Panov's avatar
Valeriy Panov committed
28
29
30
31
32
33
34
35
36
37
38
39
40
41
        top: '4px',
        [theme.breakpoints.down('sm')]: {
            marginLeft: '0',
        },
    },
    locationIconWrap: {
        [theme.breakpoints.down('sm')]: {
            display: 'block',
        },
    },
});

class LocationMap extends React.Component<ILocationMapProps, any> {

Valeriy Panov's avatar
Valeriy Panov committed
42
    constructor(props, context) {
Valeriy Panov's avatar
Valeriy Panov committed
43
        super(props, context);
Valeriy Panov's avatar
Valeriy Panov committed
44
45
46
47
48
        if (typeof window !== 'undefined') {
            Map = require('react-leaflet').Map;
            Marker = require('react-leaflet').Marker;
            TileLayer = require('react-leaflet').TileLayer;
        }
Valeriy Panov's avatar
Valeriy Panov committed
49
50
    }

Valeriy Panov's avatar
Valeriy Panov committed
51
52
    public render() {
        const {classes, locations} = this.props;
Valeriy Panov's avatar
Valeriy Panov committed
53

Valeriy Panov's avatar
Valeriy Panov committed
54
55
56
        if (!(locations && locations.length)) {
            return null;
        }
Valeriy Panov's avatar
Valeriy Panov committed
57

Valeriy Panov's avatar
Valeriy Panov committed
58
59
60
61
62
63
64
        const positions = locations
            .filter((location) => isNumeric(location.decimalLatitude) && isNumeric(location.decimalLongitude))
            .map((location) => ({
                lat: location.decimalLatitude,
                lng: location.decimalLongitude,
            }));

65
66
67
        let min: IGeoPoint;
        let max: IGeoPoint;
        let center: IGeoPoint;
Valeriy Panov's avatar
Valeriy Panov committed
68

69
70
71
72
73
        if (positions && positions.length) {
          min = positions.reduce((p, c) => ({
              lat: Math.min(p.lat, c.lat),
              lng: Math.min(p.lng, c.lng),
          }));
Valeriy Panov's avatar
Valeriy Panov committed
74

75
76
77
78
          max = positions.reduce((p, c) => ({
              lat: Math.max(p.lat, c.lat),
              lng: Math.max(p.lng, c.lng),
          }));
Valeriy Panov's avatar
Valeriy Panov committed
79

80
81
82
83
84
          center = {
              lat: (min.lat + max.lat) / 2,
              lng: (min.lng + max.lng) / 2,
          };
        }
Valeriy Panov's avatar
Valeriy Panov committed
85
86
87

        return (
            <Grid item xs={ 12 }>
88
                { typeof window !== 'undefined' && positions && positions.length > 0 && (
Valeriy Panov's avatar
Valeriy Panov committed
89
90
91
92
93
                        <div className={ classes.leafletContainer }>
                            <Map
                                center={ center }
                                bounds={ [min, max] }
                                maxZoom={ positions.length === 1 ? 6 : 7 }
Maxym Borodenko's avatar
Maxym Borodenko committed
94
95
96
97
                                zoomControl={ false }
                                dragging={ false }
                                scrollWheelZoom={ false }
                                doubleClickZoom={ false }
Valeriy Panov's avatar
Valeriy Panov committed
98
99
                            >
                                <TileLayer
Maxym Borodenko's avatar
Maxym Borodenko committed
100
101
                                    attribution={ '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }
                                    url={ 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' }
Valeriy Panov's avatar
Valeriy Panov committed
102
103
104
105
106
107
108
109
                                />
                                { positions && positions.map((position, i) => (
                                        <Marker key={ i } position={ position }/>
                                    ),
                                ) }
                            </Map>
                        </div>
                    )
Valeriy Panov's avatar
Valeriy Panov committed
110
                }
Valeriy Panov's avatar
Valeriy Panov committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
                <ul>
                    {
                        locations
                            .filter((location) => location.userCountry || location.stateProvince || location.verbatimLocality)
                            .map((location, i) => (
                                <li className="font-normal m-0" key={ i }>
                                    {
                                        [location.verbatimLocality, location.stateProvince, location.userCountry]
                                            .filter((e) => e && e.trim())
                                            .join(', ')
                                    }
                                </li>
                            ))
                    }
                </ul>
Valeriy Panov's avatar
Valeriy Panov committed
126
127
            </Grid>
        );
Matija Obreza's avatar
Matija Obreza committed
128
    }
Valeriy Panov's avatar
Valeriy Panov committed
129
130
131

}

Valeriy Panov's avatar
Valeriy Panov committed
132
export default withStyles(styles)(LocationMap);