imio.smartweb.core 1.1.14__py3-none-any.whl → 1.1.19__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 (133) hide show
  1. imio/smartweb/core/browser/configure.zcml +1 -0
  2. imio/smartweb/core/browser/controlpanel.py +24 -0
  3. imio/smartweb/core/browser/dashboards/__init__.py +0 -0
  4. imio/smartweb/core/browser/dashboards/configure.zcml +17 -0
  5. imio/smartweb/core/browser/dashboards/plausible.pt +29 -0
  6. imio/smartweb/core/browser/dashboards/plausible.py +21 -0
  7. imio/smartweb/core/browser/faceted/map.pt +3 -7
  8. imio/smartweb/core/browser/overrides/plone.app.content.browser.contents.templates.properties.pt +48 -0
  9. imio/smartweb/core/browser/static/icons/categorie-horaires.svg +2 -2
  10. imio/smartweb/core/browser/static/icons/reseausocial-facebook.svg +1 -1
  11. imio/smartweb/core/browser/static/icons/reseausocial-youtube.svg +1 -1
  12. imio/smartweb/core/browser/static/smartweb-swiperconfig-compiled.js +1 -0
  13. imio/smartweb/core/browser/static/smartweb-view-compiled.js +1 -1
  14. imio/smartweb/core/browser/static/src/swiper-config.js +46 -0
  15. imio/smartweb/core/browser/static/src/view.js +1 -46
  16. imio/smartweb/core/browser/static/swiper-bundle.min.css +4 -4
  17. imio/smartweb/core/browser/static/swiper-bundle.min.js +5 -4
  18. imio/smartweb/core/browser/static/webpack.config.js +2 -0
  19. imio/smartweb/core/browser/utils.py +33 -0
  20. imio/smartweb/core/contents/__init__.py +4 -0
  21. imio/smartweb/core/contents/cropping.py +3 -6
  22. imio/smartweb/core/contents/folder/content.py +1 -5
  23. imio/smartweb/core/contents/folder/views.py +3 -1
  24. imio/smartweb/core/contents/pages/pages.py +0 -5
  25. imio/smartweb/core/contents/pages/view.pt +3 -0
  26. imio/smartweb/core/contents/rest/base.py +16 -0
  27. imio/smartweb/core/contents/rest/directory/endpoint.py +8 -15
  28. imio/smartweb/core/contents/rest/events/endpoint.py +6 -12
  29. imio/smartweb/core/contents/rest/news/endpoint.py +6 -11
  30. imio/smartweb/core/contents/rest/search/endpoint.py +26 -6
  31. imio/smartweb/core/contents/sections/configure.zcml +1 -0
  32. imio/smartweb/core/contents/sections/contact/view.pt +1 -2
  33. imio/smartweb/core/contents/sections/contact/view.py +6 -8
  34. imio/smartweb/core/contents/sections/events/view.py +6 -7
  35. imio/smartweb/core/contents/sections/external_content/__init__.py +0 -0
  36. imio/smartweb/core/contents/sections/external_content/configure.zcml +14 -0
  37. imio/smartweb/core/contents/sections/external_content/content.py +32 -0
  38. imio/smartweb/core/contents/sections/external_content/view.pt +31 -0
  39. imio/smartweb/core/contents/sections/external_content/views.py +31 -0
  40. imio/smartweb/core/contents/sections/gallery/view.pt +1 -2
  41. imio/smartweb/core/contents/sections/macros.pt +0 -4
  42. imio/smartweb/core/contents/sections/news/view.py +6 -7
  43. imio/smartweb/core/contents/sections/text/configure.zcml +0 -6
  44. imio/smartweb/core/contents/sections/text/content.py +0 -12
  45. imio/smartweb/core/contents/sections/text/forms.py +2 -0
  46. imio/smartweb/core/contents/sections/views.py +25 -0
  47. imio/smartweb/core/permissions.zcml +6 -0
  48. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  49. imio/smartweb/core/profiles/default/rolemap.xml +6 -0
  50. imio/smartweb/core/profiles/default/types/imio.smartweb.Page.xml +1 -0
  51. imio/smartweb/core/profiles/default/types/imio.smartweb.PortalPage.xml +1 -0
  52. imio/smartweb/core/profiles/default/types/imio.smartweb.Procedure.xml +1 -0
  53. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionContact.xml +0 -1
  54. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionEvents.xml +0 -1
  55. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionExternalContent.xml +35 -0
  56. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionFiles.xml +0 -1
  57. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionGallery.xml +0 -1
  58. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionHTML.xml +1 -1
  59. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionLinks.xml +0 -1
  60. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionMap.xml +0 -1
  61. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionNews.xml +0 -1
  62. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionPostit.xml +0 -1
  63. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSelections.xml +0 -1
  64. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSendinblue.xml +0 -1
  65. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSlide.xml +0 -1
  66. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionText.xml +0 -1
  67. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionVideo.xml +0 -1
  68. imio/smartweb/core/profiles/default/types.xml +1 -0
  69. imio/smartweb/core/profiles/default/workflows.xml +1 -0
  70. imio/smartweb/core/tests/resources/json_rest_directory.json +1099 -0
  71. imio/smartweb/core/tests/resources/json_rest_events.json +1099 -0
  72. imio/smartweb/core/tests/resources/json_rest_news.json +1103 -4
  73. imio/smartweb/core/tests/test_cropping.py +6 -28
  74. imio/smartweb/core/tests/test_folder.py +17 -13
  75. imio/smartweb/core/tests/test_page.py +0 -13
  76. imio/smartweb/core/tests/test_plausibleview.py +83 -0
  77. imio/smartweb/core/tests/test_rest.py +40 -0
  78. imio/smartweb/core/tests/test_section_contact.py +45 -0
  79. imio/smartweb/core/tests/test_section_events.py +56 -10
  80. imio/smartweb/core/tests/test_section_news.py +46 -11
  81. imio/smartweb/core/tests/test_sections.py +34 -0
  82. imio/smartweb/core/upgrades/configure.zcml +90 -0
  83. imio/smartweb/core/upgrades/profiles/1037_to_1038/registry/plausible.xml +9 -0
  84. imio/smartweb/core/upgrades/profiles/1038_to_1039/rolemap.xml +12 -0
  85. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.Page.xml +11 -0
  86. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.PortalPage.xml +11 -0
  87. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.Procedure.xml +11 -0
  88. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.SectionExternalContent.xml +36 -0
  89. imio/smartweb/core/upgrades/profiles/1038_to_1039/types.xml +4 -0
  90. imio/smartweb/core/upgrades/profiles/1038_to_1039/workflows.xml +6 -0
  91. imio/smartweb/core/upgrades/profiles/1039_to_1040/types/imio.smartweb.SectionSlide.xml +14 -0
  92. imio/smartweb/core/upgrades/profiles/1040_to_1041/types/imio.smartweb.SectionText.xml +17 -0
  93. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionContact.xml +14 -0
  94. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionEvents.xml +14 -0
  95. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionExternalContent.xml +15 -0
  96. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionFiles.xml +14 -0
  97. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionGallery.xml +15 -0
  98. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionLinks.xml +14 -0
  99. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionMap.xml +15 -0
  100. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionNews.xml +14 -0
  101. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionPostit.xml +14 -0
  102. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionSelections.xml +14 -0
  103. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionSendinblue.xml +14 -0
  104. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionVideo.xml +15 -0
  105. imio/smartweb/core/webcomponents/build/css/195.smartweb-webcomponents-compiled.css +1 -1
  106. imio/smartweb/core/webcomponents/build/css/552.smartweb-webcomponents-compiled.css +1 -1
  107. imio/smartweb/core/webcomponents/build/js/195.smartweb-webcomponents-compiled.js +1 -1
  108. imio/smartweb/core/webcomponents/build/js/212.smartweb-webcomponents-compiled.js +2 -0
  109. imio/smartweb/core/webcomponents/build/js/323.smartweb-webcomponents-compiled.js +1 -1
  110. imio/smartweb/core/webcomponents/build/js/510.smartweb-webcomponents-compiled.js +1 -1
  111. imio/smartweb/core/webcomponents/build/js/552.smartweb-webcomponents-compiled.js +1 -1
  112. imio/smartweb/core/webcomponents/build/js/{462.smartweb-webcomponents-compiled.js → 565.smartweb-webcomponents-compiled.js} +1 -1
  113. imio/smartweb/core/webcomponents/build/js/{842.smartweb-webcomponents-compiled.js → 729.smartweb-webcomponents-compiled.js} +2 -2
  114. imio/smartweb/core/webcomponents/build/js/9.smartweb-webcomponents-compiled.js +1 -1
  115. imio/smartweb/core/webcomponents/build/js/9.smartweb-webcomponents-compiled.js.LICENSE.txt +2 -2
  116. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  117. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactCard/ContactCard.jsx +2 -3
  118. imio/smartweb/core/webcomponents/src/components/Events/ContactCard/ContactCard.jsx +1 -2
  119. imio/smartweb/core/webcomponents/src/components/Events/Events.jsx +0 -1
  120. imio/smartweb/core/webcomponents/src/components/News/ContactCard/ContactCard.jsx +1 -2
  121. imio/smartweb/core/webcomponents/src/components/News/ContactContent/ContactContent.jsx +1 -1
  122. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/METADATA +106 -18
  123. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/RECORD +131 -96
  124. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/WHEEL +1 -1
  125. imio/smartweb/core/webcomponents/build/assets/img-placeholder-bla.a2b8b384c46ce56c99f042dc4625d309.png +0 -0
  126. imio/smartweb/core/webcomponents/build/js/650.smartweb-webcomponents-compiled.js +0 -2
  127. /imio/smartweb/core/webcomponents/build/js/{650.smartweb-webcomponents-compiled.js.LICENSE.txt → 212.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  128. /imio/smartweb/core/webcomponents/build/js/{842.smartweb-webcomponents-compiled.js.LICENSE.txt → 729.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  129. /imio.smartweb.core-1.1.14-nspkg.pth → /imio.smartweb.core-1.1.19-py3.10-nspkg.pth +0 -0
  130. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/LICENSE.GPL +0 -0
  131. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/LICENSE.rst +0 -0
  132. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/namespace_packages.txt +0 -0
  133. {imio.smartweb.core-1.1.14.dist-info → imio.smartweb.core-1.1.19.dist-info}/top_level.txt +0 -0
@@ -41,9 +41,7 @@ class TestCropping(ImioSmartwebTestCase):
41
41
  contentFilter={"portal_type": "imio.smartweb.Footer"}
42
42
  )[0]
43
43
  adapter = ICropping(footer, alternate=None)
44
- self.assertEqual(
45
- ["affiche"], adapter.get_scales("background_image", self.request)
46
- )
44
+ self.assertEqual([], adapter.get_scales("background_image", self.request))
47
45
 
48
46
  # minisite cropping
49
47
  view = getMultiAdapter((self.folder, self.request), name="minisite_settings")
@@ -52,7 +50,7 @@ class TestCropping(ImioSmartwebTestCase):
52
50
  self.assertEqual(
53
51
  ["liste", "vignette", "slide"], adapter.get_scales("image", self.request)
54
52
  )
55
- self.assertEqual(["banner"], adapter.get_scales("banner", self.request))
53
+ self.assertEqual([], adapter.get_scales("banner", self.request))
56
54
  self.assertEqual(["preview"], adapter.get_scales("logo", self.request))
57
55
  view.disable()
58
56
 
@@ -63,14 +61,14 @@ class TestCropping(ImioSmartwebTestCase):
63
61
  self.assertEqual(
64
62
  ["liste", "vignette", "slide"], adapter.get_scales("image", self.request)
65
63
  )
66
- self.assertEqual(["banner"], adapter.get_scales("banner", self.request))
64
+ self.assertEqual([], adapter.get_scales("banner", self.request))
67
65
  self.assertEqual(["preview"], adapter.get_scales("logo", self.request))
68
66
  view.disable()
69
67
 
70
68
  # folder cropping
71
69
  adapter = ICropping(self.folder, alternate=None)
72
70
  self.assertIsNotNone(adapter)
73
- self.assertEqual(["banner"], adapter.get_scales("banner", self.request))
71
+ self.assertEqual([], adapter.get_scales("banner", self.request))
74
72
  self.assertNotIn("banner", adapter.get_scales("image", self.request))
75
73
 
76
74
  # page cropping
@@ -89,36 +87,16 @@ class TestCropping(ImioSmartwebTestCase):
89
87
  )
