imio.smartweb.core 1.2.90__py3-none-any.whl → 1.3__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 (96) hide show
  1. imio/smartweb/core/browser/controlpanel.py +42 -5
  2. imio/smartweb/core/browser/utils.py +4 -1
  3. imio/smartweb/core/configure.zcml +5 -1
  4. imio/smartweb/core/contents/__init__.py +2 -0
  5. imio/smartweb/core/contents/rest/campaign/__init__.py +0 -0
  6. imio/smartweb/core/contents/rest/campaign/configure.zcml +80 -0
  7. imio/smartweb/core/contents/rest/campaign/content.py +83 -0
  8. imio/smartweb/core/contents/rest/campaign/endpoint.py +211 -0
  9. imio/smartweb/core/contents/rest/campaign/view.pt +19 -0
  10. imio/smartweb/core/contents/rest/campaign/view.py +29 -0
  11. imio/smartweb/core/contents/rest/configure.zcml +1 -0
  12. imio/smartweb/core/interfaces.py +4 -0
  13. imio/smartweb/core/overrides.zcml +10 -0
  14. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  15. imio/smartweb/core/profiles/ideabox/browserlayer.xml +7 -0
  16. imio/smartweb/core/profiles/ideabox/metadata.xml +5 -0
  17. imio/smartweb/core/profiles/ideabox/registry/iaideabox.xml +9 -0
  18. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.CampaignView.xml +40 -0
  19. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.Folder.xml +71 -0
  20. imio/smartweb/core/profiles/ideabox/types.xml +17 -0
  21. imio/smartweb/core/profiles/ideabox_uninstall/browserlayer.xml +7 -0
  22. imio/smartweb/core/profiles/ideabox_uninstall/types/imio.smartweb.Folder.xml +25 -0
  23. imio/smartweb/core/profiles/ideabox_uninstall/types.xml +4 -0
  24. imio/smartweb/core/profiles/testing/metadata.xml +1 -0
  25. imio/smartweb/core/profiles/testing/registry.xml +2 -2
  26. imio/smartweb/core/profiles.zcml +18 -0
  27. imio/smartweb/core/subscribers.py +27 -1
  28. imio/smartweb/core/subscribers.zcml +8 -0
  29. imio/smartweb/core/tests/resources/json_ideabox_campaign.json +222 -0
  30. imio/smartweb/core/tests/resources/json_ideabox_campaigns.json +425 -0
  31. imio/smartweb/core/tests/resources/json_ideabox_projects.json +1871 -0
  32. imio/smartweb/core/tests/test_iadeliberations.py +38 -40
  33. imio/smartweb/core/tests/test_ideabox.py +120 -0
  34. imio/smartweb/core/tests/test_procedure.py +7 -3
  35. imio/smartweb/core/tests/test_rest.py +7 -0
  36. imio/smartweb/core/tests/test_vocabularies.py +8 -10
  37. imio/smartweb/core/upgrades/configure.zcml +16 -1
  38. imio/smartweb/core/upgrades/upgrades.py +64 -0
  39. imio/smartweb/core/utils.py +33 -0
  40. imio/smartweb/core/viewlets/actions.py +10 -0
  41. imio/smartweb/core/viewlets/header_actions.pt +2 -0
  42. imio/smartweb/core/viewlets/offcanvas.pt +31 -6
  43. imio/smartweb/core/viewlets/ogptags.py +9 -0
  44. imio/smartweb/core/viewlets/subsite_logo.pt +1 -1
  45. imio/smartweb/core/vocabularies.py +35 -4
  46. imio/smartweb/core/vocabularies.zcml +6 -0
  47. imio/smartweb/core/webcomponents/build/css/373.smartweb-webcomponents-compiled.css +1 -1
  48. imio/smartweb/core/webcomponents/build/css/420.smartweb-webcomponents-compiled.css +1 -0
  49. imio/smartweb/core/webcomponents/build/css/486.smartweb-webcomponents-compiled.css +1 -1
  50. imio/smartweb/core/webcomponents/build/css/666.smartweb-webcomponents-compiled.css +1 -0
  51. imio/smartweb/core/webcomponents/build/css/884.smartweb-webcomponents-compiled.css +1 -1
  52. imio/smartweb/core/webcomponents/build/css/smartweb-webcomponents-compiled.css +1 -1
  53. imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js +2 -0
  54. imio/smartweb/core/webcomponents/build/js/{828.smartweb-webcomponents-compiled.js.LICENSE.txt → 141.smartweb-webcomponents-compiled.js.LICENSE.txt} +3 -3
  55. imio/smartweb/core/webcomponents/build/js/15.smartweb-webcomponents-compiled.js +2 -0
  56. imio/smartweb/core/webcomponents/build/js/21.smartweb-webcomponents-compiled.js +1 -0
  57. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js +1 -1
  58. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js.LICENSE.txt +0 -5
  59. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  60. imio/smartweb/core/webcomponents/build/js/486.smartweb-webcomponents-compiled.js +1 -1
  61. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -0
  62. imio/smartweb/core/webcomponents/build/js/799.smartweb-webcomponents-compiled.js +1 -1
  63. imio/smartweb/core/webcomponents/build/js/824.smartweb-webcomponents-compiled.js +1 -1
  64. imio/smartweb/core/webcomponents/build/js/884.smartweb-webcomponents-compiled.js +1 -1
  65. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  66. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -0
  67. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  68. imio/smartweb/core/webcomponents/package.json +80 -80
  69. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +1 -0
  70. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.jsx +306 -0
  71. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.scss +672 -0
  72. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignCard/CampaignCard.jsx +79 -0
  73. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignContent/CampaignContent.jsx +193 -0
  74. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignList/CampaignList.jsx +67 -0
  75. imio/smartweb/core/webcomponents/src/components/Campaign/Filters/Filter.jsx +259 -0
  76. imio/smartweb/core/webcomponents/src/components/Campaign/index.js +2 -0
  77. imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +1 -0
  78. imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +0 -1
  79. imio/smartweb/core/webcomponents/src/hooks/useAxios.js +45 -9
  80. imio/smartweb/core/webcomponents/src/index.jsx +2 -0
  81. imio/smartweb/core/webcomponents/src/index.scss +2 -2
  82. imio/smartweb/core/webcomponents/src/utils/CampaignMap.jsx +177 -0
  83. imio/smartweb/core/webcomponents/src/utils/Map.jsx +1 -1
  84. imio/smartweb/core/webcomponents/src/utils/Map.scss +15 -1
  85. imio/smartweb/core/webcomponents/src/utils/translation.js +235 -199
  86. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/METADATA +18 -1
  87. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/RECORD +94 -61
  88. imio/smartweb/core/webcomponents/build/js/499.smartweb-webcomponents-compiled.js +0 -2
  89. imio/smartweb/core/webcomponents/build/js/828.smartweb-webcomponents-compiled.js +0 -2
  90. /imio/smartweb/core/webcomponents/build/js/{499.smartweb-webcomponents-compiled.js.LICENSE.txt → 15.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  91. /imio.smartweb.core-1.2.90-py3.12-nspkg.pth → /imio.smartweb.core-1.3-py3.12-nspkg.pth +0 -0
  92. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/LICENSE.GPL +0 -0
  93. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/LICENSE.rst +0 -0
  94. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/WHEEL +0 -0
  95. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/namespace_packages.txt +0 -0
  96. {imio.smartweb.core-1.2.90.dist-info → imio.smartweb.core-1.3.dist-info}/top_level.txt +0 -0
@@ -55,10 +55,8 @@ class TestIADeliberations(ImioSmartwebTestCase):
55
55
  ),
