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
@@ -9,6 +9,8 @@ module.exports = {
9
9
  entry: {
10
10
  view: './src/view.js',
11
11
  edit: './src/edit.js',
12
+ swiperconfig: './src/swiper-config.js',
13
+
12
14
  },
13
15
  output: {
14
16
  filename: 'smartweb-[name]-compiled.js',
@@ -11,6 +11,7 @@ from zope.i18n import translate
11
11
 
12
12
  import json
13
13
  import requests
14
+ import os
14
15
 
15
16
 
16
17
  class UtilsView(BrowserView):
@@ -73,3 +74,35 @@ class UtilsView(BrowserView):
73
74
  "text": _(response.reason),
74
75
  }
75
76
  )
77
+
78
+
79
+ def get_plausible_vars(self):
80
+ env_plausible_url = os.getenv("SMARTWEB_PLAUSIBLE_URL")
81
+ env_plausible_site = os.getenv("SMARTWEB_PLAUSIBLE_SITE")
82
+ env_plausible_token = os.getenv("SMARTWEB_PLAUSIBLE_TOKEN")
83
+
84
+ plausible_url = (
85
+ env_plausible_url
86
+ if (env_plausible_url and env_plausible_url != "")
87
+ else api.portal.get_registry_record("smartweb.plausible_url")
88
+ )
89
+ plausible_site = (
90
+ env_plausible_site
91
+ if (env_plausible_site and env_plausible_site != "")
92
+ else api.portal.get_registry_record("smartweb.plausible_site")
93
+ )
94
+ plausible_token = (
95
+ env_plausible_token
96
+ if (env_plausible_token and env_plausible_token != "")
97
+ else api.portal.get_registry_record("smartweb.plausible_token")
98
+ )
99
+ if not (plausible_url or plausible_site or plausible_token):
100
+ if plausible_url == "" or plausible_site == "" or plausible_token == "":
101
+ return False
102
+ else:
103
+ plausible_vars = {
104
+ "plausible_url": plausible_url,
105
+ "plausible_site": plausible_site,
106
+ "plausible_token": plausible_token,
107
+ }
108
+ return plausible_vars
@@ -14,6 +14,10 @@ from .sections.base import ISection, Section # NOQA
14
14
  from .sections.collection.content import ISectionCollection, SectionCollection # NOQA
15
15
  from .sections.contact.content import ISectionContact, SectionContact # NOQA
16
16
  from .sections.events.content import ISectionEvents, SectionEvents # NOQA
17
+ from .sections.external_content.content import (
18
+ ISectionExternalContent,
19
+ SectionExternalContent,
20
+ ) # NOQA
17
21
  from .sections.files.content import ISectionFiles, SectionFiles # NOQA
18
22
  from .sections.gallery.content import ISectionGallery, SectionGallery # NOQA
19
23
  from .sections.html.content import ISectionHTML, SectionHTML # NOQA
@@ -6,12 +6,9 @@ from imio.smartweb.common.adapters import BaseCroppingProvider
6
6
  class SmartwebCroppingProvider(BaseCroppingProvider):
7
7
  def get_scales(self, fieldname, request=None):
8
8
  """Define default cropping scales for all common fields"""
9
- if fieldname == "banner":
10
- # scale used for banner fields
11
- return ["banner"]
12
- elif fieldname == "background_image":
13
- # scales used for background_image fields
14
- return ["affiche"]
9
+ if fieldname in ["banner", "background_image"]:
10
+ # scale used for banner fields or background_image fields
11
+ return []
15
12
  elif fieldname == "image":
16
13
  # scales used for lead_image fields
17
14
  return ["liste", "vignette", "slide"]
@@ -10,7 +10,6 @@ from plone.namedfile.field import NamedBlobImage
10
10
  from plone.supermodel import model
11
11
  from plone.uuid.interfaces import IUUID
12
12
  from z3c.form.browser.radio import RadioFieldWidget
13
- from zExceptions import BadRequest
14
13
  from zope import schema
15
14
  from zope.interface import implementer
