imio.smartweb.core 1.2.91__py3-none-any.whl → 1.3.1__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 (107) hide show
  1. imio/smartweb/core/browser/configure.zcml +16 -0
  2. imio/smartweb/core/browser/controlpanel.py +42 -5
  3. imio/smartweb/core/browser/search/search.py +15 -0
  4. imio/smartweb/core/browser/sitemap.py +155 -107
  5. imio/smartweb/core/browser/utils.py +4 -1
  6. imio/smartweb/core/configure.zcml +5 -1
  7. imio/smartweb/core/contents/__init__.py +2 -0
  8. imio/smartweb/core/contents/rest/base.py +5 -2
  9. imio/smartweb/core/contents/rest/campaign/__init__.py +0 -0
  10. imio/smartweb/core/contents/rest/campaign/configure.zcml +80 -0
  11. imio/smartweb/core/contents/rest/campaign/content.py +83 -0
  12. imio/smartweb/core/contents/rest/campaign/endpoint.py +211 -0
  13. imio/smartweb/core/contents/rest/campaign/view.pt +19 -0
  14. imio/smartweb/core/contents/rest/campaign/view.py +29 -0
  15. imio/smartweb/core/contents/rest/configure.zcml +1 -0
  16. imio/smartweb/core/contents/rest/directory/endpoint.py +11 -3
  17. imio/smartweb/core/contents/rest/events/endpoint.py +11 -3
  18. imio/smartweb/core/contents/rest/news/endpoint.py +11 -3
  19. imio/smartweb/core/contents/rest/search/endpoint.py +4 -1
  20. imio/smartweb/core/contents/rest/utils.py +3 -3
  21. imio/smartweb/core/interfaces.py +6 -0
  22. imio/smartweb/core/overrides.zcml +10 -0
  23. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  24. imio/smartweb/core/profiles/ideabox/browserlayer.xml +7 -0
  25. imio/smartweb/core/profiles/ideabox/metadata.xml +5 -0
  26. imio/smartweb/core/profiles/ideabox/registry/iaideabox.xml +9 -0
  27. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.CampaignView.xml +40 -0
  28. imio/smartweb/core/profiles/ideabox/types/imio.smartweb.Folder.xml +71 -0
  29. imio/smartweb/core/profiles/ideabox/types.xml +17 -0
  30. imio/smartweb/core/profiles/ideabox_uninstall/browserlayer.xml +7 -0
  31. imio/smartweb/core/profiles/ideabox_uninstall/types/imio.smartweb.Folder.xml +25 -0
  32. imio/smartweb/core/profiles/ideabox_uninstall/types.xml +4 -0
  33. imio/smartweb/core/profiles/testing/metadata.xml +1 -0
  34. imio/smartweb/core/profiles/testing/registry.xml +2 -2
  35. imio/smartweb/core/profiles.zcml +18 -0
  36. imio/smartweb/core/subscribers.py +27 -1
  37. imio/smartweb/core/subscribers.zcml +8 -0
  38. imio/smartweb/core/tests/resources/json_ideabox_campaign.json +222 -0
  39. imio/smartweb/core/tests/resources/json_ideabox_campaigns.json +425 -0
  40. imio/smartweb/core/tests/resources/json_ideabox_projects.json +1871 -0
  41. imio/smartweb/core/tests/test_iadeliberations.py +38 -40
  42. imio/smartweb/core/tests/test_ideabox.py +152 -0
  43. imio/smartweb/core/tests/test_procedure.py +7 -3
  44. imio/smartweb/core/tests/test_rest.py +6 -1
  45. imio/smartweb/core/tests/test_sitemap.py +81 -42
  46. imio/smartweb/core/tests/test_vocabularies.py +8 -10
  47. imio/smartweb/core/tests/test_vocabulary.py +18 -0
  48. imio/smartweb/core/upgrades/configure.zcml +16 -1
  49. imio/smartweb/core/upgrades/upgrades.py +64 -0
  50. imio/smartweb/core/utils.py +33 -0
  51. imio/smartweb/core/viewlets/offcanvas.pt +2 -0
  52. imio/smartweb/core/viewlets/ogptags.py +9 -0
  53. imio/smartweb/core/vocabularies.py +35 -4
  54. imio/smartweb/core/vocabularies.zcml +6 -0
  55. imio/smartweb/core/webcomponents/build/css/373.smartweb-webcomponents-compiled.css +1 -1
  56. imio/smartweb/core/webcomponents/build/css/420.smartweb-webcomponents-compiled.css +1 -0
  57. imio/smartweb/core/webcomponents/build/css/486.smartweb-webcomponents-compiled.css +1 -1
  58. imio/smartweb/core/webcomponents/build/css/666.smartweb-webcomponents-compiled.css +1 -0
  59. imio/smartweb/core/webcomponents/build/css/884.smartweb-webcomponents-compiled.css +1 -1
  60. imio/smartweb/core/webcomponents/build/css/919.smartweb-webcomponents-compiled.css +1 -1
  61. imio/smartweb/core/webcomponents/build/css/smartweb-webcomponents-compiled.css +1 -1
  62. imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js +2 -0
  63. imio/smartweb/core/webcomponents/build/js/{828.smartweb-webcomponents-compiled.js.LICENSE.txt → 141.smartweb-webcomponents-compiled.js.LICENSE.txt} +3 -3
  64. imio/smartweb/core/webcomponents/build/js/15.smartweb-webcomponents-compiled.js +2 -0
  65. imio/smartweb/core/webcomponents/build/js/21.smartweb-webcomponents-compiled.js +1 -0
  66. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js +1 -1
  67. imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js.LICENSE.txt +0 -5
  68. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  69. imio/smartweb/core/webcomponents/build/js/486.smartweb-webcomponents-compiled.js +1 -1
  70. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -0
  71. imio/smartweb/core/webcomponents/build/js/799.smartweb-webcomponents-compiled.js +1 -1
  72. imio/smartweb/core/webcomponents/build/js/824.smartweb-webcomponents-compiled.js +1 -1
  73. imio/smartweb/core/webcomponents/build/js/884.smartweb-webcomponents-compiled.js +1 -1
  74. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  75. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -0
  76. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  77. imio/smartweb/core/webcomponents/package.json +80 -80
  78. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +1 -0
  79. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.jsx +306 -0
  80. imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.scss +672 -0
  81. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignCard/CampaignCard.jsx +79 -0
  82. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignContent/CampaignContent.jsx +193 -0
  83. imio/smartweb/core/webcomponents/src/components/Campaign/CampaignList/CampaignList.jsx +67 -0
  84. imio/smartweb/core/webcomponents/src/components/Campaign/Filters/Filter.jsx +259 -0
  85. imio/smartweb/core/webcomponents/src/components/Campaign/index.js +2 -0
  86. imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +1 -0
  87. imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +0 -1
  88. imio/smartweb/core/webcomponents/src/components/Search/Search.jsx +54 -9
  89. imio/smartweb/core/webcomponents/src/components/Search/Search.scss +9 -0
  90. imio/smartweb/core/webcomponents/src/hooks/useAxios.js +45 -9
  91. imio/smartweb/core/webcomponents/src/index.jsx +2 -0
  92. imio/smartweb/core/webcomponents/src/index.scss +2 -2
  93. imio/smartweb/core/webcomponents/src/utils/CampaignMap.jsx +177 -0
  94. imio/smartweb/core/webcomponents/src/utils/Map.jsx +1 -1
  95. imio/smartweb/core/webcomponents/src/utils/Map.scss +15 -1
  96. imio/smartweb/core/webcomponents/src/utils/translation.js +247 -199
  97. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/METADATA +24 -1
  98. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/RECORD +105 -72
  99. imio/smartweb/core/webcomponents/build/js/499.smartweb-webcomponents-compiled.js +0 -2
  100. imio/smartweb/core/webcomponents/build/js/828.smartweb-webcomponents-compiled.js +0 -2
  101. /imio/smartweb/core/webcomponents/build/js/{499.smartweb-webcomponents-compiled.js.LICENSE.txt → 15.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  102. /imio.smartweb.core-1.2.91-py3.12-nspkg.pth → /imio.smartweb.core-1.3.1-py3.12-nspkg.pth +0 -0
  103. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.GPL +0 -0
  104. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.rst +0 -0
  105. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/WHEEL +0 -0
  106. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/namespace_packages.txt +0 -0
  107. {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.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,152 @@
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
+ # CampaignNameChooser : Give th Title to our object thanks to e-guichet object Title.
89
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
90
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
91
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_basic_auth_json")
92
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_value_from_registry")
93
+ def test_campaign_name_chooser(
94
+ self,
95
+ m_get_value_from_registry_namechooser,
96
+ m_get_basic_auth_json_namechooser,
97
+ m_get_value_from_registry,
98
+ m_get_basic_auth_json,
99
+ ):
100
+ from imio.smartweb.core.contents.rest.campaign.content import CampaignView
101
+ from zope.component import queryAdapter
102
+ from zope.container.interfaces import INameChooser
103
+
104
+ m_get_value_from_registry.return_value = (
105
+ "https://staging3-formulaires.guichet-citoyen.be/api"
106
+ )
107
+ m_get_basic_auth_json.return_value = self.json_campaign_raw_mock
108
+
109
+ m_get_value_from_registry_namechooser.return_value = (
110
+ "https://staging3-formulaires.guichet-citoyen.be/api"
111
+ )
112
+ m_get_basic_auth_json_namechooser.return_value = self.json_campaign_raw_mock
113
+ campaign_view = CampaignView(id="test-campaign", title=None)
114
+ campaign_view.linked_campaign = "2"
115
+ name_chooser = queryAdapter(self.folder, INameChooser)
116
+ generated_id = name_chooser.chooseName(None, campaign_view)
117
+ self.assertEqual(campaign_view.title, "Sprint iMio Fall 2024")
118
+ self.assertEqual(generated_id, "sprint-imio-fall-2024")
119
+
120
+ @requests_mock.Mocker()
121
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
122
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
123
+ def test_get_projects(self, m_get_value_from_registry, m_get_basic_auth_json, m):
124
+ m_get_value_from_registry.return_value = (
125
+ "https://staging3-formulaires.guichet-citoyen.be/api"
126
+ )
127
+ m_get_basic_auth_json.return_value = self.json_campaign_raw_mock
128
+ campaign_view = api.content.create(
129
+ id="kamoulox",
130
+ container=self.folder,
131
+ type="imio.smartweb.CampaignView",
132
+ linked_campaign="2",
133
+ )
134
+ # react additionnal fields request.
135
+ # form={
136
+ # "taxonomy_contact_category_for_filtering": ("token"),
137
+ # "topics": "education",
138
+ # }
139
+
140
+ request = TestRequest()
141
+ endpoint = CampaignEndpoint(campaign_view, request)
142
+ url = endpoint.query_url
143
+ self.assertEqual(
144
+ url,
145
+ "https://demo-formulaires.guichet-citoyen.be/api/cards/imio-ideabox-projet/list?filter-campagne=2&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&",
146
+ )
147
+
148
+ m.get(url, text=json.dumps({}))
149
+ call = endpoint()
150
+ self.assertEqual(call, {})
151
+
152
+ # 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",
@@ -25,6 +25,7 @@ from zope.component import queryMultiAdapter
25
25
  from zope.event import notify
26
26
  from zope.publisher.browser import TestRequest
27
27
  from ZPublisher.pubevents import PubStart
28
+ from imio.smartweb.core.viewlets.ogptags import OgpTagsViewlet
28
29
 
29
30
  import json
30
31
  import requests_mock
@@ -281,6 +282,7 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
281
282
  self.assertIn('<meta property="og:image:width" content="400">', view())
282
283
  self.assertIn('<meta property="og:image:height" content="400">', view())
283
284
 
285
+ # @mock.patch.dict(os.environ, {"client_id": "Kamoulox", "client_secret": "Kamoulox"})
284
286
  @patch("imio.smartweb.core.viewlets.ogptags.get_wca_token")
285
287
  @patch("imio.smartweb.core.viewlets.ogptags.get_json")
286
288
  def test_render_rest_auth_sources_item(self, mock_get_json, mock_get_wca_token):
@@ -304,6 +306,9 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
304
306
  }
305
307
  UID = "3c436a800154449f84797fdb30561297"
306
308
  self.request.form["u"] = UID
309
+ # viewlet = OgpTagsViewlet(self.portal, self.request, None, None)
310
+ # viewlet.update()
311
+
307
312
  view = queryMultiAdapter(
308
313
  (auth_source["content"], self.request), name="view"
309
314
  )
@@ -437,8 +442,8 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
437
442
  "metadata_fields=UID&"
438
443
  "sort_on=effective&"
439
444
  "sort_order=descending&"
440
- "b_size=20&"
441
445
  "fullobjects=1&"
446
+ "b_size=20&"
442
447
  "translated_in_en=1".format(self.rest_news.selected_news_folder),
443
448
  )