56
56
  )
57
57
 
58
- @patch("imio.smartweb.core.subscribers.get_iadeliberation_json")
59
- @patch(
60
- "imio.smartweb.core.subscribers.get_iadeliberation_institution_from_registry"
61
- )
58
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
59
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
62
60
  def test_ct_publication_adding(self, m_get_institution, m_get_publication):
63
61
  m_get_institution.return_value = "https://conseil.staging.imio.be/liege"
64
62
  m_get_publication.return_value = self.json_publication_raw_mock
@@ -96,41 +94,41 @@ class TestIADeliberations(ImioSmartwebTestCase):
96
94
  api.content.delete(obj=obj)
97
95
  self.assertNotIn("publication", parent.objectIds())
98
96
 
99
- @patch("imio.smartweb.core.subscribers.get_iadeliberation_json")
100
- @patch(
101
- "imio.smartweb.core.subscribers.get_iadeliberation_institution_from_registry"
102
- )
103
- def test_publication_view(self, m_get_institution, m_get_publication):
104
- m_get_institution.return_value = "https://conseil.staging.imio.be/liege"
105
- m_get_publication.return_value = self.json_publication_raw_mock
106
- obj = api.content.create(
107
- container=self.files_section,
108
- type="imio.smartweb.Publication",
109
- id="18820593",
110
- )
111
- obj.reindexObject()
112
- title_to_get = (
113
- "Ordonnance concernant des mesures spécifiques en cas de grand froid."
114
- )
97
+ # Fix tests : timestamped publication are now a section, not an item in a file section
98
+ #
99
+ # @patch("imio.smartweb.core.subscribers.get_iadeliberation_json")
100
+ # @patch("imio.smartweb.core.subscribers.get_value_from_registry")
101
+ # def test_publication_view(self, m_get_institution, m_get_publication):
102
+ # m_get_institution.return_value = "https://conseil.staging.imio.be/liege"
103
+ # m_get_publication.return_value = self.json_publication_raw_mock
104
+ # obj = api.content.create(
105
+ # container=self.files_section,
106
+ # type="imio.smartweb.Publication",
107
+ # id="18820593",
108
+ # )
109
+ # obj.reindexObject()
110
+ # title_to_get = (
111
+ # "Ordonnance concernant des mesures spécifiques en cas de grand froid."
112
+ # )
115
113
 
