c2cgeoportal-admin 2.6.0__py3-none-any.whl → 2.7.1.156__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.
Files changed (71) hide show
  1. c2cgeoportal_admin/__init__.py +17 -10
  2. c2cgeoportal_admin/lib/lingua_extractor.py +77 -0
  3. c2cgeoportal_admin/lib/ogcserver_synchronizer.py +166 -54
  4. c2cgeoportal_admin/py.typed +0 -0
  5. c2cgeoportal_admin/routes.py +4 -3
  6. c2cgeoportal_admin/schemas/dimensions.py +12 -10
  7. c2cgeoportal_admin/schemas/functionalities.py +62 -21
  8. c2cgeoportal_admin/schemas/interfaces.py +22 -18
  9. c2cgeoportal_admin/schemas/metadata.py +99 -46
  10. c2cgeoportal_admin/schemas/restriction_areas.py +21 -19
  11. c2cgeoportal_admin/schemas/roles.py +7 -5
  12. c2cgeoportal_admin/schemas/treegroup.py +37 -16
  13. c2cgeoportal_admin/schemas/treeitem.py +2 -3
  14. c2cgeoportal_admin/static/layertree.css +3 -4
  15. c2cgeoportal_admin/static/navbar.css +36 -35
  16. c2cgeoportal_admin/static/theme.css +16 -9
  17. c2cgeoportal_admin/subscribers.py +3 -3
  18. c2cgeoportal_admin/templates/layertree.jinja2 +31 -9
  19. c2cgeoportal_admin/templates/navigation_navbar.jinja2 +33 -0
  20. c2cgeoportal_admin/templates/ogcserver_synchronize.jinja2 +12 -0
  21. c2cgeoportal_admin/templates/widgets/functionality_fields.pt +51 -0
  22. c2cgeoportal_admin/templates/widgets/metadata.pt +7 -1
  23. c2cgeoportal_admin/views/dimension_layers.py +7 -6
  24. c2cgeoportal_admin/views/functionalities.py +31 -5
  25. c2cgeoportal_admin/views/home.py +5 -5
  26. c2cgeoportal_admin/views/interfaces.py +5 -7
  27. c2cgeoportal_admin/views/layer_groups.py +9 -11
  28. c2cgeoportal_admin/views/layers.py +8 -7
  29. c2cgeoportal_admin/views/layers_vectortiles.py +30 -10
  30. c2cgeoportal_admin/views/layers_wms.py +39 -35
  31. c2cgeoportal_admin/views/layers_wmts.py +39 -35
  32. c2cgeoportal_admin/views/layertree.py +35 -27
  33. c2cgeoportal_admin/views/oauth2_clients.py +26 -21
  34. c2cgeoportal_admin/views/ogc_servers.py +57 -29
  35. c2cgeoportal_admin/views/restriction_areas.py +11 -10
  36. c2cgeoportal_admin/views/roles.py +14 -11
  37. c2cgeoportal_admin/views/themes.py +15 -14
  38. c2cgeoportal_admin/views/themes_ordering.py +13 -8
  39. c2cgeoportal_admin/views/treeitems.py +12 -11
  40. c2cgeoportal_admin/views/users.py +7 -5
  41. c2cgeoportal_admin/widgets.py +17 -14
  42. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/METADATA +15 -12
  43. c2cgeoportal_admin-2.7.1.156.dist-info/RECORD +92 -0
  44. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/WHEEL +1 -1
  45. c2cgeoportal_admin-2.7.1.156.dist-info/entry_points.txt +5 -0
  46. tests/__init__.py +9 -9
  47. tests/conftest.py +2 -1
  48. tests/test_edit_url.py +11 -13
  49. tests/test_functionalities.py +23 -10
  50. tests/test_interface.py +7 -7
  51. tests/test_layer_groups.py +13 -17
  52. tests/test_layers_vectortiles.py +11 -13
  53. tests/test_layers_wms.py +25 -36
  54. tests/test_layers_wmts.py +15 -19
  55. tests/test_layertree.py +99 -15
  56. tests/test_lingua_extractor_config.py +66 -0
  57. tests/test_main.py +3 -1
  58. tests/test_metadatas.py +34 -20
  59. tests/test_oauth2_clients.py +4 -4
  60. tests/test_ogc_servers.py +21 -10
  61. tests/test_restriction_areas.py +10 -12
  62. tests/test_role.py +37 -35
  63. tests/test_themes.py +40 -33
  64. tests/test_themes_ordering.py +1 -1
  65. tests/test_treegroup.py +2 -2
  66. tests/test_user.py +15 -13
  67. tests/themes_ordering.py +1 -1
  68. c2cgeoportal_admin/templates/navigation_vertical.jinja2 +0 -33
  69. c2cgeoportal_admin-2.6.0.dist-info/RECORD +0 -89
  70. c2cgeoportal_admin-2.6.0.dist-info/entry_points.txt +0 -3
  71. {c2cgeoportal_admin-2.6.0.dist-info → c2cgeoportal_admin-2.7.1.156.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,3 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
@@ -29,6 +27,7 @@
29
27
 
30
28
 
31
29
  from functools import partial
30
+ from typing import Any, Dict, List, cast
32
31
 
33
32
  from c2cgeoform.schema import GeoFormSchemaNode
34
33
  from c2cgeoform.views.abstract_views import AbstractViews, ItemAction, ListField, UserMessage
@@ -39,6 +38,7 @@ from sqlalchemy import inspect
39
38
 
40
39
  from c2cgeoportal_admin import _
41
40
  from c2cgeoportal_admin.lib.ogcserver_synchronizer import OGCServerSynchronizer
41
+ from c2cgeoportal_commons.lib.literal import Literal
42
42
  from c2cgeoportal_commons.models.main import OGCServer
43
43
 
44
44
  _list_field = partial(ListField, OGCServer)
@@ -48,7 +48,9 @@ base_schema.add_unique_validator(OGCServer.name, OGCServer.id)
48
48
 
49
49
 
50
50
  @view_defaults(match_param="table=ogc_servers")
51
- class OGCServerViews(AbstractViews):
51
+ class OGCServerViews(AbstractViews): # type: ignore
52
+ """The OGC server administration view."""
53
+
52
54
  _list_fields = [
53
55
  _list_field("id"),
54
56
  _list_field("name"),
@@ -73,27 +75,37 @@ class OGCServerViews(AbstractViews):
73
75
  ),
74
76
  }
