diff --git a/bower.json b/bower.json index afa3b82..1d1514b 100644 --- a/bower.json +++ b/bower.json @@ -9,15 +9,15 @@ "license": "MIT", "private": true, "dependencies": { - "angular": "^1.6.4", + "angular": "^1.6.6", "jquery": "^3.1.0", - "angular-route": "^1.6.4", + "angular-route": "^1.6.6", "angular-translate": "^2.11.1", "font-awesome": "^4.6.3", "bootstrap": "v4.0.0-alpha.6", "angular-socket-io": "^0.7.0", "socket.io-client": "^1.5.0", - "angular-sanitize": "^1.6.4", + "angular-sanitize": "^1.6.6", "videogular": "^1.4.4", "videogular-themes-default": "^1.4.4", "videogular-controls": "^1.4.4", @@ -27,10 +27,13 @@ "angular-momentjs": "^0.2.2", "three.js": "threejs#*", "components-threejs": "^0.0.79", - "ngclipboard": "^1.1.1" + "ngclipboard": "^1.1.1", + "mapbox-gl-js": "https://github.com/nicho90/mapbox-gl-js-bower.git#0.39.1" }, "resolutions": { - "angular": "1.6.4", + "angular": "1.6.6", + "angular-route": "1.6.6", + "angular-sanitize": "1.6.6", "bootstrap": "v4.0.0-alpha.6" } } diff --git a/public/backend/css/styles.css b/public/backend/css/styles.css index eb08e9c..d9690a7 100644 --- a/public/backend/css/styles.css +++ b/public/backend/css/styles.css @@ -10,6 +10,15 @@ body { margin-top: 60px; } +.navbar { + height: 60px; +} + +.view { + padding-top: 25px; + padding-bottom: 25px; +} + footer { position: absolute; bottom: 0; @@ -39,6 +48,13 @@ footer { } +#map { + width: 100%; + top: 60px; + position: absolute; +} + + .previewMap { border-radius: 3px; border: 1px solid rgba(0, 0, 0, .125); @@ -47,10 +63,12 @@ footer { border: 1px solid rgba(0, 0, 0, .125); } + .uuid { cursor: pointer; } + .card-footer > .btn-block-xs-only, .btn-block-xs-only { margin-top: 1px; margin-bottom: 1px; diff --git a/public/backend/index.html b/public/backend/index.html index 4db9e04..e8720c1 100644 --- a/public/backend/index.html +++ b/public/backend/index.html @@ -52,17 +52,23 @@ + + + + + + -
+
@@ -131,8 +137,7 @@
-
-
+
@@ -147,9 +152,7 @@
-
- -
+
@@ -203,6 +206,7 @@ + diff --git a/public/backend/js/controllers/mainController.js b/public/backend/js/controllers/mainController.js index a80584e..36dfa46 100644 --- a/public/backend/js/controllers/mainController.js +++ b/public/backend/js/controllers/mainController.js @@ -24,6 +24,21 @@ app.controller("mainController", function($scope, $rootScope, $filter, $translat } }; + + /** + * [description] + * @return {[type]} [description] + */ + $scope.isNotMapRoute = function(){ + var path = $location.path(); + if(path === '/map'){ + return false; + } else { + return true; + } + }; + + /** * [redirect description] * @param {[type]} path [description] diff --git a/public/backend/js/controllers/mapController.js b/public/backend/js/controllers/mapController.js index 35dc86f..ed68b92 100644 --- a/public/backend/js/controllers/mapController.js +++ b/public/backend/js/controllers/mapController.js @@ -1,6 +1,215 @@ var app = angular.module("ive"); // Map controller -app.controller("mapController", function($scope, $rootScope, $filter, $translate, $location, config, $authenticationService, $window) { +app.controller("mapController", function($scope, $rootScope, $filter, $translate, $location, config, $window, $locationService, $relationshipService) { $scope.$parent.loading = { status: false, message: "" }; + + /** + * Load data + * @return {[type]} [description] + */ + $scope.load = function(data){ + switch (data) { + case 'locations': { + $locationService.list() + .then(function onSuccess(response) { + $scope.locations = response.data; + $scope.location_geojson = $filter('toGeoJSON')(response.data); + + // Update sources + map.getSource('markers').setData($scope.location_geojson); + }) + .catch(function onError(response) { + $window.alert(response.data); + }); + + break; + } + case 'connected_to': { + break; + } + case 'has_parent_location': { + break; + } + default: { + + } + } + }; + + + $scope.mapStyle = 'streets-v9'; + mapboxgl.accessToken = config.mapboxAccessToken; + var map = new mapboxgl.Map({ + container: 'map', + style: 'mapbox://styles/mapbox/' + $scope.mapStyle, + center: [7.634355, 51.956875], + zoom: 14 + }); + + + /** + * [position description] + * @type {String} + */ + map.addControl(new mapboxgl.NavigationControl(), 'top-left'); + + + /** + * [features description] + * @type {[type]} + */ + map.on('load', function() { + + // Load data + $scope.load("locations"); + + + // Add geojson data as a new source + map.addSource("markers", { + "type": "geojson", + "data": { + "type": "FeatureCollection", + "features": [] + } + }); + + + // Add source as a layer and apply some styles + map.addLayer({ + "id": "locations", + "type": "circle", + "source": "markers", + "paint": { + 'circle-color': { + property: 'location_type', + type: 'categorical', + stops: [ + ['abstract', '#00ff00'], + ['outdoor', '#0000ff'], + ['indoor', '#ff0000'], + ] + }, + 'circle-radius': { + property: 'location_type', + type: 'categorical', + stops: [ + ['abstract', 5], + ['outdoor', 5], + ['indoor', 5] + ] + }, + }, + "layout": { + "visibility": "visible" + } + }); + + // Load data + var bounds = map.getBounds(); + var bbox = { + xmin: bounds.getSouthWest().lng, + ymin: bounds.getSouthWest().lat, + xmax: bounds.getNorthEast().lng, + ymax: bounds.getNorthEast().lat + }; + + // When a click event occurs near a place, open a popup at the location of + // the feature, with description HTML from its properties. + map.on('click', function (e) { + var features = map.queryRenderedFeatures(e.point, { + layers: [ + 'locations' + ] + }); + + if (!features.length) { + return; + } + + var feature = features[0]; + var popup = new mapboxgl.Popup({ + closeButton: false + }); + + console.log(feature.properties); + + var content = ""; + + if(feature.layer.id === 'locations'){ + content = '' + + '' + + '' + feature.properties.location_name + '' + + ''; + } + + popup.setLngLat(feature.geometry.coordinates) + .setHTML(content) + .addTo(map); + + }); + + // Use the same approach as above to indicate that the symbols are clickable + // by changing the cursor style to 'pointer'. + map.on('mousemove', function (e) { + var features = map.queryRenderedFeatures(e.point, { + layers: [ + 'locations' + ] + }); + map.getCanvas().style.cursor = (features.length) ? 'pointer' : ''; + }); + + + /** + * [description] + * @return {[type]} [description] + */ + map.on('zoom', function() { + var zoom = map.getZoom(); + }); + + /** + * [bounds description] + * @type {[type]} + */ + map.on('dragend', function(){ + var bounds = map.getBounds(); + var bbox = { + xmin: bounds.getSouthWest().lng, + ymin: bounds.getSouthWest().lat, + xmax: bounds.getNorthEast().lng, + ymax: bounds.getNorthEast().lat + }; + }); + + /** + * [bounds description] + * @type {[type]} + */ + map.on('rotateend', function(){ + var bounds = map.getBounds(); + var bbox = { + xmin: bounds.getSouthWest().lng, + ymin: bounds.getSouthWest().lat, + xmax: bounds.getNorthEast().lng, + ymax: bounds.getNorthEast().lat + }; + }); + + /** + * [bounds description] + * @type {[type]} + */ + map.on('zoomend', function(){ + var bounds = map.getBounds(); + var bbox = { + xmin: bounds.getSouthWest().lng, + ymin: bounds.getSouthWest().lat, + xmax: bounds.getNorthEast().lng, + ymax: bounds.getNorthEast().lat + }; + }); + }); + }); diff --git a/public/backend/js/filters/toGeoJSON.js b/public/backend/js/filters/toGeoJSON.js new file mode 100644 index 0000000..5710497 --- /dev/null +++ b/public/backend/js/filters/toGeoJSON.js @@ -0,0 +1,36 @@ +var app = angular.module("ive"); + + +// to GeoJSON filter +app.filter('toGeoJSON', function() { + return function(locations) { + var geojson = { + type: "FeatureCollection", + features: [] + }; + + for(var i=0; i -{{ 'TODO' | translate }} +
+ +
+ + + + diff --git a/public/index.html b/public/index.html index 6b8dd43..1b0a5c2 100644 --- a/public/index.html +++ b/public/index.html @@ -159,7 +159,7 @@

FRONTEND (DARK)

- Special mode for the 3 screens + Special mode for demonstrations