116
- view = queryMultiAdapter((self.files_section, self.request), name="full_view")
117
- self.assertIn(title_to_get, view())
118
- self.assertNotIn("013400000123949.PDF", view())
114
+ # view = queryMultiAdapter((self.files_section, self.request), name="full_view")
115
+ # self.assertIn(title_to_get, view())
116
+ # self.assertNotIn("013400000123949.PDF", view())
119
117
 
120
- view = queryMultiAdapter((self.files_section, self.request), name="table_view")
121
- self.assertIn(title_to_get, [item[0]["title"] for item in view.items()])
122
- self.assertEqual(
123
- [
124
- item[0]["publication_attached_file"].get("filename")
125
- for item in view.items()
126
- ][0],
127
- "013400000123949.PDF",
128
- )
129
- self.assertEqual(
130
- [item[0]["publication_document_type"] for item in view.items()][0],
131
- "Ordonnance de police administrative",
132
- )
133
- self.assertEqual(
134
- [item[0]["publication_datetime"] for item in view.items()][0],
135
- "2024-08-14T09:14:31",
136
- )
118
+ # view = queryMultiAdapter((self.files_section, self.request), name="table_view")
119
+ # self.assertIn(title_to_get, [item[0]["title"] for item in view.items()])
120
+ # self.assertEqual(
121
+ # [
122
+ # item[0]["publication_attached_file"].get("filename")
123
+ # for item in view.items()
124
+ # ][0],
125
+ # "013400000123949.PDF",
126
+ # )
127
+ # self.assertEqual(
128
+ # [item[0]["publication_document_type"] for item in view.items()][0],
129
+ # "Ordonnance de police administrative",
130
+ # )
131
+ # self.assertEqual(
132
+ # [item[0]["publication_datetime"] for item in view.items()][0],
133
+ # "2024-08-14T09:14:31",
134
+ # )
@@ -0,0 +1,120 @@
1
+ # -*- coding: utf-8 -*-
2
+ from imio.smartweb.core.contents.rest.base import BaseEndpoint
3
+ from imio.smartweb.core.contents.rest.campaign.endpoint import CampaignEndpoint
4
+ from imio.smartweb.core.contents import ICampaignView
5
+ from imio.smartweb.core.tests.utils import get_json
6
+
7
+ from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_INTEGRATION_TESTING
8
+ from imio.smartweb.core.testing import ImioSmartwebTestCase
9
+ from plone import api
10
+ from plone.app.testing import setRoles
11
+ from plone.app.testing import TEST_USER_ID
12
+ from plone.dexterity.interfaces import IDexterityFTI
13
+ from unittest.mock import patch
14
+ from zope.component import createObject
15
+ from zope.component import queryMultiAdapter
16
+ from zope.component import queryUtility
17
+ from zope.publisher.browser import TestRequest
18
+
19
+ import json
20
+ import requests_mock
21
+
22
+
23
+ class TestIdeabox(ImioSmartwebTestCase):
24
+ layer = IMIO_SMARTWEB_CORE_INTEGRATION_TESTING
25
+
26
+ def setUp(self):
27
+ """Custom shared utility setup for tests."""
28
+ self.portal = self.layer["portal"]
29
+ self.request = self.layer["request"]
30
+ setRoles(self.portal, TEST_USER_ID, ["Manager"])
31
+ self.folder = api.content.create(
32
+ container=self.portal,
33
+ type="imio.smartweb.Folder",
34
+ title="A Folder",
35
+ )
36
+ self.json_campaigns_raw_mock = get_json("resources/json_ideabox_campaigns.json")
37
+ self.json_campaign_raw_mock = get_json("resources/json_ideabox_campaign.json")
38
+
39
+ def test_ct_publication_schema(self):
40
+ fti = queryUtility(IDexterityFTI, name="imio.smartweb.CampaignView")
41
+ schema = fti.lookupSchema()
42
+ self.assertEqual(ICampaignView, schema)
43
+
44
+ def test_ct_publication_fti(self):
45
+ fti = queryUtility(IDexterityFTI, name="imio.smartweb.CampaignView")
46
+ self.assertTrue(fti)
47
+
48
+ def test_ct_publication_factory(self):
49
+ fti = queryUtility(IDexterityFTI, name="imio.smartweb.CampaignView")
50
+ factory = fti.factory
51
+ obj = createObject(factory)
52
+ self.assertTrue(
53
+ ICampaignView.providedBy(obj),
54
+ "ICampaignView not provided by {0}!".format(
55
+ obj,
56
+ ),
57
+ )
58
+
59
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
60
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
61
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_basic_auth_json")
62
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_value_from_registry")
63
+ def test_get_campaign(
64
+ self,
65
+ m_get_value_from_registry_namechooser,
66
+ m_get_basic_auth_json_namechooser,
67
+ m_get_value_from_registry,
68
+ m_get_basic_auth_json,
69
+ ):
70
+ m_get_value_from_registry.return_value = (
71
+ "https://staging3-formulaires.guichet-citoyen.be/api"
72
+ )
73
+ m_get_basic_auth_json.return_value = self.json_campaign_raw_mock
74
+
75
+ m_get_value_from_registry_namechooser.return_value = (
76
+ "https://staging3-formulaires.guichet-citoyen.be/api"
77
+ )
78
+ m_get_basic_auth_json_namechooser.return_value = self.json_campaign_raw_mock
79
+ campaign_view = api.content.create(
80
+ title="kamoulox",
81
+ container=self.folder,
82
+ type="imio.smartweb.CampaignView",
83
+ linked_campaign="2",
84
+ )
85
+ self.assertEqual(campaign_view.title, "Sprint iMio Fall 2024")
86
+ self.assertEqual(campaign_view.id, "sprint-imio-fall-2024")
87
+
88
+ @requests_mock.Mocker()
89
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
90
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
91
+ def test_get_projects(self, m_get_value_from_registry, m_get_basic_auth_json, m):
92
+ m_get_value_from_registry.return_value = (
93
+ "https://staging3-formulaires.guichet-citoyen.be/api"
94
+ )
95
+ m_get_basic_auth_json.return_value = self.json_campaign_raw_mock
96
+ campaign_view = api.content.create(
97
+ id="kamoulox",
98
+ container=self.folder,
99
+ type="imio.smartweb.CampaignView",
100
+ linked_campaign="2",
101
+ )
102
+ # react additionnal fields request.
103
+ # form={
104
+ # "taxonomy_contact_category_for_filtering": ("token"),
105
+ # "topics": "education",
106
+ # }
107
+
108
+ request = TestRequest()
109
+ endpoint = CampaignEndpoint(campaign_view, request)
110
+ url = endpoint.query_url
111
+ self.assertEqual(
112
+ url,
113
+ "https://demo-formulaires.guichet-citoyen.be/api/cards/imio-ideabox-projet/list?campagne=2&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&",
114
+ )
115
+
116
+ m.get(url, text=json.dumps({}))
117
+ call = endpoint()
118
+ self.assertEqual(call, {})
119
+
120
+ # to be continued
@@ -22,7 +22,9 @@ from zope.viewlet.interfaces import IViewletManager
22
22
  import json
