Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactors map card component #4992

Merged
merged 3 commits into from
Jul 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions arches/app/media/css/arches.css
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,10 @@ ul.tabbed-report-tab-list {
margin-top: -30px;
}

.mouse-pointer canvas {
cursor: pointer;
}

.map-card-wrapper {
flex: 1;
height: 100%;
Expand Down Expand Up @@ -1390,14 +1394,19 @@ ul.tabbed-report-tab-list {
.map-card-feature-list .table {
margin-bottom: 0;
}

.map-card-feature-tool {
font-size: 0.9em;
width: 65px;
}
.map-card-feature-tool a {
.map-card-zoom-tool, .map-card-feature-tool {
font-size: 0.9em;
}
.map-card-zoom-tool a, .map-card-feature-tool a {
color: #2f527a;
}
.map-card-zoom-tool {
float: right;
padding: 10px;
}

#map-settings {
position: relative;
Expand Down
158 changes: 83 additions & 75 deletions arches/app/media/js/views/components/cards/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,103 +3,113 @@ define([
'knockout',
'knockout-mapping',
'uuid',
'mapbox-gl',
'mapbox-gl-draw',
'geojson-extent',
'viewmodels/card-component',
'views/components/map',
'bindings/chosen'
], function(_, ko, koMapping, uuid, MapboxDraw, CardComponentViewModel, MapComponentViewModel) {
], function(_, ko, koMapping, uuid, mapboxgl, MapboxDraw, geojsonExtent, CardComponentViewModel, MapComponentViewModel) {
return ko.components.register('map-card', {
viewModel: function(params) {
var self = this;
var widgets = [];
var padding = 40;
var drawFeatures;
var newNodeId;
this.featureLookup = {};
this.selectedFeatureIds = ko.observableArray();
this.draw = null;

CardComponentViewModel.apply(this, [params]);
MapComponentViewModel.apply(this, [params]);

this.activeTab('editor');
this.featureLookup = {};
var getDrawFeatures = function() {
var drawFeatures = [];
self.card.widgets().forEach(function(widget) {
var nodeId = widget.node_id();
if (self.form && self.form.nodeLookup[nodeId].datatype() === 'geojson-feature-collection' && self.tile) {
var featureCollection = koMapping.toJS(self.tile.data[nodeId]);
if (featureCollection) {
featureCollection.features.forEach(function(feature) {
if (!feature.id) {
feature.id = uuid.generate();
}
feature.properties.nodeId = nodeId;
});
drawFeatures = drawFeatures.concat(featureCollection.features);
}
}
});
return drawFeatures;
};
var drawFeatures = getDrawFeatures();
var newNodeId;
this.card.widgets().forEach(function(widget) {
var nodeId = widget.node_id();
if (self.form && self.form.nodeLookup[nodeId].datatype() === 'geojson-feature-collection') {
self.featureLookup[nodeId] = {
if (self.form && self.tile) self.card.widgets().forEach(function(widget) {
var id = widget.node_id();
var type = self.form.nodeLookup[id].datatype();
if (type === 'geojson-feature-collection') {
widgets.push(widget);
self.featureLookup[id] = {
features: ko.computed(function() {
var features = [];
if (self.tile) {
var featureCollection = koMapping.toJS(self.tile.data[nodeId]);
if (featureCollection) {
features = featureCollection.features;
}
}
return features;
var value = koMapping.toJS(self.tile.data[id]);
if (value) return value.features;
else return [];
}),
selectedTool: ko.observable()
};
self.featureLookup[nodeId].selectedTool.subscribe(function(selectedTool) {
self.featureLookup[id].selectedTool.subscribe(function(tool) {
if (self.draw) {
if (selectedTool === '') {
if (tool === '') {
self.draw.changeMode('simple_select');
} else if (selectedTool) {
} else if (tool) {
_.each(self.featureLookup, function(value, key) {
if (key !== nodeId) {
if (key !== id) {
value.selectedTool(null);
}
});
newNodeId = nodeId;
self.draw.changeMode(selectedTool);
newNodeId = id;
self.draw.changeMode(tool);
}
}
});
}
});

var updateFeatures = function() {
var updateTiles = function() {
var featureCollection = self.draw.getAll();
_.each(self.featureLookup, function(value) {
value.selectedTool(null);
});
self.card.widgets().forEach(function(widget) {
var nodeId = widget.node_id();
if (self.form && self.form.nodeLookup[nodeId].datatype() === 'geojson-feature-collection') {
var nodeFeatures = [];
featureCollection.features.forEach(function(feature){
if (feature.properties.nodeId === nodeId) nodeFeatures.push(feature);
widgets.forEach(function(widget) {
var id = widget.node_id();
var features = [];
featureCollection.features.forEach(function(feature){
if (feature.properties.nodeId === id) features.push(feature);
});
if (ko.isObservable(self.tile.data[id])) {
self.tile.data[id]({
type: 'FeatureCollection',
features: features
});
if (ko.isObservable(self.tile.data[nodeId])) {
self.tile.data[nodeId]({
type: 'FeatureCollection',
features: nodeFeatures
});
} else {
self.tile.data[nodeId].features(nodeFeatures);
}
} else {
self.tile.data[id].features(features);
}
});
};

var getDrawFeatures = function() {
var drawFeatures = [];
widgets.forEach(function(widget) {
var id = widget.node_id();
var featureCollection = koMapping.toJS(self.tile.data[id]);
if (featureCollection) {
featureCollection.features.forEach(function(feature) {
if (!feature.id) {
feature.id = uuid.generate();
}
feature.properties.nodeId = id;
});
drawFeatures = drawFeatures.concat(featureCollection.features);
}
});
return drawFeatures;
};
drawFeatures = getDrawFeatures();

if (drawFeatures.length > 0) {
params.bounds = geojsonExtent({
type: 'FeatureCollection',
features: drawFeatures
});
params.fitBoundsOptions = { padding: padding };
}
params.activeTab = 'editor';

MapComponentViewModel.apply(this, [params]);

this.deleteFeature = function(feature) {
if (self.draw) {
self.draw.delete(feature.id);
updateFeatures();
updateTiles();
}
};

Expand All @@ -122,8 +132,16 @@ define([
map.setStyle(style);
};

this.selectedFeatureIds = ko.observableArray();
this.draw = null;
this.fitFeatures = function(features) {
var map = self.map();
var bounds = geojsonExtent({
type: 'FeatureCollection',
features: features
});
var camera = map.cameraForBounds(bounds, { padding: padding });
map.jumpTo(camera);
};

this.map.subscribe(function(map) {
self.draw = new MapboxDraw({
displayControlsDefault: false
Expand All @@ -137,11 +155,11 @@ define([
e.features.forEach(function(feature) {
self.draw.setFeatureProperty(feature.id, 'nodeId', newNodeId);
});
updateFeatures();
updateTiles();
});
map.on('draw.update', updateFeatures);
map.on('draw.delete', updateFeatures);
map.on('draw.modechange', updateFeatures);
map.on('draw.update', updateTiles);
map.on('draw.delete', updateTiles);
map.on('draw.modechange', updateTiles);
map.on('draw.selectionchange', function(e) {
self.selectedFeatureIds(e.features.map(function(feature) {
return feature.id;
Expand All @@ -157,16 +175,6 @@ define([
if (value.selectedTool()) value.selectedTool('');
});
});

setTimeout(function() {
map.resize();
if (drawFeatures.length > 0) {
self.zoomToGeoJSON({
type: 'FeatureCollection',
features: drawFeatures
});
}
}, 1);
});
},
template: {
Expand Down
75 changes: 33 additions & 42 deletions arches/app/media/js/views/components/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@ define([
'knockout',
'mapbox-gl',
'mapbox-gl-geocoder',
'geojson-extent',
'text!templates/views/components/map-popup.htm',
'bindings/mapbox-gl',
'bindings/sortable'
], function($, _, arches, ko, mapboxgl, MapboxGeocoder, geojsonExtent, popupTemplate) {
], function($, _, arches, ko, mapboxgl, MapboxGeocoder, popupTemplate) {
var viewModel = function(params) {
var self = this;
var geojsonSourceFactory = function() {
Expand Down Expand Up @@ -39,21 +38,14 @@ define([
this.basemaps = [];
this.overlays = ko.observableArray();
this.activeBasemap = ko.observable();
this.activeTab = ko.observable();
this.activeTab = ko.observable(params.activeTab);
this.hideSidePanel = function() {
self.activeTab(undefined);
};
this.activeTab.subscribe(function() {
var map = self.map();
if (map) setTimeout(function() { map.resize(); }, 1);
});
this.zoomToGeoJSON = function(data, fly) {
var method = fly ? 'flyTo' : 'jumpTo';
var map = self.map();
var bounds = new mapboxgl.LngLatBounds(geojsonExtent(data));
var options = map.cameraForBounds(bounds, {padding: 40});
map[method](options);
};

mapLayers.forEach(function(layer) {
if (!layer.isoverlay) {
Expand Down Expand Up @@ -157,7 +149,8 @@ define([
center: [x, y],
zoom: zoom
},
bounds: bounds
bounds: bounds,
fitBoundsOptions: params.fitBoundsOptions
};

this.toggleTab = function(tabName) {
Expand All @@ -180,35 +173,27 @@ define([
};

var resourceLookup = {};
var lookupResourceData = function(feature) {
var resourceData = feature.properties;
var resourceId = resourceData.resourceinstanceid;
if (resourceLookup[resourceId]) {
return resourceLookup[resourceId];
}
resourceData = _.defaults(resourceData, {
'loading': true,
'displaydescription': '',
'map_popup': '',
'displayname': '',
'graphid': '',
'graph_name': '',
'geometries': []
});
resourceData = ko.mapping.fromJS(resourceData);
resourceData.reportURL = arches.urls.resource_report;
resourceData.editURL = arches.urls.resource_editor;

resourceLookup[resourceId] = resourceData;
$.get(arches.urls.resource_descriptors + resourceId, function(data) {
data.loading = false;
ko.mapping.fromJS(data, resourceLookup[resourceId]);
});
return resourceLookup[resourceId];
};

this.getPopupData = function(feature) {
return lookupResourceData(feature);
var data = feature.properties;
var id = data.resourceinstanceid;
if (id) {
if (resourceLookup[id]) return resourceLookup[id];
data = _.defaults(data, {
'loading': true,
'displayname': '',
'graph_name': ''
});
data = ko.mapping.fromJS(data);
data.reportURL = arches.urls.resource_report;
data.editURL = arches.urls.resource_editor;

resourceLookup[id] = data;
$.get(arches.urls.resource_descriptors + id, function(data) {
data.loading = false;
ko.mapping.fromJS(data, resourceLookup[id]);
});
return resourceLookup[id];
}
};

this.setupMap = function(map) {
Expand All @@ -221,7 +206,7 @@ define([
accessToken: mapboxgl.accessToken,
mapboxgl: mapboxgl,
placeholder: arches.geocoderPlaceHolder,
bbox: bounds
bbox: arches.hexBinBounds
}), 'top-right');

layers.subscribe(self.updateLayers);
Expand All @@ -239,18 +224,24 @@ define([

map.on('click', function(e) {
if (hoverFeature) {
var p = new mapboxgl.Popup()
var selectedFeature = hoverFeature;
var popup = new mapboxgl.Popup()
.setLngLat(e.lngLat)
.setHTML(self.popupTemplate)
.addTo(map);
ko.applyBindingsToDescendants(
self.getPopupData(hoverFeature),
p._content
popup._content
);
map.setFeatureState(selectedFeature, { selected: true });
popup.on('close', function() {
map.setFeatureState(selectedFeature, { selected: false });
});
}
});

self.map(map);
setTimeout(function() { map.resize(); }, 1);
});
};
};
Expand Down
Loading