Skip to content

Commit 712b676

Browse files
authored
Merge pull request #515 from mapswipe/dev
Prepare new production release 2.3.1
2 parents 16b0254 + 1452df8 commit 712b676

33 files changed

+1293
-571
lines changed

.github/workflows/actions.yml

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ jobs:
5959
POSTGRES_PASSWORD: test
6060
POSTGRES_USER: test
6161
POSTGRES_DB: test
62+
OSMCHA_API_KEY: ${{ secrets.OSMCHA_API_KEY }}
6263
run: |
6364
docker-compose run mapswipe_workers_creation python -m unittest discover --verbose --start-directory tests/unittests/
6465
docker-compose run mapswipe_workers_creation python -m unittest discover --verbose --start-directory tests/integration/

api/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<h1>Welcome to Mapswipe API</h1>
99
<a href="https://mapswipe-workers.readthedocs.io/en/benni.new-project-types/api.html">Read the Documentation</a>
1010

11-
<h2>Directory Tree</h1>
11+
<h2>Directory Tree</h2>
1212
<a href="./stats.json">stats.json</a><br>
1313
<a href="./projects.json">projects.json</a><br>
1414
<a href="./users.json">users.json</a><br>

docker-compose.development.yaml

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
version: '3'
2+
networks:
3+
mapswipe_network:
4+
driver: bridge
5+
ipam:
6+
config: [{subnet: 172.21.0.0/16}]
7+
api:
8+
manager_dashboard:
9+
mapswipe_workers:
10+
postgres:
11+
12+
services:
13+
manager_dashboard:
14+
container_name: manager_dashboard
15+
build:
16+
context: manager_dashboard/
17+
restart: unless-stopped
18+
ports:
19+
- '5000:80'
20+
expose:
21+
- "80"
22+
volumes:
23+
- ./manager_dashboard/manager_dashboard:/usr/share/nginx/html/manager_dashboard
24+
networks:
25+
- manager_dashboard
26+
27+
postgres:
28+
container_name: postgres
29+
build:
30+
context: postgres/
31+
dockerfile: Dockerfile-dev
32+
environment:
33+
POSTGRES_PASSWORD: '${POSTGRES_PASSWORD}'
34+
POSTGRES_USER: '${POSTGRES_USER}'
35+
POSTGRES_DB: '${POSTGRES_DB}'
36+
PGDATA: '/var/lib/postgresql/mapswipe'
37+
command: postgres
38+
volumes:
39+
- ./postgres-data:/var/lib/postgresql/mapswipe
40+
restart: unless-stopped
41+
ports:
42+
- "5431:5432"
43+
networks:
44+
- postgres

docker-compose.yaml

+4-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ services:
7373
SLACK_TOKEN: '${SLACK_TOKEN}'
7474
SLACK_CHANNEL: '${SLACK_CHANNEL}'
7575
SENTRY_DSN: '${SENTRY_DSN}'
76+
OSMCHA_API_KEY: '${OSMCHA_API_KEY}'
7677
depends_on:
7778
- postgres
7879
command: mapswipe_workers --verbose run --analysis_type=creation --schedule --time_interval=5
@@ -107,6 +108,7 @@ services:
107108
SLACK_TOKEN: '${SLACK_TOKEN}'
108109
SLACK_CHANNEL: '${SLACK_CHANNEL}'
109110
SENTRY_DSN: '${SENTRY_DSN}'
111+
OSMCHA_API_KEY: '${OSMCHA_API_KEY}'
110112
depends_on:
111113
- postgres
112114
command: mapswipe_workers --verbose run --analysis_type=generate-stats --schedule --time_interval=60
@@ -141,6 +143,7 @@ services:
141143
SLACK_TOKEN: '${SLACK_TOKEN}'
142144
SLACK_CHANNEL: '${SLACK_CHANNEL}'
143145
SENTRY_DSN: '${SENTRY_DSN}'
146+
OSMCHA_API_KEY: '${OSMCHA_API_KEY}'
144147
depends_on:
145148
- postgres
146149
command: mapswipe_workers --verbose run --analysis_type=firebase-to-postgres --schedule --time_interval=2
@@ -197,4 +200,4 @@ services:
197200
FIREBASE_DB: '${FIREBASE_DB}'
198201
command: sh -c "firebase use $FIREBASE_DB && firebase deploy --token $FIREBASE_TOKEN --only functions,database:rules"
199202
volumes:
200-
- ./firebase:/firebase
203+
- ./firebase:/firebase