16
15
  from zope.interface import alsoProvides
@@ -49,10 +48,6 @@ class IFolder(model.Schema):
49
48
  class Folder(Container):
50
49
  """Folder class"""
51
50
 
52
- def checkValidId(self, id, allow_dup=0):
53
- if hasattr(self, id) and id not in self.contentIds():
54
- raise BadRequest()
55
-
56
51
  def canSetDefaultPage(self):
57
52
  return False
58
53
 
@@ -67,6 +62,7 @@ class Folder(Container):
67
62
  idxs=("object_provides", "exclude_from_nav")
68
63
  )
69
64
  self.default_page_uid = None
65
+ self.reindexObject()
70
66
 
71
67
  def get_default_item(self, object=False):
72
68
  if self.default_page_uid:
@@ -67,7 +67,9 @@ class FolderView(BaseFolderView):
67
67
  if self.context.quick_access_items is None:
68
68
  return {"results": results, "quick_access": []}
69
69
  quick_access_uids = [
70
- item.to_object.UID() for item in self.context.quick_access_items
70
+ item.to_object.UID()
71
+ for item in self.context.quick_access_items
72
+ if item.isBroken() is False
71
73
  ]
72
74
  quick_access_brains = api.content.find(
73
75
  UID=quick_access_uids,
@@ -1,7 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from plone.dexterity.content import Container
4
- from zExceptions import BadRequest
5
4
  from zope.interface import Interface
6
5
  from zope.interface import implementer
7
6
 
@@ -18,9 +17,5 @@ class IDefaultPages(Interface):
18
17
  class Pages(Container):
19
18
  """Shared base class for Pages"""
20
19
 
21
- def checkValidId(self, id, allow_dup=0):
22
- if hasattr(self, id) and id not in self.contentIds():
23
- raise BadRequest()
24
-
25
20
  def canSetDefaultPage(self):
26
21
  return False
@@ -11,6 +11,9 @@
11
11
  <script src=""
12
12
  tal:attributes="src string:${portal_url}/++plone++imio.smartweb.core/swiper-bundle.min.js">
13
13
  </script>
14
+ <script src=""
15
+ tal:attributes="src string:${portal_url}/++plone++imio.smartweb.core/smartweb-swiperconfig-compiled.js">
16
+ </script>
14
17
  </metal:head>
15
18
 
16
19
  <metal:content-core fill-slot="content-core">
@@ -23,6 +23,22 @@ class BaseEndpoint(object):
23
23
  def query_url(self):
24
24
  raise NotImplementedError
25
25
 
26
+ def convert_cached_image_scales(
27
+ self,
28
+ item,
29
+ modified_hash,
30
+ field="image",
31
+ scales=["preview", "extralarge", "affiche"],
32
+ ):
33
+ """Remove image from result dict and add generated image scales URLs
34
+ with cache key"""
35
+ for scale in scales:
36
+ cached_scale_url = (
37
+ f"{item['@id']}/@@images/{field}/{scale}?cache_key={modified_hash}"
38
+ )
39
+ item[f"{field}_{scale}_scale"] = cached_scale_url
40
+ del item[field]
41
+
26
42
  def get_extra_params(self, params):
27
43
  form = self.request.form
28
44
  extra_params = []
@@ -17,24 +17,17 @@ class BaseDirectoryEndpoint(BaseEndpoint):
17
17
  if not results.get("items"):
18
18
  return results
19
19
  for result in results["items"]:
20
+ modified_hash = hash_md5(result["modified"])
20
21
  if result.get("image"):
21
- modified_hash = hash_md5(result["modified"])
22
- preview_scale = (
23
- f"{result['@id']}/@@images/image/preview?cache_key={modified_hash}"
24
- )
25
- extralarge_scale = f"{result['@id']}/@@images/image/extralarge?cache_key={modified_hash}"
26
- affiche_scale = (
27
- f"{result['@id']}/@@images/image/affiche?cache_key={modified_hash}"
28
- )
29
- result["image_preview_scale"] = preview_scale
30
- result["image_extralarge_scale"] = extralarge_scale
31
- result["image_affiche_scale"] = affiche_scale
22
+ self.convert_cached_image_scales(result, modified_hash)
32
23
  if result.get("logo"):
33
- modified_hash = hash_md5(result["modified"])
34
- thumb_scale = (
35
- f"{result['@id']}/@@images/logo/thumb?cache_key={modified_hash}"
24
+ self.convert_cached_image_scales(
25
+ result, modified_hash, "logo", ["thumb"]
36
26
  )
37
- result["logo_thumb_scale"] = thumb_scale
27
+ for sub_content in result.get("items", []):
28
+ if sub_content["@type"] != "Image":
29
+ continue
30
+ self.convert_cached_image_scales(sub_content, modified_hash)
38
31
  return results
39
32
 
40
33
  @property
@@ -14,22 +14,16 @@ from zope.interface import Interface
14
14
  class BaseEventsEndpoint(BaseEndpoint):
15
15
  def __call__(self):
16
16
  results = super(BaseEventsEndpoint, self).__call__()
17
- # https://agenda.enwallonie.be/braine-lalleud/citoyens/bc573e7592ee4f6498ad3cba8097358e/@@images/image/preview?
18
17
  if not results.get("items"):
19
18
  return results
20
19
  for result in results["items"]:
20
+ modified_hash = hash_md5(result["modified"])
21
21
  if result.get("image"):
22
- modified_hash = hash_md5(result["modified"])
23
- preview_scale = (
24
- f"{result['@id']}/@@images/image/preview?cache_key={modified_hash}"
25
- )
26
- extralarge_scale = f"{result['@id']}/@@images/image/extralarge?cache_key={modified_hash}"
27
- affiche_scale = (
28
- f"{result['@id']}/@@images/image/affiche?cache_key={modified_hash}"
29
- )
30
- result["image_preview_scale"] = preview_scale
31
- result["image_extralarge_scale"] = extralarge_scale
32
- result["image_affiche_scale"] = affiche_scale
22
+ self.convert_cached_image_scales(result, modified_hash)
23
+ for sub_content in result.get("items", []):
24
+ if sub_content["@type"] != "Image":
25
+ continue
26
+ self.convert_cached_image_scales(sub_content, modified_hash)
33
27
  return results
34
28
 
35
29
  @property
@@ -16,18 +16,13 @@ class BaseNewsEndpoint(BaseEndpoint):
16
16
  if not results.get("items"):
17
17
  return results
18
18
  for result in results["items"]:
19
+ modified_hash = hash_md5(result["modified"])
19
20
  if result.get("image"):
20
- modified_hash = hash_md5(result["modified"])
21
- preview_scale = (
22
- f"{result['@id']}/@@images/image/preview?cache_key={modified_hash}"
23
- )
24
- extralarge_scale = f"{result['@id']}/@@images/image/extralarge?cache_key={modified_hash}"
25
- affiche_scale = (
26
- f"{result['@id']}/@@images/image/affiche?cache_key={modified_hash}"
27
- )
28
- result["image_preview_scale"] = preview_scale
29
- result["image_extralarge_scale"] = extralarge_scale
30
- result["image_affiche_scale"] = affiche_scale
21
+ self.convert_cached_image_scales(result, modified_hash)
22
+ for sub_content in result.get("items", []):
23
+ if sub_content["@type"] != "Image":
24
+ continue
25
+ self.convert_cached_image_scales(sub_content, modified_hash)
31
26
  return results
32
27
 
33
28
  @property
@@ -100,7 +100,8 @@ class ExtendedSearchHandler(SearchHandler):
100
100
  if "use_solr" not in query:
101
101
  query["use_solr"] = True # enforce use of SolR by default
102
102
  if "_core" in query:
103
- parameters = self._core_query(query["_core"])
103
+ language = api.portal.get_current_language(context=self.context)
104
+ parameters = self._core_query(query["_core"], language=language)
104
105
  del query["_core"]
105
106
  if parameters:
106
107
  if "metadata_fields" in query:
@@ -110,9 +111,16 @@ class ExtendedSearchHandler(SearchHandler):
110
111
  )
111
112
  self.request.form["metadata_fields"] = parameters["metadata_fields"]
112
113
  query.update(parameters)
114
+ if language != "fr" and "SearchableText" in query:
115
+ basesearch = query["SearchableText"]
116
+ query[f"SearchableText_{language}"] = {
117
+ "query": [basesearch, f"{basesearch}*"],
118
+ "operator": "or",
119
+ }
120
+ del query["SearchableText"]
113
121
  result = super(ExtendedSearchHandler, self).search(query)
114
122
  if "core" in query:
115
- return self._adapt_result(result, query["core"])
123
+ return self._adapt_result(result, query["core"], language=language)
116
124
  return result
117
125
 
118
126
  def _get_source_url(self, path, core):
@@ -123,18 +131,25 @@ class ExtendedSearchHandler(SearchHandler):
123
131
  }
