goodmap 0.3.1__tar.gz → 0.4.1__tar.gz
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.
- {goodmap-0.3.1 → goodmap-0.4.1}/PKG-INFO +16 -1
- {goodmap-0.3.1 → goodmap-0.4.1}/README.md +13 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/core.py +3 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/core_api.py +49 -13
- goodmap-0.4.1/goodmap/data_models/location.py +37 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/data_validator.py +1 -1
- goodmap-0.4.1/goodmap/db.py +116 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/formatter.py +5 -3
- goodmap-0.4.1/goodmap/goodmap.py +52 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/templates/map.html +16 -2
- {goodmap-0.3.1 → goodmap-0.4.1}/pyproject.toml +3 -1
- goodmap-0.3.1/goodmap/data_models/location.py +0 -15
- goodmap-0.3.1/goodmap/db.py +0 -23
- goodmap-0.3.1/goodmap/goodmap.py +0 -30
- {goodmap-0.3.1 → goodmap-0.4.1}/LICENSE.md +0 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/__init__.py +0 -0
- {goodmap-0.3.1 → goodmap-0.4.1}/goodmap/templates/admin.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: goodmap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Map engine to serve all the people :)
|
|
5
5
|
Author: Krzysztof Kolodzinski
|
|
6
6
|
Author-email: krzysztof.kolodzinski@problematy.pl
|
|
@@ -9,12 +9,14 @@ Classifier: Programming Language :: Python :: 3
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.10
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.11
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
12
13
|
Requires-Dist: Babel (>=2.10.3,<3.0.0)
|
|
13
14
|
Requires-Dist: Flask (==3.0.3)
|
|
14
15
|
Requires-Dist: Flask-Babel (>=4.0.0,<5.0.0)
|
|
15
16
|
Requires-Dist: Flask-WTF (>=1.2.1,<2.0.0)
|
|
16
17
|
Requires-Dist: PyYAML (>=6.0,<7.0)
|
|
17
18
|
Requires-Dist: aiohttp (>=3.8.4,<4.0.0)
|
|
19
|
+
Requires-Dist: deprecation (>=2.1.0,<3.0.0)
|
|
18
20
|
Requires-Dist: flask-restx (>=1.3.0,<2.0.0)
|
|
19
21
|
Requires-Dist: google-cloud-storage (>=2.7.0,<3.0.0)
|
|
20
22
|
Requires-Dist: gql (>=3.4.0,<4.0.0)
|
|
@@ -33,6 +35,19 @@ Map engine to serve all the people ;)
|
|
|
33
35
|
|
|
34
36
|
## Setup
|
|
35
37
|
|
|
38
|
+
#### 0. Clone the repo
|
|
39
|
+
```
|
|
40
|
+
git clone --recursive
|
|
41
|
+
```
|
|
42
|
+
Remember, everytime you want to pull the newest changes, run:
|
|
43
|
+
```
|
|
44
|
+
git pull
|
|
45
|
+
git submodule update
|
|
46
|
+
```
|
|
47
|
+
because `goodmap` contains a submodule.
|
|
48
|
+
|
|
49
|
+
#TODO remove all submodule connected instructions after removing platzky submodule (see #157)
|
|
50
|
+
|
|
36
51
|
#### 1. Use python 3.10
|
|
37
52
|
If you have a different version of Python on your system, install python 3.10 alongside. For that, you can use [`pyenv`](https://github.com/pyenv/pyenv). Follow the [documentation](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation). Useful commands: `pyenv help <command>`, `pyenv install`, `pyenv shell`, `pyenv versions`.
|
|
38
53
|
|
|
@@ -7,6 +7,19 @@ Map engine to serve all the people ;)
|
|
|
7
7
|
|
|
8
8
|
## Setup
|
|
9
9
|
|
|
10
|
+
#### 0. Clone the repo
|
|
11
|
+
```
|
|
12
|
+
git clone --recursive
|
|
13
|
+
```
|
|
14
|
+
Remember, everytime you want to pull the newest changes, run:
|
|
15
|
+
```
|
|
16
|
+
git pull
|
|
17
|
+
git submodule update
|
|
18
|
+
```
|
|
19
|
+
because `goodmap` contains a submodule.
|
|
20
|
+
|
|
21
|
+
#TODO remove all submodule connected instructions after removing platzky submodule (see #157)
|
|
22
|
+
|
|
10
23
|
#### 1. Use python 3.10
|
|
11
24
|
If you have a different version of Python on your system, install python 3.10 alongside. For that, you can use [`pyenv`](https://github.com/pyenv/pyenv). Follow the [documentation](https://github.com/pyenv/pyenv?tab=readme-ov-file#installation). Useful commands: `pyenv help <command>`, `pyenv install`, `pyenv shell`, `pyenv versions`.
|
|
12
25
|
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import importlib.metadata
|
|
2
|
+
import uuid
|
|
2
3
|
|
|
4
|
+
import deprecation
|
|
3
5
|
from flask import Blueprint, jsonify, make_response, request
|
|
4
6
|
from flask_babel import gettext
|
|
5
7
|
from flask_restx import Api, Resource, fields
|
|
6
8
|
from platzky.config import LanguagesMapping
|
|
7
9
|
|
|
8
|
-
from goodmap.
|
|
9
|
-
|
|
10
|
-
from .core import get_queried_data
|
|
11
|
-
from .formatter import prepare_pin
|
|
10
|
+
from goodmap.core import get_queried_data
|
|
11
|
+
from goodmap.formatter import prepare_pin
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
def make_tuple_translation(keys_to_translate):
|
|
@@ -16,7 +16,7 @@ def make_tuple_translation(keys_to_translate):
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def core_pages(
|
|
19
|
-
database, languages: LanguagesMapping, notifier_function, csrf_generator
|
|
19
|
+
database, languages: LanguagesMapping, notifier_function, csrf_generator, location_model
|
|
20
20
|
) -> Blueprint:
|
|
21
21
|
core_api_blueprint = Blueprint("api", __name__, url_prefix="/api")
|
|
22
22
|
core_api = Api(core_api_blueprint, doc="/doc", version="0.1")
|
|
@@ -29,26 +29,28 @@ def core_pages(
|
|
|
29
29
|
},
|
|
30
30
|
)
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
# TODO get this from Location pydantic model
|
|
33
|
+
suggested_location_model = core_api.model(
|
|
33
34
|
"LocationSuggestion",
|
|
34
35
|
{
|
|
35
|
-
"name": fields.String(required=
|
|
36
|
-
"
|
|
36
|
+
"name": fields.String(required=False, description="Organization name"),
|
|
37
|
+
"position": fields.String(required=True, description="Location of the suggestion"),
|
|
37
38
|
"photo": fields.String(required=False, description="Photo of the location"),
|
|
38
39
|
},
|
|
39
40
|
)
|
|
40
41
|
|
|
41
42
|
@core_api.route("/suggest-new-point")
|
|
42
43
|
class NewLocation(Resource):
|
|
43
|
-
@core_api.expect(
|
|
44
|
+
@core_api.expect(suggested_location_model)
|
|
44
45
|
def post(self):
|
|
45
46
|
"""Suggest new location"""
|
|
46
47
|
try:
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
suggested_location = request.get_json()
|
|
49
|
+
suggested_location.update({"UUID": str(uuid.uuid4())})
|
|
50
|
+
location = location_model.model_validate(suggested_location)
|
|
49
51
|
message = (
|
|
50
|
-
f"A new location has been suggested: '{location.
|
|
51
|
-
f"at position: {location.
|
|
52
|
+
f"A new location has been suggested under UUID: '{location.UUID}' "
|
|
53
|
+
f"at position: {location.position}"
|
|
52
54
|
)
|
|
53
55
|
notifier_function(message)
|
|
54
56
|
except ValueError as e:
|
|
@@ -75,6 +77,12 @@ def core_pages(
|
|
|
75
77
|
|
|
76
78
|
@core_api.route("/data")
|
|
77
79
|
class Data(Resource):
|
|
80
|
+
@deprecation.deprecated(
|
|
81
|
+
deprecated_in="0.4.1",
|
|
82
|
+
removed_in="0.5.0",
|
|
83
|
+
current_version=importlib.metadata.version("goodmap"),
|
|
84
|
+
details="Use /locations or /location/<point_id> instead",
|
|
85
|
+
)
|
|
78
86
|
def get(self):
|
|
79
87
|
"""
|
|
80
88
|
Shows all data filtered by query parameters
|
|
@@ -90,6 +98,34 @@ def core_pages(
|
|
|
90
98
|
formatted_data = [prepare_pin(x, visible_data, meta_data) for x in queried_data]
|
|
91
99
|
return jsonify(formatted_data)
|
|
92
100
|
|
|
101
|
+
@core_api.route("/locations")
|
|
102
|
+
class GetLocations(Resource):
|
|
103
|
+
def get(self):
|
|
104
|
+
"""
|
|
105
|
+
Shows list of locations with UUID and position
|
|
106
|
+
"""
|
|
107
|
+
query_params = request.args.to_dict(flat=False)
|
|
108
|
+
all_locations = database.get_locations(query_params)
|
|
109
|
+
return jsonify([x.basic_info() for x in all_locations])
|
|
110
|
+
|
|
111
|
+
@core_api.route("/location/<location_id>")
|
|
112
|
+
class GetLocation(Resource):
|
|
113
|
+
def get(self, location_id):
|
|
114
|
+
"""
|
|
115
|
+
Shows a single location with all data
|
|
116
|
+
"""
|
|
117
|
+
location = database.get_location(location_id)
|
|
118
|
+
|
|
119
|
+
# TODO getting visible_data and meta_data should be taken from db methods
|
|
120
|
+
# e.g. db.get_visible_data() and db.get_meta_data()
|
|
121
|
+
# visible_data and meta_data should be models
|
|
122
|
+
all_data = database.get_data()
|
|
123
|
+
visible_data = all_data["visible_data"]
|
|
124
|
+
meta_data = all_data["meta_data"]
|
|
125
|
+
|
|
126
|
+
formatted_data = prepare_pin(location.model_dump(), visible_data, meta_data)
|
|
127
|
+
return jsonify(formatted_data)
|
|
128
|
+
|
|
93
129
|
@core_api.route("/version")
|
|
94
130
|
class Version(Resource):
|
|
95
131
|
def get(self):
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from typing import Any, Type
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field, create_model, field_validator
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class LocationBase(BaseModel, extra="allow"):
|
|
7
|
+
position: tuple[float, float]
|
|
8
|
+
UUID: str
|
|
9
|
+
|
|
10
|
+
@field_validator("position")
|
|
11
|
+
@classmethod
|
|
12
|
+
def position_must_be_valid(cls, v):
|
|
13
|
+
if v[0] < -90 or v[0] > 90:
|
|
14
|
+
raise ValueError("latitude must be in range -90 to 90")
|
|
15
|
+
if v[1] < -180 or v[1] > 180:
|
|
16
|
+
raise ValueError("longitude must be in range -180 to 180")
|
|
17
|
+
return v
|
|
18
|
+
|
|
19
|
+
def basic_info(self):
|
|
20
|
+
return {"UUID": self.UUID, "position": self.position}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def create_location_model(obligatory_fields: list[tuple[str, Type[Any]]]) -> Type[BaseModel]:
|
|
24
|
+
fields = {
|
|
25
|
+
field_name: (field_type, Field(...)) for (field_name, field_type) in obligatory_fields
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return create_model(
|
|
29
|
+
"Location",
|
|
30
|
+
__config__=None,
|
|
31
|
+
__doc__=None,
|
|
32
|
+
__module__="Location",
|
|
33
|
+
__validators__=None,
|
|
34
|
+
__base__=LocationBase,
|
|
35
|
+
__cls_kwargs__=None,
|
|
36
|
+
**fields,
|
|
37
|
+
)
|
|
@@ -76,7 +76,7 @@ def report_data_violations_from_json(json_database):
|
|
|
76
76
|
map_data = json_database["map"]
|
|
77
77
|
datapoints = map_data["data"]
|
|
78
78
|
categories = map_data["categories"]
|
|
79
|
-
obligatory_fields = map_data["
|
|
79
|
+
obligatory_fields = map_data["location_obligatory_fields"]
|
|
80
80
|
|
|
81
81
|
data_violations = []
|
|
82
82
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from functools import partial
|
|
3
|
+
|
|
4
|
+
from goodmap.core import get_queried_data
|
|
5
|
+
|
|
6
|
+
# TODO file is temporary solution to be compatible with old, static code,
|
|
7
|
+
# it should be replaced with dynamic solution
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ------------------------------------------------
|
|
11
|
+
# get_location_obligatory_fields
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def json_db_get_location_obligatory_fields(db):
|
|
15
|
+
return db.data["location_obligatory_fields"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def json_file_db_get_location_obligatory_fields(db):
|
|
19
|
+
with open(db.data_file_path, "r") as file:
|
|
20
|
+
return json.load(file)["map"]["location_obligatory_fields"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def google_json_db_get_location_obligatory_fields(db):
|
|
24
|
+
return json.loads(db.blob.download_as_text(client=None))["map"]["location_obligatory_fields"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_location_obligatory_fields(db):
|
|
28
|
+
return globals()[f"{db.module_name}_get_location_obligatory_fields"](db)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# ------------------------------------------------
|
|
32
|
+
# get_data
|
|
33
|
+
def google_json_db_get_data(self):
|
|
34
|
+
return json.loads(self.blob.download_as_text(client=None))["map"]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def json_file_db_get_data(self):
|
|
38
|
+
with open(self.data_file_path, "r") as file:
|
|
39
|
+
return json.load(file)["map"]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def json_db_get_data(self):
|
|
43
|
+
return self.data
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_data(db):
|
|
47
|
+
return globals()[f"{db.module_name}_get_data"]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# ------------------------------------------------
|
|
51
|
+
# get_location
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_location_from_raw_data(raw_data, UUID, location_model):
|
|
55
|
+
point = next((point for point in raw_data["data"] if point["UUID"] == UUID), None)
|
|
56
|
+
return location_model.model_validate(point) if point else None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def google_json_db_get_location(self, UUID, location_model):
|
|
60
|
+
return get_location_from_raw_data(
|
|
61
|
+
json.loads(self.blob.download_as_text(client=None))["map"], UUID, location_model
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def json_file_db_get_location(self, UUID, location_model):
|
|
66
|
+
with open(self.data_file_path, "r") as file:
|
|
67
|
+
point = get_location_from_raw_data(json.load(file)["map"], UUID, location_model)
|
|
68
|
+
return point
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def json_db_get_location(self, UUID, location_model):
|
|
72
|
+
return get_location_from_raw_data(self.data, UUID, location_model)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_location(db, location_model):
|
|
76
|
+
return partial(globals()[f"{db.module_name}_get_location"], location_model=location_model)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# ------------------------------------------------
|
|
80
|
+
# get_locations
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def get_locations_list_from_raw_data(map_data, query, location_model):
|
|
84
|
+
filtered_locations = get_queried_data(map_data["data"], map_data["categories"], query)
|
|
85
|
+
return [location_model.model_validate(point) for point in filtered_locations]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def google_json_db_get_locations(self, query, location_model):
|
|
89
|
+
return get_locations_list_from_raw_data(
|
|
90
|
+
json.loads(self.blob.download_as_text(client=None))["map"], query, location_model
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def json_file_db_get_locations(self, query, location_model):
|
|
95
|
+
with open(self.data_file_path, "r") as file:
|
|
96
|
+
return get_locations_list_from_raw_data(json.load(file)["map"], query, location_model)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def json_db_get_locations(self, query, location_model):
|
|
100
|
+
return get_locations_list_from_raw_data(self.data, query, location_model)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_locations(db, location_model):
|
|
104
|
+
return partial(globals()[f"{db.module_name}_get_locations"], location_model=location_model)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# TODO extension function should be replaced with simple extend which would take a db plugin
|
|
108
|
+
# it could look like that:
|
|
109
|
+
# `db.extend(goodmap_db_plugin)` in plugin all those functions would be organized
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def extend_db_with_goodmap_queries(db, location_model):
|
|
113
|
+
db.extend("get_data", get_data(db))
|
|
114
|
+
db.extend("get_locations", get_locations(db, location_model))
|
|
115
|
+
db.extend("get_location", get_location(db, location_model))
|
|
116
|
+
return db
|
|
@@ -18,8 +18,10 @@ def prepare_pin(place, visible_fields, meta_data):
|
|
|
18
18
|
"metadata": {
|
|
19
19
|
gettext(field): safe_gettext(place[field]) for field in meta_data if field in place
|
|
20
20
|
},
|
|
21
|
-
"data":
|
|
22
|
-
gettext(field)
|
|
23
|
-
|
|
21
|
+
"data": [
|
|
22
|
+
[gettext(field), safe_gettext(place[field])]
|
|
23
|
+
for field in visible_fields
|
|
24
|
+
if field in place
|
|
25
|
+
],
|
|
24
26
|
}
|
|
25
27
|
return pin_data
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
from flask import Blueprint, render_template
|
|
4
|
+
from flask_wtf.csrf import CSRFProtect, generate_csrf
|
|
5
|
+
from platzky import platzky
|
|
6
|
+
from platzky.config import Config, languages_dict
|
|
7
|
+
|
|
8
|
+
from goodmap.core_api import core_pages
|
|
9
|
+
from goodmap.data_models.location import create_location_model
|
|
10
|
+
from goodmap.db import extend_db_with_goodmap_queries, get_location_obligatory_fields
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def create_app(config_path: str) -> platzky.Engine:
|
|
14
|
+
config = Config.parse_yaml(config_path)
|
|
15
|
+
return create_app_from_config(config)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# TODO Checking if there is a feature flag secition should be part of configs logic not client app
|
|
19
|
+
def is_feature_enabled(config: Config, feature: str) -> bool:
|
|
20
|
+
return config.feature_flags.get(feature, False) if config.feature_flags else False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def create_app_from_config(config: Config) -> platzky.Engine:
|
|
24
|
+
directory = os.path.dirname(os.path.realpath(__file__))
|
|
25
|
+
|
|
26
|
+
locale_dir = os.path.join(directory, "locale")
|
|
27
|
+
config.translation_directories.append(locale_dir)
|
|
28
|
+
app = platzky.create_app_from_config(config)
|
|
29
|
+
|
|
30
|
+
if is_feature_enabled(config, "USE_LAZY_LOADING"):
|
|
31
|
+
location_obligatory_fields = get_location_obligatory_fields(app.db)
|
|
32
|
+
else:
|
|
33
|
+
location_obligatory_fields = []
|
|
34
|
+
|
|
35
|
+
location_model = create_location_model(location_obligatory_fields)
|
|
36
|
+
|
|
37
|
+
app.db = extend_db_with_goodmap_queries(app.db, location_model)
|
|
38
|
+
|
|
39
|
+
CSRFProtect(app)
|
|
40
|
+
|
|
41
|
+
cp = core_pages(
|
|
42
|
+
app.db, languages_dict(config.languages), app.notify, generate_csrf, location_model
|
|
43
|
+
)
|
|
44
|
+
app.register_blueprint(cp)
|
|
45
|
+
goodmap = Blueprint("goodmap", __name__, url_prefix="/", template_folder="templates")
|
|
46
|
+
|
|
47
|
+
@goodmap.route("/")
|
|
48
|
+
def index():
|
|
49
|
+
return render_template("map.html", feature_flags=config.feature_flags)
|
|
50
|
+
|
|
51
|
+
app.register_blueprint(goodmap)
|
|
52
|
+
return app
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
{% extends "base.html" %}
|
|
2
2
|
|
|
3
|
+
{% block head_meta %}
|
|
4
|
+
|
|
5
|
+
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
|
|
6
|
+
integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
|
|
7
|
+
crossorigin=""/>
|
|
8
|
+
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css" />
|
|
9
|
+
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css" />
|
|
10
|
+
|
|
11
|
+
{% endblock %}
|
|
12
|
+
|
|
13
|
+
|
|
3
14
|
{% block left_panel %}
|
|
4
15
|
<div id="filter-form"></div>
|
|
5
16
|
{% endblock %}
|
|
@@ -24,12 +35,11 @@
|
|
|
24
35
|
</style>
|
|
25
36
|
|
|
26
37
|
<div id="loadingPopup" class="loading-popup">
|
|
27
|
-
|
|
38
|
+
{{ gettext('Loading') }}...
|
|
28
39
|
</div>
|
|
29
40
|
|
|
30
41
|
<div id="map" class="map h-100 w-100"></div>
|
|
31
42
|
|
|
32
|
-
|
|
33
43
|
<script type="text/javascript">
|
|
34
44
|
|
|
35
45
|
(function() {
|
|
@@ -102,6 +112,10 @@ function hideLoading() {
|
|
|
102
112
|
window.APP_LANG = "{{ current_language }}";
|
|
103
113
|
window.SECONDARY_COLOR = "{{ secondary_color }}";
|
|
104
114
|
window.PRIMARY_COLOR = "{{ primary_color }}";
|
|
115
|
+
|
|
116
|
+
window.SHOW_SUGGEST_NEW_POINT_BUTTON = {{ feature_flags.SHOW_SUGGEST_NEW_POINT_BUTTON | default(false) | tojson }};
|
|
117
|
+
window.SHOW_SEARCH_BAR = {{ feature_flags.SHOW_SEARCH_BAR | default(false) | tojson }};
|
|
118
|
+
window.USE_LAZY_LOADING = {{ feature_flags.USE_LAZY_LOADING | default(false) | tojson }};
|
|
105
119
|
</script>
|
|
106
120
|
<script src="/static/map.js"></script>
|
|
107
121
|
{% endblock %}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "goodmap"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.4.1"
|
|
4
4
|
description = "Map engine to serve all the people :)"
|
|
5
5
|
authors = ["Krzysztof Kolodzinski <krzysztof.kolodzinski@problematy.pl>"]
|
|
6
6
|
readme = "README.md"
|
|
7
|
+
exclude = ["goodmap/locale/*/LC_MESSAGES/*.po"]
|
|
7
8
|
|
|
8
9
|
[tool.poetry.dependencies]
|
|
9
10
|
python = "^3.10"
|
|
@@ -20,6 +21,7 @@ gql = "^3.4.0"
|
|
|
20
21
|
aiohttp = "^3.8.4"
|
|
21
22
|
pydantic = "^2.7.1"
|
|
22
23
|
platzky = "^0.2.5"
|
|
24
|
+
deprecation = "^2.1.0"
|
|
23
25
|
|
|
24
26
|
[tool.poetry.group.dev.dependencies]
|
|
25
27
|
pytest = "^7.1.2"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
from pydantic import BaseModel, field_validator
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Location(BaseModel):
|
|
5
|
-
name: str
|
|
6
|
-
coordinates: tuple[float, float]
|
|
7
|
-
|
|
8
|
-
@field_validator("coordinates")
|
|
9
|
-
@classmethod
|
|
10
|
-
def coordinates_must_be_valid(cls, v):
|
|
11
|
-
if v[0] < -90 or v[0] > 90:
|
|
12
|
-
raise ValueError("latitude must be in range -90 to 90")
|
|
13
|
-
if v[1] < -180 or v[1] > 180:
|
|
14
|
-
raise ValueError("longitude must be in range -180 to 180")
|
|
15
|
-
return v
|
goodmap-0.3.1/goodmap/db.py
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
|
|
3
|
-
# TODO file is temporary solution to be compatible with old, static code,
|
|
4
|
-
# it should be replaced with dynamic solution
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def google_json_db_get_data(self):
|
|
8
|
-
raw_data = self.blob.download_as_text(client=None)
|
|
9
|
-
return json.loads(raw_data)["map"]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def json_file_db_get_data(self):
|
|
13
|
-
with open(self.data_file_path, "r") as file:
|
|
14
|
-
return json.load(file)["map"]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def json_db_get_data(self):
|
|
18
|
-
return self.data
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def get_data(db):
|
|
22
|
-
function_name = f"{db.module_name}_get_data"
|
|
23
|
-
return globals()[function_name]
|
goodmap-0.3.1/goodmap/goodmap.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from flask import Blueprint, render_template
|
|
2
|
-
from flask_wtf.csrf import CSRFProtect, generate_csrf
|
|
3
|
-
from platzky import platzky
|
|
4
|
-
from platzky.config import Config, languages_dict
|
|
5
|
-
|
|
6
|
-
from .core_api import core_pages
|
|
7
|
-
from .db import get_data
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def create_app(config_path: str) -> platzky.Engine:
|
|
11
|
-
config = Config.parse_yaml(config_path)
|
|
12
|
-
return create_app_from_config(config)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def create_app_from_config(config: Config) -> platzky.Engine:
|
|
16
|
-
app = platzky.create_app_from_config(config)
|
|
17
|
-
|
|
18
|
-
app.db.extend("get_data", get_data(app.db))
|
|
19
|
-
CSRFProtect(app)
|
|
20
|
-
|
|
21
|
-
cp = core_pages(app.db, languages_dict(config.languages), app.notify, generate_csrf)
|
|
22
|
-
app.register_blueprint(cp)
|
|
23
|
-
goodmap = Blueprint("goodmap", __name__, url_prefix="/", template_folder="templates")
|
|
24
|
-
|
|
25
|
-
@goodmap.route("/")
|
|
26
|
-
def index():
|
|
27
|
-
return render_template("map.html")
|
|
28
|
-
|
|
29
|
-
app.register_blueprint(goodmap)
|
|
30
|
-
return app
|
|
File without changes
|
|
File without changes
|
|
File without changes
|