imio.smartweb.core 1.1.15__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 (112) 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/utils.py +33 -0
  9. imio/smartweb/core/contents/__init__.py +4 -0
  10. imio/smartweb/core/contents/cropping.py +2 -5
  11. imio/smartweb/core/contents/folder/content.py +1 -0
  12. imio/smartweb/core/contents/rest/base.py +16 -0
  13. imio/smartweb/core/contents/rest/directory/endpoint.py +8 -15
  14. imio/smartweb/core/contents/rest/events/endpoint.py +6 -12
  15. imio/smartweb/core/contents/rest/news/endpoint.py +6 -11
  16. imio/smartweb/core/contents/rest/search/endpoint.py +26 -6
  17. imio/smartweb/core/contents/sections/configure.zcml +1 -0
  18. imio/smartweb/core/contents/sections/contact/view.pt +1 -2
  19. imio/smartweb/core/contents/sections/external_content/__init__.py +0 -0
  20. imio/smartweb/core/contents/sections/external_content/configure.zcml +14 -0
  21. imio/smartweb/core/contents/sections/external_content/content.py +32 -0
  22. imio/smartweb/core/contents/sections/external_content/view.pt +31 -0
  23. imio/smartweb/core/contents/sections/external_content/views.py +31 -0
  24. imio/smartweb/core/contents/sections/gallery/view.pt +1 -2
  25. imio/smartweb/core/contents/sections/macros.pt +0 -4
  26. imio/smartweb/core/contents/sections/text/configure.zcml +0 -6
  27. imio/smartweb/core/contents/sections/text/content.py +0 -12
  28. imio/smartweb/core/contents/sections/text/forms.py +2 -0
  29. imio/smartweb/core/permissions.zcml +6 -0
  30. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  31. imio/smartweb/core/profiles/default/rolemap.xml +6 -0
  32. imio/smartweb/core/profiles/default/types/imio.smartweb.Page.xml +1 -0
  33. imio/smartweb/core/profiles/default/types/imio.smartweb.PortalPage.xml +1 -0
  34. imio/smartweb/core/profiles/default/types/imio.smartweb.Procedure.xml +1 -0
  35. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionContact.xml +0 -1
  36. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionEvents.xml +0 -1
  37. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionExternalContent.xml +35 -0
  38. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionFiles.xml +0 -1
  39. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionGallery.xml +0 -1
  40. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionHTML.xml +1 -1
  41. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionLinks.xml +0 -1
  42. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionMap.xml +0 -1
  43. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionNews.xml +0 -1
  44. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionPostit.xml +0 -1
  45. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSelections.xml +0 -1
  46. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSendinblue.xml +0 -1
  47. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionSlide.xml +0 -1
  48. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionText.xml +0 -1
  49. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionVideo.xml +0 -1
  50. imio/smartweb/core/profiles/default/types.xml +1 -0
  51. imio/smartweb/core/profiles/default/workflows.xml +1 -0
  52. imio/smartweb/core/tests/resources/json_rest_directory.json +1099 -0
  53. imio/smartweb/core/tests/resources/json_rest_events.json +1099 -0
  54. imio/smartweb/core/tests/resources/json_rest_news.json +1103 -4
  55. imio/smartweb/core/tests/test_cropping.py +2 -24
  56. imio/smartweb/core/tests/test_folder.py +17 -0
  57. imio/smartweb/core/tests/test_plausibleview.py +83 -0
  58. imio/smartweb/core/tests/test_rest.py +40 -0
  59. imio/smartweb/core/tests/test_section_news.py +0 -1
  60. imio/smartweb/core/tests/test_sections.py +34 -0
  61. imio/smartweb/core/upgrades/configure.zcml +90 -0
  62. imio/smartweb/core/upgrades/profiles/1037_to_1038/registry/plausible.xml +9 -0
  63. imio/smartweb/core/upgrades/profiles/1038_to_1039/rolemap.xml +12 -0
  64. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.Page.xml +11 -0
  65. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.PortalPage.xml +11 -0
  66. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.Procedure.xml +11 -0
  67. imio/smartweb/core/upgrades/profiles/1038_to_1039/types/imio.smartweb.SectionExternalContent.xml +36 -0
  68. imio/smartweb/core/upgrades/profiles/1038_to_1039/types.xml +4 -0
  69. imio/smartweb/core/upgrades/profiles/1038_to_1039/workflows.xml +6 -0
  70. imio/smartweb/core/upgrades/profiles/1039_to_1040/types/imio.smartweb.SectionSlide.xml +14 -0
  71. imio/smartweb/core/upgrades/profiles/1040_to_1041/types/imio.smartweb.SectionText.xml +17 -0
  72. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionContact.xml +14 -0
  73. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionEvents.xml +14 -0
  74. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionExternalContent.xml +15 -0
  75. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionFiles.xml +14 -0
  76. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionGallery.xml +15 -0
  77. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionLinks.xml +14 -0
  78. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionMap.xml +15 -0
  79. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionNews.xml +14 -0
  80. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionPostit.xml +14 -0
  81. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionSelections.xml +14 -0
  82. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionSendinblue.xml +14 -0
  83. imio/smartweb/core/upgrades/profiles/1041_to_1042/types/imio.smartweb.SectionVideo.xml +15 -0
  84. imio/smartweb/core/webcomponents/build/css/195.smartweb-webcomponents-compiled.css +1 -1
  85. imio/smartweb/core/webcomponents/build/css/552.smartweb-webcomponents-compiled.css +1 -1
  86. imio/smartweb/core/webcomponents/build/js/195.smartweb-webcomponents-compiled.js +1 -1
  87. imio/smartweb/core/webcomponents/build/js/212.smartweb-webcomponents-compiled.js +2 -0
  88. imio/smartweb/core/webcomponents/build/js/323.smartweb-webcomponents-compiled.js +1 -1
  89. imio/smartweb/core/webcomponents/build/js/510.smartweb-webcomponents-compiled.js +1 -1
  90. imio/smartweb/core/webcomponents/build/js/552.smartweb-webcomponents-compiled.js +1 -1
  91. imio/smartweb/core/webcomponents/build/js/{462.smartweb-webcomponents-compiled.js → 565.smartweb-webcomponents-compiled.js} +1 -1
  92. imio/smartweb/core/webcomponents/build/js/{842.smartweb-webcomponents-compiled.js → 729.smartweb-webcomponents-compiled.js} +2 -2
  93. imio/smartweb/core/webcomponents/build/js/9.smartweb-webcomponents-compiled.js +1 -1
  94. imio/smartweb/core/webcomponents/build/js/9.smartweb-webcomponents-compiled.js.LICENSE.txt +2 -2
  95. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  96. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactCard/ContactCard.jsx +2 -3
  97. imio/smartweb/core/webcomponents/src/components/Events/ContactCard/ContactCard.jsx +1 -2
  98. imio/smartweb/core/webcomponents/src/components/Events/Events.jsx +0 -1
  99. imio/smartweb/core/webcomponents/src/components/News/ContactCard/ContactCard.jsx +1 -2
  100. imio/smartweb/core/webcomponents/src/components/News/ContactContent/ContactContent.jsx +1 -1
  101. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/METADATA +63 -1
  102. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/RECORD +110 -78
  103. imio/smartweb/core/webcomponents/build/assets/img-placeholder-bla.a2b8b384c46ce56c99f042dc4625d309.png +0 -0
  104. imio/smartweb/core/webcomponents/build/js/650.smartweb-webcomponents-compiled.js +0 -2
  105. /imio/smartweb/core/webcomponents/build/js/{650.smartweb-webcomponents-compiled.js.LICENSE.txt → 212.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  106. /imio/smartweb/core/webcomponents/build/js/{842.smartweb-webcomponents-compiled.js.LICENSE.txt → 729.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  107. /imio.smartweb.core-1.1.15-py3.10-nspkg.pth → /imio.smartweb.core-1.1.19-py3.10-nspkg.pth +0 -0
  108. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/LICENSE.GPL +0 -0
  109. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/LICENSE.rst +0 -0
  110. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/WHEEL +0 -0
  111. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/namespace_packages.txt +0 -0
  112. {imio.smartweb.core-1.1.15.dist-info → imio.smartweb.core-1.1.19.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,7 @@
12
12
  />
13
13
 
14
14
  <include package=".banner" />
15
+ <include package=".dashboards" />
15
16
  <include package=".faceted" />
16
17
  <include package=".footer" />
17
18
  <include package=".herobanner" />
@@ -141,6 +141,30 @@ class ISmartwebControlPanel(Interface):
141
141
  )
142
142
  directives.widget("sendinblue_button_text", DataGridFieldFactory, auto_append=False)
143
143
 
144
+ plausible_url = schema.TextLine(
145
+ title=_("Plausible URL"),
146
+ description=_(
147
+ "Example : plausible.imio.be (SMARTWEB_PLAUSIBLE_URL varenv has precedence over this.)"
148
+ ),
149
+ required=False,
150
+ )
151
+
152
+ plausible_site = schema.TextLine(
153
+ title=_("Plausible Site"),
154
+ description=_(
155
+ "Example : namur.be (SMARTWEB_PLAUSIBLE_SITE varenv has precedence over this.)"
156
+ ),
157
+ required=False,
158
+ )
159
+
160
+ plausible_token = schema.TextLine(
161
+ title=_("Plausible Token"),
162
+ description=_(
163
+ "Plausible authentification token (SMARTWEB_PLAUSIBLE_TOKEN varenv has precedence over this.)"
164
+ ),
165
+ required=False,
166
+ )
167
+
144
168
 
145
169
  class SmartwebControlPanelForm(RegistryEditForm):
146
170
  schema = ISmartwebControlPanel
File without changes
@@ -0,0 +1,17 @@
1
+ <configure
2
+ xmlns="http://namespaces.zope.org/zope"
3
+ xmlns:browser="http://namespaces.zope.org/browser"
4
+ >
5
+ <include package="plone.app.contentmenu" />
6
+ <browser:page
7
+ name="stats"
8
+ title="Plausible dashboard"
9
+ template="plausible.pt"
10
+ menu="plone_displayviews"
11
+ for="plone.base.interfaces.siteroot.IPloneSiteRoot"
12
+ class=".plausible.PlausibleView"
13
+ permission="cmf.ModifyPortalContent"
14
+ layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
15
+ />
16
+
17
+ </configure>
@@ -0,0 +1,29 @@
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
+ metal:use-macro="context/main_template/macros/master"
6
+ i18n:domain="imio.smartweb">
7
+ <body>
8
+ <metal:main fill-slot="content-core">
9
+ <iframe plausible-embed
10
+ src=""
11
+ scrolling="no"
12
+ frameborder="0"
13
+ loading="lazy"
14
+ id="plausible"
15
+ style="width: 1px; min-width: 100%; height: 1600px;"
16
+ tal:condition="view/is_plausible_set"
17
+ tal:attributes="src view/get_iframe_src">
18
+ </iframe>
19
+ <script async
20
+ src=""
21
+ tal:condition="view/is_plausible_set"
22
+ tal:attributes="src view/get_embedhostjs_src">
23
+ </script>
24
+ <h2 tal:condition="not:view/is_plausible_set" i18n:domain="imio.smartweb" i18n:translate="">
25
+ Plausible analytics is not set
26
+ </h2>
27
+ </metal:main>
28
+ </body>
29
+ </html>
@@ -0,0 +1,21 @@
1
+ from Products.Five.browser import BrowserView
2
+ from imio.smartweb.core.browser.utils import get_plausible_vars
3
+
4
+
5
+ class PlausibleView(BrowserView):
6
+ @property
7
+ def is_plausible_set(self):
8
+ if not get_plausible_vars(self):
9
+ return False
10
+ else:
11
+ return True
12
+
13
+ @property
14
+ def get_embedhostjs_src(self):
15
+ vars = get_plausible_vars(self)
16
+ return f"https://{vars['plausible_url']}/js/embed.host.js"
17
+
18
+ @property
19
+ def get_iframe_src(self):
20
+ vars = get_plausible_vars(self)
21
+ return f"https://{vars['plausible_url']}/share/{vars['plausible_site']}?auth={vars['plausible_token']}&embed=true&theme=light&background=transparent"
@@ -68,13 +68,9 @@
68
68
  var data = $("#faceted-results-items").attr("data-geojson");
69
69
  if ( typeof data != "undefined" && data ) {
70
70
  data = JSON.parse(data);
71
- if ( data.features.length > 0 ) {
72
- $('#faceted-map-container').trigger('leaflet.refresh', data);
73
- }
74
- } else {
75
- $('#faceted-map-container').trigger('leaflet.refresh', data);
76
- }
77
- }
71
+ $('#faceted-map-container').trigger('leaflet.refresh', data);
72
+ window.dispatchEvent(new Event('resize'));
73
+ }};
78
74
 