124
132
  return "{0}/{1}".format(base_urls.get(core, ""), "/".join(path.split("/")[2:]))
125
133
 
126
- def _adapt_result(self, result, core):
134
+ def _adapt_result(self, result, core, language=None):
127
135
  """Transform result"""
128
136
  mapping = get_views_mapping(self._navigation_root)
129
137
  result["items"] = [
130
- self._adapt_result_url(i, mapping, core) for i in result["items"]
138
+ self._adapt_result_values(i, mapping, core, language=language)
139
+ for i in result["items"]
131
140
  ]
132
141
  return result
133
142
 
134
- def _adapt_result_url(self, item, mapping, core):
143
+ def _adapt_result_values(self, item, mapping, core, language=None):
135
144
  """Ensure that url to external objects are adapted based on react views"""
136
145
  if item["@type"] not in mapping:
137
146
  return item
147
+ if language is not None and language != "fr":
148
+ for field in ("description", "title"):
149
+ fname = f"{field}_{language}"
150
+ if fname in item:
151
+ item[field] = item[fname]
152
+ del item[fname]
138
153
  type_mapping = mapping[item["@type"]]
139
154
  base_url = type_mapping.get(item["container_uid"], type_mapping["default"])
140
155
  item["_url"] = "{base}#/content?u={item_uid}".format(
@@ -153,7 +168,7 @@ class ExtendedSearchHandler(SearchHandler):
153
168
  original = [original]
154
169
  return [*original, *[e for e in new if e not in original]]
155
170
 
156
- def _core_query(self, core):
171
+ def _core_query(self, core, language=None):
157
172
  """Return core specific query parameters"""
158
173
  mapping = get_views_mapping(self._navigation_root)
159
174
  parameters = {
@@ -232,4 +247,9 @@ class ExtendedSearchHandler(SearchHandler):
232
247
  if not parameters.get(required_field)["query"]:
233
248
  # This avoid having unwanted results if no view was created
234
249
  parameters[required_field] = ["None"]
250
+ if language is not None and language != "fr":
251
+ parameters["metadata_fields"].extend(
252
+ [f"title_{language}", f"description_{language}"]
253
+ )
254
+ parameters[f"translated_in_{language}"] = True
235
255
  return parameters
@@ -5,6 +5,7 @@
5
5
  <include package=".collection" />
6
6
  <include package=".contact" />
7
7
  <include package=".events" />
8
+ <include package=".external_content" />
8
9
  <include package=".files" />
9
10
  <include package=".gallery" />
10
11
  <include package=".html" />
@@ -169,8 +169,7 @@
169
169
  tal:attributes="class string:${nb_class} contact_gallery">
170
170
  <!-- fix some css for usage in Plone -->
171
171
  <style type="text/css">
172
- #spotlight .header { padding-right: 120px !important; }
173
- #content-core a { border-bottom: 0px solid transparent !important;}
172
+ #spotlight .header { padding-right: 120px; }
174
173
  </style>
175
174
  <div id="swiper1" class="swiper" style="width:100%"
176
175
  tal:attributes="data-nb-results-by-batch context/nb_results_by_batch"
@@ -5,7 +5,7 @@ from datetime import timedelta
5
5
  from decimal import Decimal
6
6
  from imio.smartweb.common.utils import rich_description
7
7
  from imio.smartweb.core.config import DIRECTORY_URL
8
- from imio.smartweb.core.contents.sections.views import SectionView
8
+ from imio.smartweb.core.contents.sections.views import HashableJsonSectionView
9
9
  from imio.smartweb.core.utils import batch_results
10
10
  from imio.smartweb.core.utils import get_json
11
11
  from imio.smartweb.core.utils import hash_md5
@@ -18,7 +18,7 @@ from zope.i18nmessageid import MessageFactory
18
18
  import json
19
19
 
20
20
 
21
- class ContactView(SectionView):
21
+ class ContactView(HashableJsonSectionView):
22
22
  """Contact Section view"""
23
23
 
24
24
  @property
@@ -30,13 +30,11 @@ class ContactView(SectionView):
30
30
  current_lang = api.portal.get_current_language()[:2]
31
31
  if current_lang != "fr":
32
32
  url = f"{url}&translated_in_{current_lang}=1"
33
- json_search_contact = get_json(url)
34
- if (
35
- json_search_contact is None
36
- or len(json_search_contact.get("items", [])) == 0 # NOQA
37
- ):
33
+ self.json_data = get_json(url)
34
+ self.refresh_modification_date()
35
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
38
36
  return
39
- return json_search_contact.get("items")[0]
37
+ return self.json_data.get("items")[0]
40
38
 
41
39
  @property
42
40
  def contact_type_class(self):
@@ -4,6 +4,7 @@ from datetime import date
4
4
  from dateutil.parser import parse
5
5
  from imio.smartweb.core.config import EVENTS_URL
6
6
  from imio.smartweb.core.contents.sections.views import CarouselOrTableSectionView
7
+ from imio.smartweb.core.contents.sections.views import HashableJsonSectionView
7
8
  from imio.smartweb.core.utils import batch_results
8
9
  from imio.smartweb.core.utils import get_json
9
10
  from imio.smartweb.core.utils import hash_md5
@@ -11,7 +12,7 @@ from plone import api
11
12
  from Products.CMFPlone.utils import normalizeString
12
13
 
13
14
 
14
- class EventsView(CarouselOrTableSectionView):
15
+ class EventsView(CarouselOrTableSectionView, HashableJsonSectionView):
15
16
  """Events Section view"""
16
17
 
17
18
  @property
@@ -44,15 +45,13 @@ class EventsView(CarouselOrTableSectionView):
44
45
  "sort_on=event_dates",
45
46
  ]
46
47
  url = "{}/@events?{}".format(EVENTS_URL, "&".join(params))
47
- json_search_events = get_json(url)
48
- if (
49
- json_search_events is None
50
- or len(json_search_events.get("items", [])) == 0 # NOQA
51
- ):
48
+ self.json_data = get_json(url)
49
+ self.refresh_modification_date()
50
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
52
51
  return []
53
52
  linking_view_url = self.context.linking_rest_view.to_object.absolute_url()
54
53
  image_scale = self.image_scale
55
- items = json_search_events.get("items")[:max_items]
54
+ items = self.json_data.get("items")[:max_items]
56
55
  results = []
57
56
  for item in items:
58
57
  item_id = normalizeString(item["title"])
@@ -0,0 +1,14 @@
1
+ <configure
2
+ xmlns="http://namespaces.zope.org/zope"
3
+ xmlns:browser="http://namespaces.zope.org/browser">
4
+
5
+ <browser:page
6
+ name="view"
7
+ for="imio.smartweb.core.contents.ISectionExternalContent"
8
+ class="imio.smartweb.core.contents.sections.external_content.views.ExternalContentView"
9
+ template="view.pt"
10
+ permission="zope2.View"
11
+ layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
12
+ />
13
+
14
+ </configure>
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from imio.smartweb.common.config import DESCRIPTION_MAX_LENGTH
4
+ from imio.smartweb.core.contents.sections.base import ISection
5
+ from imio.smartweb.core.contents.sections.base import Section
6
+ from imio.smartweb.locales import SmartwebMessageFactory as _
7
+ from zope.interface import implementer
8
+ from zope import schema
9
+
10
+
11
+ class ISectionExternalContent(ISection):
12
+ """Marker interface and Dexterity Python Schema for SectionVideo"""
13
+
14
+ description = schema.Text(
15
+ title=_("Description"),
16
+ description=_(
17
+ "Use **text** to set text in bold. Limited to ${max} characters.",
18
+ mapping={"max": DESCRIPTION_MAX_LENGTH},
19
+ ),
20
+ max_length=DESCRIPTION_MAX_LENGTH,
21
+ required=False,
22
+ )
23
+
24
+ external_content_url = schema.URI(
25
+ title=_("External content url"),
26
+ required=True,
27
+ )
28
+
29
+
30
+ @implementer(ISectionExternalContent)
31
+ class SectionExternalContent(Section):
32
+ """SectionVideo class"""
@@ -0,0 +1,31 @@
1
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
2
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
3
+ xmlns:metal="http://xml.zope.org/namespaces/metal"
4
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
5
+ lang="en"
6
+ metal:use-macro="context/@@main_template/macros/master"
7
+ i18n:domain="plone">
8
+ <body>
9
+
10
+ <metal:main fill-slot="content-core">
11
+ <metal:content-core define-macro="content-core">
12
+ <metal:macro use-macro="context/@@sections_macros/section_edition" />
13
+ <div class="container section-container section-video"
14
+ id=""
15
+ tal:attributes="id string:container-section-${context/id}">
16
+
17
+ <metal:macro use-macro="context/@@sections_macros/section_title" />
18
+
19
+ <p tal:replace="structure context/@@description" />
20
+
21
+ <div tal:define="collapse_klass python: 'collapse' if context.collapsible_section else ''"
22
+ tal:attributes="class string:body-section ratio ratio-16x9 ${collapse_klass};
23
+ id string:body-section-${context/id}"
24
+ tal:content="structure view/get_embed_external_content" />
25
+
26
+ </div>
27
+ </metal:content-core>
28
+ </metal:main>
29
+
30
+ </body>
31
+ </html>
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from embeddify import Embedder
4
+ from embeddify import Plugin
5
+ from imio.smartweb.core.contents.sections.views import SectionView
6
+ from imio.smartweb.locales import SmartwebMessageFactory as _
7
+
8
+
9
+ class ExternalContentView(SectionView):
10
+ def get_embed_external_content(self, width="100%", height=600):
11
+ plugins = [EaglebePlugin(), UnknowServicePlugin()]
12
+ plugin_config = {
13
+ "eaglebeplugin": {"width": width},
14
+ "unknowserviceplugin": {"width": width},
15
+ }
16
+ embedder = Embedder(plugins=plugins, plugin_config=plugin_config)
17
+ url = self.context.external_content_url
18
+ return embedder(url, config={"width": width})
19
+
20
+
21
+ class EaglebePlugin(Plugin):
22
+ def __call__(self, parts, config={}):
23
+ if "app.eaglebe.com" in parts.netloc:
24
+ return f'<iframe class="eaglebe" src="{parts.geturl()}" scrolling="no" width="{config["width"]}">'
25
+ #
26
+ return None
27
+
28
+
29
+ class UnknowServicePlugin(Plugin):
30
+ def __call__(self, parts, config={}):
31
+ return _("<p class='unknow_service'>Unknow service</p>")
@@ -25,8 +25,7 @@
25
25
  id string:body-section-${context/id}">
26
26
  <!-- fix some css for usage in Plone -->
27
27
  <style type="text/css">
28
- #spotlight .header { padding-right: 120px !important; }
29
- #content-core a { border-bottom: 0px solid transparent !important;}
28
+ #spotlight .header { padding-right: 120px; }
30
29
  </style>
31
30
 
32
31
  <div tal:define="portal context/@@plone_portal_state/portal;
@@ -37,10 +37,6 @@
37
37
  <a class="edit-section" tal:attributes="href string:${context/absolute_url}/edit"
38
38
  i18n:translate="">Edit section</a>
39
39
 
40
- <span class="icon-image"></span>
41
- <a class="edit-section-cropping" tal:attributes="href string:${context/absolute_url}/@@croppingeditor"
42
- i18n:translate="">Image cropping</a>
43
-
44
40
  <tal:if tal:condition="context/manage_content">
45
41
  <span class="icon-folderContents"></span>
46
42
  <a class="edit-section-content" tal:attributes="href string:${context/absolute_url}/folder_contents"
@@ -2,6 +2,7 @@
2
2
 
3
3
  from imio.smartweb.core.config import NEWS_URL
4
4
  from imio.smartweb.core.contents.sections.views import CarouselOrTableSectionView
5
+ from imio.smartweb.core.contents.sections.views import HashableJsonSectionView
5
6
  from imio.smartweb.core.utils import batch_results
6
7
  from imio.smartweb.core.utils import get_json
7
8
  from imio.smartweb.core.utils import hash_md5
@@ -9,7 +10,7 @@ from plone import api
9
10
  from Products.CMFPlone.utils import normalizeString
10
11
 
11
12
 
12
- class NewsView(CarouselOrTableSectionView):
13
+ class NewsView(CarouselOrTableSectionView, HashableJsonSectionView):
13
14
  """News Section view"""
14
15
 
15
16
  @property
@@ -40,15 +41,13 @@ class NewsView(CarouselOrTableSectionView):
40
41
  "sort_order=descending",
41
42
  ]
