geo-activity-playground 1.0.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geo_activity_playground/alembic/versions/dc8073871da7_add_plotspec_group_by.py +28 -0
- geo_activity_playground/core/config.py +1 -0
- geo_activity_playground/core/datamodel.py +41 -3
- geo_activity_playground/core/parametric_plot.py +101 -47
- geo_activity_playground/webui/app.py +7 -0
- geo_activity_playground/webui/blueprints/activity_blueprint.py +11 -10
- geo_activity_playground/webui/blueprints/auth_blueprint.py +3 -2
- geo_activity_playground/webui/blueprints/bubble_chart_blueprint.py +2 -1
- geo_activity_playground/webui/blueprints/calendar_blueprint.py +3 -2
- geo_activity_playground/webui/blueprints/eddington_blueprints.py +3 -2
- geo_activity_playground/webui/blueprints/entry_views.py +11 -11
- geo_activity_playground/webui/blueprints/equipment_blueprint.py +2 -1
- geo_activity_playground/webui/blueprints/explorer_blueprint.py +47 -13
- geo_activity_playground/webui/blueprints/export_blueprint.py +3 -2
- geo_activity_playground/webui/blueprints/hall_of_fame_blueprint.py +79 -0
- geo_activity_playground/webui/blueprints/photo_blueprint.py +65 -56
- geo_activity_playground/webui/blueprints/plot_builder_blueprint.py +38 -19
- geo_activity_playground/webui/blueprints/settings_blueprint.py +17 -0
- geo_activity_playground/webui/blueprints/summary_blueprint.py +114 -240
- geo_activity_playground/webui/columns.py +40 -7
- geo_activity_playground/webui/static/{browserconfig.xml → favicons/browserconfig.xml} +1 -1
- geo_activity_playground/webui/static/{site.webmanifest → favicons/site.webmanifest} +2 -2
- geo_activity_playground/webui/static/server-side-explorer.js +7 -2
- geo_activity_playground/webui/templates/activity/name.html.j2 +4 -4
- geo_activity_playground/webui/templates/activity/show.html.j2 +8 -8
- geo_activity_playground/webui/templates/eddington/distance.html.j2 +3 -3
- geo_activity_playground/webui/templates/eddington/elevation_gain.html.j2 +3 -3
- geo_activity_playground/webui/templates/elevation_eddington/index.html.j2 +3 -3
- geo_activity_playground/webui/templates/equipment/index.html.j2 +4 -4
- geo_activity_playground/webui/templates/explorer/server-side.html.j2 +5 -4
- geo_activity_playground/webui/templates/hall_of_fame/index.html.j2 +57 -0
- geo_activity_playground/webui/templates/home.html.j2 +2 -12
- geo_activity_playground/webui/templates/page.html.j2 +23 -37
- geo_activity_playground/webui/templates/photo/new.html.j2 +1 -1
- geo_activity_playground/webui/templates/plot-macros.html.j2 +72 -0
- geo_activity_playground/webui/templates/plot_builder/edit.html.j2 +12 -7
- geo_activity_playground/webui/templates/plot_builder/import-spec.html.j2 +24 -0
- geo_activity_playground/webui/templates/plot_builder/index.html.j2 +5 -0
- geo_activity_playground/webui/templates/settings/index.html.j2 +9 -0
- geo_activity_playground/webui/templates/settings/tile-source.html.j2 +33 -0
- geo_activity_playground/webui/templates/summary/index.html.j2 +23 -230
- geo_activity_playground/webui/templates/summary/vega-chart.html.j2 +3 -0
- {geo_activity_playground-1.0.0.dist-info → geo_activity_playground-1.2.0.dist-info}/METADATA +1 -1
- {geo_activity_playground-1.0.0.dist-info → geo_activity_playground-1.2.0.dist-info}/RECORD +73 -66
- /geo_activity_playground/webui/static/{bootstrap-dark-mode.js → bootstrap/bootstrap-dark-mode.js} +0 -0
- /geo_activity_playground/webui/static/{bootstrap.bundle.min.js → bootstrap/bootstrap.bundle.min.js} +0 -0
- /geo_activity_playground/webui/static/{bootstrap.min.css → bootstrap/bootstrap.min.css} +0 -0
- /geo_activity_playground/webui/static/{android-chrome-192x192.png → favicons/android-chrome-192x192.png} +0 -0
- /geo_activity_playground/webui/static/{android-chrome-512x512.png → favicons/android-chrome-512x512.png} +0 -0
- /geo_activity_playground/webui/static/{apple-touch-icon.png → favicons/apple-touch-icon.png} +0 -0
- /geo_activity_playground/webui/static/{favicon-16x16.png → favicons/favicon-16x16.png} +0 -0
- /geo_activity_playground/webui/static/{favicon-32x32.png → favicons/favicon-32x32.png} +0 -0
- /geo_activity_playground/webui/static/{favicon-48x48.png → favicons/favicon-48x48.png} +0 -0
- /geo_activity_playground/webui/static/{favicon.ico → favicons/favicon.ico} +0 -0
- /geo_activity_playground/webui/static/{favicon.svg → favicons/favicon.svg} +0 -0
- /geo_activity_playground/webui/static/{mstile-150x150.png → favicons/mstile-150x150.png} +0 -0
- /geo_activity_playground/webui/static/{web-app-manifest-192x192.png → favicons/web-app-manifest-192x192.png} +0 -0
- /geo_activity_playground/webui/static/{web-app-manifest-512x512.png → favicons/web-app-manifest-512x512.png} +0 -0
- /geo_activity_playground/webui/static/{Leaflet.fullscreen.min.js → leaflet/Leaflet.fullscreen.min.js} +0 -0
- /geo_activity_playground/webui/static/{MarkerCluster.Default.css → leaflet/MarkerCluster.Default.css} +0 -0
- /geo_activity_playground/webui/static/{MarkerCluster.css → leaflet/MarkerCluster.css} +0 -0
- /geo_activity_playground/webui/static/{fullscreen.png → leaflet/fullscreen.png} +0 -0
- /geo_activity_playground/webui/static/{fullscreen@2x.png → leaflet/fullscreen@2x.png} +0 -0
- /geo_activity_playground/webui/static/{leaflet.css → leaflet/leaflet.css} +0 -0
- /geo_activity_playground/webui/static/{leaflet.fullscreen.css → leaflet/leaflet.fullscreen.css} +0 -0
- /geo_activity_playground/webui/static/{leaflet.js → leaflet/leaflet.js} +0 -0
- /geo_activity_playground/webui/static/{leaflet.markercluster.js → leaflet/leaflet.markercluster.js} +0 -0
- /geo_activity_playground/webui/static/{vega-embed@6 → vega/vega-embed@6.js} +0 -0
- /geo_activity_playground/webui/static/{vega-lite@4 → vega/vega-lite@4.js} +0 -0
- /geo_activity_playground/webui/static/{vega@5 → vega/vega@5.js} +0 -0
- {geo_activity_playground-1.0.0.dist-info → geo_activity_playground-1.2.0.dist-info}/LICENSE +0 -0
- {geo_activity_playground-1.0.0.dist-info → geo_activity_playground-1.2.0.dist-info}/WHEEL +0 -0
- {geo_activity_playground-1.0.0.dist-info → geo_activity_playground-1.2.0.dist-info}/entry_points.txt +0 -0
@@ -35,7 +35,7 @@
|
|
35
35
|
<div class="row mb-3">
|
36
36
|
<div class="col">
|
37
37
|
<h2>Monthly Equipment Usage</h2>
|
38
|
-
{{ vega_direct(
|
38
|
+
{{ vega_direct(stacked_area_chart) }}
|
39
39
|
</div>
|
40
40
|
</div>
|
41
41
|
|
@@ -49,13 +49,13 @@
|
|
49
49
|
<h3>{{ equipment }}</h3>
|
50
50
|
<div class="row mb-3">
|
51
51
|
<div class="col-md-4">
|
52
|
-
{{ vega_direct(data.
|
52
|
+
{{ vega_direct(data.total_distances_plot) }}
|
53
53
|
</div>
|
54
54
|
<div class="col-md-4">
|
55
|
-
{{ vega_direct(data.
|
55
|
+
{{ vega_direct(data.yearly_distance_plot) }}
|
56
56
|
</div>
|
57
57
|
<div class="col-md-4">
|
58
|
-
{{ vega_direct(data.
|
58
|
+
{{ vega_direct(data.usages_plot) }}
|
59
59
|
</div>
|
60
60
|
</div>
|
61
61
|
{% endfor %}
|
@@ -25,7 +25,8 @@
|
|
25
25
|
</div>
|
26
26
|
|
27
27
|
<div class="btn-group mb-3" role="group">
|
28
|
-
<button type="button" class="btn btn-primary" onclick="changeColor('
|
28
|
+
<button type="button" class="btn btn-primary" onclick="changeColor('colorful_cluster')">Colorful Cluster</button>
|
29
|
+
<button type="button" class="btn btn-primary" onclick="changeColor('max_cluster')">Max Cluster</button>
|
29
30
|
<button type="button" class="btn btn-primary" onclick="changeColor('first')">First Visit</button>
|
30
31
|
<button type="button" class="btn btn-primary" onclick="changeColor('last')">Last Visit</button>
|
31
32
|
<button type="button" class="btn btn-primary" onclick="changeColor('visits')">Number of Visits</button>
|
@@ -58,17 +59,17 @@
|
|
58
59
|
<div class="row mb-3">
|
59
60
|
<div class="col-md-4">
|
60
61
|
{% if plot_tile_evolution|length > 0 %}
|
61
|
-
{{ vega_direct(
|
62
|
+
{{ vega_direct(plot_tile_evolution) }}
|
62
63
|
{% endif %}
|
63
64
|
</div>
|
64
65
|
<div class="col-md-4">
|
65
66
|
{% if plot_cluster_evolution|length > 0 %}
|
66
|
-
{{ vega_direct(
|
67
|
+
{{ vega_direct(plot_cluster_evolution) }}
|
67
68
|
{% endif %}
|
68
69
|
</div>
|
69
70
|
<div class="col-md-4">
|
70
71
|
{% if plot_square_evolution|length > 0 %}
|
71
|
-
{{ vega_direct(
|
72
|
+
{{ vega_direct(plot_square_evolution) }}
|
72
73
|
{% endif %}
|
73
74
|
</div>
|
74
75
|
</div>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
{% extends "page.html.j2" %}
|
2
|
+
|
3
|
+
{% block container %}
|
4
|
+
|
5
|
+
<h1>Hall of Fame</h1>
|
6
|
+
|
7
|
+
<div class="mb-3">
|
8
|
+
{% include "search_form.html.j2" %}
|
9
|
+
</div>
|
10
|
+
|
11
|
+
<script>
|
12
|
+
function add_map(id, geojson) {
|
13
|
+
let map = L.map(`map-${id}`, {
|
14
|
+
fullscreenControl: true
|
15
|
+
})
|
16
|
+
L.tileLayer('/tile/color/{z}/{x}/{y}.png', {
|
17
|
+
maxZoom: 19,
|
18
|
+
attribution: '{{ map_tile_attribution|safe }}'
|
19
|
+
}).addTo(map)
|
20
|
+
|
21
|
+
let geojson_layer = L.geoJSON(geojson).addTo(map)
|
22
|
+
map.fitBounds(geojson_layer.getBounds())
|
23
|
+
return map
|
24
|
+
}
|
25
|
+
</script>
|
26
|
+
|
27
|
+
{% for activity_batch in nominations|batch(3) %}
|
28
|
+
<div class="row row-cols-1 row-cols-md-3 g-4 mb-3">
|
29
|
+
{% for activity, reasons, line_geojson in activity_batch %}
|
30
|
+
<div class="col">
|
31
|
+
<div class="card">
|
32
|
+
<div class="card-img-top" id="map-{{ activity.id }}" style="height: 200px; width: 100%;"></div>
|
33
|
+
<script>
|
34
|
+
let map{{ activity.id }} = add_map("{{ activity.id }}", {{ line_geojson | safe }})
|
35
|
+
</script>
|
36
|
+
<div class="card-body">
|
37
|
+
<a href="{{ url_for('activity.show', id=activity.id) }}">
|
38
|
+
<h5 class="card-title">{{ activity["name"] }}</h5>
|
39
|
+
</a>
|
40
|
+
<p class="card-text">
|
41
|
+
<ul style='list-style-type: "🏆 "'>
|
42
|
+
{% for reason in reasons %}
|
43
|
+
<li>{{ reason }}</li>
|
44
|
+
{% endfor %}
|
45
|
+
</ul>
|
46
|
+
</p>
|
47
|
+
<p class="card-text"><small class="text-body-secondary"></small>{{ activity.emoji_string }} on {{
|
48
|
+
activity.start|dt }}</small></p>
|
49
|
+
</div>
|
50
|
+
</div>
|
51
|
+
</div>
|
52
|
+
{% endfor %}
|
53
|
+
</div>
|
54
|
+
{% endfor %}
|
55
|
+
|
56
|
+
|
57
|
+
{% endblock %}
|
@@ -8,10 +8,7 @@
|
|
8
8
|
<div class="row mb-3">
|
9
9
|
<div class="col">
|
10
10
|
<h2>Last 30 days</h2>
|
11
|
-
{{
|
12
|
-
{% if elevation_gain_last_30_days_plot %}
|
13
|
-
{{ vega_direct("elevation-gain-last-30-days", elevation_gain_last_30_days_plot) }}
|
14
|
-
{% endif %}
|
11
|
+
{{ tabbed_vega(last_30_days_plot) }}
|
15
12
|
</div>
|
16
13
|
</div>
|
17
14
|
|
@@ -49,14 +46,7 @@
|
|
49
46
|
<h5 class="card-title">{{ elem.activity.name }}</h5>
|
50
47
|
</a>
|
51
48
|
<p class="card-text">
|
52
|
-
{{ elem.activity.
|
53
|
-
📏 {{ (elem.activity.distance_km)|round(1) }} km
|
54
|
-
{% if elem.activity.elapsed_time %}
|
55
|
-
⏱️ {{ elem.activity.elapsed_time|td }}
|
56
|
-
{% endif %}
|
57
|
-
{% if elem.activity.elevation_gain %}
|
58
|
-
⛰️ {{ (elem.activity.elevation_gain)|round|int }} m
|
59
|
-
{% endif %}
|
49
|
+
{{ elem.activity.emoji_string }}
|
60
50
|
</p>
|
61
51
|
{% if elem.activity.start %}
|
62
52
|
<p class="card-text"><small class="text-body-secondary">{{ elem.activity.start|dt }}</small></p>
|
@@ -1,6 +1,8 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
2
|
<html lang="en">
|
3
3
|
|
4
|
+
{% from "plot-macros.html.j2" import vega, vega_direct, activity_tag, tabbed_vega %}
|
5
|
+
|
4
6
|
<head>
|
5
7
|
<meta charset="utf-8">
|
6
8
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
@@ -8,37 +10,37 @@
|
|
8
10
|
<title>Geo Activity Playground</title>
|
9
11
|
|
10
12
|
<!-- Bootstrap CSS. -->
|
11
|
-
<link href="/static/bootstrap.min.css" rel="stylesheet">
|
13
|
+
<link href="/static/bootstrap/bootstrap.min.css" rel="stylesheet">
|
12
14
|
|
13
15
|
<!-- Leaflet for interactive maps. -->
|
14
|
-
<link rel="stylesheet" href="/static/leaflet.css" />
|
15
|
-
<script src="/static/leaflet.js"></script>
|
16
|
+
<link rel="stylesheet" href="/static/leaflet/leaflet.css" />
|
17
|
+
<script src="/static/leaflet/leaflet.js"></script>
|
16
18
|
|
17
19
|
<!-- Fullscreen button for Leaflet. -->
|
18
|
-
<link href='/static/leaflet.fullscreen.css' rel='stylesheet' />
|
19
|
-
<script src='/static/Leaflet.fullscreen.min.js'></script>
|
20
|
+
<link href='/static/leaflet/leaflet.fullscreen.css' rel='stylesheet' />
|
21
|
+
<script src='/static/leaflet/Leaflet.fullscreen.min.js'></script>
|
20
22
|
|
21
|
-
<link rel="stylesheet" href="/static/MarkerCluster.css" />
|
22
|
-
<link rel="stylesheet" href="/static/MarkerCluster.Default.css" />
|
23
|
-
<script src="/static/leaflet.markercluster.js"></script>
|
23
|
+
<link rel="stylesheet" href="/static/leaflet/MarkerCluster.css" />
|
24
|
+
<link rel="stylesheet" href="/static/leaflet/MarkerCluster.Default.css" />
|
25
|
+
<script src="/static/leaflet/leaflet.markercluster.js"></script>
|
24
26
|
|
25
27
|
<!-- Vega for plots.-->
|
26
|
-
<script src="/static/vega@5"></script>
|
27
|
-
<script src="/static/vega-lite@4"></script>
|
28
|
-
<script src="/static/vega-embed@6"></script>
|
28
|
+
<script src="/static/vega/vega@5.js"></script>
|
29
|
+
<script src="/static/vega/vega-lite@4.js"></script>
|
30
|
+
<script src="/static/vega/vega-embed@6.js"></script>
|
29
31
|
|
30
|
-
<script src="/static/bootstrap-dark-mode.js"></script>
|
32
|
+
<script src="/static/bootstrap/bootstrap-dark-mode.js"></script>
|
31
33
|
|
32
34
|
<script src="/static/table-sort.min.js"></script>
|
33
35
|
|
34
36
|
<!-- Favicon. -->
|
35
|
-
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
36
|
-
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
|
37
|
-
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
|
38
|
-
<link rel="manifest" href="/static/site.webmanifest">
|
39
|
-
<link rel="shortcut icon" href="/static/favicon.ico">
|
37
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
|
38
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
|
39
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
|
40
|
+
<link rel="manifest" href="/static/favicons/site.webmanifest">
|
41
|
+
<link rel="shortcut icon" href="/static/favicons/favicon.ico">
|
40
42
|
<meta name="msapplication-TileColor" content="#da532c">
|
41
|
-
<meta name="msapplication-config" content="/static/browserconfig.xml">
|
43
|
+
<meta name="msapplication-config" content="/static/favicons/browserconfig.xml">
|
42
44
|
<meta name="theme-color" content="#ffffff">
|
43
45
|
</head>
|
44
46
|
|
@@ -78,6 +80,8 @@
|
|
78
80
|
<li><a class="dropdown-item" href="{{ url_for('summary.index') }}">Summary
|
79
81
|
Statistics</a>
|
80
82
|
</li>
|
83
|
+
<li><a class="dropdown-item" href="{{ url_for('hall_of_fame.index') }}">Hall of Fame</a>
|
84
|
+
</li>
|
81
85
|
<li><a class="dropdown-item" href="{{ url_for('eddington.distance') }}">Eddington
|
82
86
|
Number</a>
|
83
87
|
</li>
|
@@ -183,24 +187,6 @@
|
|
183
187
|
</div>
|
184
188
|
</nav>
|
185
189
|
|
186
|
-
{% macro vega(id, path) %}
|
187
|
-
<div id="{{ id }}"></div>
|
188
|
-
<script type="text/javascript">
|
189
|
-
vegaEmbed('#{{ id }}', "{{ path }}").then(function (result) { }).catch(console.error);
|
190
|
-
</script>
|
191
|
-
{% endmacro %}
|
192
|
-
|
193
|
-
{% macro vega_direct(id, spec) %}
|
194
|
-
<div id="{{ id }}"></div>
|
195
|
-
<script type="text/javascript">
|
196
|
-
vegaEmbed('#{{ id }}', {{ spec| safe }}).then(function (result) { }).catch(console.error);
|
197
|
-
</script>
|
198
|
-
{% endmacro %}
|
199
|
-
|
200
|
-
{% macro activity_tag(tag) %}
|
201
|
-
<span class="badge" style="background-color: {{ tag.color or '#0d6efd' }}">{{ tag.tag }}</span>
|
202
|
-
{% endmacro %}
|
203
|
-
|
204
190
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
205
191
|
{% if messages %}
|
206
192
|
{% for category, message in messages %}
|
@@ -235,7 +221,7 @@
|
|
235
221
|
</div>
|
236
222
|
</div>
|
237
223
|
|
238
|
-
<script src="/static/bootstrap.bundle.min.js"></script>
|
224
|
+
<script src="/static/bootstrap/bootstrap.bundle.min.js"></script>
|
239
225
|
</body>
|
240
226
|
|
241
227
|
</html>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<form method="POST" enctype="multipart/form-data">
|
7
7
|
<div class="mb-3">
|
8
8
|
<label for="file" class="form-label">Photo file</label>
|
9
|
-
<input type="file" name="file" id="file" class="form-control">
|
9
|
+
<input type="file" name="file" id="file" class="form-control" multiple>
|
10
10
|
</div>
|
11
11
|
<button type="submit" class="btn btn-primary">Upload</button>
|
12
12
|
</form>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
{% macro vega(path) %}
|
2
|
+
{% set id = unique_id() %}
|
3
|
+
<div id="{{ id }}"></div>
|
4
|
+
<script type="text/javascript">
|
5
|
+
vegaEmbed('#{{ id }}', "{{ path }}").then(function (result) { }).catch(console.error);
|
6
|
+
</script>
|
7
|
+
{% endmacro %}
|
8
|
+
|
9
|
+
{% macro vega_direct(spec) %}
|
10
|
+
{% set id = unique_id() %}
|
11
|
+
<div id="{{ id }}"></div>
|
12
|
+
<script type="text/javascript">
|
13
|
+
vegaEmbed('#{{ id }}', {{ spec| safe }}).then(function (result) { }).catch(console.error);
|
14
|
+
</script>
|
15
|
+
{% endmacro %}
|
16
|
+
|
17
|
+
{% macro activity_tag(tag) %}
|
18
|
+
<span class="badge" style="background-color: {{ tag.color or '#0d6efd' }}">{{ tag.tag }}</span>
|
19
|
+
{% endmacro %}
|
20
|
+
|
21
|
+
{% macro tabbed_vega(tab_dict, last=False) %}
|
22
|
+
{% set id = unique_id() %}
|
23
|
+
<ul class="nav nav-pills mb-3" role="tablist">
|
24
|
+
{% for key in tab_dict.keys() %}
|
25
|
+
{% set plot_id = id ~ "-" ~ loop.index %}
|
26
|
+
<li class="nav-item" role="presentation">
|
27
|
+
<button class="nav-link {% if (last and loop.last) or (not last and loop.first) %} active {% endif %}"
|
28
|
+
id="{{ plot_id }}-tab" data-bs-toggle="tab" data-bs-target="#{{ plot_id }}-pane" type="button" role="tab"
|
29
|
+
aria-controls="{{ plot_id }}-pane" aria-selected="{{ loop.last }}">{{ key }}</button>
|
30
|
+
</li>
|
31
|
+
{% endfor %}
|
32
|
+
</ul>
|
33
|
+
<div class="tab-content mb-3">
|
34
|
+
{% for plot in tab_dict.values() %}
|
35
|
+
{% set plot_id = id ~ "-" ~ loop.index %}
|
36
|
+
<div class="tab-pane fade {% if (last and loop.last) or (not last and loop.first) %} show active {% endif %}"
|
37
|
+
id="{{ plot_id }}-pane" role="tabpanel" aria-labelledby="{{ plot_id }}-tab" tabindex="0">
|
38
|
+
{{ vega_direct(plot) }}
|
39
|
+
</div>
|
40
|
+
{% endfor %}
|
41
|
+
</div>
|
42
|
+
{% endmacro %}
|
43
|
+
|
44
|
+
{% macro parametric_plot(spec, plot_groups, outer_loop_index) %}
|
45
|
+
{% if spec.group_by %}
|
46
|
+
<ul class="nav nav-pills mb-3" id="myTab_{{ outer_loop_index }}" role="tablist">
|
47
|
+
{% for key, plot in plot_groups.items() %}
|
48
|
+
{% set plot_id = "custom_plot_" ~ outer_loop_index ~ "_" ~ loop.index %}
|
49
|
+
<li class="nav-item" role="presentation">
|
50
|
+
<button class="nav-link {% if loop.last %} active {% endif %}" id="{{ plot_id }}-tab" data-bs-toggle="tab"
|
51
|
+
data-bs-target="#{{ plot_id }}-pane" type="button" role="tab" aria-controls="{{ plot_id }}-pane"
|
52
|
+
aria-selected="{{ loop.last }}">{{ key }}</button>
|
53
|
+
</li>
|
54
|
+
{% endfor %}
|
55
|
+
</ul>
|
56
|
+
<div class="tab-content mb-3" id="myTabContent_{{ outer_loop_index }}">
|
57
|
+
{% for key, plot in plot_groups.items() %}
|
58
|
+
{% set plot_id = "custom_plot_" ~ outer_loop_index ~ "_" ~ loop.index %}
|
59
|
+
<div class="tab-pane fade {% if loop.last %} show active {% endif %}" id="{{ plot_id }}-pane" role="tabpanel"
|
60
|
+
aria-labelledby="{{ plot_id }}-tab" tabindex="0">
|
61
|
+
{{ vega_direct(plot) }}
|
62
|
+
</div>
|
63
|
+
{% endfor %}
|
64
|
+
</div>
|
65
|
+
{% else %}
|
66
|
+
<div class="row mb-3">
|
67
|
+
<div class="col">
|
68
|
+
{{ vega_direct(plot_groups[""]) }}
|
69
|
+
</div>
|
70
|
+
</div>
|
71
|
+
{% endif %}
|
72
|
+
{% endmacro %}
|
@@ -1,11 +1,17 @@
|
|
1
1
|
{% extends "page.html.j2" %}
|
2
2
|
|
3
|
-
{%
|
3
|
+
{% from "plot-macros.html.j2" import parametric_plot %}
|
4
4
|
|
5
|
-
|
5
|
+
{% block container %}
|
6
6
|
|
7
|
-
<
|
7
|
+
<nav aria-label="breadcrumb">
|
8
|
+
<ol class="breadcrumb">
|
9
|
+
<li class="breadcrumb-item"><a href="{{ url_for('.index') }}">Plot Builder</a></li>
|
10
|
+
<li class="breadcrumb-item active" aria-current="page">Edit</li>
|
11
|
+
</ol>
|
12
|
+
</nav>
|
8
13
|
|
14
|
+
<h1 class="row mb-3">Plot Builder</h1>
|
9
15
|
|
10
16
|
<div class="row mb-3">
|
11
17
|
<div class="col-md-4">
|
@@ -22,12 +28,13 @@
|
|
22
28
|
</div>
|
23
29
|
{% endmacro %}
|
24
30
|
|
25
|
-
<form>
|
31
|
+
<form method="post">
|
26
32
|
<div class="mb-3">
|
27
33
|
<label for="name">Name</label>
|
28
34
|
<input type="text" name="name" id="name" class="form-control" value="{{ spec.name }}">
|
29
35
|
</div>
|
30
36
|
|
37
|
+
{{ select_field("Group by", "group_by", group_by, spec.group_by)}}
|
31
38
|
{{ select_field("Mark", "mark", marks, spec.mark)}}
|
32
39
|
|
33
40
|
{{ select_field("X", "x", continuous, spec.x)}}
|
@@ -45,7 +52,7 @@
|
|
45
52
|
</div>
|
46
53
|
<div class="col-md-8">
|
47
54
|
{% if plot %}
|
48
|
-
{{
|
55
|
+
{{ parametric_plot(spec, plot, 0) }}
|
49
56
|
{% endif %}
|
50
57
|
</div>
|
51
58
|
</div>
|
@@ -58,6 +65,4 @@
|
|
58
65
|
|
59
66
|
<code><pre>{{ spec.to_json() }}</pre></code>
|
60
67
|
|
61
|
-
|
62
|
-
|
63
68
|
{% endblock %}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
{% extends "page.html.j2" %}
|
2
|
+
|
3
|
+
{% block container %}
|
4
|
+
|
5
|
+
<nav aria-label="breadcrumb">
|
6
|
+
<ol class="breadcrumb">
|
7
|
+
<li class="breadcrumb-item"><a href="{{ url_for('.index') }}">Plot Builder</a></li>
|
8
|
+
<li class="breadcrumb-item active" aria-current="page">Import</li>
|
9
|
+
</ol>
|
10
|
+
</nav>
|
11
|
+
|
12
|
+
<h1 class="mb-3">Import Custom Plot</h1>
|
13
|
+
|
14
|
+
<form method="post">
|
15
|
+
<div class="mb-3">
|
16
|
+
<label for="spec_json" class="form-label">Plot specification JSON</label>
|
17
|
+
<textarea class="form-control" id="spec_json" rows="3" name="spec_json"></textarea>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<button type="submit" class="btn btn-primary">Import & Preview</button>
|
21
|
+
</form>
|
22
|
+
|
23
|
+
|
24
|
+
{% endblock %}
|
@@ -2,8 +2,11 @@
|
|
2
2
|
|
3
3
|
{% block container %}
|
4
4
|
|
5
|
+
|
5
6
|
<h1 class="row mb-3">Plot Builder</h1>
|
6
7
|
|
8
|
+
<p>Build custom plots here. For inspiration, check out <a href="https://martin-ueding.github.io/geo-activity-playground/build-custom-plots/" target="_blank">the documentation</a>.</p>
|
9
|
+
|
7
10
|
{% if specs %}
|
8
11
|
<table class="table mb-3">
|
9
12
|
<thead>
|
@@ -29,4 +32,6 @@
|
|
29
32
|
|
30
33
|
<a class="btn btn-primary" href="{{ url_for('.new') }}">New</a>
|
31
34
|
|
35
|
+
<a class="btn btn-primary" href="{{ url_for('.import_spec') }}">Import</a>
|
36
|
+
|
32
37
|
{% endblock %}
|
@@ -56,6 +56,15 @@
|
|
56
56
|
</div>
|
57
57
|
</div>
|
58
58
|
</div>
|
59
|
+
<div class="col">
|
60
|
+
<div class="card">
|
61
|
+
<div class="card-body">
|
62
|
+
<h5 class="card-title">Map tile source</h5>
|
63
|
+
<p class="card-text">Change the source of the map tiles.</p>
|
64
|
+
<a href="{{ url_for('.tile_source') }}" class="btn btn-primary">Change tile source</a>
|
65
|
+
</div>
|
66
|
+
</div>
|
67
|
+
</div>
|
59
68
|
<div class="col">
|
60
69
|
<div class="card">
|
61
70
|
<div class="card-body">
|
@@ -0,0 +1,33 @@
|
|
1
|
+
{% extends "page.html.j2" %}
|
2
|
+
|
3
|
+
{% block container %}
|
4
|
+
|
5
|
+
<h1 class="mb-3">Tile Source</h1>
|
6
|
+
|
7
|
+
<p>You can change the tile source to be whatever you like. Be aware that different sources have different licensing
|
8
|
+
constraints. It is on you to make sure that you are allowed to use the tiles from the source that you enter. See <a
|
9
|
+
href="https://wiki.openstreetmap.org/wiki/Raster_tile_providers" target="_blank">this list of raster tile
|
10
|
+
providers</a> for inspiration.</p>
|
11
|
+
|
12
|
+
|
13
|
+
<form action="" method="POST" class="mb-3">
|
14
|
+
<div class="mb-3">
|
15
|
+
<label for="map_tile_url" class="form-label">Map tile URL</label>
|
16
|
+
<input type="text" class="form-control" id="map_tile_url" name="map_tile_url" value="{{ map_tile_url }}" />
|
17
|
+
</div>
|
18
|
+
<div class="mb-3">
|
19
|
+
<label for="map_tile_attribution" class="form-label">Map tile attribution</label>
|
20
|
+
<input type="text" class="form-control" id="map_tile_attribution" name="map_tile_attribution"
|
21
|
+
value="{{ map_tile_attribution|e }}" />
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<button type="submit" class="btn btn-primary">Save</button>
|
25
|
+
</form>
|
26
|
+
|
27
|
+
<h2>Test image</h2>
|
28
|
+
|
29
|
+
<p>This is a tile using your current tile source:</p>
|
30
|
+
|
31
|
+
<p><img src="{{ test_url }}"></p>
|
32
|
+
|
33
|
+
{% endblock %}
|