90
88
  adapter = ICropping(section, alternate=None)
91
89
  self.assertIsNotNone(adapter)
92
- self.assertIn(
93
- "affiche", adapter.get_scales("background_image", self.request)
94
- )
90
+ self.assertEqual([], adapter.get_scales("background_image", self.request))
95
91
  self.assertNotIn("banner", adapter.get_scales("image", self.request))
96
- if section_type == "imio.smartweb.SectionText":
97
- self.assertEqual(
98
- ["affiche"], adapter.get_scales("background_image", self.request)
99
- )
100
- section.image = NamedBlobImage(**make_named_image())
101
- section.image_size = "preview"
102
- self.assertEqual(["preview"], adapter.get_scales("image", self.request))
103
- section.image_size = "large"
104
- self.assertEqual(["large"], adapter.get_scales("image", self.request))
105
- section.image_size = "mini"
106
- self.assertEqual(["mini"], adapter.get_scales("image", self.request))
107
92
 
108
93
  def test_cropping_view(self):
109
94
  cropping_view = getMultiAdapter(
110
95
  (self.folder, self.request), name="croppingeditor"
111
96
  )
112
- self.assertEqual(len(list(cropping_view._scales("banner"))), 1)
97
+ self.assertEqual(len(list(cropping_view._scales("banner"))), 0)
113
98
  self.assertEqual(len(list(cropping_view._scales("image"))), 3)