444
449
  m.get(url, text=json.dumps({}))
@@ -3,6 +3,8 @@
3
3
  from freezegun import freeze_time
4
4
  from gzip import GzipFile
5
5
  from io import BytesIO
6
+ from imio.smartweb.core.browser.sitemap import CatalogSiteMap
7
+ from imio.smartweb.core.browser.sitemap import get_endpoint_data
6
8
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
7
9
  from imio.smartweb.core.testing import ImioSmartwebTestCase
8
10
  from imio.smartweb.core.tests.utils import get_json
@@ -14,9 +16,9 @@ from plone.app.textfield.value import RichTextValue
14
16
  from plone.base.utils import safe_text
15
17
  from plone.namedfile.file import NamedBlobImage
16
18
  from unittest.mock import patch
19
+ from unittest.mock import Mock
17
20
  from zope.component import getMultiAdapter
18
21
 
19
- import json
20
22
  import requests_mock
21
23
 
22
24
 
@@ -76,6 +78,10 @@ class TestPage(ImioSmartwebTestCase):
76
78
  title="news view",
77
79
  )
78
80
  self.rest_news.selected_news_folder = "64f4cbee9a394a018a951f6d94452914"
81
+ self.json_rest_directory = get_json("resources/json_rest_directory.json")
82
+ self.json_rest_events = get_json("resources/json_rest_events.json")
83
+ self.json_rest_news = get_json("resources/json_rest_news.json")
84
+
79
85
  api.content.transition(self.rest_directory, "publish")