23
23
  import requests_mock
24
24
 
25
- GUICHET_URL = "https://demo.guichet-citoyen.be/api/formdefs/"
25
+ # formdefs/
26
+ GUICHET_URL = "https://demo.guichet-citoyen.be/api/"
27
+ WCS_URL = "https://demo-formulaires.guichet-citoyen.be/api/"
26
28
 
27
29
 
28
30
  class TestProcedure(ImioSmartwebTestCase):
@@ -102,7 +104,8 @@ class TestProcedure(ImioSmartwebTestCase):
102
104
 
103
105
  @requests_mock.Mocker()
104
106
  def test_procedure_invariant(self, m):
105
- m.get(GUICHET_URL, text=json.dumps(self.json_procedures_raw_mock))
107
+ url = f"{WCS_URL}formdefs/"
108
+ m.get(url, text=json.dumps(self.json_procedures_raw_mock))
106
109
  request = TestRequest(
107
110
  form={
108
111
  "form.widgets.IBasic.title": "My Procedure",
@@ -145,7 +148,8 @@ class TestProcedure(ImioSmartwebTestCase):
145
148
 
146
149
  @requests_mock.Mocker()
147
150
  def test_procedure_viewlet(self, m):
148
- m.get(GUICHET_URL, text=json.dumps(self.json_procedures_raw_mock))
151
+ url = f"{WCS_URL}formdefs/"
152
+ m.get(url, text=json.dumps(self.json_procedures_raw_mock))
149
153
  procedure = api.content.create(
150
154
  container=self.portal,
151
155
  type="imio.smartweb.Procedure",
@@ -18,6 +18,7 @@ from plone.app.testing import TEST_USER_ID
18
18
  from plone.app.testing import TEST_USER_PASSWORD
19
19
  from plone.namedfile.file import NamedBlobImage
20
20
  from plone.restapi.testing import RelativeSession
21
+ from unittest import mock
21
22
  from unittest.mock import patch
22
23
  from urllib.parse import urlparse
23
24
  from urllib.parse import parse_qs
@@ -25,8 +26,10 @@ from zope.component import queryMultiAdapter
25
26
  from zope.event import notify
26
27
  from zope.publisher.browser import TestRequest
27
28
  from ZPublisher.pubevents import PubStart
29
+ from imio.smartweb.core.viewlets.ogptags import OgpTagsViewlet
28
30
 
29
31
  import json
32
+ import os
30
33
  import requests_mock
31
34
  import transaction
32
35
 
@@ -281,6 +284,7 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
281
284
  self.assertIn('<meta property="og:image:width" content="400">', view())
282
285
  self.assertIn('<meta property="og:image:height" content="400">', view())
283
286
 
287
+ # @mock.patch.dict(os.environ, {"client_id": "Kamoulox", "client_secret": "Kamoulox"})
284
288
  @patch("imio.smartweb.core.viewlets.ogptags.get_wca_token")
285
289
  @patch("imio.smartweb.core.viewlets.ogptags.get_json")
286
290
  def test_render_rest_auth_sources_item(self, mock_get_json, mock_get_wca_token):
@@ -304,6 +308,9 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
304
308
  }
305
309
  UID = "3c436a800154449f84797fdb30561297"
306
310
  self.request.form["u"] = UID
311
+ # viewlet = OgpTagsViewlet(self.portal, self.request, None, None)
312
+ # viewlet.update()
313
+
307
314
  view = queryMultiAdapter(
308
315
  (auth_source["content"], self.request), name="view"
309
316
  )
@@ -10,6 +10,7 @@ from plone import api
10
10
  from unittest.mock import patch
11
11
 
12
12
  import json
13
+ import re
13
14
  import requests
14
15
  import requests_mock
15
16
 
@@ -38,7 +39,10 @@ class TestVocabularies(ImioSmartwebTestCase):
38
39
 
39
40
  @requests_mock.Mocker()
40
41
  def test_procedure_keys(self, m):
41
- m.get(GUICHET_URL, text=json.dumps(self.json_procedures_raw_mock))
42
+ GUICHET = re.compile(
43
+ r"https://demo-formulaires\.guichet-citoyen\.be/api/formdefs/.*"
44
+ )
45
+ m.get(GUICHET, text=json.dumps(self.json_procedures_raw_mock))
42
46
  self.assertVocabularyLen("imio.smartweb.vocabulary.PublikProcedures", 3)
43
47
  vocabulary = get_vocabulary("imio.smartweb.vocabulary.PublikProcedures")
44
48
  self.assertEqual(
@@ -59,12 +63,8 @@ class TestVocabularies(ImioSmartwebTestCase):
59
63
  ).title,
60
64
  "Acte de mariage",
61
65
  )
62
- api.portal.set_registry_record(
63
- "smartweb.url_formdefs_api",
64
- "https://demo.guichet-citoyen.be/api/formdefs/?query=kamoulox",
65
- )
66
66
  m.get(
67
- "https://demo.guichet-citoyen.be/api/formdefs/?query=kamoulox",
67
+ GUICHET,
68
68
  text=json.dumps(self.json_procedures_raw_mock),
69
69
  )
70
70
  self.assertVocabularyLen("imio.smartweb.vocabulary.PublikProcedures", 3)
@@ -77,7 +77,7 @@ class TestVocabularies(ImioSmartwebTestCase):
77
77
  m.get(GUICHET_URL, status_code=404)
78
78
  self.assertVocabularyLen("imio.smartweb.vocabulary.PublikProcedures", 0)
79
79
 
80
- api.portal.set_registry_record("smartweb.url_formdefs_api", "")
80
+ api.portal.set_registry_record("smartweb.url_ts", "")
81
81
  m.get(GUICHET_URL, text=json.dumps(self.json_procedures_raw_mock))
82
82
  self.assertVocabularyLen("imio.smartweb.vocabulary.PublikProcedures", 0)
83
83
 
@@ -316,9 +316,7 @@ class TestVocabularies(ImioSmartwebTestCase):
316
316
  "Waremme",
317
317
  )
