Skip to content

Commit 723fedc

Browse files
authored
Merge pull request #440 from mapswipe/dev
Manager Dashboard Docker Volume and Project Creation Bug Fixes
2 parents b1db2bb + 808a5e9 commit 723fedc

29 files changed

+628
-117
lines changed

docker-compose.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ services:
4444
restart: unless-stopped
4545
expose:
4646
- "80"
47+
volumes:
48+
- ./manager_dashboard/manager_dashboard:/usr/share/nginx/html/manager_dashboard
4749
networks:
4850
- manager_dashboard
4951

docs/source/cli.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,46 @@ Options:
102102
--help Show this message and exit.
103103
```
104104

105+
## Archive Projects
106+
107+
```
108+
Usage: mapswipe_workers archive [OPTIONS]
109+
110+
Archive projects in Postgres. Delete groups, tasks and results from
111+
Firebase.
112+
113+
Options:
114+
-i, --project-id TEXT Archive project with giving project id
115+
--project-ids TEXT Archive multiple projects. Provide project id strings
116+
as a list: '["project_a", "project_b"]'
117+
118+
--help Show this message and exit.
119+
120+
```
121+
122+
You can get the project ids for the projects to be archive either from the manager dashboard or query directly in postgres. For example:
123+
124+
```
125+
SELECT project_id
126+
FROM projects
127+
WHERE status = 'finished' AND created < '2020-09-01'
128+
```
129+
130+
## Delete Projects
131+
132+
```
133+
Usage: mapswipe_workers delete [OPTIONS]
134+
135+
Delete tasks, groups, project and results.
136+
137+
Options:
138+
-i, --project-id TEXT Delete project with giving project id
139+
--project-ids TEXT Delete multiple projects. Provide project id strings
140+
as a list: '["project_a", "project_b"]'
141+
142+
--help Show this message and exit.
143+
```
144+
105145

106146
## Create Tutorial from json file (e.g. provided in sample data)
107147

manager_dashboard/Dockerfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
FROM nginx:stable
2-
COPY nginx.conf /etc/nginx/conf.d/
3-
COPY manager_dashboard/ /usr/share/nginx/html/manager_dashboard/
2+
COPY nginx.conf /etc/nginx/conf.d/

mapswipe_workers/mapswipe_workers/definitions.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ def constructor(self):
145145
@property
146146
def tutorial(self):
147147
# Imports are first made once this method get called to avoid circular imports.
148+
from mapswipe_workers.project_types.arbitrary_geometry.tutorial import (
149+
Tutorial as ArbitraryGeometryTutorial,
150+
)
148151
from mapswipe_workers.project_types.tile_map_service_grid.tutorial import (
149152
Tutorial as tmsg_tutorial,
150153
)
@@ -156,7 +159,7 @@ def tutorial(self):
156159

157160
project_type_classes = {
158161
1: tmsg_tutorial,
159-
# 2: ArbitraryGeometriesTutorial,
162+
2: ArbitraryGeometryTutorial,
160163
3: tmsg_tutorial,
161164
4: tmsg_tutorial,
162165
}

mapswipe_workers/mapswipe_workers/firebase_to_postgres/transfer_results.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ def transfer(current_results):
6969
f"{project_id}: Firebase transaction for "
7070
f"transfering results failed to commit"
7171
)
72+
sentry.capture_exception()
7273

7374
del fb_db
7475
return project_id_list

mapswipe_workers/mapswipe_workers/mapswipe_workers.py

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,12 @@ def run_create_projects():
9090
project.save_project()
9191
send_slack_message(MessageType.SUCCESS, project_name, project.projectId)
9292
logger.info("Success: Project Creation ({0})".format(project_name))
93-
except CustomError:
93+
except CustomError as e:
9494
ref = fb_db.reference(f"v2/projectDrafts/{project_draft_id}")
9595
ref.set({})
96-
send_slack_message(MessageType.FAIL, project_name, project.projectId)
96+
send_slack_message(
97+
MessageType.FAIL, project_name, project.projectId, str(e)
98+
)
9799
logger.exception("Failed: Project Creation ({0}))".format(project_name))
98100
sentry.capture_exception()
99101
continue
@@ -118,6 +120,7 @@ def run_firebase_to_postgres() -> list:
118120
help=(
119121
"Project ids for which to generate stats as a list of strings: "
120122
""" '["project_a", "project_b"]' """
123+
"(You need the quotes.)"
121124
),
122125
)
123126
def run_generate_stats(project_ids: list) -> None:
@@ -142,8 +145,16 @@ def run_generate_stats_all_projects() -> None:
142145

143146

144147
@cli.command("user-management")
148+
@click.option("--email", help="The email of the MapSwipe user.", type=str)
145149
@click.option(
146-
"--email", help="The email of the MapSwipe user.", required=True, type=str
150+
"--emails",
151+
cls=PythonLiteralOption,
152+
default="[]",
153+
help=(
154+
"The emails of the MapSwipe users as a list of strings: "
155+
""" '["email_a", "email_b"]' """
156+
"(You need the quotes.)"
157+
),
147158
)
148159
@click.option("--team_id", "-i", help="The id of the team in Firebase.", type=str)
149160
@click.option(
@@ -158,27 +169,33 @@ def run_generate_stats_all_projects() -> None:
158169
["add-manager-rights", "remove-manager-right", "add-team", "remove-team"]
159170
),
160171
)
161-
def run_user_management(email, action, team_id) -> None:
172+
def run_user_management(email, emails, action, team_id) -> None:
162173
"""
163174
Manage project manager credentials
164175
165176
Grant or remove credentials.
166177
"""
167-
try:
168-
if action == "add-manager-rights":
169-
user_management.set_project_manager_rights(email)
170-
elif action == "remove-manager-rights":
171-
user_management.remove_project_manager_rights(email)
172-
elif action == "add-team":
173-
if not team_id:
174-
click.echo("Missing argument: --team_id")
175-
return None
176-
user_management.add_user_to_team(email, team_id)
177-
elif action == "remove-team":
178-
user_management.remove_user_from_team(email)
179-
except Exception:
180-
logger.exception("grant user credentials failed")
181-
sentry.capture_exception()
178+
if email:
179+
email_list = [email]
180+
else:
181+
email_list = emails
182+
183+
for email in email_list:
184+
try:
185+
if action == "add-manager-rights":
186+
user_management.set_project_manager_rights(email)
187+
elif action == "remove-manager-rights":
188+
user_management.remove_project_manager_rights(email)
189+
elif action == "add-team":
190+
if not team_id:
191+
click.echo("Missing argument: --team_id")
192+
return None
193+
user_management.add_user_to_team(email, team_id)
194+
elif action == "remove-team":
195+
user_management.remove_user_from_team(email)
196+
except Exception:
197+
logger.exception("grant user credentials failed")
198+
sentry.capture_exception()
182199

183200

184201
@cli.command("team-management")
@@ -298,7 +315,7 @@ def run_create_tutorials() -> None:
298315
help=(
299316
"Archive multiple projects. "
300317
"Provide project id strings as a list: "
301-
"""["project_a", "project_b"]"""
318+
"""'["project_a", "project_b"]'"""
302319
),
303320
)
304321
def run_archive_project(project_id, project_ids):
@@ -326,7 +343,7 @@ def run_archive_project(project_id, project_ids):
326343
help=(
327344
"Delete multiple projects. "
328345
"Provide project id strings as a list: "
329-
"""["project_a", "project_b"]"""
346+
"""'["project_a", "project_b"]'"""
330347
),
331348
)
332349
def run_delete_project(project_id, project_ids):

mapswipe_workers/mapswipe_workers/project_types/arbitrary_geometry/group.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ def __init__(self, project: object, groupId: int) -> None:
99
super().__init__(project, groupId)
1010

1111
def create_tasks(
12-
self, feature_ids: List, feature_geometries: List, center_points: List
12+
self,
13+
feature_ids: List,
14+
feature_geometries: List,
15+
center_points: List,
16+
reference: List,
17+
screen: List,
1318
) -> None:
1419
"""Create tasks for a group
1520
@@ -19,6 +24,13 @@ def create_tasks(
1924
Every coordinate pair is a vertex.
2025
"""
2126
for i in range(0, len(feature_ids)):
22-
task = Task(self, feature_ids[i], feature_geometries[i], center_points[i])
27+
task = Task(
28+
self,
29+
feature_ids[i],
30+
feature_geometries[i],
31+
center_points[i],
32+
reference[i],
33+
screen[i],
34+
)
2335
self.tasks.append(task)
2436
self.numberOfTasks = len(self.tasks)

mapswipe_workers/mapswipe_workers/project_types/arbitrary_geometry/grouping_functions.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,34 @@ def group_input_geometries(input_geometries_file, group_size):
6666
"feature_ids": [],
6767
"feature_geometries": [],
6868
"center_points": [],
69+
"reference": [],
70+
"screen": [],
6971
}
7072

7173
groups[group_id_string]["feature_ids"].append(feature.GetFID())
7274
groups[group_id_string]["feature_geometries"].append(
7375
json.loads(feature.GetGeometryRef().ExportToJson())
7476
)
75-
try:
76-
center_x = feature.GetFieldAsDouble("center_x")
77-
center_y = feature.GetFieldAsDouble("center_y")
77+
78+
# from gdal documentation GetFieldAsDouble():
79+
# OFTInteger fields will be cast to double.
80+
# Other field types, or errors will result in a return value of zero.
81+
center_x = feature.GetFieldAsDouble("center_x")
82+
center_y = feature.GetFieldAsDouble("center_y")
83+
84+
# check if center attribute has been provided in geojson
85+
# normal tasks will never have a center of 0.0, 0.0
86+
# this is just in the middle of the ocean
87+
if (center_x == 0.0) and (center_y == 0.0):
88+
groups[group_id_string]["center_points"].append(None)
89+
else:
7890
groups[group_id_string]["center_points"].append([center_x, center_y])
79-
except: # noqa
80-
groups[group_id_string]["center_points"].append([])
91+
92+
# this is relevant for the tutorial
93+
reference = feature.GetFieldAsDouble("reference")
94+
screen = feature.GetFieldAsDouble("screen")
95+
groups[group_id_string]["reference"].append(reference)
96+
groups[group_id_string]["screen"].append(screen)
8197

8298
return groups
8399

mapswipe_workers/mapswipe_workers/project_types/arbitrary_geometry/project.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ def create_groups(self):
145145
for group_id, item in raw_groups.items():
146146
group = Group(self, group_id)
147147
group.create_tasks(
148-
item["feature_ids"], item["feature_geometries"], item["center_points"]
148+
item["feature_ids"],
149+
item["feature_geometries"],
150+
item["center_points"],
151+
item["reference"],
152+
item["screen"],
149153
)
150154

151155
# only append valid groups

mapswipe_workers/mapswipe_workers/project_types/arbitrary_geometry/task.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Dict, List
1+
from typing import Dict, List, Optional, Union
22

33
from osgeo import ogr
44

@@ -7,7 +7,13 @@
77

88
class Task(BaseTask):
99
def __init__(
10-
self, group: object, featureId: int, featureGeometry: Dict, center: List
10+
self,
11+
group: object,
12+
featureId: Union[int, str],
13+
featureGeometry: Dict,
14+
center: Optional[List[float]],
15+
reference: Optional[int],
16+
screen: Optional[int],
1117
):
1218
"""
1319
Parameters
@@ -21,13 +27,23 @@ def __init__(
2127
task_id = f"t{featureId}"
2228
super().__init__(group, taskId=task_id)
2329
self.geojson = featureGeometry
24-
self.center = center
30+
31+
# only tasks that use Google tile map service need this
32+
if center:
33+
self.center = center
34+
35+
# only tasks that are part of a tutorial need this
36+
if screen:
37+
self.screen = screen
38+
self.reference = reference
2539

2640
# Remove projectId and groupId for tasks of Footprint project type
2741
del self.projectId
2842
del self.groupId
2943

3044
# create wkt geometry from geojson
45+
# this geometry will be stored in postgres
46+
# it will be remove before storing the data in firebase
3147
poly = ogr.CreateGeometryFromJson(str(featureGeometry))
3248
wkt_geometry = poly.ExportToWkt()
3349
self.geometry = wkt_geometry

0 commit comments

Comments
 (0)