Skip to content

Commit 2853abf

Browse files
author
Paweł Marynowski
committed
feat(map): add map view
1 parent f259ca0 commit 2853abf

4 files changed

Lines changed: 229 additions & 1 deletion

File tree

src/components/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import main from './main/main';
22
import dashboard from './main/dashboard/dashboard';
33
import list from './main/list/list';
4+
import map from './main/map/map';
45
import monument from './main/monument/monument';
56

67
export default () => {
78
main();
89
dashboard();
910
list();
11+
map();
1012
monument();
11-
};
13+
};

src/components/main/map/map.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<md-toolbar class="toolbar toolbar--wide md-whiteframe-3dp" layout="column" layout-align="start center">
2+
<div class="md-toolbar-tools">
3+
<md-button ui-sref="main.dashboard">
4+
Dashboard
5+
</md-button>
6+
<span flex></span>
7+
</div>
8+
</md-toolbar>
9+
<div class="container" layout="column" layout-align="space-between stretch" flex>
10+
<md-content layout="row" layout-align="start stretch" flex>
11+
<div class="list" layout="column" layout-align="start stretch" flex="none">
12+
<md-virtual-repeat-container class="list__container" flex>
13+
<md-list-item>
14+
<span ng-if="!$ctrl.loading">{{$ctrl.list.length}} results</span>
15+
<span ng-if="$ctrl.loading">Loading...</span>
16+
</md-list-item>
17+
<md-list-item class="md-2-line"
18+
md-virtual-repeat="item in $ctrl.list | orderBy: 'name.value'"
19+
ui-sref="main.object({id: item.name.value_id.substring(1)})">
20+
<div class="list__image" layout="row" layout-align="center center">
21+
<img ng-src="{{item.image}}" alt="{{item.name.value}}" ng-if="item.image">
22+
</div>
23+
<div class="md-list-item-text" layout="column">
24+
<p>{{item.name.value}}</p>
25+
<p class="muted">{{item.admin.value}}</p>
26+
</div>
27+
</md-list-item>
28+
<md-list-item class="md-2-line" ng-if="$ctrl.loading">
29+
<div class="list__image" layout="row" layout-align="center center"></div>
30+
<div class="md-list-item-text" layout="column"></div>
31+
</md-list-item>
32+
<md-list-item class="md-2-line" ng-if="$ctrl.loading">
33+
<div class="list__image" layout="row" layout-align="center center"></div>
34+
<div class="md-list-item-text" layout="column"></div>
35+
</md-list-item>
36+
<md-list-item class="md-2-line" ng-if="$ctrl.loading">
37+
<div class="list__image" layout="row" layout-align="center center"></div>
38+
<div class="md-list-item-text" layout="column"></div>
39+
</md-list-item>
40+
<md-list-item class="md-2-line" ng-if="$ctrl.loading">
41+
<div class="list__image" layout="row" layout-align="center center"></div>
42+
<div class="md-list-item-text" layout="column"></div>
43+
</md-list-item>
44+
<md-list-item class="md-2-line" ng-if="$ctrl.loading">
45+
<div class="list__image" layout="row" layout-align="center center"></div>
46+
<div class="md-list-item-text" layout="column"></div>
47+
</md-list-item>
48+
</md-virtual-repeat-container>
49+
</div>
50+
<div class="list__map" flex>
51+
<leaflet ng-if="!$ctrl.loadingMap"
52+
markers="$ctrl.map.markers"
53+
layers="$ctrl.map.layers"
54+
url-hash-center="yes"
55+
center="$ctrl.map.center" flex></leaflet>
56+
</div>
57+
</md-content>
58+
</div>