318
318
 
319
- @patch(
320
- "imio.smartweb.core.vocabularies.get_iadeliberation_institution_from_registry"
321
- )
319
+ @patch("imio.smartweb.core.vocabularies.get_value_from_registry")
322
320
  @patch("imio.smartweb.core.vocabularies.get_iadeliberation_url_from_registry")
323
321
  @requests_mock.Mocker()
324
322
  def test_remote_iadeliberations_publications(self, m_url, m_institution, m):
@@ -944,6 +944,22 @@
944
944
  import_profile="imio.smartweb.core.upgrades:upgrade_1063_to_1064"
945
945
  />
946
946
  </genericsetup:upgradeSteps>
947
+
948
+ <genericsetup:upgradeStep
949
+ title="Update control panel combo api url"
950
+ source="1064"
951
+ destination="1065"
952
+ handler=".upgrades.update_control_panel_combo_api_url"
953
+ profile="imio.smartweb.core:default"
954
+ />
955
+
956
+ <genericsetup:upgradeStep
957
+ title="Update control panel combo api fieldname"
958
+ source="1065"
959
+ destination="1066"
960
+ handler=".upgrades.update_control_panel_combo_api_fieldname"
961
+ profile="imio.smartweb.core:default"
962
+ />
947
963
 
948
964
  <!--genericsetup:upgradeStep