example.env

+3
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,6 @@ SLACK_CHANNEL=
2828

2929
# sentry configuration
3030
SENTRY_DSN=
31+
32+
# osmcha configuration
33+
OSMCHA_API_KEY=

manager_dashboard/manager_dashboard/create.html

+330-287
Large diffs are not rendered by default.

manager_dashboard/manager_dashboard/css/mapswipe.css

+27-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
padding: 2px 5px 2px 5px;
6565
color: #B9B9B9;
6666
font-size: 20px;
67-
overflow: hidden;
6867
font-family: Arial, Helvetica, sans-serif;
6968
}
7069
.form-style-7 input[type="text"],
@@ -105,7 +104,7 @@
105104
.form-style-7 select:focus
106105
{
107106
}
108-
.form-style-7 li > span{
107+
.form-style-7 li > span, .ownspan{
109108
background: #F3F3F3;
110109
display: block;
111110
padding: 3px;
@@ -133,7 +132,7 @@
133132
color:#fff;
134133
}
135134

136-
#geometryMap { height: 300px; width: 100%}
135+
#geometryMap { height: 300px; width: 100%; z-index: 0;}
137136
#geometryChangeDetectionMap { height: 300px; width: 100%}
138137
#geometryCompletenessMap { height: 300px; width: 100%}
139138

@@ -200,4 +199,29 @@ th.sorting_desc::after{
200199
color: black;
201200
text-decoration: none;
202201
cursor: pointer;
202+
}
203+
204+
.button {
205+
padding: 3px;
206+
border-radius: 3px;
207+
background-color: #6B9FFF;
208+
border-bottom: 3px solid #5994FF;
209+
color: white;
210+
width: fit-content;
211+
margin-bottom: 0px;
212+
}
213+
214+
.button:hover {
215+
background-color: #5994FF;
216+
cursor: pointer;
217+
}
218+
219+
.button:active {
220+
color: #b3cdff;
221+
}
222+
223+
.flex-inline-div{
224+
display: inline-flex;
225+
align-items: center;
226+
width:100%;"
203227
}

manager_dashboard/manager_dashboard/js/forms.js

+68-26
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ function displayProjectTypeForm(projectType) {
117117
}
118118
}
119119