79
75
  jQuery(document).ready(function($) {
80
76
  $("#faceted-map-container").insertAfter($("#faceted-results"));
@@ -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
9
+ if fieldname in ["banner", "background_image"]:
10
+ # scale used for banner fields or background_image fields
11
11
  return []
12
- elif fieldname == "background_image":
13
- # scales used for background_image fields
14
- return ["affiche"]
15
12
  elif fieldname == "image":
16
13
  # scales used for lead_image fields
17
14
  return ["liste", "vignette", "slide"]
@@ -62,6 +62,7 @@ class Folder(Container):
62
62
  idxs=("object_provides", "exclude_from_nav")
63
63
  )
64
64
  self.default_page_uid = None
65
+ self.reindexObject()
65
66
 
66
67
  def get_default_item(self, object=False):
67
68
  if self.default_page_uid:
@@ -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"
@@ -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,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
 
@@ -23,6 +23,7 @@ class TextCustomAddForm(CustomAddForm):
23
23
  def updateFields(self):
24
24
  super(TextCustomAddForm, self).updateFields()
25
25
  self.fields["ILeadImageBehavior.image_caption"].mode = INPUT_MODE
26
+ self.fields["image_size"].mode = HIDDEN_MODE
26
27
 
27
28
 
28
29
  class TextCustomAddView(DefaultAddView):
@@ -42,6 +43,7 @@ class TextCustomEditForm(SmartwebCustomEditForm):
42
43
  def updateFields(self):
43
44
  super(TextCustomEditForm, self).updateFields()
44
45
  self.fields["ILeadImageBehavior.image_caption"].mode = INPUT_MODE
46
+ self.fields["image_size"].mode = HIDDEN_MODE
45
47
 
46
48
 
47
49
  TextCustomEditView = layout.wrap_form(TextCustomEditForm)
@@ -56,6 +56,12 @@
56
56
  description=""
57
57
  />
58
58
 
59
+ <permission
60
+ id="imio.smartweb.core.CanManageSectionExternalContent"
61
+ title="imio.smartweb.core: Can add section External Content"
62
+ description=""
63
+ />
64
+
59
65
  <permission
60
66
  id="imio.smartweb.core.CanEditMinisiteLogo"
61
67
  title="imio.smartweb.core: Edit Minisite Logo"
@@ -1,6 +1,6 @@
1
1
  <?xml version='1.0' encoding='UTF-8'?>
2
2
  <metadata>
3
- <version>1037</version>
3
+ <version>1042</version>
4
4
  <dependencies>
5
5
  <dependency>profile-plone.app.dexterity:default</dependency>
6
6
  <dependency>profile-plone.app.imagecropping:default</dependency>