80
86
  api.content.transition(self.rest_agenda, "publish")
81
87
  api.content.transition(self.rest_news, "publish")
@@ -111,60 +117,93 @@ class TestPage(ImioSmartwebTestCase):
111
117
  (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
112
118
  )
113
119
  xml = self.uncompress(sitemap())
114
- self.assertIn(
115
- "<loc>http://nohost/plone/folder/page1/gallery/image/view</loc>", xml
116
- )
120
+ self.assertIn("<loc>http://nohost/plone/folder/page1/gallery/image</loc>", xml)
117
121
  # Gallery and image created 2024-02-02 10:00:00
118
122
  self.assertIn(
119
- "<loc>http://nohost/plone/folder/page1/gallery/image/view</loc>\n <lastmod >2024-02-02T10:00:00",
123
+ "<loc>http://nohost/plone/folder/page1/gallery/image</loc>\n <lastmod >2024-02-02T10:00:00",
120
124
  xml,
121
125
  )
122
-
123
- rest_views = {
124
- "directory": self.rest_directory,
125
- "events": self.rest_agenda,
126
- "news": self.rest_news,
127
- }
128
- contact_search_url = news_search_url = events_search_url = (
129
- "http://localhost:8080/Plone/@querystring-search"
130
- )
131
- for k, v in rest_views.items():
132
- api.portal.set_registry_record(f"smartweb.default_{k}_view", v.UID())
133
126
  with patch(
134
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
135
- return_value="kamoulox",
136
- ):
137
- self.json_contacts = get_json("resources/json_contacts_raw_mock.json")
138
- m.post(contact_search_url, text=json.dumps(self.json_contacts))
139
- sitemap = getMultiAdapter(
140
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
127
+ "imio.smartweb.core.contents.rest.news.endpoint.BaseNewsEndpoint.__call__",
128
+ return_value=self.json_rest_news,
129
+ ) as mypatch:
130
+ xml = self.uncompress(sitemap())
131
+ self.assertIn(
132
+ "<loc>http://nohost/plone/news-view/ceci-est-une-deuxieme-actualite",
133
+ xml,
141
134
  )