75
77
 
76
- @view_config(route_name="c2cgeoform_index", renderer="../templates/index.jinja2")
77
- def index(self):
78
- return super().index()
78
+ @view_config(route_name="c2cgeoform_index", renderer="../templates/index.jinja2") # type: ignore
79
+ def index(self) -> Dict[str, Any]:
80
+ return super().index() # type: ignore
79
81
 
80
- @view_config(route_name="c2cgeoform_grid", renderer="fast_json")
81
- def grid(self):
82
- return super().grid()
82
+ @view_config(route_name="c2cgeoform_grid", renderer="fast_json") # type: ignore
83
+ def grid(self) -> Dict[str, Any]:
84
+ return super().grid() # type: ignore
83
85
 
84
- def schema(self):
86
+ def schema(self) -> GeoFormSchemaNode:
85
87
  try:
86
88
  obj = self._get_object()
87
89
  except HTTPNotFound:
88
90
  obj = None
89
91
 
90
92
  schema = self._base_schema.clone()
91
- schema["url"].description = obj.url_description(self._request)
92
- schema["url_wfs"].description = obj.url_wfs_description(self._request)
93
+ schema["url"].description = Literal(
94
+ _("{}<br>Current runtime value is: {}").format(
95
+ schema["url"].description,
96
+ obj.url_description(self._request),
97
+ )
98
+ )
99
+ schema["url_wfs"].description = Literal(
100
+ _("{}<br>Current runtime value is: {}").format(
101
+ schema["url_wfs"].description,
102
+ obj.url_wfs_description(self._request),
103
+ )
104
+ )
93
105
  return schema
94
106
 
95
- def _item_actions(self, item, readonly=False):
96
- actions = super()._item_actions(item, readonly)
107
+ def _item_actions(self, item: OGCServer, readonly: bool = False) -> List[Any]:
108
+ actions = cast(List[Any], super()._item_actions(item, readonly))
97
109
  if inspect(item).persistent:
98
110
  actions.insert(
99
111
  next((i for i, v in enumerate(actions) if v.name() == "delete")),
@@ -106,16 +118,20 @@ class OGCServerViews(AbstractViews):
106
118
  )
107
119
  return actions
108
120
 
109
- @view_config(route_name="c2cgeoform_item", request_method="GET", renderer="../templates/edit.jinja2")
110
- def view(self):
111
- return super().edit(self.schema())
121
+ @view_config( # type: ignore
122
+ route_name="c2cgeoform_item", request_method="GET", renderer="../templates/edit.jinja2"
123
+ )
124
+ def view(self) -> Dict[str, Any]:
125
+ return super().edit(self.schema()) # type: ignore
112
126
 
113
- @view_config(route_name="c2cgeoform_item", request_method="POST", renderer="../templates/edit.jinja2")
114
- def save(self):
115
- return super().save()
127
+ @view_config( # type: ignore
128
+ route_name="c2cgeoform_item", request_method="POST", renderer="../templates/edit.jinja2"
129
+ )
130
+ def save(self) -> Dict[str, Any]:
131
+ return super().save() # type: ignore
116
132
 
117
- @view_config(route_name="c2cgeoform_item", request_method="DELETE", renderer="fast_json")
118
- def delete(self):
133
+ @view_config(route_name="c2cgeoform_item", request_method="DELETE", renderer="fast_json") # type: ignore
134
+ def delete(self) -> Dict[str, Any]:
119
135
  obj = self._get_object()
120
136
  if len(obj.layers) > 0:
121
137
  return {
@@ -127,16 +143,18 @@ class OGCServerViews(AbstractViews):
127
143
  _query=[("msg_col", "cannot_delete")],
128
144
  ),
129
145
  }
130
- return super().delete()
146
+ return super().delete() # type: ignore
131
147
 
132
- @view_config(
148
+ @view_config( # type: ignore
133
149
  route_name="c2cgeoform_item_duplicate", request_method="GET", renderer="../templates/edit.jinja2"
134
150
  )
135
- def duplicate(self):
136
- return super().duplicate()
151
+ def duplicate(self) -> Dict[str, Any]:
152
+ return super().duplicate() # type: ignore
137
153
 
138
- @view_config(route_name="ogcserver_synchronize", renderer="../templates/ogcserver_synchronize.jinja2")
139
- def synchronize(self):
154
+ @view_config( # type: ignore
155
+ route_name="ogcserver_synchronize", renderer="../templates/ogcserver_synchronize.jinja2"
156
+ )
157
+ def synchronize(self) -> Dict[str, Any]:
140
158
  obj = self._get_object()
141
159
 
142
160
  if self._request.method == "GET":
@@ -147,7 +165,17 @@ class OGCServerViews(AbstractViews):
147
165
  }
148
166
 
149
167
  if self._request.method == "POST":
150
- synchronizer = OGCServerSynchronizer(self._request, obj)
168
+ force_parents = self._request.POST.get("force-parents", "false") == "on"
169
+ force_ordering = self._request.POST.get("force-ordering", "false") == "on"
170
+ clean = self._request.POST.get("clean", "false") == "on"
171
+
172
+ synchronizer = OGCServerSynchronizer(
173
+ self._request,
174
+ obj,
175
+ force_parents=force_parents,
176
+ force_ordering=force_ordering,
177
+ clean=clean,
178
+ )
151
179
  if "check" in self._request.params:
152
180
  synchronizer.check_layers()
153
181
  elif "dry-run" in self._request.params:
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -37,7 +35,6 @@ from deform.widget import FormWidget
37
35
  from pyramid.view import view_config, view_defaults
38
36
  from sqlalchemy.orm import subqueryload
39
37
 
40
- from c2cgeoportal_admin import _
41
38
  from c2cgeoportal_admin.schemas.roles import roles_schema_node
42
39
  from c2cgeoportal_admin.schemas.treegroup import treeitem_edit_url
43
40
  from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
@@ -46,18 +43,19 @@ from c2cgeoportal_commons.models.main import Layer, RestrictionArea
46
43
  _list_field = partial(ListField, RestrictionArea)