114
99
  cropping_view = getMultiAdapter(
115
100
  (self.page, self.request), name="croppingeditor"
116
101
  )
117
102
  self.assertEqual(len(list(cropping_view._scales("image"))), 3)
118
- section = api.content.create(
119
- container=self.page,
120
- type="imio.smartweb.SectionText",
121
- title="Text section",
122
- )
123
- cropping_view = getMultiAdapter((section, self.request), name="croppingeditor")
124
- self.assertEqual(len(list(cropping_view._scales("image"))), 1)
@@ -1,7 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from imio.smartweb.core.contents import IFolder
4
- from imio.smartweb.core.contents import Page
5
4
  from imio.smartweb.core.interfaces import IImioSmartwebCoreLayer
6
5
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
7
6
  from imio.smartweb.core.testing import ImioSmartwebTestCase
@@ -17,7 +16,6 @@ from plone.uuid.interfaces import IUUID
17
16
  from plone.dexterity.interfaces import IDexterityFTI
18
17
  from plone.namedfile.file import NamedBlobImage
19
18
  from plone.testing.zope import Browser
20
- from plone.base.utils import check_id
21
19
  from time import sleep
22
20
  from zope.annotation.interfaces import IAnnotations
23
21
  from zope.component import createObject
@@ -123,17 +121,6 @@ class TestFolder(ImioSmartwebTestCase):
123
121
  title="My {}".format(t),
124
122
  )
125
123
 
126
- def test_checkValidId(self):
127
- folder = api.content.create(
128
- container=self.portal,
129
- type="imio.smartweb.Folder",
130
- title="Folder",
131
- )
132
- page = Page()
133
- self.assertEqual(
134
- check_id(page, "image", contained_by=folder), "${name} is reserved."
135
- )
136
-
137
124
  def test_leadimage_in_folder_block_view(self):
