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

add optional model for map layers #3

Open
wants to merge 29 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
96e8669
add optional model for map layers
finnus May 24, 2023
96d26df
add unit and name to choropleths
finnus May 30, 2023
43f8d9e
read legend name and unit from map_store
Josephine-Marie May 30, 2023
26ddf2e
change layer order to show clusters on top of other layers
finnus Jun 1, 2023
56b7cdf
exclude blank choropleth_field
finnus Jun 1, 2023
ad42c41
add optional model for map layers
finnus May 24, 2023
37046ab
add unit and name to choropleths
finnus May 30, 2023
5809def
change layer order to show clusters on top of other layers
finnus Jun 1, 2023
d6dd963
exclude blank choropleth_field
finnus Jun 1, 2023
b0edbe2
Chart options are read from popup data and not modified in JS
henhuy Jun 12, 2023
cda3dfd
Update version to v0.10.0
henhuy Jun 12, 2023
72080ba
Fix no choropleths set
henhuy Jun 12, 2023
c6903c3
Minor change
henhuy Jun 12, 2023
1a50429
Minor change
henhuy Jun 15, 2023
67a7726
Chart creation in popup is handled by project app (not mapengine)
henhuy Jun 15, 2023
af88549
Add .gitignore
henhuy Jun 15, 2023
8b9f272
Merge remote-tracking branch 'origin/optional_map_layer_model' into o…
finnus Jun 22, 2023
a7fa820
change keyword to adapt to new legend
finnus Jun 22, 2023
5863644
hand correct title to legend
finnus Jun 22, 2023
622ec02
SHow cluster layer on top of all layers
henhuy Jun 27, 2023
0cc4cb6
Add cluster properties
henhuy Jul 5, 2023
06c0d2e
Fix choropleth legend unit brackets
henhuy Jul 13, 2023
e286998
Update version to v0.13.1
henhuy Jul 13, 2023
14204e2
Fix map_store initialization
henhuy Aug 23, 2023
d97f475
add optional model for map layers
finnus May 24, 2023
2b25537
add unit and name to choropleths
finnus May 30, 2023
3c18c50
exclude blank choropleth_field
finnus Jun 1, 2023
d2cc9a1
change keyword to adapt to new legend
finnus Jun 22, 2023
c384ff9
Merge remote-tracking branch 'origin/optional_map_layer_model' into o…
finnus Aug 25, 2023
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea/*
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@ and the versioning aim to respect [Semantic Versioning](http://semver.org/spec/v

Here is a template for new release sections

## [0.13.2] - 2023-08-23
### Fixed
- map store initialization

## [0.13.1] - 2023-07-13
### Fixed
- choropleth legend unit brackets

## [0.13.0] - 2023-07-05
### Added
- cluster properties to forward model attributes to map engine

## [0.12.0] - 2023-06-27
### Changed
- layer ordering; cluster layers are shown on top of other layers

## [0.11.0] - 2023-06-15
### Changed
- chart creation function must be declared by project app

### Fixed
- chart errors in popups

## [0.10.0] - 2023-06-12
### Changed
- chart options are taken from backend; no frontend modifications

### Fixed
- no choropleths set in settings

## [0.9.0] - 2023-06-09
### Added
- title and unit for choropleths in legend
Expand Down
2 changes: 1 addition & 1 deletion django_mapengine/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Map Engine init, holds version"""

__version__ = "0.9.0"
__version__ = "0.13.2"
3 changes: 3 additions & 0 deletions django_mapengine/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class MapEngineConf(AppConf):
# IMAGES
IMAGES: List[Dict[str, str]] = []

# CHOROPLETHS
CHOROPLETHS = []

# POPUPS
POPUPS: List[str] = []

Expand Down
4 changes: 2 additions & 2 deletions django_mapengine/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ def get_all_layers() -> List[MapLayer]:
"""
# Order is important! Last items are shown on top!
layers = list(get_region_layers())
for cluster_layer in get_cluster_layers():
layers.extend(cluster_layer.get_map_layers())
for static_layer in get_static_layers():
layers.extend(static_layer.get_map_layers())
for cluster_layer in get_cluster_layers():
layers.extend(cluster_layer.get_map_layers())
return layers
4 changes: 3 additions & 1 deletion django_mapengine/setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Setup module is used in settings of django projects to set up mapengine"""

from collections import namedtuple
from dataclasses import dataclass
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, List, Optional

from django.apps import apps
Expand Down Expand Up @@ -42,8 +42,10 @@ def model(self) -> "Model":


# pylint:disable=R0903
@dataclass
class ClusterAPI(ModelAPI):
"""Exists only to distinguish between "normal" and clustered API"""
properties: list = field(default_factory=lambda: [])


@dataclass
Expand Down
2 changes: 1 addition & 1 deletion django_mapengine/static/django_mapengine/js/choropleth.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ function initDefaultChoropleths() {
}
}

function deactivateChoropleth(choroplethName) {
function deactivateChoropleth() {
for (const choropleth in map_store.cold.choropleths) {
for (const layerID of map_store.cold.choropleths[choropleth].layers) {
setPaintProperties(layerID, map_store.cold.storedChoroplethPaintProperties["default"][layerID]);
Expand Down
4 changes: 2 additions & 2 deletions django_mapengine/static/django_mapengine/js/init.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

const map_store = initStore();
const map_store = initMapStore();
const map = initMap();


Expand All @@ -26,7 +26,7 @@ function initMap() {
}


function initStore() {
function initMapStore() {
const storeColdInit = JSON.parse(document.getElementById("mapengine_store_cold_init").textContent);
storeColdInit.state = {};
storeColdInit.storedChoroplethPaintProperties = {"default": {}};
Expand Down
2 changes: 1 addition & 1 deletion django_mapengine/static/django_mapengine/js/legend.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const createLegend = (title, unit, colors, valueRanges, nextColumnStartIndex = 3
<div class="legend__heading">
<span class="legend__title">Legend -&nbsp;</span>
<span class="legend__detail">${title}</span>
<div class="legend__unit">(${unit})</div>
<div class="legend__unit">${unit ? `(${unit})` : ""}</div>
</div>
<div class="legend__wrap">
<div class="legend__column">
Expand Down
90 changes: 7 additions & 83 deletions django_mapengine/static/django_mapengine/js/popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,91 +61,15 @@ function add_popup(layerID) {
const {html} = data;
popup.innerHTML = html;

if ("chart" in data) {
// Chart Title
const {chart: {title}} = data;
new maplibregl.Popup({
// https://maplibre.org/maplibre-gl-js-docs/api/markers/#popup-parameters
maxWidth: "280px",
}).setLngLat(coordinates).setHTML(popup.innerHTML).addTo(map);

// Chart
const chartElement = popup.querySelector("#js-popup__chart");
const chart = echarts.init(chartElement, null, {renderer: 'svg'});
// TODO: use lookup property in payload to construct chart dynamically. For now we assume bar chart type.
// TODO: In this fetch we always expect one payload item. Make failsafe.
const {chart: {series}} = data;
const xAxisData = createListByName("key", series[0].data);
const yAxisData = createListByName("value", series[0].data);
const option = {
title: {
text: title,
textStyle: {
color: '#002E50',
fontSize: 14,
fontWeight: 400,
lineHeight: 16
},
left: 'center'
},
animation: false,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}
},
grid: {
left: 16,
right: 0,
bottom: 32,
top: 48,
containLabel: true
},
textStyle: {
color: '#002E50'
},
xAxis: [{
type: 'category',
data: xAxisData,
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: '#ECF2F6'
}
},
}],
yAxis: [{
type: 'value',
splitLine: {
show: true,
lineStyle: {
color: '#ECF2F6'
}
}
}],
series: [{
name: 'Direct',
type: 'line',
symbol: 'circle',
symbolSize: 6,
data: yAxisData,
lineStyle: {
color: '#002E50'
},
itemStyle: {
color: '#002E50'
}
}]
};
chart.setOption(option);
if ("chart" in data) {
// createChart function must be defined in project app (not in mapengine)
createChart("js-popup__chart", data.chart);
}

requestAnimationFrame(() => {
new maplibregl.Popup({
// https://maplibre.org/maplibre-gl-js-docs/api/markers/#popup-parameters
maxWidth: "280px",
}).setLngLat(coordinates).setHTML(popup.innerHTML).addTo(map);
});
}
});
});
Expand Down
2 changes: 1 addition & 1 deletion django_mapengine/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
urlpatterns += [
path(
f"clusters/{cluster.layer_id}.geojson",
GeoJSONLayerView.as_view(model=cluster.model),
GeoJSONLayerView.as_view(model=cluster.model, properties=cluster.properties),
name=f"{cluster.layer_id}_cluster",
)
for cluster in settings.MAP_ENGINE_API_CLUSTERS
Expand Down
50 changes: 49 additions & 1 deletion django_mapengine/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
"""Views and mixins in order to use mapengine"""

from django.apps import apps
from django.conf import settings
from django.http import JsonResponse
from django.views.generic.base import ContextMixin

from django.core.exceptions import FieldDoesNotExist
from . import __version__, layers, sources


Expand Down Expand Up @@ -65,6 +66,53 @@ def get_context_data(self, **kwargs) -> dict:
"choropleths": {choropleth.name: choropleth.as_dict() for choropleth in settings.MAP_ENGINE_CHOROPLETHS},
}

if settings.MAP_ENGINE_MAPLAYER_MODEL:
# get MapLayerModel from settings
try:
MapLayerModel = apps.get_model(app_label='map', model_name=settings.MAP_ENGINE_MAPLAYER_MODEL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the MapLayerModel would be integrated in mapengine's models.py ?
This would make model available in all projects which use mapengine automatically.
Also this would remove need for app.get_model and currently hardcoded "map" namespace.

except ImportError:
raise LookupError("The MapLayerModel does not exist.")

# get choropleth fields
try:
model_field = MapLayerModel._meta.get_field("choropleth_field")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would also be obsolete, as we make sure field exists by providing model from within mapengine

except FieldDoesNotExist:
raise LookupError("Your MapLayerModel has no field named 'choropleth_field', which is mandatory.")
choropleths = MapLayerModel.objects.exclude(choropleth_field="").filter(choropleth_field__isnull=False).values_list(
"identifier", "geom_layer", "choropleth_unit", "name")
store["choropleths"] = {
item[0]: {
'layers': [item[1]],
'useFeatureState': True,
'unit': [item[2]],
'title': [item[3]]
}
for item in choropleths
}

# get popups
try:
model_field = MapLayerModel._meta.get_field("popup_fields")
except FieldDoesNotExist:
raise LookupError("Your MapLayerModel has no field named 'popup_fields', which is mandatory.")

popups = MapLayerModel.objects.filter(popup_fields__isnull=False).values_list("identifier", "geom_layer")
transformed_popups = {}
for item in popups:
layer_id = item[1]
choropleth = item[0]

if layer_id not in transformed_popups:
transformed_popups[layer_id] = {
'layerID': layer_id,
'atDefaultLayer': False,
'choropleths': []
}

transformed_popups[layer_id]['choropleths'].append(choropleth)

store["popups"] = transformed_popups

context["mapengine_store_cold_init"] = store

return context
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: django_oemof
name: django_mapengine
dependencies:
- python=3.9
Loading