949
965
  title="Check contact itinerary if address was checked in visible blocks"
@@ -953,5 +969,4 @@
953
969
  handler=".upgrades.migrate_external_links"
954
970
  profile="imio.smartweb.core:default"
955
971
  /-->
956
-
957
972
  </configure>
@@ -2,14 +2,18 @@
2
2
 
3
3
  from imio.smartweb.core.browser.controlpanel import ISmartwebControlPanel
4
4
  from imio.smartweb.core.contents import IPages
5
+ from imio.smartweb.locales import SmartwebMessageFactory as _
5
6
  from eea.facetednavigation.interfaces import ICriteria
6
7
  from eea.facetednavigation.subtypes.interfaces import IFacetedNavigable
7
8
  from plone import api
8
9
  from plone.app.imagecropping import PAI_STORAGE_KEY
10
+ from plone.registry import field
11
+ from plone.registry import Record
9
12
  from plone.registry.interfaces import IRegistry
10
13
  from zope.annotation.interfaces import IAnnotations
11
14
  from zope.component import getUtility
12
15
  from zope.schema import getFieldNames
16
+ from zope.schema import TextLine
13
17
 
14
18
  import logging
15
19
 
@@ -227,3 +231,63 @@ def migrate_old_sizes_from_section_text(context):
227
231
  logger.info(
228
232
  f"Migrated deprecated scale from {old_scale} to {new_scale} for {obj.absolute_url()}"
229
233
  )
