affinitic.smartweb 1.0.0a17__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 (146) hide show
  1. affinitic/smartweb/__init__.py +6 -0
  2. affinitic/smartweb/behavior/configure.zcml +15 -0
  3. affinitic/smartweb/behavior/image_scales.py +20 -0
  4. affinitic/smartweb/browser/__init__.py +0 -0
  5. affinitic/smartweb/browser/configure.zcml +32 -0
  6. affinitic/smartweb/browser/import_document.py +427 -0
  7. affinitic/smartweb/browser/overrides/.gitkeep +0 -0
  8. affinitic/smartweb/browser/portlets/__init__.py +0 -0
  9. affinitic/smartweb/browser/portlets/configure.zcml +19 -0
  10. affinitic/smartweb/browser/portlets/image_portlet.pt +29 -0
  11. affinitic/smartweb/browser/portlets/image_portlet.py +78 -0
  12. affinitic/smartweb/browser/static/.gitkeep +0 -0
  13. affinitic/smartweb/browser/static/dist/index.9b029128174957df01c4.js +2 -0
  14. affinitic/smartweb/browser/static/dist/index.9b029128174957df01c4.js.map +1 -0
  15. affinitic/smartweb/browser/static/dist/index.css +2 -0
  16. affinitic/smartweb/browser/static/dist/index.css.map +1 -0
  17. affinitic/smartweb/browser/static/package.json +40 -0
  18. affinitic/smartweb/browser/static/pnpm-lock.yaml +6041 -0
  19. affinitic/smartweb/browser/static/src/index.js +3 -0
  20. affinitic/smartweb/browser/static/src/js/views.js +110 -0
  21. affinitic/smartweb/browser/static/src/scss/_collections.scss +9 -0
  22. affinitic/smartweb/browser/static/src/scss/_nav.scss +23 -0
  23. affinitic/smartweb/browser/static/src/scss/_view.scss +150 -0
  24. affinitic/smartweb/browser/static/src/scss/main.scss +7 -0
  25. affinitic/smartweb/browser/static/svg/arrow_left_circle.svg +4 -0
  26. affinitic/smartweb/browser/static/svg/plus_circle.svg +4 -0
  27. affinitic/smartweb/browser/static/webpack.prod.js +108 -0
  28. affinitic/smartweb/configure.zcml +60 -0
  29. affinitic/smartweb/contents/__init__.py +8 -0
  30. affinitic/smartweb/contents/configure.zcml +6 -0
  31. affinitic/smartweb/contents/folders/__init__.py +0 -0
  32. affinitic/smartweb/contents/folders/event_folder/__init__.py +0 -0
  33. affinitic/smartweb/contents/folders/event_folder/content.py +15 -0
  34. affinitic/smartweb/contents/folders/news_folder/__init__.py +0 -0
  35. affinitic/smartweb/contents/folders/news_folder/content.py +15 -0
  36. affinitic/smartweb/contents/pages/__init__.py +0 -0
  37. affinitic/smartweb/contents/pages/event/__init__.py +0 -0
  38. affinitic/smartweb/contents/pages/event/content.py +16 -0
  39. affinitic/smartweb/contents/pages/news/__init__.py +0 -0
  40. affinitic/smartweb/contents/pages/news/content.py +16 -0
  41. affinitic/smartweb/contents/sections/__init__.py +0 -0
  42. affinitic/smartweb/contents/sections/collection/configure.zcml +27 -0
  43. affinitic/smartweb/contents/sections/common_templates/carousel.pt +111 -0
  44. affinitic/smartweb/contents/sections/common_templates/list.pt +129 -0
  45. affinitic/smartweb/contents/sections/common_templates/mini-list.pt +119 -0
  46. affinitic/smartweb/contents/sections/common_templates/table.pt +133 -0
  47. affinitic/smartweb/contents/sections/configure.zcml +10 -0
  48. affinitic/smartweb/contents/sections/event_infos/__init__.py +0 -0
  49. affinitic/smartweb/contents/sections/event_infos/configure.zcml +14 -0
  50. affinitic/smartweb/contents/sections/event_infos/content.py +39 -0
  51. affinitic/smartweb/contents/sections/event_infos/view.pt +20 -0
  52. affinitic/smartweb/contents/sections/event_infos/view.py +69 -0
  53. affinitic/smartweb/contents/sections/events/__init__.py +0 -0
  54. affinitic/smartweb/contents/sections/events/configure.zcml +57 -0
  55. affinitic/smartweb/contents/sections/events/content.py +74 -0
  56. affinitic/smartweb/contents/sections/events/macros.pt +34 -0
  57. affinitic/smartweb/contents/sections/events/view.py +64 -0
  58. affinitic/smartweb/contents/sections/news/__init__.py +0 -0
  59. affinitic/smartweb/contents/sections/news/configure.zcml +49 -0
  60. affinitic/smartweb/contents/sections/news/content.py +74 -0
  61. affinitic/smartweb/contents/sections/news/view.py +39 -0
  62. affinitic/smartweb/contents/sections/section_copy_link/__init__.py +0 -0
  63. affinitic/smartweb/contents/sections/section_copy_link/configure.zcml +14 -0
  64. affinitic/smartweb/contents/sections/section_copy_link/content.py +32 -0
  65. affinitic/smartweb/contents/sections/section_copy_link/view.pt +79 -0
  66. affinitic/smartweb/contents/sections/section_copy_link/view.py +64 -0
  67. affinitic/smartweb/interfaces.py +8 -0
  68. affinitic/smartweb/locales/README.rst +37 -0
  69. affinitic/smartweb/locales/__init__.py +0 -0
  70. affinitic/smartweb/locales/affinitic.smartweb.pot +189 -0
  71. affinitic/smartweb/locales/en/LC_MESSAGES/affinitic.smartweb.mo +0 -0
  72. affinitic/smartweb/locales/en/LC_MESSAGES/affinitic.smartweb.po +186 -0
  73. affinitic/smartweb/locales/en/LC_MESSAGES/plone.mo +0 -0
  74. affinitic/smartweb/locales/en/LC_MESSAGES/plone.po +116 -0
  75. affinitic/smartweb/locales/fr/LC_MESSAGES/affinitic.smartweb.mo +0 -0
  76. affinitic/smartweb/locales/fr/LC_MESSAGES/affinitic.smartweb.po +186 -0
  77. affinitic/smartweb/locales/fr/LC_MESSAGES/plone.mo +0 -0
  78. affinitic/smartweb/locales/fr/LC_MESSAGES/plone.po +116 -0
  79. affinitic/smartweb/locales/nl/LC_MESSAGES/affinitic.smartweb.mo +0 -0
  80. affinitic/smartweb/locales/nl/LC_MESSAGES/affinitic.smartweb.po +186 -0
  81. affinitic/smartweb/locales/nl/LC_MESSAGES/plone.mo +0 -0
  82. affinitic/smartweb/locales/nl/LC_MESSAGES/plone.po +116 -0
  83. affinitic/smartweb/locales/plone.pot +119 -0
  84. affinitic/smartweb/locales/update.py +74 -0
  85. affinitic/smartweb/locales/update.sh +16 -0
  86. affinitic/smartweb/permissions.zcml +12 -0
  87. affinitic/smartweb/profiles/default/browserlayer.xml +7 -0
  88. affinitic/smartweb/profiles/default/catalog.xml +4 -0
  89. affinitic/smartweb/profiles/default/metadata.xml +8 -0
  90. affinitic/smartweb/profiles/default/registry/bundles.xml +15 -0
  91. affinitic/smartweb/profiles/default/registry/main.xml +8 -0
  92. affinitic/smartweb/profiles/default/rolemap.xml +7 -0
  93. affinitic/smartweb/profiles/default/types/LRF.xml +16 -0
  94. affinitic/smartweb/profiles/default/types/affinitic.smartweb.SectionCopyLink.xml +34 -0
  95. affinitic/smartweb/profiles/default/types/imio.smartweb.CirkwiView.xml +10 -0
  96. affinitic/smartweb/profiles/default/types/imio.smartweb.DirectoryView.xml +10 -0
  97. affinitic/smartweb/profiles/default/types/imio.smartweb.EventsView.xml +10 -0
  98. affinitic/smartweb/profiles/default/types/imio.smartweb.Folder.xml +24 -0
  99. affinitic/smartweb/profiles/default/types/imio.smartweb.NewsView.xml +10 -0
  100. affinitic/smartweb/profiles/default/types/imio.smartweb.Page.xml +40 -0
  101. affinitic/smartweb/profiles/default/types/imio.smartweb.PortalPage.xml +28 -0
  102. affinitic/smartweb/profiles/default/types/imio.smartweb.Procedure.xml +10 -0
  103. affinitic/smartweb/profiles/default/types/imio.smartweb.SectionSlide.xml +12 -0
  104. affinitic/smartweb/profiles/default/types.xml +12 -0
  105. affinitic/smartweb/profiles/event_news/metadata.xml +6 -0
  106. affinitic/smartweb/profiles/event_news/taxonomies/event_category.cfg +9 -0
  107. affinitic/smartweb/profiles/event_news/taxonomies/event_category.xml +57 -0
  108. affinitic/smartweb/profiles/event_news/taxonomies/news_category.cfg +9 -0
  109. affinitic/smartweb/profiles/event_news/taxonomies/news_category.xml +57 -0
  110. affinitic/smartweb/profiles/event_news/types/LRF.xml +12 -0
  111. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.Event.xml +69 -0
  112. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.EventFolder.xml +57 -0
  113. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.News.xml +63 -0
  114. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.NewsFolder.xml +57 -0
  115. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.SectionEventInfo.xml +34 -0
  116. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.SectionEvents.xml +46 -0
  117. affinitic/smartweb/profiles/event_news/types/affinitic.smartweb.SectionNews.xml +46 -0
  118. affinitic/smartweb/profiles/event_news/types/imio.smartweb.Folder.xml +12 -0
  119. affinitic/smartweb/profiles/event_news/types/imio.smartweb.Page.xml +10 -0
  120. affinitic/smartweb/profiles/event_news/types/imio.smartweb.PortalPage.xml +10 -0
  121. affinitic/smartweb/profiles/event_news/types/imio.smartweb.SectionCollection.xml +20 -0
  122. affinitic/smartweb/profiles/event_news/types.xml +13 -0
  123. affinitic/smartweb/profiles/event_news/workflows.xml +7 -0
  124. affinitic/smartweb/profiles/portlets/metadata.xml +6 -0
  125. affinitic/smartweb/profiles/portlets/portlets.xml +7 -0
  126. affinitic/smartweb/profiles/portlets/rolemap.xml +12 -0
  127. affinitic/smartweb/profiles/portlets/viewlets.xml +6 -0
  128. affinitic/smartweb/profiles/uninstall/browserlayer.xml +7 -0
  129. affinitic/smartweb/profiles/uninstall_types/types.xml +10 -0
  130. affinitic/smartweb/setuphandlers.py +37 -0
  131. affinitic/smartweb/testing.py +50 -0
  132. affinitic/smartweb/tests/__init__.py +0 -0
  133. affinitic/smartweb/tests/robot/test_example.robot +66 -0
  134. affinitic/smartweb/tests/test_robot.py +31 -0
  135. affinitic/smartweb/tests/test_setup.py +55 -0
  136. affinitic/smartweb/upgrades.py +49 -0
  137. affinitic/smartweb/upgrades.zcml +128 -0
  138. affinitic/smartweb/utils.py +45 -0
  139. affinitic.smartweb-1.0.0a17-py3.11-nspkg.pth +1 -0
  140. affinitic_smartweb-1.0.0a17.dist-info/METADATA +353 -0
  141. affinitic_smartweb-1.0.0a17.dist-info/RECORD +146 -0
  142. affinitic_smartweb-1.0.0a17.dist-info/WHEEL +5 -0
  143. affinitic_smartweb-1.0.0a17.dist-info/entry_points.txt +5 -0
  144. affinitic_smartweb-1.0.0a17.dist-info/licenses/LICENSE.rst +14 -0
  145. affinitic_smartweb-1.0.0a17.dist-info/namespace_packages.txt +1 -0
  146. affinitic_smartweb-1.0.0a17.dist-info/top_level.txt +1 -0