135
+ with patch(
136
+ "imio.smartweb.core.contents.rest.directory.endpoint.BaseDirectoryEndpoint.__call__",
137
+ return_value=self.json_rest_directory,
138
+ ) as mypatch:
142
139
  xml = self.uncompress(sitemap())
143
- self.assertIn("<loc>http://nohost/plone/directory-view/contact1-title", xml)
144
-
140
+ self.assertIn(
141
+ "<loc>http://nohost/plone/directory-view/service-communication-de-ladministration-communale",
142
+ xml,
143
+ )
145
144
  with patch(
146
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
147
- return_value="kamoulox",
145
+ "imio.smartweb.core.contents.rest.events.endpoint.BaseEventsEndpoint.__call__",
146
+ return_value=self.json_rest_events,
148
147
  ):
149
- self.json_news = get_json("resources/json_rest_news.json")
150
- m.post(news_search_url, text=json.dumps(self.json_news))
151
- sitemap = getMultiAdapter(
152
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
153
- )
154
148
  xml = self.uncompress(sitemap())
155
- self.assertIn("<loc>http://nohost/plone/news-view/", xml)
149
+ self.assertIn(
150
+ "<loc>http://nohost/plone/agenda-view/evenement-recurrent-tous-les-samedi",
151
+ xml,
152
+ )
153
+
154
+ def test_site_map_for_user_display(self):
155
+ sitemap = CatalogSiteMap(self.portal, self.request)
156
+ # 3 authentic sources
157
+ self.assertEqual(len(sitemap.siteMap().get("children")), 3)
158
+ self.assertNotIn(
159
+ "Folder",
160
+ [child.get("Title") for child in sitemap.siteMap().get("children")],
161
+ )
162
+
163
+ # Publish folder and page (private content don't appear in sitemap)
164
+ api.content.transition(self.folder, "publish")
165
+ api.content.transition(self.page, "publish")
166
+ sitemap = CatalogSiteMap(self.portal, self.request)
167
+ self.assertEqual(len(sitemap.siteMap().get("children")), 4)
168
+ self.assertIn(
169
+ "Folder",
170
+ [child.get("Title") for child in sitemap.siteMap().get("children")],
171
+ )
172
+ folder_entry = [
173
+ child
174
+ for child in sitemap.siteMap().get("children")
175
+ if child.get("Title") == "Folder"
176
+ ][0]
177
+ self.assertIn(
178
+ "Page 1", [child.get("Title") for child in folder_entry.get("children")]
179
+ )
180
+
181
+ directory_entry = [
182
+ child
183
+ for child in sitemap.siteMap().get("children")
184
+ if child.get("Title") == "directory view"
185
+ ][0]
186
+ self.assertEqual(len(directory_entry.get("children")), 0)
156
187
 