234
+
235
+
236
+ def update_control_panel_combo_api_url(context):
237
+ url_ts = ""
238
+ try:
239
+ url_ts = api.portal.get_registry_record("smartweb.url_formdefs_api") or ""
240
+ except:
241
+ logger.info("La clé 'smartweb.url_formdefs_api' a été supprimée.")
242
+ return
243
+ url_ts = url_ts.replace("/api", "")
244
+ url_ts = url_ts.replace("-formulaires", "")
245
+ api.portal.set_registry_record("smartweb.url_formdefs_api", url_ts)
246
+
247
+
248
+ def update_control_panel_combo_api_fieldname(context):
249
+ url_ts = ""
250
+ try:
251
+ url_ts = api.portal.get_registry_record("smartweb.url_formdefs_api") or ""
252
+ except:
253
+ logger.info("La clé 'smartweb.url_formdefs_api' a été supprimée.")
254
+ registry = getUtility(IRegistry)
255
+ records = registry.records
256
+ if "smartweb.url_ts" in records:
257
+ return
258
+ logger.info("Adding smartweb.url_ts to registry") # noqa
259
+ record = Record(
260
+ field.TextLine(
261
+ title=_("Url to e-guichet"),
262
+ description=_("Exemple : https://COMMUNE.guichet-citoyen.be"),
263
+ required=False,
264
+ ),
265
+ value=url_ts,
266
+ )
267
+ records["smartweb.url_ts"] = record
268
+
269
+ record = Record(
270
+ field.TextLine(
271
+ title=_(
272
+ "Username to consume e-guichet ideabox API (get Campaign, projects,...)"
273
+ ),
274
+ default="ideabox",
275
+ required=False,
276
+ )
277
+ )
278
+ records["smartweb.iaideabox_api_username"] = record
279
+
280
+ record = Record(
281
+ field.Password(
282
+ title=_(
283
+ "Password to consume e-guichet ideabox API (get Campaign, projects,...)"
284
+ ),
285
+ required=False,
286
+ )
287
+ )
288
+ records["smartweb.iaideabox_api_password"] = record
289
+ try:
290
+ del registry.records["smartweb.url_formdefs_api"]
291
+ logger.info("La clé 'smartweb.url_formdefs_api' a été supprimée.")
292
+ except KeyError:
293
+ logger.info("La clé 'smartweb.url_formdefs_api' n'existe pas dans le registre.")
@@ -12,6 +12,7 @@ from plone.dexterity.interfaces import IDexterityContent
12
12
  from Products.CMFPlone.defaultpage import get_default_page
13
13
  from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot
14
14
  from Products.CMFPlone.utils import base_hasattr
15
+ from urllib.parse import urlparse, urlunparse
15
16
  from zope.component import getSiteManager
16
17
  from zope.component import queryMultiAdapter
17
18
 
@@ -204,6 +205,11 @@ def get_plausible_vars():
204
205
  return None
205
206
 
206
207
 
208
+ def get_value_from_registry(key):
209
+ val = api.portal.get_registry_record(key)
210
+ return val
211
+
212
+
207
213
  def get_iadeliberation_url_from_registry():
208
214
  iadeliberation_url = api.portal.get_registry_record("smartweb.iadeliberations_url")
209
215
  return iadeliberation_url
@@ -230,6 +236,33 @@ def get_iadeliberation_json(url):
230
236
  return json
231
237
 
232
238
 
239
+ def get_iaideabox_json(url):
240
+ user = api.portal.get_registry_record("smartweb.iaideabox_api_username")
241
+ pwd = api.portal.get_registry_record("smartweb.iaideabox_api_password")
242
+ usrPass = f"{user}:{pwd}".encode("utf-8")
243
+ b64Val = base64.b64encode(usrPass)
244
+ json = get_json(url, auth=f"Basic {b64Val.decode('utf-8')}", timeout=20)
245
+ return json
246
+
247
+
248
+ def get_basic_auth_json(url, user, pwd):
249
+ usrPass = f"{user}:{pwd}".encode("utf-8")
250
+ b64Val = base64.b64encode(usrPass)
251
+ json = get_json(url, auth=f"Basic {b64Val.decode('utf-8')}", timeout=20)
252
+ return json
253
+
254
+
255
+ def get_ts_api_url(service="wcs"):
256
+ url_ts = get_value_from_registry("smartweb.url_ts")
257
+ parsed_url = urlparse(url_ts)
258
+ if "wcs" in service:
259
+ new_netloc = parsed_url.netloc.replace(
260
+ ".guichet-citoyen.be", "-formulaires.guichet-citoyen.be"
261
+ )
262
+ api_url = urlunparse(parsed_url._replace(netloc=new_netloc, path="/api"))
263
+ return api_url
264
+
265
+
233
266
  def remove_cache_key(json_data: dict) -> dict:
234
267
  pattern = re.compile(r"&cache_key=[a-f0-9]{32}")
235
268
  if json_data is None:
@@ -1,7 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from imio.smartweb.locales import SmartwebMessageFactory as _
4
+ from plone import api
3
5
  from plone.app.layout.viewlets import common
4
6
  from zope.component import getMultiAdapter
7
+ from zope.i18n import translate
5
8
  from zope.viewlet.interfaces import IViewletManager
6
9
 
7
10
 