src/components/main/map/map.js

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import _ from 'lodash';
2+
3+
import './map.scss';
4+
import template from './map.html';
5+
6+
const MapComponent = { controller, template };
7+
8+
function controller($location, $scope, $state, $stateParams, $timeout, leafletData, localStorageService, mapService, wikidata) {
9+
const vm = this;
10+
const icon = mapService.getMapIcon();
11+
12+
// bindings
13+
14+
vm.goToItem = item => $state.go('main.list', { id: item.id.substring(1) });
15+
vm.map = mapService.getMapInstance({ center: { lat: 51.686, lng: 19.545, zoom: 7 } });
16+
vm.list = [];
17+
vm.listParams = {};
18+
vm.loading = vm.loadingMap = true;
19+
vm.search = {};
20+
21+
// activate
22+
23+
$scope.$on('centerUrlHash', (event, centerHash) => {
24+
$location.search({ c: centerHash });
25+
});
26+
27+
$timeout(() => {
28+
vm.loadingMap = false;
29+
leafletData.getMap().then((map) => {
30+
getDataBB(map.getBounds());
31+
map.on('dragend zoomend', () => {
32+
getDataBB(map.getBounds());
33+
});
34+
});
35+
}, 100);
36+
37+
// functions
38+
39+
function getDataBB(bounds) {
40+
vm.loading = true;
41+
wikidata.getSPARQL(`SELECT ?item ?itemLabel ?admin ?adminLabel ?image ?coord WHERE {
42+
SERVICE wikibase:box {
43+
?item wdt:P625 ?coord .
44+
bd:serviceParam wikibase:cornerWest "Point(${bounds.getSouthWest().lng} ${bounds.getSouthWest().lat})"^^geo:wktLiteral .
45+
bd:serviceParam wikibase:cornerEast "Point(${bounds.getNorthEast().lng} ${bounds.getNorthEast().lat})"^^geo:wktLiteral .
46+
}
47+
OPTIONAL { ?item wdt:P131 ?admin . }
48+
OPTIONAL { ?item wdt:P18 ?image . }
49+
SERVICE wikibase:label { bd:serviceParam wikibase:language "pl" }
50+
}`).then((data) => {
51+
vm.map.markers = {};
52+
vm.list = data.map(element => setListElement(element));
53+
vm.list.forEach((element) => {
54+
vm.map.markers[element.name.value_id] = setMarker(element);
55+
});
56+
vm.loading = false;
57+
});
58+
}
59+
60+
function getImage(image) {
61+
if (image) {
62+
const newImage = image.value.replace('wiki/Special:FilePath', 'w/index.php?title=Special:Redirect/file');
63+
return `${newImage}&width=120`;
64+
}
65+
return false;
66+
}
67+
68+
function getMessage(element) {
69+
return `<md-list-item class="md-2-line" ui-sref="main.object({id: ${element.name.value_id.substring(1)}})">
70+
<div class="md-list-item-text" layout="column">
71+
<p>${element.name.value}</p>
72+
</div>
73+
</md-list-item>`;
74+
}
75+
76+
function setListElement(element) {
77+
const id = element.item.value;
78+
const obj = {
79+
name: {
80+
value_id: id.substring(id.indexOf('/Q') + 1),
81+
value: element.itemLabel.value,
82+
},
83+
coord: element.coord.value ? element.coord.value.replace('Point(', '').replace(')', '').split(' ') : false,
84+
image: getImage(element.image),
85+
};
86+
if (element.admin) {
87+
obj.admin = {
88+
value_id: element.admin.value.substring(element.admin.value.indexOf('/Q') + 1),
89+
value: element.adminLabel ? element.adminLabel.value : element.admin.value.substring(element.admin.value.indexOf('/Q') + 1),
90+
};
91+
}
92+
return obj;
93+
}
94+
95+
function setMarker(element) {
96+
return {
97+
lat: +element.coord[1],
98+
lng: +element.coord[0],
99+
message: getMessage(element),
100+
layer: 'monuments',
101+
icon,
102+
};
103+
}
104+
}
105+
106+
export default () => {
107+
angular
108+
.module('monumental')
109+
.component('moMap', MapComponent);
110+
};

src/components/main/map/map.scss

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
@import '../../../styles/variables';
2+
@import '../../../styles/responsive';
3+
4+
mo-map {
5+
.list {
6+
width: 450px;
7+
height: calc(100vh - 105px);
8+
}
9+
10+
.list__container {
11+
margin-right: 20px;
12+
13+
md-list-item.md-2-line {
14+
border-bottom: 1px solid $softGrey;
15+
}
16+
}
17+
18+
.list__image {
19+
width: 75px;
20+
min-width: 75px;
21+
height: 75px;
22+
background: $softGrey;
23+
margin: 15px 15px 15px 0;
24+
25+
img {
26+
max-width: 100%;
27+
max-height: 100%;
28+
}
29+
}
30+
31+
.list__map {
32+
background: $softGrey;
33+
34+
.angular-leaflet-map {
35+
width: 100%;
36+
height: 100%;
37+
}
38+
39+
.leaflet-popup-close-button {
40+
z-index: 1;
41+
padding: 5px;
42+
}
43+
44+
.leaflet-popup-content-wrapper {
45+
border-radius: 2px;
46+
}
47+
48+
.leaflet-popup-content {
49+
min-width: 300px;
50+
margin: 0;
51+
font: 16px Roboto, Arial, sans-serif;
52+
}
53+
}
54+
55+
md-autocomplete {
56+
margin: 20px;
57+
}
58+
}

0 commit comments

Comments
 (0)