188
+ # Populate directory view with 6 contacts
157
189
  with patch(
158
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
159
- return_value="kamoulox",
190
+ "imio.smartweb.core.contents.rest.directory.endpoint.BaseDirectoryEndpoint.__call__",
191
+ return_value=self.json_rest_directory,
160
192
  ):
161
- self.json_events = get_json("resources/json_rest_events.json")
162
- m.post(events_search_url, text=json.dumps(self.json_events))
163
- sitemap = getMultiAdapter(
164
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
165
- )
166
- xml = self.uncompress(sitemap())
167
- self.assertIn("<loc>http://nohost/plone/agenda-view/", xml)
193
+ sitemap = CatalogSiteMap(self.portal, self.request)
194
+ directory_entry = [
195
+ child
196
+ for child in sitemap.siteMap().get("children")
197
+ if child.get("Title") == "directory view"
198
+ ][0]
199
+ self.assertEqual(len(directory_entry.get("children")), 6)
200
+
201
+ def test_bad_portal_type(self):
202
+ obj = Mock()
203
+ obj.portal_type = None
204
+ request = Mock()
205
+ result = get_endpoint_data(obj, request)
206
+ assert result == {}
168
207
 
169
208
  def uncompress(self, sitemapdata):
170
209
  sio = BytesIO(sitemapdata)
@@ -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):
@@ -41,3 +41,21 @@ class TestVocabulary(ImioSmartwebTestCase):
41
41
  self.assertEqual(
42
42
  result["results"][0]["text"], "Activités et divertissement"
43
43
  )
44
+
45
+ self.page = api.content.create(
46
+ container=self.portal,
47
+ type="imio.smartweb.Page",
48
+ title="My Page",
49
+ )
50
+ self.contacts = api.content.create(
51
+ container=self.page,
52
+ type="imio.smartweb.SectionContact",
53
+ title="My contancts",
54
+ )
55
+ self.request.form = {
56
+ "name": "imio.smartweb.vocabulary.RemoteContacts",
57
+ "field": "related_contacts",
58
+ }
59
+ view = queryMultiAdapter((self.contacts, self.request), name="getVocabulary")
60
+ result = json.loads(view())
61
+ self.assertEqual(result["results"], [])
@@ -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.")