47
44
 
48
45
  base_schema = GeoFormSchemaNode(RestrictionArea, widget=FormWidget(fields_template="restriction_area_fields"))
49
- base_schema.add_before("area", roles_schema_node("roles"))
46
+ base_schema.add_before("area", roles_schema_node(RestrictionArea.roles))
50
47
  base_schema.add_unique_validator(RestrictionArea.name, RestrictionArea.id)
51
48
 
52
49
 
53
50
  def layers(node, kw): # pylint: disable=unused-argument
51
+ """Get the layers serializable representation."""
54
52
  dbsession = kw["request"].dbsession
55
53
  query = dbsession.query(Layer).order_by(Layer.name)
56
54
  return [
57
55
  {
58
56
  "id": layer.id,
59
57
  "label": layer.name,
60
- "icon_class": "icon-{}".format(layer.item_type),
58
+ "icon_class": f"icon-{layer.item_type}",
61
59
  "edit_url": treeitem_edit_url(kw["request"], layer),
62
60
  "group": "All",
63
61
  }
@@ -75,12 +73,13 @@ base_schema.add(
75
73
  input_name="id",
76
74
  model=Layer,
77
75
  label_field="name",
78
- icon_class=lambda layer: "icon-{}".format(layer.item_type),
76
+ icon_class=lambda layer: f"icon-{layer.item_type}",
79
77
  edit_url=treeitem_edit_url,
80
78
  ),
81
79
  ),
82
80
  name="layers",
83
- title=_("Layers"),
81
+ title=RestrictionArea.layers.info["colanderalchemy"]["title"],
82
+ description=RestrictionArea.layers.info["colanderalchemy"]["description"],
84
83
  candidates=colander.deferred(layers),
85
84
  widget=ChildrenWidget(child_input_name="id", orderable=False),
86
85
  )