@@ -10,7 +13,14 @@ class HeaderActionsViewlet(common.ViewletBase):
10
13
  context_state = getMultiAdapter(
11
14
  (self.context, self.request), name="plone_context_state"
12
15
  )
16
+ language = api.portal.get_current_language(context=self.context)
13
17
  self.actions = context_state.actions("header_actions")
18
+ for action in self.actions:
19
+ if action["id"] == "account":
20
+ action["link_target"] = "_blank"
21
+ desc = translate(_(action["description"]), target_language=language)
22
+ new_tab = translate(_("New tab"), target_language=language)
23
+ action["description"] = f"{desc} ({new_tab})"
14
24
 
15
25
 
16
26
  class HeaderActionsContainerViewlet(common.ViewletBase):
@@ -5,6 +5,8 @@
5
5
  <a href="#"
6
6
  tal:define="icon nocall:link/icon"
7
7
  tal:attributes="class link/id;
8
+ target link/link_target;
9
+ title link/description;
8
10
  href link/url;">
9
11
  <span tal:condition="not:icon"
10
12
  tal:content="link/title">
@@ -1,13 +1,38 @@
1
1
  <div class="offcanvas offcanvas-start" tabindex="-1" id="offcanvasSearch" aria-labelledby="offcanvasSearchLabel">
2
2
  <div class="offcanvas-header">
3
- <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
3
+ <button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close" tabindex="-1"></button>
4
4
  </div>
5
5
  <div class="offcanvas-body">
6
- <div class="search">
7
- <smartweb-search tal:attributes="current-language view/current_language;
8
- query-url view/navroot_url;
9
- result-option view/get_search_result_option">
10
- </smartweb-search >
6
+ <div class="search" id="search-container">
7
+ <template id="search-template">
8
+ <smartweb-search tal:attributes="current-language view/current_language;
9
+ query-url view/navroot_url;
10
+ result-option view/get_search_result_option">
11
+ </smartweb-search>
12
+ </template>
11
13
  </div>
12
14
  </div>
13
15
  </div>
16
+
17
+ <script>
18
+ document.addEventListener('DOMContentLoaded', function() {
19
+ const offcanvas = document.getElementById('offcanvasSearch');
20
+ const searchContainer = document.getElementById('search-container');
21
+ const template = document.getElementById('search-template');
22
+ let searchContent = null;
23
+
24
+ offcanvas.addEventListener('show.bs.offcanvas', function () {
25
+ if (!searchContent) {
26
+ searchContent = template.content.cloneNode(true);
27
+ searchContainer.appendChild(searchContent);
28
+ }
29
+ });
30
+
31
+ offcanvas.addEventListener('hidden.bs.offcanvas', function () {
32
+ if (searchContent) {
33
+ searchContainer.innerHTML = '';
34
+ searchContent = null;
35
+ }
36
+ });
37
+ });
38
+ </script>
@@ -55,6 +55,13 @@ class OgpTagsViewlet(HeaderViewlet):
55
55
  self._set_image()
56
56
 
57
57
  def set_ogp_informations_for_item(self):
58
+ result_json = None
59
+ if (
60
+ not IDirectoryView.providedBy(self.context)
61
+ and not IEventsView.providedBy(self.context)
62
+ and not INewsView.providedBy(self.context)
63
+ ):
64
+ return result_json
58
65
  uid = self.request.form["u"]
59
66
  auth_source_url = ""
60
67
  endpoint = "@search"
@@ -75,6 +82,8 @@ class OgpTagsViewlet(HeaderViewlet):
75
82
  client_id = os.environ.get("RESTAPI_NEWS_CLIENT_ID")
76
83
  client_secret = os.environ.get("RESTAPI_NEWS_CLIENT_SECRET")
77
84
  auth = get_wca_token(client_id, client_secret)
85
+ if not auth:
86
+ return
78
87
  auth_source_url = f"{auth_source_url}/{endpoint}?UID={uid}&{params}"
79
88
  result_json = get_json(auth_source_url, auth=auth)
80
89
  if result_json:
@@ -1,5 +1,5 @@
1
1
  <div id="subsite-logo" tal:condition="view/available">
2
- <a tal:attributes="href string:${view/subsite_root/absolute_url}">
2
+ <a tal:attributes="href string:${view/subsite_root/absolute_url}; aria-label string:accueil du sous-site">
3
3
  <img tal:condition="view/show_logo"
4
4
  tal:attributes="src view/get_logo_scale_url;
5
5
  alt view/subsite_root/title;