@@ -0,0 +1,6 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Init and utils."""
3
+ from zope.i18nmessageid import MessageFactory
4
+
5
+
6
+ _ = MessageFactory("affinitic.smartweb")
@@ -0,0 +1,15 @@
1
+ <configure
2
+ xmlns="http://namespaces.zope.org/zope"
3
+ xmlns:plone="http://namespaces.plone.org/plone"
4
+ i18n_domain="affinitic.smartweb">
5
+
6
+ <include package="plone.behavior" file="meta.zcml"/>
7
+
8
+ <plone:behavior
9
+ name="affinitic.smartweb.image_scales"
10
+ title="Image Scales"
11
+ description="Allow to choose images scales for current context."
12
+ provides=".image_scales.IImageScales"
13
+ />
14
+
15
+ </configure>
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from imio.smartweb.locales import SmartwebMessageFactory as _
4
+ from plone.autoform import directives
5
+ from plone.autoform.interfaces import IFormFieldProvider
6
+ from plone.supermodel import model
7
+ from zope import schema
8
+ from zope.interface import provider
9
+
10
+
11
+ @provider(IFormFieldProvider)
12
+ class IImageScales(model.Schema):
13
+
14
+ model.fieldset("settings", fields=["image_scale"])
15
+ image_scale = schema.Choice(
16
+ title=_("Image scale for images (only for gallery mode)"),
17
+ default="affiche",
18
+ vocabulary="imio.smartweb.vocabulary.Scales",
19
+ required=True,
20
+ )
File without changes
@@ -0,0 +1,32 @@
1
+ <configure
2
+ xmlns="http://namespaces.zope.org/zope"
3
+ xmlns:browser="http://namespaces.zope.org/browser"
4
+ xmlns:plone="http://namespaces.plone.org/plone"
5
+ i18n_domain="affinitic.smartweb">
6
+
7
+ <!-- Set overrides folder for Just-a-Bunch-Of-Templates product -->
8
+ <include package="z3c.jbot" file="meta.zcml" />
9
+ <browser:jbot
10
+ directory="overrides"
11
+ layer="affinitic.smartweb.interfaces.IAffiniticSmartwebLayer"
12
+ />
13
+
14
+ <include package=".portlets"/>
15
+
16
+ <!-- Publish static files -->
17
+ <plone:static
18
+ name="affinitic.smartweb"
19
+ type="plone"
20
+ directory="static"
21
+ />
22
+
23
+ <browser:page
24
+ name="import_content"
25
+ for="zope.interface.Interface"
26
+ class=".import_document.CustomImportDocumentContent"
27
+ layer="affinitic.smartweb.interfaces.IAffiniticSmartwebLayer"
28
+ permission="cmf.ManagePortal"
29
+ />
30
+
31
+
32
+ </configure>
@@ -0,0 +1,427 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from Acquisition import aq_parent
4
+ from affinitic.smartweb.contents import IEventFolder
5
+ from affinitic.smartweb.contents import INewsFolder
6
+ from affinitic.smartweb.utils import check_if_folder_exist
7
+ from collective.exportimport.import_content import ImportContent
8
+ from plone import api
9
+ from plone.app.textfield.value import RichTextValue
10
+ from plone.i18n.normalizer import idnormalizer
11
+ from six.moves.urllib.parse import unquote
12
+ from six.moves.urllib.parse import urlparse
13
+
14
+ import logging
15
+ import re
16
+ import os
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ class CustomImportDocumentContent(ImportContent):
22
+
23
+ PORTAL_TYPE_MAPPING = {
24
+ "Document": "imio.smartweb.Page",
25
+ "Folder": "imio.smartweb.Folder",
26
+ }
27
+
28
+ ALLOWED_TYPES = [
29
+ "Collection",
30
+ "Link",
31
+ "imio.smartweb.DirectoryView",
32
+ "imio.smartweb.EventsView",
33
+ "imio.smartweb.Folder",
34
+ "imio.smartweb.NewsView",
35
+ "imio.smartweb.Page",
36
+ "imio.smartweb.PortalPage",
37
+ "imio.smartweb.Procedure",
38
+ ]
39
+
40
+ def dict_hook_document(self, item):
41
+ item["@type"] = "imio.smartweb.Page"
42
+ item["layout"] = "full_view"
43
+ return item
44
+
45
+ def dict_hook_collage(self, item):
46
+ item["@type"] = "imio.smartweb.Page"
47
+ item["old_type"] = "Collage"
48
+ item["layout"] = "full_view"
49
+ return item
50
+
51
+ def dict_hook_folder(self, item):
52
+ item["@type"] = "imio.smartweb.Folder"
53
+ item["layout"] = "block_view"
54
+ return item
55
+
56
+ def dict_hook_event(self, item):
57
+ item["@type"] = "affinitic.smartweb.Event"
58
+ item["layout"] = "full_view"
59
+ return item
60
+
61
+ def dict_hook_newsitem(self, item):
62
+ item["@type"] = "affinitic.smartweb.News"
63
+ item["layout"] = "full_view"
64
+ return item
65
+
66
+ def dict_hook_topic(self, item):
67
+ item["@type"] = "Collection"
68
+ item["layout"] = "view"
69
+ return item
70
+
71
+ def _remove_localhost(self, path, plone=True):
72
+ if plone:
73
+ return path.replace("http://localhost:8080/Plone", "")
74
+ return path.replace("http://localhost:8080", "")
75
+
76
+ def _path_to_uid(self, path):
77
+ obj = api.content.get(path=self._remove_localhost(path, False))
78
+ if not obj:
79
+ return None, self._remove_localhost(path)
80
+ return obj.UID(), None
81
+
82
+ def _handle_link(self, item):
83
+ text = item.get("text", None)
84
+ if not text:
85
+ return item
86
+ data = text.get("data", None)
87
+ if not data:
88
+ return item
89
+ item["text"]["data"] = re.sub(r'(https?:\/\/localhost\:8080\/Plone)', "", data)
90
+ return item
91
+
92
+ def dict_hook_publication(self, item):
93
+ ref_ebook = item.get('ref_ebook', None)
94
+ ref_pdf = item.get('ref_pdf', None)
95
+ errors = []
96
+ if ref_ebook:
97
+ item['ref_ebook'], error = self._path_to_uid(ref_ebook)
98
+ if error:
99
+ errors.append(error)
100
+ if ref_pdf:
101
+ item['ref_pdf'], error = self._path_to_uid(ref_pdf)
102
+ if error:
103
+ errors.append(error)
104
+
105
+ if len(errors) > 0:
106
+ msg = f"Error : Cannot find {' and '.join(errors)}"
107
+
108
+ description = item.get("description", None)
109
+ logger.warning("{} : {}".format(item['@id'], msg))
110
+ if description:
111
+ item['description'] = f"{msg} - {description}"
112
+ else:
113
+ item['description'] = f"{msg}"
114
+
115
+ item = self._handle_link(item)
116
+
117
+ return item
118
+
119
+ def _add_subfolder_in_path(self, path, subfolder, position=-1):
120
+ path_split = path.split("/")
121
+ path_split.insert(position, subfolder)
122
+ return "/".join(path_split)
123
+
124
+ def handle_collage_document(self, obj, collage):
125
+ target = collage.get("target", None)
126
+ if target is None:
127
+ return
128
+
129
+ if collage["target_type"] == "News Item":
130
+ target = self._add_subfolder_in_path(target, "news")
131
+
132
+ # safer path lookup
133
+ site = api.portal.get()
134
+ target_obj = site.unrestrictedTraverse(target.lstrip("/"), None)
135
+ if target_obj is None:
136
+ logger.warning(f"Target not found for collage: {target}")
137
+ return
138
+
139
+ sections = target_obj.listFolderContents()
140
+ if not sections:
141
+ logger.info(f"No sections found in target {target}")
142
+ return
143
+
144
+ for section in sections:
145
+ # copy via Zope API instead of api.content.copy
146
+ cp = target_obj.manage_copyObjects(ids=[section.getId()])
147
+ result = obj.manage_pasteObjects(cp)
148
+
149
+ if result:
150
+ new_id = result[0]['new_id']
151
+ logger.info(
152
+ "Section %s (%s) copied into %s as %s",
153
+ section.id,
154
+ section.portal_type,
155
+ "/".join(obj.getPhysicalPath()),
156
+ new_id,
157
+ )
158
+ else:
159
+ logger.warning(
160
+ "Failed to paste section %s into %s",
161
+ section.id,
162
+ "/".join(obj.getPhysicalPath()),
163
+ )
164
+
165
+ def handle_collage_image(self, obj, collage):
166
+ target = collage.get("target", None)
167
+ id = collage["id"]
168
+ if target is not None:
169
+ id = target.split("/")[-1]
170
+ api.content.create(
171
+ container=obj,
172
+ type="imio.smartweb.SectionGallery",
173
+ id=id
174
+ )
175
+
176
+ def handle_collage_topic(self, obj, collage):
177
+ target = collage.get("target", None)
178
+ if target is None:
179
+ return
180
+ section = api.content.create(
181
+ container=obj,
182
+ type="imio.smartweb.SectionCollection",
183
+ title=collage["title"]
184
+ )
185
+ target_obj = api.content.get(path=target)
186
+ if target_obj and target_obj.portal_type == "Collection":
187
+ section.collection = target_obj
188
+
189
+ def handle_collage_news(self, obj, collage):
190
+ target = collage.get("target", None)
191
+ id = collage["id"]
192
+ if target is not None:
193
+ id = target.split("/")[-1]
194
+ section = api.content.create(
195
+ container=obj,
196
+ type="affinitic.smartweb.SectionNews",
197
+ title=collage["title"]
198
+ )
199
+ target_obj = api.content.get(path=target)
200
+ if target_obj and target_obj.portal_type == "Collection":
201
+ section.collection = target_obj
202
+
203
+ def handle_collage(self, obj, item):
204
+ collages = item.get("collages", None)
205
+ if collages is None:
206
+ return
207
+ for collage in collages:
208
+ target_type = collage.get("target_type", None)
209
+ if not target_type:
210
+ continue
211
+ adpater = {
212
+ "Document": self.handle_collage_document,
213
+ "Image": self.handle_collage_image,
214
+ "Topic": self.handle_collage_topic,
215
+ "News Item": self.handle_collage_document
216
+ }
217
+ adpater[collage["target_type"]](obj, collage)
218
+
219
+ def global_obj_hook(self, obj, item):
220
+ old_type = item.get("old_type", None)
221
+ if old_type and old_type == "Collage":
222
+ self.handle_collage(obj, item)
223
+ return obj
224
+
225
+ def _create_text_section(self, text, title, container):
226
+ if idnormalizer.normalize(title) in container:
227
+ return
228
+
229
+ api.content.create(
230
+ container=container,
231
+ type="imio.smartweb.SectionText",
232
+ title=title,
233
+ text=RichTextValue(
234
+ raw=text,
235
+ mimeType="text/html",
236
+ outputMimeType="text/x-html-safe",
237
+ ),
238
+ hide_title=True,
239
+ )
240
+
241
+ def _create_gallery_section(self, id, container):
242
+ if id in container:
243
+ return
244
+
245
+ api.content.create(
246
+ container=container,
247
+ type="imio.smartweb.SectionGallery",
248
+ id=id,
249
+ hide_title=True,
250
+ )
251
+
252
+ def _create_file_section(self, id, container):
253
+ if id in container:
254
+ return
255
+
256
+ section = api.content.create(
257
+ container=container,
258
+ type="imio.smartweb.SectionFiles",
259
+ id=id,
260
+ hide_title=True,
261
+ )
262
+ return section
263
+
264
+ def _add_file_to_section(self, section_obj, section_info, context_path):
265
+
266
+ file_path = section_info["href"]
267
+ if not file_path.startswith("/Plone/"):
268
+ file_path = os.path.normpath(os.path.join(context_path, file_path))
269
+ file_obj = api.content.get(path=file_path)
270
+ if not file_obj:
271
+ return
272
+ cp = aq_parent(file_obj).manage_copyObjects(ids=[file_obj.getId()])
273
+ result = section_obj.manage_pasteObjects(cp)
274
+
275
+ if result:
276
+ new_id = result[0]['new_id']
277
+ logger.info(
278
+ "File %s (%s) copied into %s as %s",
279
+ file_obj.id,
280
+ file_obj.portal_type,
281
+ "/".join(section_obj.getPhysicalPath()),
282
+ new_id,
283
+ )
284
+ else:
285
+ logger.warning(
286
+ "Failed to paste File %s into %s",
287
+ file_obj.id,
288
+ "/".join(section_obj.getPhysicalPath()),
289
+ )
290
+
291
+ def _get_gallery_id(self, section):
292
+ if "id" in section:
293
+ return section["id"].replace(".", "-")
294
+ return "_".join(section["merge_data"]).replace(".", "-")
295
+
296
+ def global_obj_hook_before_deserializing(self, obj, item):
297
+ """Hook to modify the created obj before deserializing the data."""
298
+ sections_content = item.get("section_content", False)
299
+
300
+ if (
301
+ "title" not in item
302
+ or not item["title"]
303
+ or item["title"].replace(" ", "") == ""
304
+ ):
305
+ item["title"] = item["id"]
306
+ logger.warning(
307
+ "{} does not have a title, we take the id ({}) instead".format(
308
+ item["@id"], item["id"]
309
+ )
310
+ )
311
+
312
+ if item["description"] and len(item["description"]) > 700:
313
+ item["description"] = item["description"][:699]
314
+ logger.warning(
315
+ "{} have a descritpion to long, we trim it to 700 characters".format(
316
+ item["@id"], item["id"]
317
+ )
318
+ )
319
+
320
+ if not sections_content:
321
+ return obj, item
322
+
323
+ for count, section in enumerate(sections_content):
324
+ if section["type"] == "text":
325
+ self._create_text_section(
326
+ text=section["data"],
327
+ title=f"{item.get('title')} Section Text {count}",
328
+ container=obj,
329
+ )
330
+
331
+ if section["type"] == "image":
332
+ self._create_gallery_section(
333
+ id=self._get_gallery_id(section), container=obj
334
+ )
335
+
336
+ if section["type"] == "link":
337
+ section_obj = self._create_file_section(
338
+ id=os.path.basename(section["href"]), container=obj
339
+ )
340
+ self._add_file_to_section(
341
+ section_obj, section, "/".join(obj.getPhysicalPath())
342
+ )
343
+
344
+ return obj, item
345
+
346
+ def get_parent_as_container(self, item):
347
+ folder = super(CustomImportDocumentContent, self).get_parent_as_container(item)
348
+
349
+ if item["@type"] == "News Item" or item["@type"] == "affinitic.smartweb.News":
350
+ if not check_if_folder_exist(folder, "news", INewsFolder):
351
+ folder = api.content.create(
352
+ container=folder,
353
+ type="affinitic.smartweb.NewsFolder",
354
+ title="News",
355
+ )
356
+ else:
357
+ folder = getattr(folder, "news", False)
358
+
359
+ if item["@type"] == "Event" or item["@type"] == "affinitic.smartweb.Event":
360
+ if not check_if_folder_exist(folder, "events", IEventFolder):
361
+ folder = api.content.create(
362
+ container=folder,
363
+ type="affinitic.smartweb.EventFolder",
364
+ title="Events",
365
+ )
366
+ else:
367
+ folder = getattr(folder, "events", False)
368
+
369
+ return folder
370
+
371
+ def create_container(self, item):
372
+ folder = self.context
373
+ parent_url = unquote(item["parent"]["@id"])
374
+ parent_url_parsed = urlparse(parent_url)
375
+ # Get the path part, split it, remove the always empty first element.
376
+ parent_path = parent_url_parsed.path.split("/")[1:]
377
+ if (
378
+ len(parent_url_parsed.netloc.split(":")) > 1
379
+ or parent_url_parsed.netloc == "nohost"
380
+ ):
381
+ # For example localhost:8080, or nohost when running tests.
382
+ # First element will then be a Plone Site id.
383
+ # Get rid of it.
384
+ parent_path = parent_path[1:]
385
+
386
+ # create original structure for imported content
387
+ for element in parent_path:
388
+ if element not in folder:
389
+ folder = api.content.create(
390
+ container=folder,
391
+ type="imio.smartweb.Folder",
392
+ id=element,
393
+ title=element,
394
+ )
395
+ logger.info(
396
+ "Created container {} to hold {}".format(
397
+ folder.absolute_url(), item["@id"]
398
+ )
399
+ )
400
+ else:
401
+ folder = folder[element]
402
+
403
+ return folder
404
+
405
+ def handle_image_container_multi(self, path):
406
+ basename = os.path.basename(path)
407
+ dirname = os.path.dirname(path)
408
+ page = api.content.get(path=dirname)
409
+ if not page:
410
+ return None
411
+ galleries_sections = page.listFolderContents(
412
+ contentFilter={"portal_type": "imio.smartweb.SectionGallery"}
413
+ )
414
+ for section in galleries_sections:
415
+ section_id = section.id
416
+ if basename.replace(".", "-") in section_id:
417
+ return section
418
+
419
+ def handle_image_container(self, item):
420
+ section_image = item.get("section_image", None)
421
+ if not section_image:
422
+ return self.get_parent_as_container(item)
423
+ path = section_image.replace("http://localhost:8080", "").replace(".", "-")
424
+ output = api.content.get(path=path)
425
+ if not output:
426
+ output = self.handle_image_container_multi(path)
427
+ return output
File without changes
File without changes
@@ -0,0 +1,19 @@
1
+ <configure
2
+ xmlns="http://namespaces.zope.org/zope"
3
+ xmlns:browser="http://namespaces.zope.org/browser"
4
+ xmlns:plone='http://namespaces.plone.org/plone'
5
+ i18n_domain='affinitic.smartweb'>
6
+
7
+ <include package="plone.app.portlets" />
8
+
9
+
10
+ <plone:portlet
11
+ name="affinitic.smartweb.image_portlet"
12
+ addview=".image_portlet.AddForm"
13
+ editview=".image_portlet.EditForm"
14
+ assignment=".image_portlet.Assignment"
15
+ renderer=".image_portlet.Renderer"
16
+ interface=".image_portlet.IImagePortlet"
17
+ />
18
+
19
+ </configure>
@@ -0,0 +1,29 @@
1
+ <html
2
+ xmlns="http://www.w3.org/1999/xhtml"
3
+ xmlns:tal="http://xml.zope.org/namespaces/tal"
4
+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
5
+ tal:omit-tag=""
6
+ >
7
+ <div class="card portlet" i18n:domain="my-example">
8
+ <div class="card-header" tal:condition="view/portlet_title" tal:content="view/portlet_title">Title</div>
9
+
10
+ <div class="card-body" tal:define="image view/image" tal:condition="view/image">
11
+ <tal:if tal:condition="python: not view.url()">
12
+ <img src="" alt="" tal:attributes="
13
+ src string:${context/absolute_url}/${view/portlet_context}/@@display-file/image/${image/filename};
14
+ height picture/_height | nothing;
15
+ width picture/_width | nothing;
16
+ alt view/portlet_title"/>
17
+ </tal:if>
18
+ <tal:if tal:condition="python: view.url()">
19
+ <a href="" tal:attributes="href view/url">
20
+ <img src="" alt="" tal:attributes="
21
+ src string:${context/absolute_url}/${view/portlet_context}/@@display-file/image/${image/filename};
22
+ height picture/_height | nothing;
23
+ width picture/_width | nothing;
24
+ alt view/portlet_title"/>
25
+ </a>
26
+ </tal:if>
27
+ </div>
28
+ </div>
29
+ </html>
@@ -0,0 +1,78 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from affinitic.smartweb import _
4
+ from plone.app.portlets.portlets import base
5
+ from plone.portlets.interfaces import IPortletDataProvider
6
+ from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
7
+ from plone import schema
8
+ from zope.interface import implementer
9
+ from plone.namedfile.field import NamedBlobImage
10
+
11
+ class IImagePortlet(IPortletDataProvider):
12
+ """A portlet that displays a greeting message."""
13
+
14
+ portlet_title = schema.TextLine(
15
+ title = _("Title"),
16
+ required=False
17
+ )
18
+
19
+ image = NamedBlobImage(
20
+ title= _("Image")
21
+ )
22
+
23
+ url = schema.URI(
24
+ title=_('URL'),
25
+ required=False
26
+ )
27
+
28
+
29
+ @implementer(IImagePortlet)
30
+ class Assignment(base.Assignment):
31
+ """Portlet assignment."""
32
+
33
+ def __init__(self, image=None, portlet_title="", url=None):
34
+ self.image = image
35
+ self.portlet_title = portlet_title
36
+ self.url = url
37
+
38
+
39
+ class Renderer(base.Renderer):
40
+ """Portlet renderer."""
41
+
42
+ # Define the page template that will be used to render the portlet
43
+ template = ViewPageTemplateFile("image_portlet.pt")
44
+
45
+ def image(self):
46
+ return self.data.image
47
+
48
+ def portlet_title(self):
49
+ return self.data.portlet_title
50
+
51
+ def url(self):
52
+ return self.data.url
53
+
54
+ def portlet_context(self):
55
+ return "/".join(self.data.getPhysicalPath())
56
+
57
+ def render(self):
58
+ """This method is called whenever the portlet is rendered."""
59
+ return self.template()
60
+
61
+
62
+ class AddForm(base.AddForm):
63
+ """Portlet add form."""
64
+
65
+ schema = IImagePortlet
66
+ label = "Add Greeting Portlet"
67
+ description = "This portlet displays a greeting."
68
+
69
+ def create(self, data):
70
+ return Assignment(**data)
71
+
72
+
73
+ class EditForm(base.EditForm):
74
+ """Portlet edit form."""
75
+
76
+ schema = IImagePortlet
77
+ label = "Edit Greeting Portlet"
78
+ description = "This portlet displays a greeting."
File without changes
@@ -0,0 +1,2 @@
1
+ (()=>{"use strict";var e={682:()=>{jQuery(document).ready((function(e){e(".opening_informations").click((function(t){e(this).siblings(".table_schedule").toggleClass("table_schedule--active"),t.preventDefault()})),e(document).click((function(t){e(".table_schedule").hasClass("table_schedule--active")&&(e(".table_schedule").is(t.target)||e(".opening_informations").is(t.target)||e(".table_schedule td").is(t.target)||e(".table_schedule").toggleClass("table_schedule--active"))}))})),$(document).ready((function(){if(document.body.clientWidth<992){var e=function(){t.removeClass("activated"),s.removeClass("activated"),document.body.classList.remove("submenu-open-nav-overflow"),document.documentElement.classList.remove("submenu-open-nav-overflow"),$(".show-nav").removeClass("show-nav"),$(".mask-menu").removeClass("in")},t=$("#portal-globalnav"),s=$("#subsite-navigation");$(".close-nav").click((function(){e()})),$(document).mouseup((function(a){t.is(a.target)||0!==t.has(a.target).length||s.is(a.target)||0!==s.has(a.target).length||e()})),$("li.has_subtree > a").click((function(){return $(this).closest(t).length>0&&(!$("#portal-globalnav .show-nav").length>0&&($(t).toggleClass("activated"),$(".mask-menu").toggleClass("in")),$(this).parent().toggleClass("show-nav"),$(this).parent().find(".show-nav").toggleClass("show-nav"),$(this).parent().siblings(".show-nav").toggleClass("show-nav"),$(this).parent().find(".activated").toggleClass(".activated"),!$("#portal-globalnav .show-nav").length>0&&e()),$(this).closest(s).length>0&&(!$("#subsite-navigation .show-nav").length>0&&($(s).toggleClass("activated"),document.body.classList.add("submenu-open-nav-overflow"),document.documentElement.classList.add("submenu-open-nav-overflow")),$(this).parent().toggleClass("show-nav"),$(this).parent().find(".show-nav").toggleClass("show-nav"),$(this).parent().siblings(".show-nav").toggleClass("show-nav"),$(this).parent().find(".activated").toggleClass(".activated"),!$("#subsite-navigation .show-nav").length>0&&e()),!1})),t.on("focusout",(function(s){setTimeout((function(){t.has(document.activeElement).length||e()}),0)}))}$(".prev-nav").click((function(){$(this).closest(".show-nav").toggleClass("show-nav")}))}))},246:(e,t,s)=>{s.r(t)}},t={};function s(a){var n=t[a];if(void 0!==n)return n.exports;var o=t[a]={exports:{}};return e[a](o,o.exports,s),o.exports}s.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s(682),s(246)})();
2
+ //# sourceMappingURL=index.9b029128174957df01c4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.9b029128174957df01c4.js","mappings":"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","sources":["webpack://affinitic.smartweb/./src/js/views.js","webpack://affinitic.smartweb/webpack/bootstrap","webpack://affinitic.smartweb/webpack/runtime/make namespace object","webpack://affinitic.smartweb/./src/index.js"],"sourcesContent":["// import './view.less'\njQuery(document).ready(function ($) {\n\n // Show full schedule table when clicking on today's schedule\n $(\".opening_informations\").click(function (e) {\n $(this).siblings(\".table_schedule\").toggleClass(\"table_schedule--active\");\n // $(this).toggle(\"fast\");\n e.preventDefault();\n });\n $(document).click(function (e) {\n if ($(\".table_schedule\").hasClass(\"table_schedule--active\")) {\n if (!$(\".table_schedule\").is(e.target)\n && !$(\".opening_informations\").is(e.target)\n && !$(\".table_schedule td\").is(e.target)) {\n $(\".table_schedule\").toggleClass(\"table_schedule--active\");\n }\n }\n });\n \n});\n// New navigation\n\n$(document).ready(function () {\n if(document.body.clientWidth < 992) {\n const menu = $('#portal-globalnav');\n const submenu = $('#subsite-navigation');\n \n $(\".close-nav\").click(function () {\n closeNav();\n });\n \n $(document).mouseup(e => {\n if (!menu.is(e.target) // if the target of the click isn't the container...\n && menu.has(e.target).length === 0\n && !submenu.is(e.target)\n && submenu.has(e.target).length === 0\n ) // ... nor a descendant of the container\n {\n closeNav();\n }\n });\n \n // when you click a toggle show-nav its dropdown menu\n \n $(\"li.has_subtree > a\").click(function () {\n \n \n // MENU\n if ($(this).closest(menu).length > 0) {\n if (!$(\"#portal-globalnav .show-nav\").length > 0) {\n $(menu).toggleClass(\"activated\");\n $(\".mask-menu\").toggleClass(\"in\");\n }\n $(this).parent().toggleClass(\"show-nav\");\n $(this).parent().find(\".show-nav\").toggleClass(\"show-nav\");\n $(this).parent().siblings(\".show-nav\").toggleClass(\"show-nav\")\n $(this).parent().find(\".activated\").toggleClass(\".activated\");\n if (!$(\"#portal-globalnav .show-nav\").length > 0) {\n closeNav()\n }\n }\n \n // SUBMENU\n if ($(this).closest(submenu).length > 0) {\n if (!$(\"#subsite-navigation .show-nav\").length > 0) {\n $(submenu).toggleClass(\"activated\");\n document.body.classList.add('submenu-open-nav-overflow');\n document.documentElement.classList.add('submenu-open-nav-overflow');\n \n }\n $(this).parent().toggleClass(\"show-nav\");\n $(this).parent().find(\".show-nav\").toggleClass(\"show-nav\");\n $(this).parent().siblings(\".show-nav\").toggleClass(\"show-nav\")\n $(this).parent().find(\".activated\").toggleClass(\".activated\");\n if (!$(\"#subsite-navigation .show-nav\").length > 0) {\n closeNav()\n }\n }\n return false\n });\n\n // close nav fonction\n function closeNav() {\n menu.removeClass('activated');\n submenu.removeClass('activated');\n document.body.classList.remove('submenu-open-nav-overflow');\n document.documentElement.classList.remove('submenu-open-nav-overflow');\n $('.show-nav').removeClass('show-nav');\n $(\".mask-menu\").removeClass(\"in\");\n }\n\n // ici on ferme le menu au focusout\n menu.on('focusout', function(e) {\n // Utilisez setTimeout pour s'assurer que document.activeElement est mis à jour\n setTimeout(function() {\n if (!menu.has(document.activeElement).length) {\n closeNav();\n }\n }, 0);\n });\n }\n\n // Prev nav\n $(\".prev-nav\").click(function () {\n $(this).closest(\".show-nav\").toggleClass(\"show-nav\")\n });\n\n\n\n});","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","require(\"./scss/main.scss\");\n\nimport \"./js/views.js\"\n"],"names":["jQuery","document","ready","$","click","e","this","siblings","toggleClass","preventDefault","hasClass","is","target","body","clientWidth","closeNav","menu","removeClass","submenu","classList","remove","documentElement","mouseup","has","length","closest","parent","find","add","on","setTimeout","activeElement","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","exports","module","__webpack_modules__","r","Symbol","toStringTag","Object","defineProperty","value","require"],"sourceRoot":""}