42
43
  url = "{}/@search?{}".format(NEWS_URL, "&".join(params))
43
- json_search_news = get_json(url)
44
- if (
45
- json_search_news is None
46
- or len(json_search_news.get("items", [])) == 0 # NOQA
47
- ):
44
+ self.json_data = get_json(url)
45
+ self.refresh_modification_date()
46
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
48
47
  return []
49
48
  linking_view_url = self.context.linking_rest_view.to_object.absolute_url()
50
49
  image_scale = self.image_scale
51
- items = json_search_news.get("items")[:max_items]
50
+ items = self.json_data.get("items")[:max_items]
52
51
  results = []
53
52
  for item in items:
54
53
  item_id = normalizeString(item["title"])
@@ -2,12 +2,6 @@
2
2
  xmlns="http://namespaces.zope.org/zope"
3
3
  xmlns:browser="http://namespaces.zope.org/browser">
4
4
 
5
- <adapter
6
- for=".content.SectionText"
7
- provides="imio.smartweb.common.interfaces.ICropping"
8
- factory=".content.SectionTextCroppingProvider"
9
- />
10
-
11
5
  <browser:page
12
6
  name="view"
13
7
  for="imio.smartweb.core.contents.ISectionText"
@@ -1,6 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- from imio.smartweb.core.contents.cropping import SmartwebCroppingProvider
4
3
  from imio.smartweb.core.contents.sections.base import ISection
5
4
  from imio.smartweb.core.contents.sections.base import Section
6
5
  from imio.smartweb.locales import SmartwebMessageFactory as _
@@ -9,17 +8,6 @@ from zope import schema
9
8
  from zope.interface import implementer
10
9
 
11
10
 
12
- class SectionTextCroppingProvider(SmartwebCroppingProvider):
13
- def get_scales(self, fieldname, request=None):
14
- if fieldname == "image":
15
- # scale used for lead image field
16
- return [self.context.image_size]
17
- else:
18
- return super(SectionTextCroppingProvider, self).get_scales(
19
- fieldname, request
20
- )
21
-
22
-
23
11
  class ISectionText(ISection):
24
12
  """Marker interface and Dexterity Python Schema for SectionText"""
25
13