@@ -88,7 +87,9 @@ base_schema.add(
88
87
 
89
88
 
90
89
  @view_defaults(match_param="table=restriction_areas")
91
- class RestrictionAreaViews(AbstractViews):
90
+ class RestrictionAreaViews(AbstractViews): # type: ignore
91
+ """The restriction area administration view."""
92
+
92
93
  _list_fields = [
93
94
  _list_field("id"),
94
95
  _list_field("name"),
@@ -100,7 +101,7 @@ class RestrictionAreaViews(AbstractViews):
100
101
  _list_field(
101
102
  "layers",
102
103
  renderer=lambda restriction_area: ", ".join(
103
- "{}-{}".format(layer.item_type, layer.name) or "" for layer in restriction_area.layers
104
+ f"{layer.item_type}-{layer.name}" or "" for layer in restriction_area.layers
104
105
  ),
105
106
  ),
106
107
  ]
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -37,7 +35,6 @@ from deform.widget import FormWidget
37
35
  from pyramid.view import view_config, view_defaults
38
36
  from sqlalchemy.orm import subqueryload
39
37
 
40
- from c2cgeoportal_admin import _
41
38
  from c2cgeoportal_admin.schemas.functionalities import functionalities_schema_node
42
39
  from c2cgeoportal_admin.schemas.restriction_areas import restrictionareas_schema_node
43
40
  from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
@@ -47,12 +44,13 @@ from c2cgeoportal_commons.models.static import User
47
44
  _list_field = partial(ListField, Role)
48
45
 
49
46
  base_schema = GeoFormSchemaNode(Role, widget=FormWidget(fields_template="role_fields"))
50
- base_schema.add_before("extent", functionalities_schema_node.clone())
51
- base_schema.add_before("extent", restrictionareas_schema_node.clone())
47
+ base_schema.add_before("extent", functionalities_schema_node(Role.functionalities, Role))
48
+ base_schema.add_before("extent", restrictionareas_schema_node(Role.restrictionareas))
52
49
  base_schema.add_unique_validator(Role.name, Role.id)
53
50
 
54
51
 
55
52
  def users(node, kw): # pylint: disable=unused-argument
53
+ """Get the user serializable metadata."""
56
54
  dbsession = kw["request"].dbsession
57
55
  query = dbsession.query(User).order_by(User.username)
58
56
  return [
@@ -75,7 +73,7 @@ base_schema.add(
75
73
  colander.SequenceSchema(
76
74
  GeoFormManyToManySchemaNode(
77
75
  User,
78
- name="layer",
76
+ name="user",
79
77
  includes=["id"],
80
78
  widget=ChildWidget(
81
79
  input_name="id",
@@ -89,23 +87,28 @@ base_schema.add(
89
87
  ),
90
88
  ),
91
89
  ),
92
- name="users",
93
- title=_("Users"),
90
+ name=Role.users.key,
91
+ title=Role.users.info["colanderalchemy"]["title"],
92
+ description=Role.users.info["colanderalchemy"]["description"],
94
93
  candidates=colander.deferred(users),
95
94
  widget=ChildrenWidget(child_input_name="id", orderable=False, category="structural"),
96
95
  )
97
96
  )
97
+ # Not possible to overwrite this in constructor.
98
+ base_schema["users"].children[0].description = ""
98
99
 
99
100
 
100
101
  @view_defaults(match_param="table=roles")
101
- class RoleViews(AbstractViews):
102
+ class RoleViews(AbstractViews): # type: ignore
103
+ """The roles administration view."""
104
+
102
105
  _list_fields = [
103
106
  _list_field("id"),
104
107
  _list_field("name"),
105
108
  _list_field("description"),
106
109
  _list_field(
107
110
  "functionalities",
108
- renderer=lambda role: ", ".join(["{}={}".format(f.name, f.value) for f in role.functionalities]),
111
+ renderer=lambda role: ", ".join([f"{f.name}={f.value}" for f in role.functionalities]),
109
112
  ),
110
113
  _list_field(
111
114
  "restrictionareas", renderer=lambda role: ", ".join([r.name or "" for r in role.restrictionareas])
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -29,7 +27,9 @@
29
27
 
30
28
 
31
29
  from functools import partial
30
+ from typing import Optional, cast
32
31
 
32
+ import sqlalchemy
33
33
  from c2cgeoform.schema import GeoFormSchemaNode
34
34
  from c2cgeoform.views.abstract_views import ListField
35
35
  from deform.widget import FormWidget
@@ -39,7 +39,7 @@ from sqlalchemy.sql.functions import concat
39
39
 
40
40
  from c2cgeoportal_admin.schemas.functionalities import functionalities_schema_node
41
41
  from c2cgeoportal_admin.schemas.interfaces import interfaces_schema_node
42
- from c2cgeoportal_admin.schemas.metadata import metadatas_schema_node
42
+ from c2cgeoportal_admin.schemas.metadata import metadata_schema_node
43
43
  from c2cgeoportal_admin.schemas.roles import roles_schema_node
44
44
  from c2cgeoportal_admin.schemas.treegroup import children_schema_node
45
45
  from c2cgeoportal_admin.views.treeitems import TreeItemViews
@@ -49,15 +49,16 @@ _list_field = partial(ListField, Theme)
49
49
 
50
50
  base_schema = GeoFormSchemaNode(Theme, widget=FormWidget(fields_template="theme_fields"))
51
51
  base_schema.add(children_schema_node(only_groups=True))
52
- base_schema.add(functionalities_schema_node.clone())
53
- base_schema.add(roles_schema_node("restricted_roles"))
54
- base_schema.add(interfaces_schema_node.clone())
55
- base_schema.add(metadatas_schema_node.clone())
52
+ base_schema.add(functionalities_schema_node(Theme.functionalities, Theme))
53
+ base_schema.add(roles_schema_node(Theme.restricted_roles))
54
+ base_schema.add(interfaces_schema_node(Theme.interfaces))
55
+ base_schema.add(metadata_schema_node(Theme.metadatas, Theme))
56
56
  base_schema.add_unique_validator(Theme.name, Theme.id)
57
57
 
58
58
 
59
59
  @view_defaults(match_param="table=themes")
60
60
  class ThemeViews(TreeItemViews):
61
+ """The theme administration view."""
61
62
 
62
63
  _list_fields = (
63
64
  TreeItemViews._list_fields
@@ -69,8 +70,8 @@ class ThemeViews(TreeItemViews):
69
70
  "functionalities",
70
71
  renderer=lambda themes: ", ".join(
71
72
  [
72
- "{}={}".format(f.name, f.value)
73
- for f in sorted(themes.functionalities, key=lambda f: f.name)
73
+ f"{f.name}={f.value}"
74
+ for f in sorted(themes.functionalities, key=lambda f: cast(str, f.name))
74
75
  ]
75
76
  ),
76
77
  filter_column=concat(Functionality.name, "=", Functionality.value),
@@ -83,7 +84,7 @@ class ThemeViews(TreeItemViews):
83
84
  _list_field(
84
85
  "interfaces",
85
86
  renderer=lambda themes: ", ".join(
86
- [i.name or "" for i in sorted(themes.interfaces, key=lambda i: i.name)]
87
+ [i.name or "" for i in sorted(themes.interfaces, key=lambda i: cast(str, i.name))]
87
88
  ),
88
89
  filter_column=Interface.name,
89
90
  ),
@@ -95,13 +96,13 @@ class ThemeViews(TreeItemViews):
95
96
  _model = Theme
96
97
  _base_schema = base_schema
97
98
 
98
- def _base_query(self, query=None):
99
+ def _base_query(self, query: Optional[sqlalchemy.orm.query.Query] = None) -> sqlalchemy.orm.query.Query:
99
100
  return super()._base_query(
100
101
  self._request.dbsession.query(Theme)
101
102
  .distinct()
102
103
  .outerjoin("interfaces")
103
- .outerjoin("restricted_roles")
104
- .outerjoin("functionalities")
104
+ .outerjoin(Theme.restricted_roles)
105
+ .outerjoin(Theme.functionalities)
105
106
  .options(subqueryload("functionalities"))
106
107
  .options(subqueryload("restricted_roles"))
107
108
  .options(subqueryload("interfaces"))
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -41,7 +39,9 @@ from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
41
39
  from c2cgeoportal_commons.models.main import Theme, TreeItem
42
40
 
43
41
 
44
- class ThemeOrderSchema(GeoFormSchemaNode): # pylint: disable=abstract-method
42
+ class ThemeOrderSchema(GeoFormSchemaNode): # type: ignore # pylint: disable=abstract-method
43
+ """The theme order schema."""
44
+
45
45
  def objectify(self, dict_, context=None):
46
46
  context = self.dbsession.query(Theme).get(dict_["id"])
47
47
  context = super().objectify(dict_, context)
@@ -50,14 +50,16 @@ class ThemeOrderSchema(GeoFormSchemaNode): # pylint: disable=abstract-method
50
50
 
51
51
  @colander.deferred
52
52
  def themes(node, kw): # pylint: disable=unused-argument
53
+ """Get some theme metadata."""
53
54
  query = kw["dbsession"].query(Theme).order_by(Theme.ordering, Theme.name)
54
55
  return [
55
- {"id": item.id, "label": item.name, "icon_class": "icon-{}".format(item.item_type), "group": "All"}
56
+ {"id": item.id, "label": item.name, "icon_class": f"icon-{item.item_type}", "group": "All"}
56
57
  for item in query
57
58
  ]
58
59
 
59
60
 
60
61
  def themes_validator(node, cstruct):
62
+ """Validate the theme."""
61
63
  for dict_ in cstruct:
62
64
  if not dict_["id"] in [item["id"] for item in node.candidates]:
63
65
  raise colander.Invalid(
@@ -66,7 +68,9 @@ def themes_validator(node, cstruct):
66
68
  )
67
69
 
68
70
 
69
- class ThemesOrderingSchema(colander.MappingSchema):
71
+ class ThemesOrderingSchema(colander.MappingSchema): # type: ignore
72
+ """The theme ordering schema."""
73
+
70
74
  themes = colander.SequenceSchema(
71
75
  ThemeOrderSchema(
72
76
  Theme,
@@ -76,7 +80,7 @@ class ThemesOrderingSchema(colander.MappingSchema):
76
80
  input_name="id",
77
81
  model=TreeItem,
78
82
  label_field="name",
79
- icon_class=lambda item: "icon-{}".format(item.item_type),
83
+ icon_class=lambda item: f"icon-{item.item_type}",
80
84
  edit_url=treeitem_edit_url,
81
85
  ),
82
86
  ),
@@ -87,7 +91,8 @@ class ThemesOrderingSchema(colander.MappingSchema):
87
91
  )
88
92
 
89
93
 
90
- class ThemesOrdering(AbstractViews):
94
+ class ThemesOrdering(AbstractViews): # type: ignore
95
+ """The theme ordering admin view."""
91
96
 
92
97
  _base_schema = ThemesOrderingSchema()
93
98
 
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2021, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -30,6 +28,7 @@
30
28
 
31
29
  from functools import partial
32
30
 
31
+ import sqlalchemy
33
32
  from c2cgeoform.views.abstract_views import AbstractViews, ListField
34
33
  from pyramid.view import view_config
35
34
  from sqlalchemy.orm import subqueryload
@@ -40,7 +39,9 @@ from c2cgeoportal_commons.models.main import LayergroupTreeitem, Metadata, TreeG
40
39
  _list_field = partial(ListField, TreeItem)
41
40
 
42
41
 
43
- class TreeItemViews(AbstractViews):
42
+ class TreeItemViews(AbstractViews): # type: ignore
43
+ """The admin tree item view."""
44
+
44
45
  _list_fields = [
45
46
  _list_field("id"),
46
47
  _list_field("name"),
@@ -50,9 +51,7 @@ class TreeItemViews(AbstractViews):
50
51
  _extra_list_fields_no_parents = [
51
52
  _list_field(
52
53
  "metadatas",
53
- renderer=lambda layers_group: ", ".join(
54
- ["{}: {}".format(m.name, m.value) or "" for m in layers_group.metadatas]
55
- ),
54
+ renderer=lambda treeitem: ", ".join([f"{m.name}: {m.value}" or "" for m in treeitem.metadatas]),
56
55
  filter_column=concat(Metadata.name, ": ", Metadata.value).label("metadata"),
57
56
  )
58
57
  ]
@@ -72,16 +71,18 @@ class TreeItemViews(AbstractViews):
72
71
  def save(self):
73
72
  response = super().save()
74
73
  # correctly handles the validation error as if there is a validation error, cstruct is empty
75
- has_to_be_registred_in_parent = (
74
+ has_to_be_registered_in_parent = (
76
75
  hasattr(self, "_appstruct") and self._appstruct is not None and self._appstruct.get("parent_id")
77
76
  )
78
- if has_to_be_registred_in_parent:
79
- parent = self._request.dbsession.query(TreeGroup).get(has_to_be_registred_in_parent)
77
+ if has_to_be_registered_in_parent:
78
+ parent = self._request.dbsession.query(TreeGroup).get(has_to_be_registered_in_parent)
80
79
  rel = LayergroupTreeitem(parent, self._obj, 100)
81
80
  self._request.dbsession.add(rel)
82
81
  return response
83
82
 
84
- def _base_query(self, query): # pylint: disable=arguments-differ
83
+ def _base_query( # pylint: disable=arguments-differ
84
+ self, query: sqlalchemy.orm.query.Query
85
+ ) -> sqlalchemy.orm.query.Query:
85
86
  return (
86
87
  query.outerjoin("metadatas")
87
88
  .options(subqueryload("parents_relation").joinedload("treegroup"))
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2017-2020, Camptocamp SA
1
+ # Copyright (c) 2017-2022, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -46,14 +44,16 @@ from c2cgeoportal_commons.models.static import User
46
44
  _list_field = partial(ListField, User)
47
45
 
48
46
  base_schema = GeoFormSchemaNode(User, widget=FormWidget(fields_template="user_fields"))
49
- base_schema.add(roles_schema_node("roles"))
47
+ base_schema.add(roles_schema_node(User.roles))
50
48
  base_schema.add_unique_validator(User.username, User.id)
51
49
 
52
50
  settings_role = aliased(Role)
53
51
 
54
52
 
55
53
  @view_defaults(match_param="table=users")
56
- class UserViews(AbstractViews):
54
+ class UserViews(AbstractViews): # type: ignore
55
+ """The admin user view."""
56
+
57
57
  _list_fields = [
58
58
  _list_field("id"),
59
59
  _list_field("username"),
@@ -119,6 +119,8 @@ class UserViews(AbstractViews):
119
119
  email=user.email,
120
120
  user=user.username,
121
121
  password=password,
122
+ application_url=self._request.route_url("base"),
123
+ current_url=self._request.current_route_url(),
122
124
  )
123
125
 
124
126
  return response
@@ -1,6 +1,4 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- # Copyright (c) 2018-2020, Camptocamp SA
1
+ # Copyright (c) 2018-2024, Camptocamp SA
4
2
  # All rights reserved.
5
3
 
6
4
  # Redistribution and use in source and binary forms, with or without
@@ -27,9 +25,10 @@
27
25
  # of the authors and should not be interpreted as representing official policies,
28
26
  # either expressed or implied, of the FreeBSD Project.
29
27
 
30
- from typing import Optional
28
+ from typing import Any, Optional
31
29
 
32
30
  import colander
31
+ import pyramid.request
33
32
  from colander import Mapping, SchemaNode
34
33
  from deform import widget
35
34
  from deform.widget import MappingWidget, SequenceWidget
@@ -55,10 +54,11 @@ widget.DateTimeInputWidget._pstruct_schema = SchemaNode( # pylint: disable=prot
55
54
  )
56
55
 
57
56
 
58
- class ChildWidget(MappingWidget):
57
+ class ChildWidget(MappingWidget): # type: ignore
59
58
  """
60
- Extension of the widget ````deform.widget.MappingWidget`` to be used in conjunction with ChildrenWidget,
61
- to manage n-m relationships.
59
+ Extension of the widget ````deform.widget.MappingWidget``.
60
+
61
+ To be used in conjunction with ChildrenWidget, to manage n-m relationships.
62
62
 
63
63
  Do not embed complete children forms, but just an hidden input for child primary key.
64
64
 
@@ -82,7 +82,7 @@ class ChildWidget(MappingWidget):
82
82
 
83
83
  For further attributes, please refer to the documentation of
84
84
  ``deform.widget.MappingWidget`` in the deform documentation:
85
- <http://deform.readthedocs.org/en/latest/api.html>
85
+ <https://deform.readthedocs.org/en/latest/api.html>
86
86
  """
87
87
 
88
88
  template = "child"
@@ -90,11 +90,13 @@ class ChildWidget(MappingWidget):
90
90
  model = TreeItem
91
91
  label_field = "name"
92
92
 
93
- def icon_class(self, child) -> Optional[str]: # pylint: disable=no-self-use,useless-return
93
+ def icon_class(self, child: Any) -> Optional[str]: # pylint: disable=no-self-use,useless-return
94
94
  del child
95
95
  return None
96
96
 
97
- def edit_url(self, request, child) -> Optional[str]: # pylint: disable=no-self-use,useless-return
97
+ def edit_url( # pylint: disable=no-self-use,useless-return
98
+ self, request: pyramid.request.Request, child: Any
99
+ ) -> Optional[str]:
98
100
  del request
99
101
  del child
100
102
  return None
@@ -107,10 +109,11 @@ class ChildWidget(MappingWidget):
107
109
  return super().serialize(field, cstruct, **kw)
108
110
 
109
111
 
110
- class ChildrenWidget(SequenceWidget):
112
+ class ChildrenWidget(SequenceWidget): # type: ignore
111
113
  """
112
- Extension of the widget ````deform.widget.SequenceWidget``, to be used in conjunction with ChildWidget,
113
- to manage n-m relationships.
114
+ Extension of the widget ````deform.widget.SequenceWidget``.
115
+
116
+ To be used in conjunction with ChildWidget, to manage n-m relationships.
114
117
 
115
118
  Use Magicsuggest for searching into parent schema candidates property, which should be a list of
116
119
  dictionaries of the form:
@@ -129,7 +132,7 @@ class ChildrenWidget(SequenceWidget):
129
132
 
130
133
  For further attributes, please refer to the documentation of
131
134
  ``deform.widget.SequenceWidget`` in the deform documentation:
132
- <http://deform.readthedocs.org/en/latest/api.html>
135
+ <https://deform.readthedocs.org/en/latest/api.html>
133
136
  """
134
137
 
135
138
  template = "children"