138
125
  folder = api.content.create(
139
126
  container=self.portal,
@@ -379,3 +366,20 @@ class TestFolder(ImioSmartwebTestCase):
379
366
  uuid = IUUID(page2)
380
367
  brains = api.content.find(UID=uuid)
381
368
  self.assertEqual(len(brains), 0)
369
+
370
+ def test_select_view_template(self):
371
+ folder = api.content.create(
372
+ container=self.portal,
373
+ type="imio.smartweb.Folder",
374
+ title="My folder",
375
+ )
376
+ self.request.form = {
377
+ "templateId": "block_view_with_images",
378
+ "form.buttons.apply": "Apply",
379
+ }
380
+ creation_date = folder.ModificationDate()
381
+ view = getMultiAdapter((folder, self.request), name="selectViewTemplate")
382
+ sleep(1)
383
+ view.selectViewTemplate()
384
+ new_date = folder.ModificationDate()
385
+ self.assertNotEqual(creation_date, new_date)
@@ -2,7 +2,6 @@
2
2
 
3
3
  from collective.geolocationbehavior.geolocation import IGeolocatable
4
4
  from imio.smartweb.core.contents import IPage
5
- from imio.smartweb.core.contents import SectionText
6
5
  from imio.smartweb.core.interfaces import IImioSmartwebCoreLayer
7
6
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_INTEGRATION_TESTING
8
7
  from imio.smartweb.core.testing import ImioSmartwebTestCase
@@ -14,7 +13,6 @@ from plone.app.testing import TEST_USER_ID
14
13
  from plone.dexterity.interfaces import IDexterityFTI
15
14
  from plone.formwidget.geolocation.geolocation import Geolocation
16
15
  from plone.uuid.interfaces import IUUID
17
- from plone.base.utils import check_id
18
16
  from time import sleep
19
17
  from unittest.mock import patch
20
18
  from zope.component import createObject
@@ -130,17 +128,6 @@ class TestPage(ImioSmartwebTestCase):
130
128
  title="My {}".format(t),
131
129
  )
132
130
 
133
- def test_checkValidId(self):
134
- page = api.content.create(
135
- container=self.folder,
136
- type="imio.smartweb.Page",
137
- title="Page",
138
- )
139
- section = SectionText()
140
- self.assertEqual(
141
- check_id(section, "image", contained_by=page), "${name} is reserved."
142
- )
143
-
144
131
  def test_js_bundles(self):