120+
120121
function addTileServerCredits (tileServerName, which) {
121122
var credits = {
122123
"bing": "© 2019 Microsoft Corporation, Earthstar Geographics SIO",
@@ -159,45 +160,51 @@ function displayTileServer (tileServerName, which) {
159160
addTileServerCredits(tileServerName, which)
160161
}
161162

163+
162164
function clear_fields() {
163165
console.log('clear fields.')
164166
document.getElementById('projectNumber').value = 1
165167
document.getElementById('inputAoi').value = null
166-
document.getElementById('geometryInfo').innerHTML = ''
168+
$(".inputInfo").each(()=>{$(this).text('')})
167169
document.getElementById('geometryContent').innerHTML = ''
168170
aoiLayer.clearLayers()
169171
displayProjectTypeForm("build_area")
170172
}
171173

174+
172175
function displaySuccessMessage() {
173176
//document.getElementById("import-formular").style.display = "None";
174177
alert('Your project has been uploaded. It can take up to one hour for the project to appear in the dashboard.')
175178
}
176179

180+
177181
function displayImportForm() {
178182
document.getElementById("import-formular").style.display = "block";
179183
}
180184

185+
181186
function openFile(event) {
182187
var input = event.target;
188+
let maxFilesize = 1 * 1024 * 1024
189+
let maxFeatures = 10
183190

184191
// clear info field
185-
var info_output = document.getElementById("geometryInfo");
186-
info_output.innerHTML = '';
187-
info_output.style.display = 'block'
192+
var infoOutput = $(input).siblings(".inputInfo")[0];
193+
infoOutput.innerHTML = '';
194+
infoOutput.style.display = 'block'
188195

189196
// clear map layers
190197
aoiLayer.clearLayers()
191198

192199
// Check file size before loading
193200
var filesize = input.files[0].size;
194-
if (filesize > 1 * 1024 * 1024) {
195-
var err='filesize is too big (max 1MB): ' + filesize/(1000*1000)
196-
info_output.innerHTML = '<b>Error reading GeoJSON file</b><br>' + err;
197-
info_output.style.display = 'block'
201+
if (filesize > maxFilesize) {
202+
var err=`filesize is too big (max ${maxFilesize}MB): ${filesize/(1024*1024)}`
203+
infoOutput.innerHTML = '<b>Error reading GeoJSON file</b><br>' + err;
204+
infoOutput.style.display = 'block'
198205
} else {
199-
info_output.innerHTML += 'File Size is valid <br>';
200-
info_output.style.display = 'block'
206+
infoOutput.innerHTML += 'File Size is valid <br>';
207+
infoOutput.style.display = 'block'
201208

202209
var reader = new FileReader();
203210
reader.onload = function(){
@@ -209,11 +216,11 @@ function openFile(event) {
209216
numberOfFeatures = geojsonData['features'].length
210217

211218
console.log('number of features: ' + numberOfFeatures)
212-
if (numberOfFeatures > 10) {
219+
if (numberOfFeatures > maxFeatures) {
213220
throw 'too many features: ' + numberOfFeatures
214221
}
215-
info_output.innerHTML += 'Number of Features: ' + numberOfFeatures + '<br>';
216-
info_output.style.display = 'block'
222+
infoOutput.innerHTML += 'Number of Features: ' + numberOfFeatures + '<br>';
223+
infoOutput.style.display = 'block'
217224

218225
sumArea = 0
219226
// check input geometry type
@@ -225,9 +232,8 @@ function openFile(event) {
225232
if (type !== 'Polygon' & type !== 'MultiPolygon') {
226233
throw 'GeoJson contains one or more wrong geometry type(s): ' + type
227234
}
228-
229-
info_output.innerHTML += 'Feature Type: ' + type + '<br>';
230-
info_output.style.display = 'block'
235+
infoOutput.innerHTML += 'Feature Type: ' + type + '<br>';
236+
infoOutput.style.display = 'block'
231237
sumArea += turf.area(feature)/1000000 // area in square kilometers
232238
}
233239

@@ -243,53 +249,89 @@ function openFile(event) {
243249
throw 'project is to large: ' + sumArea + ' sqkm; ' + 'max allowed size for this zoom level: ' + maxArea + ' sqkm'
244250
}
245251

246-
info_output.innerHTML += 'Project Size: ' + sumArea + ' sqkm<br>';
247-
info_output.style.display = 'block'
252+
infoOutput.innerHTML += 'Project Size: ' + sumArea + ' sqkm<br>';
253+
infoOutput.style.display = 'block'
248254

249255
// add feature to map
250256
aoiLayer.addData(geojsonData);
251257
ProjectAoiMap.fitBounds(aoiLayer.getBounds());
252258
console.log('added input geojson feature')
253259

254260
// add text to html object
255-
info_output.innerHTML += 'Project seems to be valid :)';
256-
info_output.style.display = 'block'
261+
infoOutput.innerHTML += 'Project seems to be valid :)';
262+
infoOutput.style.display = 'block'
257263

258264
// set project aoi geometry
259265
projectAoiGeometry = text
260266
}
261267
catch(err) {
262-
info_output.innerHTML = '<b>Error reading GeoJSON file</b><br>' + err;
263-
info_output.style.display = 'block'
268+
infoOutput.innerHTML = '<b>Error reading GeoJSON file</b><br>' + err;
269+
infoOutput.style.display = 'block'
264270
}
265271
};
266272
reader.readAsText(input.files[0]);
267273
}
268274
};
269275

276+
270277
function openImageFile(event) {
271278
var input = event.target;
272-
element_id = event.target.id + 'File'
279+
elementId = event.target.id + 'File'
273280

274281
var reader = new FileReader();
275282
reader.onload = function(){
276283
try {
277284
var dataURL = reader.result;
278-
var output = document.getElementById(element_id);
285+
var output = document.getElementById(elementId);
279286
output.src = dataURL;
280287
}
281288
catch(err) {
282-
element_id = event.target.id + 'Text'
283-
var output = document.getElementById(element_id);
289+
elementId = event.target.id + 'Text'
290+
var output = document.getElementById(elementId);
284291
output.innerHTML = '<b>Error reading Image file</b><br>' + err;
285292
}
286293
};
287294
reader.readAsDataURL(input.files[0]);
288295
};
289296

297+
290298
function closeModal() {
291299
var modal = document.getElementById("uploadModal");
292300
modal.style.display = "none";
293301
var modalSuccess = document.getElementById("modalSuccess");
294302
modalSuccess.style.display = "none";
295303
}
304+
305+
306+
function toggleFilterText(select){
307+
$("#inputFilterDiv").toggle();
308+
}
309+
310+
311+
function showInput(select){
312+
let linkDiv = $("#inputTaskGeometries_Link");
313+
let aoi_fileDiv = $("#inputTaskGeometries_File");
314+
let idDiv = $("#inputTaskGeometries_TMId");
315+
let filterDiv = $("#inputFilterLi");
316+
317+
switch(select.value){
318+
case "link":
319+
linkDiv.css("display", "block");
320+
aoi_fileDiv.css("display", "none");
321+
idDiv.css("display", "none");
322+
filterDiv.css("display", "none");
323+
break;
324+
case "aoi_file":
325+
linkDiv.css("display", "none");
326+
aoi_fileDiv.css("display", "block");
327+
idDiv.css("display", "none");
328+
filterDiv.css("display", "block");
329+
break;
330+
case "id":
331+
linkDiv.css("display", "none");
332+
aoi_fileDiv.css("display", "none");
333+
idDiv.css("display", "block");
334+
filterDiv.css("display", "block");
335+
break;
336+
}
337+
}

manager_dashboard/manager_dashboard/js/upload-tutorial.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,14 @@ function getFormInput() {
5252
};
5353
break;
5454
}
55-
5655
form_data.screens = JSON.parse(screens)
5756
form_data.tutorialTasks = JSON.parse(tutorialTasks)
5857

5958
return form_data
6059
}
6160

62-
function upload_project_image(id) {
6361

62+
function uploadProjectImage(id) {
6463
var file = document.getElementById(id).files[0]
6564
console.log(file)
6665
var filename = file.name
@@ -98,11 +97,10 @@ function upload_project_image(id) {
9897
}
9998
});
10099
});
101-
102-
103100
}
104101

105-
function upload_to_firebase() {
102+
103+
function uploadToFirebase() {
106104
switch (currentUid) {
107105
case null:
108106
alert("You are not logged in.");
@@ -119,9 +117,8 @@ function upload_to_firebase() {
119117
// TODO: add checks if all input values are valid, e.g. image available
120118
mapswipe_import = getFormInput()
121119

122-
upload_project_image("image1")
123-
upload_project_image("image2")
124-
120+
uploadProjectImage("image1")
121+
uploadProjectImage("image2")
125122

126123
// TODO: this should be implemented better...
127124
setTimeout(function() {

0 commit comments

Comments
 (0)