145
132
  page = api.content.create(
146
133
  container=self.portal,
@@ -0,0 +1,83 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from plone import api
4
+ from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_INTEGRATION_TESTING
5
+ from imio.smartweb.core.testing import ImioSmartwebTestCase
6
+ from imio.smartweb.core.browser.dashboards.plausible import PlausibleView
7
+ from unittest import mock
8
+ from zope.component import queryMultiAdapter
9
+
10
+ import os
11
+
12
+
13
+ class Testplausible(ImioSmartwebTestCase):
14
+ layer = IMIO_SMARTWEB_CORE_INTEGRATION_TESTING
15
+
16
+ def setUp(self):
17
+ """Custom shared utility setup for tests"""
18
+ self.request = self.layer["request"]
19
+ self.portal = self.layer["portal"]
20
+
21
+ def set_registry_records(self):
22
+ api.portal.set_registry_record("smartweb.plausible_site", "site-registry.be")
23
+ api.portal.set_registry_record("smartweb.plausible_token", "token-registry")
24
+ api.portal.set_registry_record("smartweb.plausible_url", "url-registry.be")
25
+
26
+ @mock.patch.dict(
27
+ os.environ,
28
+ {
29
+ "SMARTWEB_PLAUSIBLE_SITE": "",
30
+ "SMARTWEB_PLAUSIBLE_TOKEN": "",
31
+ "SMARTWEB_PLAUSIBLE_URL": "",
32
+ },
33
+ )
34
+ def test_noenv(self):
35
+ view = PlausibleView(self.portal, self.request)
36
+ self.assertFalse(view.is_plausible_set)
37
+ self.set_registry_records()
38
+ self.assertTrue(view.is_plausible_set)
39
+ self.assertEqual(
40
+ view.get_iframe_src,
41
+ "https://url-registry.be/share/site-registry.be?auth=token-registry&embed=true&theme=light&background=transparent",
42
+ )
43
+ self.assertEqual(
44
+ view.get_embedhostjs_src,
45
+ "https://url-registry.be/js/embed.host.js",
46
+ )
47
+
48
+ @mock.patch.dict(
49
+ os.environ,
50
+ {
51
+ "SMARTWEB_PLAUSIBLE_SITE": "site-varenv.be",
52
+ "SMARTWEB_PLAUSIBLE_TOKEN": "token-varenv",
53
+ "SMARTWEB_PLAUSIBLE_URL": "url-varenv.be",
54
+ },
55
+ )
56
+ def test_env(self):
57
+ view = PlausibleView(self.portal, self.request)
58
+ self.assertTrue(view.is_plausible_set)
59
+ self.assertEqual(
60
+ view.get_iframe_src,
61
+ "https://url-varenv.be/share/site-varenv.be?auth=token-varenv&embed=true&theme=light&background=transparent",
62
+ )
63
+ self.assertEqual(
64
+ view.get_embedhostjs_src,
65
+ "https://url-varenv.be/js/embed.host.js",
66
+ )
67
+ self.set_registry_records()
68
+ self.assertEqual(
69
+ view.get_iframe_src,
70
+ "https://url-varenv.be/share/site-varenv.be?auth=token-varenv&embed=true&theme=light&background=transparent",
71
+ )
72
+ self.assertEqual(
73
+ view.get_embedhostjs_src,
74
+ "https://url-varenv.be/js/embed.host.js",
75
+ )
76
+
77
+ def test_plausible_view(self):
78
+ view = queryMultiAdapter((self.portal, self.request), name="stats")
79
+ self.assertNotIn("iframe", view())
80
+ self.assertIn("Plausible analytics is not set", view())
81
+ self.set_registry_records()
82
+ self.assertIn("iframe", view())
83
+ self.assertNotIn("Plausible analytics is not set", view())
@@ -2,6 +2,7 @@
2
2
 
3
3
  from freezegun import freeze_time
4
4
  from imio.smartweb.core import config
5
+ from imio.smartweb.core.contents.rest.base import BaseEndpoint
5
6
  from imio.smartweb.core.contents.rest.directory.endpoint import DirectoryEndpoint
6
7
  from imio.smartweb.core.contents.rest.events.endpoint import EventsEndpoint
7
8
  from imio.smartweb.core.contents.rest.news.endpoint import NewsEndpoint
@@ -72,6 +73,45 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
72
73
  def tearDown(self):
73
74
  self.api_session.close()
74
75
 
76
+ @freeze_time("2021-09-14 8:00:00")
77
+ def test_convert_cached_image_scales(self):
78
+ endpoint = BaseEndpoint(self.portal, self.request)
79
+ modified_hash = "78fd1bab198354b6877aed44e2ea0b4d"
80
+
81
+ item = {"@id": "http://host.com/content", "image": {"scales": {}}}
82
+ endpoint.convert_cached_image_scales(item, modified_hash)
83
+ self.assertNotIn("image", item.keys())
84
+ self.assertEqual(
85
+ item["image_preview_scale"],
86
+ "http://host.com/content/@@images/image/preview?cache_key=78fd1bab198354b6877aed44e2ea0b4d",
87
+ )
88
+ self.assertEqual(
89
+ item["image_extralarge_scale"],
90
+ "http://host.com/content/@@images/image/extralarge?cache_key=78fd1bab198354b6877aed44e2ea0b4d",
91
+ )
92
+ self.assertEqual(
93
+ item["image_affiche_scale"],
94
+ "http://host.com/content/@@images/image/affiche?cache_key=78fd1bab198354b6877aed44e2ea0b4d",
95
+ )
96
+
97
+ item = {"@id": "http://host.com/content", "logo": {"scales": {}}}
98
+ endpoint.convert_cached_image_scales(item, modified_hash, "logo", ["thumb"])
99
+ self.assertNotIn("logo", item.keys())
100
+ self.assertEqual(
101
+ item["logo_thumb_scale"],
102
+ "http://host.com/content/@@images/logo/thumb?cache_key=78fd1bab198354b6877aed44e2ea0b4d",
103
+ )
104
+
105
+ item = {
106
+ "@id": "http://host.com/content",
107
+ "image": {"scales": {}},
108
+ "logo": {"scales": {}},
109
+ }
110
+ endpoint.convert_cached_image_scales(item, modified_hash, "logo", ["thumb"])
111
+ self.assertEqual(len(item.keys()), 3)
112
+ endpoint.convert_cached_image_scales(item, modified_hash)
113
+ self.assertEqual(len(item.keys()), 5)
114
+
75
115
  def test_get_extra_params(self):
76
116
  request = TestRequest(
77
117
  form={"taxonomy_contact_category": '("token")', "topics": "education"}
@@ -6,6 +6,7 @@ from datetime import timedelta
6
6
  from freezegun import freeze_time
7
7
  from imio.smartweb.core.contents.sections.contact.view import formatted_schedule
8
8
  from imio.smartweb.core.contents.sections.contact.view import get_schedule_for_today
9
+ from imio.smartweb.core.contents.sections.views import SECTION_ITEMS_HASH_KEY
9
10
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
10
11
  from imio.smartweb.core.testing import ImioSmartwebTestCase
11
12
  from imio.smartweb.core.tests.utils import clear_cache
@@ -16,6 +17,8 @@ from plone.app.testing import TEST_USER_ID
16
17
  from plone.app.testing import TEST_USER_NAME
17
18
  from plone.app.testing import TEST_USER_PASSWORD
18
19
  from plone.testing.zope import Browser
20
+ from time import sleep
21
+ from zope.annotation.interfaces import IAnnotations
19
22
  from zope.component import queryMultiAdapter
20
23
 
21
24
  import json
@@ -497,3 +500,45 @@ class TestSectionContact(ImioSmartwebTestCase):
497
500
  self.assertNotIn("contact_leadimage portrait", view())
498
501
  contact.is_in_portrait_mode = True
499
502
  self.assertIn("contact_leadimage portrait", view())
503
+
504
+ @requests_mock.Mocker()
505
+ def test_contact_modified(self, m):
506
+ contact = api.content.create(
507
+ container=self.page,
508
+ type="imio.smartweb.SectionContact",
509
+ title="My contact",
510
+ )
511
+ authentic_contact_uid = "2dc381f0fb584381b8e4a19c84f53b35"
512
+ contact.related_contact = authentic_contact_uid
513
+ contact_search_url = (
514
+ "http://localhost:8080/Plone/@search?UID={}&fullobjects=1".format(
515
+ authentic_contact_uid
516
+ )
517
+ )
518
+ m.get(contact_search_url, text=json.dumps(self.json_contact))
519
+ contact_view = queryMultiAdapter((contact, self.request), name="view")
520
+
521
+ annotations = IAnnotations(contact)
522
+ self.assertIsNone(annotations.get(SECTION_ITEMS_HASH_KEY))
523
+
524
+ self.assertIsNotNone(contact_view.contact)
525
+ hash_1 = annotations.get(SECTION_ITEMS_HASH_KEY)
526
+ self.assertIsNotNone(hash_1)
527
+ first_modification = self.page.ModificationDate()
528
+
529
+ sleep(1)
530
+ clear_cache(self.request)
531
+ m.get(contact_search_url, text=json.dumps(self.json_no_contact))
532
+ self.assertIsNone(contact_view.contact)
533
+ next_modification = self.page.ModificationDate()
534
+ hash_2 = annotations.get(SECTION_ITEMS_HASH_KEY)
535
+ self.assertNotEqual(hash_1, hash_2)
536
+ self.assertNotEqual(first_modification, next_modification)
537
+
538
+ sleep(1)
539
+ clear_cache(self.request)
540
+ self.assertIsNone(contact_view.contact)
541
+ last_modification = self.page.ModificationDate()
542
+ hash_3 = annotations.get(SECTION_ITEMS_HASH_KEY)
543
+ self.assertEqual(hash_2, hash_3)
544
+ self.assertEqual(next_modification, last_modification)
@@ -1,13 +1,17 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from datetime import datetime
3
4
  from freezegun import freeze_time
5
+ from imio.smartweb.core.contents.sections.views import SECTION_ITEMS_HASH_KEY
4
6
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
5
7
  from imio.smartweb.core.testing import ImioSmartwebTestCase
6
8
  from imio.smartweb.core.tests.utils import get_json
7
9
  from plone import api
8
10
  from plone.app.testing import setRoles
9
11
  from plone.app.testing import TEST_USER_ID
12
+ from time import sleep
10
13
  from z3c.relationfield import RelationValue
14
+ from zope.annotation.interfaces import IAnnotations
11
15
  from zope.component import getUtility
12
16
  from zope.component import queryMultiAdapter
13
17
  from zope.intid.interfaces import IIntIds
@@ -30,33 +34,75 @@ class TestSectionEvents(ImioSmartwebTestCase):
30
34
  )
31
35
  self.json_events = get_json("resources/json_rest_events.json")
32
36
  self.json_specific_event = get_json("resources/json_rest_specific_events.json")
33
-
34
- @requests_mock.Mocker()
35
- @freeze_time("2021-11-15")
36
- def test_events(self, m):
37
- rest_events_view = api.content.create(
37
+ self.rest_events_view = api.content.create(
38
38
  container=self.portal,
39
39
  type="imio.smartweb.EventsView",
40
40
  title="Rest events view",
41
41
  )
42
- events = api.content.create(
42
+ self.events = api.content.create(
43
43
  container=self.portalpage,
44
44
  type="imio.smartweb.SectionEvents",
45
45
  title="My events",
46
46
  )
47
+
48
+ @requests_mock.Mocker()
49
+ @freeze_time("2021-11-15")
50
+ def test_events(self, m):
47
51
  intids = getUtility(IIntIds)
48
- events.related_events = "e73e6a81afea4a579cd0da2773af8d29"
49
- events.linking_rest_view = RelationValue(intids.getId(rest_events_view))
52
+ self.events.related_events = "e73e6a81afea4a579cd0da2773af8d29"
53
+ self.events.linking_rest_view = RelationValue(
54
+ intids.getId(self.rest_events_view)
55
+ )
50
56
  view = queryMultiAdapter((self.portalpage, self.request), name="full_view")
51
57
  self.assertIn("My events", view())
52
- events_view = queryMultiAdapter((events, self.request), name="carousel_view")
58
+ events_view = queryMultiAdapter(
59
+ (self.events, self.request), name="carousel_view"
60
+ )
53
61
  self.assertEqual(events_view.items, [])
54
62
  url = "http://localhost:8080/Plone/@events?selected_agendas=e73e6a81afea4a579cd0da2773af8d29&metadata_fields=category_title&metadata_fields=start&metadata_fields=end&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=UID&event_dates.query=2021-11-15&event_dates.range=min&b_size=6&translated_in_en=1&sort_on=event_dates"
55
63
  m.get(url, text=json.dumps(self.json_events))
56
64
  self.assertEqual(events_view.items[0][0].get("title"), "Journée de l'ATL")
57
65
  self.assertEqual(len(events_view.items[0]), 2)
58
- events.specific_related_events = ["1178188bddde4ced95a6cf8bf04c443c"]
66
+ self.events.specific_related_events = ["1178188bddde4ced95a6cf8bf04c443c"]
59
67
  url = "http://localhost:8080/Plone/@events?UID=1178188bddde4ced95a6cf8bf04c443c&metadata_fields=category_title&metadata_fields=start&metadata_fields=end&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=UID&event_dates.query=2021-11-15&event_dates.range=min&b_size=6&translated_in_en=1"
60
68
  m.get(url, text=json.dumps(self.json_specific_event))
61
69
  self.assertEqual(len(events_view.items[0]), 1)
62
70
  self.assertEqual(events_view.items[0][0].get("title"), "Bonne cheville")
71
+
72
+ @requests_mock.Mocker()
73
+ def test_events_modified(self, m):
74
+ today = datetime.now()
75
+ today_str = today.strftime("%Y-%m-%d")
76
+ intids = getUtility(IIntIds)
77
+ self.events.related_events = "e73e6a81afea4a579cd0da2773af8d29"
78
+ self.events.linking_rest_view = RelationValue(
79
+ intids.getId(self.rest_events_view)
80
+ )
81
+ annotations = IAnnotations(self.events)
82
+ self.assertIsNone(annotations.get(SECTION_ITEMS_HASH_KEY))
83
+
84
+ events_view = queryMultiAdapter(
85
+ (self.events, self.request), name="carousel_view"
86
+ )
87
+ url = f"http://localhost:8080/Plone/@events?selected_agendas=e73e6a81afea4a579cd0da2773af8d29&metadata_fields=category_title&metadata_fields=start&metadata_fields=end&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=UID&event_dates.query={today_str}&event_dates.range=min&b_size=6&translated_in_en=1&sort_on=event_dates"
88
+ m.get(url, text=json.dumps(self.json_events))
89
+ self.assertEqual(len(events_view.items[0]), 2)
90
+ hash_1 = annotations.get(SECTION_ITEMS_HASH_KEY)
91
+ self.assertIsNotNone(hash_1)
92
+ first_modification = self.portalpage.ModificationDate()
93
+
94
+ sleep(1)
95
+ url = f"http://localhost:8080/Plone/@events?selected_agendas=e73e6a81afea4a579cd0da2773af8d29&metadata_fields=category_title&metadata_fields=start&metadata_fields=end&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=UID&event_dates.query={today_str}&event_dates.range=min&b_size=6&translated_in_en=1&sort_on=event_dates"
96
+ m.get(url, text="{}")
97
+ self.assertEqual(len(events_view.items), 0)
98
+ next_modification = self.portalpage.ModificationDate()
99
+ hash_2 = annotations.get(SECTION_ITEMS_HASH_KEY)
100
+ self.assertNotEqual(hash_1, hash_2)
101
+ self.assertNotEqual(first_modification, next_modification)
102
+
103
+ sleep(1)
104
+ self.assertEqual(len(events_view.items), 0)
105
+ last_modification = self.portalpage.ModificationDate()
106
+ hash_3 = annotations.get(SECTION_ITEMS_HASH_KEY)
107
+ self.assertEqual(hash_2, hash_3)
108
+ self.assertEqual(next_modification, last_modification)
@@ -1,12 +1,15 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from imio.smartweb.core.contents.sections.views import SECTION_ITEMS_HASH_KEY
3
4
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
4
5
  from imio.smartweb.core.testing import ImioSmartwebTestCase
5
6
  from imio.smartweb.core.tests.utils import get_json
6
7
  from plone import api
7
8
  from plone.app.testing import setRoles
8
9
  from plone.app.testing import TEST_USER_ID
10
+ from time import sleep
9
11
  from z3c.relationfield import RelationValue
12
+ from zope.annotation.interfaces import IAnnotations
10
13
  from zope.component import getUtility
11
14
  from zope.component import queryMultiAdapter
12
15
  from zope.intid.interfaces import IIntIds
@@ -29,33 +32,33 @@ class TestSectionNews(ImioSmartwebTestCase):
29
32
  )
30
33
  self.json_news = get_json("resources/json_rest_news.json")
31
34
  self.json_specific_news = get_json("resources/json_rest_specific_news.json")
32
-
33
- @requests_mock.Mocker()
34
- def test_news(self, m):
35
- rest_news_view = api.content.create(
35
+ self.rest_news_view = api.content.create(
36
36
  container=self.portal,
37
37
  type="imio.smartweb.NewsView",
38
38
  title="Rest news view",
39
39
  )
40
- news = api.content.create(
40
+ self.news = api.content.create(
41
41
  container=self.portalpage,
42
42
  type="imio.smartweb.SectionNews",
43
43
  title="My news",
44
44
  )
45
+
46
+ @requests_mock.Mocker()
47
+ def test_news(self, m):
45
48
  intids = getUtility(IIntIds)
46
- news.related_news = "64f4cbee9a394a018a951f6d94452914"
47
- news.linking_rest_view = RelationValue(intids.getId(rest_news_view))
48
- news.link_text = "Voir toutes les actualités"
49
+ self.news.related_news = "64f4cbee9a394a018a951f6d94452914"
50
+ self.news.linking_rest_view = RelationValue(intids.getId(self.rest_news_view))
51
+ self.news.link_text = "Voir toutes les actualités"
49
52
  view = queryMultiAdapter((self.portalpage, self.request), name="full_view")
50
53
  self.assertIn("My news", view())
51
- news_view = queryMultiAdapter((news, self.request), name="carousel_view")
54
+ news_view = queryMultiAdapter((self.news, self.request), name="carousel_view")
52
55
  self.assertEqual(news_view.items, [])
53
56
  url = "http://localhost:8080/Plone/@search?selected_news_folders=64f4cbee9a394a018a951f6d94452914&portal_type=imio.news.NewsItem&metadata_fields=category_title&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=effective&metadata_fields=UID&sort_limit=6&translated_in_en=1&sort_on=effective&sort_order=descending"
54
57
  m.get(url, text=json.dumps(self.json_news))
55
58
  self.assertEqual(news_view.items[0][0].get("title"), "Première actualité")
56
59
  self.assertEqual(len(news_view.items[0]), 3)
57
60
 
58
- news.specific_related_newsitems = [
61
+ self.news.specific_related_newsitems = [
59
62
  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
60
63
  "bfe2b4391a0f4a8db6d8b7fed63d1c4a",
61
64
  ]
@@ -66,7 +69,7 @@ class TestSectionNews(ImioSmartwebTestCase):
66
69
  news_view.items[0][0].get("title"), "Restauration de la piscine"
67
70
  )
68
71
 
69
- news.specific_related_newsitems = [
72
+ self.news.specific_related_newsitems = [
70
73
  "bfe2b4391a0f4a8db6d8b7fed63d1c4a",
71
74
  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
72
75
  ]
@@ -74,3 +77,35 @@ class TestSectionNews(ImioSmartwebTestCase):
74
77
  self.assertEqual(
75
78
  news_view.items[0][0].get("title"), "Restauration de la Bibliothèque"
76
79
  )
80
+
81
+ @requests_mock.Mocker()
82
+ def test_news_modified(self, m):
83
+ intids = getUtility(IIntIds)
84
+ self.news.related_news = "64f4cbee9a394a018a951f6d94452914"
85
+ self.news.linking_rest_view = RelationValue(intids.getId(self.rest_news_view))
86
+ annotations = IAnnotations(self.news)
87
+ self.assertIsNone(annotations.get(SECTION_ITEMS_HASH_KEY))
88
+
89
+ news_view = queryMultiAdapter((self.news, self.request), name="carousel_view")
90
+ url = "http://localhost:8080/Plone/@search?selected_news_folders=64f4cbee9a394a018a951f6d94452914&portal_type=imio.news.NewsItem&metadata_fields=category_title&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=effective&metadata_fields=UID&sort_limit=6&translated_in_en=1&sort_on=effective&sort_order=descending"
91
+ m.get(url, text=json.dumps(self.json_news))
92
+ self.assertEqual(len(news_view.items[0]), 3)
93
+ hash_1 = annotations.get(SECTION_ITEMS_HASH_KEY)
94
+ self.assertIsNotNone(hash_1)
95
+ first_modification = self.portalpage.ModificationDate()
96
+
97
+ sleep(1)
98
+ url = "http://localhost:8080/Plone/@search?selected_news_folders=64f4cbee9a394a018a951f6d94452914&portal_type=imio.news.NewsItem&metadata_fields=category_title&metadata_fields=has_leadimage&metadata_fields=modified&metadata_fields=effective&metadata_fields=UID&sort_limit=6&translated_in_en=1&sort_on=effective&sort_order=descending"
99
+ m.get(url, text="{}")
100
+ self.assertEqual(len(news_view.items), 0)
101
+ next_modification = self.portalpage.ModificationDate()
102
+ hash_2 = annotations.get(SECTION_ITEMS_HASH_KEY)
103
+ self.assertNotEqual(hash_1, hash_2)
104
+ self.assertNotEqual(first_modification, next_modification)
105
+
106
+ sleep(1)
107
+ self.assertEqual(len(news_view.items), 0)
108
+ last_modification = self.portalpage.ModificationDate()
109
+ hash_3 = annotations.get(SECTION_ITEMS_HASH_KEY)
110
+ self.assertEqual(hash_2, hash_3)
111
+ self.assertEqual(next_modification, last_modification)
@@ -1,5 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from AccessControl.unauthorized import Unauthorized
3
4
  from bs4 import BeautifulSoup
4
5
  from collective.geolocationbehavior.geolocation import IGeolocatable
5
6
  from functools import reduce
@@ -110,6 +111,39 @@ class TestSections(ImioSmartwebTestCase):
110
111
  "https://www.youtube.com/embed/_dOAthafoGQ?feature=oembed", embedded_video
111
112
  )
112
113
 
114
+ def test_external_content_section(self):
115
+ setRoles(self.portal, TEST_USER_ID, ["Contributor"])
116
+ with self.assertRaises(Unauthorized):
117
+ api.content.create(
118
+ container=self.page,
119
+ type="imio.smartweb.SectionExternalContent",
120
+ title="Section External Content",
121
+ )
122
+ setRoles(self.portal, TEST_USER_ID, ["Manager"])
123
+ section = api.content.create(
124
+ container=self.page,
125
+ type="imio.smartweb.SectionExternalContent",
126
+ title="Section External Content",
127
+ )
128
+ section.external_content_url = (
129
+ "https://app.eaglebe.com/fr-be/map/la%20louvi%C3%A8re"
130
+ )
131
+ view = queryMultiAdapter((section, self.request), name="view")
132
+ embedded_content = view.get_embed_external_content()
133
+ self.assertIn("iframe", embedded_content)
134
+ self.assertIn('class="eaglebe"', embedded_content)
135
+ self.assertIn('scrolling="no"', embedded_content)
136
+ self.assertIn(
137
+ "https://app.eaglebe.com/fr-be/map/la%20louvi%C3%A8re", embedded_content
138
+ )
139
+
140
+ section.external_content_url = "http://www.perdu.com"
141
+ view = queryMultiAdapter((section, self.request), name="view")
142
+ embedded_content = view.get_embed_external_content()
143
+ self.assertNotIn("iframe", embedded_content)
144
+ self.assertNotIn("class='eaglebe'", embedded_content)
145
+ self.assertIn("<p class='unknow_service'>Unknow service</p>", embedded_content)
146
+
113
147
  def test_map_section(self):
114
148
  section = api.content.create(
115
149
  container=self.page,