imio.smartweb.core 1.2.91__py3-none-any.whl → 1.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imio/smartweb/core/browser/configure.zcml +16 -0
- imio/smartweb/core/browser/controlpanel.py +42 -5
- imio/smartweb/core/browser/search/search.py +15 -0
- imio/smartweb/core/browser/sitemap.py +155 -107
- imio/smartweb/core/browser/utils.py +4 -1
- imio/smartweb/core/configure.zcml +5 -1
- imio/smartweb/core/contents/__init__.py +2 -0
- imio/smartweb/core/contents/rest/base.py +5 -2
- imio/smartweb/core/contents/rest/campaign/__init__.py +0 -0
- imio/smartweb/core/contents/rest/campaign/configure.zcml +80 -0
- imio/smartweb/core/contents/rest/campaign/content.py +83 -0
- imio/smartweb/core/contents/rest/campaign/endpoint.py +211 -0
- imio/smartweb/core/contents/rest/campaign/view.pt +19 -0
- imio/smartweb/core/contents/rest/campaign/view.py +29 -0
- imio/smartweb/core/contents/rest/configure.zcml +1 -0
- imio/smartweb/core/contents/rest/directory/endpoint.py +11 -3
- imio/smartweb/core/contents/rest/events/endpoint.py +11 -3
- imio/smartweb/core/contents/rest/news/endpoint.py +11 -3
- imio/smartweb/core/contents/rest/search/endpoint.py +4 -1
- imio/smartweb/core/contents/rest/utils.py +3 -3
- imio/smartweb/core/interfaces.py +6 -0
- imio/smartweb/core/overrides.zcml +10 -0
- imio/smartweb/core/profiles/default/metadata.xml +1 -1
- imio/smartweb/core/profiles/ideabox/browserlayer.xml +7 -0
- imio/smartweb/core/profiles/ideabox/metadata.xml +5 -0
- imio/smartweb/core/profiles/ideabox/registry/iaideabox.xml +9 -0
- imio/smartweb/core/profiles/ideabox/types/imio.smartweb.CampaignView.xml +40 -0
- imio/smartweb/core/profiles/ideabox/types/imio.smartweb.Folder.xml +71 -0
- imio/smartweb/core/profiles/ideabox/types.xml +17 -0
- imio/smartweb/core/profiles/ideabox_uninstall/browserlayer.xml +7 -0
- imio/smartweb/core/profiles/ideabox_uninstall/types/imio.smartweb.Folder.xml +25 -0
- imio/smartweb/core/profiles/ideabox_uninstall/types.xml +4 -0
- imio/smartweb/core/profiles/testing/metadata.xml +1 -0
- imio/smartweb/core/profiles/testing/registry.xml +2 -2
- imio/smartweb/core/profiles.zcml +18 -0
- imio/smartweb/core/subscribers.py +27 -1
- imio/smartweb/core/subscribers.zcml +8 -0
- imio/smartweb/core/tests/resources/json_ideabox_campaign.json +222 -0
- imio/smartweb/core/tests/resources/json_ideabox_campaigns.json +425 -0
- imio/smartweb/core/tests/resources/json_ideabox_projects.json +1871 -0
- imio/smartweb/core/tests/test_iadeliberations.py +38 -40
- imio/smartweb/core/tests/test_ideabox.py +152 -0
- imio/smartweb/core/tests/test_procedure.py +7 -3
- imio/smartweb/core/tests/test_rest.py +6 -1
- imio/smartweb/core/tests/test_sitemap.py +81 -42
- imio/smartweb/core/tests/test_vocabularies.py +8 -10
- imio/smartweb/core/tests/test_vocabulary.py +18 -0
- imio/smartweb/core/upgrades/configure.zcml +16 -1
- imio/smartweb/core/upgrades/upgrades.py +64 -0
- imio/smartweb/core/utils.py +33 -0
- imio/smartweb/core/viewlets/offcanvas.pt +2 -0
- imio/smartweb/core/viewlets/ogptags.py +9 -0
- imio/smartweb/core/vocabularies.py +35 -4
- imio/smartweb/core/vocabularies.zcml +6 -0
- imio/smartweb/core/webcomponents/build/css/373.smartweb-webcomponents-compiled.css +1 -1
- imio/smartweb/core/webcomponents/build/css/420.smartweb-webcomponents-compiled.css +1 -0
- imio/smartweb/core/webcomponents/build/css/486.smartweb-webcomponents-compiled.css +1 -1
- imio/smartweb/core/webcomponents/build/css/666.smartweb-webcomponents-compiled.css +1 -0
- imio/smartweb/core/webcomponents/build/css/884.smartweb-webcomponents-compiled.css +1 -1
- imio/smartweb/core/webcomponents/build/css/919.smartweb-webcomponents-compiled.css +1 -1
- imio/smartweb/core/webcomponents/build/css/smartweb-webcomponents-compiled.css +1 -1
- imio/smartweb/core/webcomponents/build/js/141.smartweb-webcomponents-compiled.js +2 -0
- imio/smartweb/core/webcomponents/build/js/{828.smartweb-webcomponents-compiled.js.LICENSE.txt → 141.smartweb-webcomponents-compiled.js.LICENSE.txt} +3 -3
- imio/smartweb/core/webcomponents/build/js/15.smartweb-webcomponents-compiled.js +2 -0
- imio/smartweb/core/webcomponents/build/js/21.smartweb-webcomponents-compiled.js +1 -0
- imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/218.smartweb-webcomponents-compiled.js.LICENSE.txt +0 -5
- imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/486.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -0
- imio/smartweb/core/webcomponents/build/js/799.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/824.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/884.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -0
- imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/package.json +80 -80
- imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +1 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.jsx +306 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/Campaign.scss +672 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/CampaignCard/CampaignCard.jsx +79 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/CampaignContent/CampaignContent.jsx +193 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/CampaignList/CampaignList.jsx +67 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/Filters/Filter.jsx +259 -0
- imio/smartweb/core/webcomponents/src/components/Campaign/index.js +2 -0
- imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +1 -0
- imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +0 -1
- imio/smartweb/core/webcomponents/src/components/Search/Search.jsx +54 -9
- imio/smartweb/core/webcomponents/src/components/Search/Search.scss +9 -0
- imio/smartweb/core/webcomponents/src/hooks/useAxios.js +45 -9
- imio/smartweb/core/webcomponents/src/index.jsx +2 -0
- imio/smartweb/core/webcomponents/src/index.scss +2 -2
- imio/smartweb/core/webcomponents/src/utils/CampaignMap.jsx +177 -0
- imio/smartweb/core/webcomponents/src/utils/Map.jsx +1 -1
- imio/smartweb/core/webcomponents/src/utils/Map.scss +15 -1
- imio/smartweb/core/webcomponents/src/utils/translation.js +247 -199
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/METADATA +24 -1
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/RECORD +105 -72
- imio/smartweb/core/webcomponents/build/js/499.smartweb-webcomponents-compiled.js +0 -2
- imio/smartweb/core/webcomponents/build/js/828.smartweb-webcomponents-compiled.js +0 -2
- /imio/smartweb/core/webcomponents/build/js/{499.smartweb-webcomponents-compiled.js.LICENSE.txt → 15.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
- /imio.smartweb.core-1.2.91-py3.12-nspkg.pth → /imio.smartweb.core-1.3.1-py3.12-nspkg.pth +0 -0
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.GPL +0 -0
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.rst +0 -0
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/WHEEL +0 -0
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/namespace_packages.txt +0 -0
- {imio.smartweb.core-1.2.91.dist-info → imio.smartweb.core-1.3.1.dist-info}/top_level.txt +0 -0
@@ -96,6 +96,22 @@
|
|
96
96
|
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
97
97
|
/>
|
98
98
|
|
99
|
+
<adapter
|
100
|
+
factory="imio.smartweb.core.browser.sitemap.SitemapNavtreeStrategy"
|
101
|
+
provides="imio.smartweb.core.browser.sitemap.ISmartwebNavtreeStrategy"
|
102
|
+
for="*
|
103
|
+
imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
104
|
+
/>
|
105
|
+
|
106
|
+
<browser:page
|
107
|
+
name="sitemap_builder_view"
|
108
|
+
for="*"
|
109
|
+
class=".sitemap.CatalogSiteMap"
|
110
|
+
allowed_attributes="siteMap"
|
111
|
+
permission="zope.Public"
|
112
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
113
|
+
/>
|
114
|
+
|
99
115
|
<browser:page
|
100
116
|
name="events_view"
|
101
117
|
for="*"
|
@@ -22,11 +22,10 @@ class ISendinblueTextRowSchema(Interface):
|
|
22
22
|
|
23
23
|
|
24
24
|
class ISmartwebControlPanel(Interface):
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
),
|
25
|
+
# https://COMMUNE-formulaires.guichet-citoyen.be/api
|
26
|
+
url_ts = schema.TextLine(
|
27
|
+
title=_("Url to e-guichet"),
|
28
|
+
description=_("Example : https://COMMUNE.guichet-citoyen.be"),
|
30
29
|
required=False,
|
31
30
|
)
|
32
31
|
|
@@ -36,6 +35,21 @@ class ISmartwebControlPanel(Interface):
|
|
36
35
|
required=False,
|
37
36
|
)
|
38
37
|
|
38
|
+
iaideabox_api_username = schema.TextLine(
|
39
|
+
title=_(
|
40
|
+
"Username to consume e-guichet ideabox API (get Campaign, projects,...)"
|
41
|
+
),
|
42
|
+
default="ideabox",
|
43
|
+
required=False,
|
44
|
+
)
|
45
|
+
|
46
|
+
iaideabox_api_password = schema.Password(
|
47
|
+
title=_(
|
48
|
+
"Password to consume e-guichet ideabox API (get Campaign, projects,...)"
|
49
|
+
),
|
50
|
+
required=False,
|
51
|
+
)
|
52
|
+
|
39
53
|
propose_directory_url = schema.URI(
|
40
54
|
title=_("Url to propose a new citizen contact"),
|
41
55
|
required=False,
|
@@ -203,17 +217,40 @@ class SmartwebControlPanelForm(RegistryEditForm):
|
|
203
217
|
iadeliberation_pwd = api.portal.get_registry_record(
|
204
218
|
"smartweb.iadeliberation_api_password"
|
205
219
|
)
|
220
|
+
|
221
|
+
iaideabox_pwd = api.portal.get_registry_record(
|
222
|
+
"smartweb.iaideabox_api_password"
|
223
|
+
)
|
224
|
+
|
206
225
|
secret_key_api = api.portal.get_registry_record("smartweb.secret_key_api")
|
207
226
|
|
208
227
|
# if data is None when we apply changes for password fields we keep password from registry
|
209
228
|
if not data.get("iadeliberation_api_password"):
|
210
229
|
data["iadeliberation_api_password"] = iadeliberation_pwd
|
211
230
|
|
231
|
+
if not data.get("iaideabox_api_password"):
|
232
|
+
data["iaideabox_api_password"] = iaideabox_pwd
|
233
|
+
|
212
234
|
if not data.get("secret_key_api"):
|
213
235
|
data["secret_key_api"] = secret_key_api
|
214
236
|
|
215
237
|
return super().applyChanges(data)
|
216
238
|
|
239
|
+
def updateFields(self):
|
240
|
+
"""Override updateFields to hide fields based on ideabox profile installation."""
|
241
|
+
super(SmartwebControlPanelForm, self).updateFields()
|
242
|
+
|
243
|
+
# Check if the 'ideabox' profile is installed
|
244
|
+
portal_setup = api.portal.get_tool(name="portal_setup")
|
245
|
+
profile_version = portal_setup.getLastVersionForProfile(
|
246
|
+
"imio.smartweb.core:ideabox"
|
247
|
+
)
|
248
|
+
|
249
|
+
if profile_version == "unknown":
|
250
|
+
# Hide the field related to Idea Box if the profile is not installed
|
251
|
+
self.fields = self.fields.omit("iaideabox_api_username")
|
252
|
+
self.fields = self.fields.omit("iaideabox_api_password")
|
253
|
+
|
217
254
|
|
218
255
|
SmartwebControlPanelView = layout.wrap_form(
|
219
256
|
SmartwebControlPanelForm, ControlPanelFormWrapper
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
from imio.smartweb.core.contents.rest.search.endpoint import get_default_view_url
|
3
4
|
from plone import api
|
4
5
|
from Products.CMFPlone.browser.search import Search
|
5
6
|
from Products.CMFPlone.utils import normalizeString
|
@@ -68,6 +69,20 @@ class Search(Search):
|
|
68
69
|
|
69
70
|
return json.dumps(response)
|
70
71
|
|
72
|
+
@property
|
73
|
+
def are_views_available(self):
|
74
|
+
news = False if get_default_view_url("news") == "" else True
|
75
|
+
events = False if get_default_view_url("events") == "" else True
|
76
|
+
directory = False if get_default_view_url("directory") == "" else True
|
77
|
+
return json.dumps({"news": news, "events": events, "directory": directory})
|
78
|
+
|
79
|
+
@property
|
80
|
+
def context_user_has_roles(self):
|
81
|
+
# is current user has more role(s) than just authenticated
|
82
|
+
if len(api.user.get_roles()) > 1:
|
83
|
+
return True
|
84
|
+
return False
|
85
|
+
|
71
86
|
@property
|
72
87
|
def current_language(self):
|
73
88
|
return api.portal.get_current_language()[:2]
|
@@ -1,49 +1,108 @@
|
|
1
|
+
from Acquisition import aq_inner
|
1
2
|
from BTrees.OOBTree import OOBTree
|
2
3
|
from imio.smartweb.core.config import DIRECTORY_URL
|
3
4
|
from imio.smartweb.core.config import EVENTS_URL
|
4
5
|
from imio.smartweb.core.config import NEWS_URL
|
5
|
-
from imio.smartweb.core.contents.rest.
|
6
|
-
from imio.smartweb.core.contents.rest.
|
7
|
-
from
|
8
|
-
from
|
6
|
+
from imio.smartweb.core.contents.rest.directory.endpoint import DirectoryEndpointGet
|
7
|
+
from imio.smartweb.core.contents.rest.events.endpoint import EventsEndpointGet
|
8
|
+
from imio.smartweb.core.contents.rest.news.endpoint import NewsEndpointGet
|
9
|
+
from imio.smartweb.core.interfaces import IImioSmartwebCoreLayer
|
10
|
+
from plone.app.layout.navigation.navtree import buildFolderTree
|
9
11
|
from plone.app.layout.sitemap.sitemap import SiteMapView
|
10
|
-
from plone.
|
12
|
+
from plone.base.interfaces import IPloneSiteRoot
|
13
|
+
from Products.CMFPlone.browser.navigation import CatalogSiteMap as BaseCatalogSiteMap
|
14
|
+
from Products.CMFPlone.browser.navtree import (
|
15
|
+
SitemapNavtreeStrategy as BaseSitemapNavtreeStrategy,
|
16
|
+
)
|
17
|
+
from Products.CMFPlone.browser.navtree import (
|
18
|
+
SitemapQueryBuilder as BaseSitemapQueryBuilder,
|
19
|
+
)
|
11
20
|
from Products.CMFCore.utils import getToolByName
|
12
21
|
from Products.CMFPlone.utils import normalizeString
|
13
|
-
from zope.component import
|
22
|
+
from zope.component import getMultiAdapter
|
23
|
+
from zope.interface import implementer
|
24
|
+
from zope.interface import Interface
|
14
25
|
|
15
26
|
import logging
|
27
|
+
import Missing
|
16
28
|
|
17
29
|
logger = logging.getLogger("imio.smartweb.core")
|
18
30
|
|
19
31
|
|
32
|
+
FRIENDLY_TYPES = [
|
33
|
+
"Collection",
|
34
|
+
"Image",
|
35
|
+
"Link",
|
36
|
+
"imio.smartweb.Folder",
|
37
|
+
"imio.smartweb.Page",
|
38
|
+
"imio.smartweb.PortalPage",
|
39
|
+
"imio.smartweb.Procedure",
|
40
|
+
"imio.smartweb.CirkwiView",
|
41
|
+
"imio.smartweb.DirectoryView",
|
42
|
+
"imio.smartweb.EventsView",
|
43
|
+
"imio.smartweb.NewsView",
|
44
|
+
]
|
45
|
+
|
46
|
+
|
47
|
+
def get_endpoint_data(obj, request):
|
48
|
+
"""Retourne les données issues du bon endpoint pour un objet donné"""
|
49
|
+
endpoint_mapping = {
|
50
|
+
"imio.smartweb.DirectoryView": DirectoryEndpointGet,
|
51
|
+
"imio.smartweb.EventsView": EventsEndpointGet,
|
52
|
+
"imio.smartweb.NewsView": NewsEndpointGet,
|
53
|
+
}
|
54
|
+
|
55
|
+
endpoint_class = endpoint_mapping.get(obj.portal_type)
|
56
|
+
if not endpoint_class:
|
57
|
+
return {}
|
58
|
+
|
59
|
+
endpoint = endpoint_class()
|
60
|
+
batch_size = 1000 if obj.portal_type == "imio.smartweb.DirectoryView" else 365
|
61
|
+
return (
|
62
|
+
endpoint.reply_for_given_object(
|
63
|
+
obj, request, fullobjects=0, batch_size=batch_size
|
64
|
+
)
|
65
|
+
or {}
|
66
|
+
)
|
67
|
+
|
68
|
+
|
69
|
+
def format_sitemap_items(items, base_url):
|
70
|
+
"""Formatte les items pour le sitemap"""
|
71
|
+
formatted_items = []
|
72
|
+
for item in items:
|
73
|
+
item_id = normalizeString(item.get("title"))
|
74
|
+
item_uid = item.get("id")
|
75
|
+
lastmod = item.get("modified") or "1970-01-01T00:00:00Z"
|
76
|
+
formatted_items.append(
|
77
|
+
{
|
78
|
+
"loc": f"{base_url}/{item_id}?u={item_uid}",
|
79
|
+
"lastmod": lastmod,
|
80
|
+
"Title": item_id,
|
81
|
+
"Description": item.get("description", ""),
|
82
|
+
"getURL": f"{base_url}/{item_id}?u={item_uid}",
|
83
|
+
"getRemoteUrl": Missing.Value,
|
84
|
+
"currentItem": False,
|
85
|
+
"currentParent": False,
|
86
|
+
"normalized_review_state": "published",
|
87
|
+
"normalized_portal_type": "imio-smartweb-directory-item",
|
88
|
+
}
|
89
|
+
)
|
90
|
+
return formatted_items
|
91
|
+
|
92
|
+
|
20
93
|
class CustomSiteMapView(SiteMapView):
|
94
|
+
"""Custom sitemap view. (get items for sitemap.xml.gz)"""
|
21
95
|
|
22
96
|
def objects(self):
|
23
97
|
"""Returns the data to create the sitemap."""
|
24
|
-
|
25
|
-
friendlytypes = [
|
26
|
-
"Link",
|
27
|
-
"imio.smartweb.Folder",
|
28
|
-
"LIF",
|
29
|
-
"LRF",
|
30
|
-
"imio.smartweb.Page",
|
31
|
-
"imio.smartweb.Procedure",
|
32
|
-
"File",
|
33
|
-
"Collection",
|
34
|
-
"imio.smartweb.PortalPage",
|
35
|
-
"Image",
|
36
|
-
"imio.smartweb.CirkwiView",
|
37
|
-
]
|
98
|
+
friendlytypes = FRIENDLY_TYPES
|
38
99
|
|
39
100
|
catalog = getToolByName(self.context, "portal_catalog")
|
40
|
-
query = {
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
registry.get("plone.types_use_view_action_in_listings", [])
|
46
|
-
)
|
101
|
+
query = {
|
102
|
+
"portal_type": getToolByName(
|
103
|
+
self.context, "plone_utils"
|
104
|
+
).getUserFriendlyTypes(friendlytypes)
|
105
|
+
}
|
47
106
|
|
48
107
|
is_plone_site_root = IPloneSiteRoot.providedBy(self.context)
|
49
108
|
if not is_plone_site_root:
|
@@ -56,93 +115,82 @@ class CustomSiteMapView(SiteMapView):
|
|
56
115
|
value = (item.modified.micros(), item.modified.ISO8601())
|
57
116
|
default_page_modified[key] = value
|
58
117
|
|
59
|
-
# The plone site root is not catalogued.
|
60
118
|
if is_plone_site_root:
|
61
119
|
loc = self.context.absolute_url()
|
62
120
|
date = self.context.modified()
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
modified = max(modified, default_modified)
|
68
|
-
lastmod = modified[1]
|
69
|
-
yield {
|
70
|
-
"loc": loc,
|
71
|
-
"lastmod": lastmod,
|
72
|
-
# 'changefreq': 'always',
|
73
|
-
# hourly/daily/weekly/monthly/yearly/never
|
74
|
-
# 'prioriy': 0.5, # 0.0 to 1.0
|
75
|
-
}
|
121
|
+
modified = max(
|
122
|
+
(date.micros(), date.ISO8601()), default_page_modified.get(loc, (0, ""))
|
123
|
+
)
|
124
|
+
yield {"loc": loc, "lastmod": modified[1]}
|
76
125
|
|
77
126
|
query["is_default_page"] = False
|
78
127
|
for item in catalog.searchResults(query):
|
79
128
|
loc = item.getURL()
|
80
129
|
date = item.modified
|
81
|
-
|
82
|
-
|
83
|
-
default_modified = default_page_modified.get(loc, None)
|
84
|
-
if default_modified is not None:
|
85
|
-
modified = max(modified, default_modified)
|
86
|
-
lastmod = modified[1]
|
87
|
-
if item.portal_type in typesUseViewActionInListings:
|
88
|
-
loc += "/view"
|
89
|
-
yield {
|
90
|
-
"loc": loc,
|
91
|
-
"lastmod": lastmod,
|
92
|
-
}
|
93
|
-
|
94
|
-
auth_sources = {
|
95
|
-
"directory": {
|
96
|
-
"entity_reg_var": "smartweb.directory_entity_uid",
|
97
|
-
"main_rest_view": "smartweb.default_directory_view",
|
98
|
-
"vocabulary": "imio.smartweb.vocabulary.RemoteDirectoryEntities",
|
99
|
-
"url": DIRECTORY_URL,
|
100
|
-
},
|
101
|
-
"events": {
|
102
|
-
"entity_reg_var": "smartweb.events_entity_uid",
|
103
|
-
"main_rest_view": "smartweb.default_events_view",
|
104
|
-
"vocabulary": "imio.smartweb.vocabulary.RemoteEventsEntities",
|
105
|
-
"url": EVENTS_URL,
|
106
|
-
},
|
107
|
-
"news": {
|
108
|
-
"entity_reg_var": "smartweb.news_entity_uid",
|
109
|
-
"main_rest_view": "smartweb.default_news_view",
|
110
|
-
"vocabulary": "imio.smartweb.vocabulary.RemoteNewsEntities",
|
111
|
-
"url": NEWS_URL,
|
112
|
-
},
|
113
|
-
}
|
114
|
-
for auth_source_key, auth_source_value in auth_sources.items():
|
115
|
-
entity_uid = api.portal.get_registry_record(
|
116
|
-
auth_source_value.get("entity_reg_var")
|
117
|
-
)
|
118
|
-
if entity_uid is None:
|
119
|
-
return self.request.response.setStatus(404, "No entity found")
|
120
|
-
entity_id = get_entity_id(auth_source_value.get("vocabulary"), entity_uid)
|
121
|
-
auth_source_uid = api.portal.get_registry_record(
|
122
|
-
f"smartweb.default_{auth_source_key}_view", default=None
|
130
|
+
modified = max(
|
131
|
+
(date.micros(), date.ISO8601()), default_page_modified.get(loc, (0, ""))
|
123
132
|
)
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
133
|
+
yield {"loc": loc, "lastmod": modified[1]}
|
134
|
+
|
135
|
+
for brain in catalog(
|
136
|
+
portal_type=[
|
137
|
+
"imio.smartweb.EventsView",
|
138
|
+
"imio.smartweb.NewsView",
|
139
|
+
"imio.smartweb.DirectoryView",
|
140
|
+
]
|
141
|
+
):
|
142
|
+
obj = brain.getObject()
|
143
|
+
data = get_endpoint_data(obj, obj.REQUEST)
|
144
|
+
yield from format_sitemap_items(data.get("items", {}), obj.absolute_url())
|
145
|
+
|
146
|
+
|
147
|
+
@implementer(IImioSmartwebCoreLayer)
|
148
|
+
class CatalogSiteMap(BaseCatalogSiteMap):
|
149
|
+
def siteMap(self):
|
150
|
+
context = aq_inner(self.context)
|
151
|
+
|
152
|
+
queryBuilder = SitemapQueryBuilder(context)
|
153
|
+
query = queryBuilder()
|
154
|
+
strategy = getMultiAdapter((context, self), ISmartwebNavtreeStrategy)
|
155
|
+
base_folder_tree = buildFolderTree(
|
156
|
+
context, obj=context, query=query, strategy=strategy
|
157
|
+
)
|
158
|
+
|
159
|
+
for child in base_folder_tree.get("children"):
|
160
|
+
obj = child.get("item").getObject()
|
161
|
+
data = get_endpoint_data(obj, obj.REQUEST)
|
162
|
+
if not data:
|
139
163
|
continue
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
164
|
+
child["children"] = format_sitemap_items(
|
165
|
+
data.get("items", []), obj.absolute_url()
|
166
|
+
)
|
167
|
+
|
168
|
+
return base_folder_tree
|
169
|
+
|
170
|
+
|
171
|
+
class SitemapQueryBuilder(BaseSitemapQueryBuilder):
|
172
|
+
"""Construit la requête pour le sitemap avec des types de contenu personnalisés."""
|
173
|
+
|
174
|
+
def __init__(self, context):
|
175
|
+
self.context = context
|
176
|
+
|
177
|
+
def __call__(self):
|
178
|
+
query = {}
|
179
|
+
custom_query = getattr(self.context, "getCustomNavQuery", None)
|
180
|
+
if custom_query and callable(custom_query):
|
181
|
+
query = custom_query()
|
182
|
+
query["portal_type"] = FRIENDLY_TYPES
|
183
|
+
query["review_state"] = "published"
|
184
|
+
return query
|
185
|
+
|
186
|
+
|
187
|
+
class ISmartwebNavtreeStrategy(Interface):
|
188
|
+
"""Marker interface for the smartweb navtree strategy."""
|
189
|
+
|
190
|
+
|
191
|
+
@implementer(ISmartwebNavtreeStrategy)
|
192
|
+
class SitemapNavtreeStrategy(BaseSitemapNavtreeStrategy):
|
193
|
+
|
194
|
+
def nodeFilter(self, node):
|
195
|
+
# Return all nodes in sitemap even if they are exclude from nav
|
196
|
+
return True
|
@@ -2,6 +2,8 @@
|
|
2
2
|
from imio.smartweb.core.contents import IPages
|
3
3
|
from imio.smartweb.core.contents.pages.procedure.utils import sign_url
|
4
4
|
from imio.smartweb.core.utils import get_plausible_vars
|
5
|
+
from imio.smartweb.core.utils import get_ts_api_url
|
6
|
+
from imio.smartweb.core.utils import get_value_from_registry
|
5
7
|
from imio.smartweb.locales import SmartwebMessageFactory as _
|
6
8
|
from plone import api
|
7
9
|
from plone.api.portal import get_registry_record
|
@@ -54,7 +56,8 @@ class UtilsView(BrowserView):
|
|
54
56
|
|
55
57
|
def is_eguichet_aware(self):
|
56
58
|
self.request.response.setHeader("Content-Type", "application/json")
|
57
|
-
|
59
|
+
wcs_api = get_ts_api_url("wcs")
|
60
|
+
url = f"{wcs_api}/formdefs/"
|
58
61
|
key = api.portal.get_registry_record("smartweb.secret_key_api")
|
59
62
|
orig = "ia.smartweb"
|
60
63
|
if not url:
|
@@ -14,7 +14,10 @@
|
|
14
14
|
<include package="collective.solr" />
|
15
15
|
<include package="collective.taxonomy" />
|
16
16
|
<include package="collective.z3cform.datagridfield" />
|
17
|
-
|
17
|
+
|
18
|
+
<!-- Call this one before overrides adapter zope.container.interfaces.INameChooser-->
|
19
|
+
<include package="plone.app.content" />
|
20
|
+
|
18
21
|
<!-- Temporary fix for plone.gallery 1.0.1 -->
|
19
22
|
<include package="plone.app.contentmenu" />
|
20
23
|
<include package="plone.gallery" />
|
@@ -24,6 +27,7 @@
|
|
24
27
|
<include package="imio.smartweb.locales" />
|
25
28
|
|
26
29
|
<include file="indexers.zcml" />
|
30
|
+
<include file="overrides.zcml" />
|
27
31
|
<include file="permissions.zcml" />
|
28
32
|
<include file="profiles.zcml" />
|
29
33
|
<include file="subscribers.zcml" />
|
@@ -21,6 +21,8 @@ from .publication.content import Publication # NOQA
|
|
21
21
|
from .publication.content import IPublication # NOQA
|
22
22
|
from .rest.base import RestView # NOQA
|
23
23
|
from .rest.base import IRestView # NOQA
|
24
|
+
from .rest.campaign.content import CampaignView # NOQA
|
25
|
+
from .rest.campaign.content import ICampaignView # NOQA
|
24
26
|
from .rest.directory.content import DirectoryView # NOQA
|
25
27
|
from .rest.directory.content import IDirectoryView # NOQA
|
26
28
|
from .rest.events.content import EventsView # NOQA
|
@@ -15,9 +15,12 @@ class BaseEndpoint(object):
|
|
15
15
|
language = "fr"
|
16
16
|
remote_endpoint = ""
|
17
17
|
|
18
|
-
def __init__(self, context, request):
|
18
|
+
def __init__(self, context, request, fullobjects=1, batch_size=0):
|
19
|
+
|
19
20
|
self.context = context
|
20
21
|
self.request = request
|
22
|
+
self.fullobjects = fullobjects
|
23
|
+
self.batch_size = batch_size
|
21
24
|
|
22
25
|
def __call__(self):
|
23
26
|
results = get_json(self.query_url, timeout=20)
|
@@ -46,7 +49,7 @@ class BaseEndpoint(object):
|
|
46
49
|
item[f"{field}_full_scale"] = (
|
47
50
|
f"{item['@id']}/@@images/{field}/?cache_key={modified_hash}"
|
48
51
|
)
|
49
|
-
|
52
|
+
item.pop(field, None)
|
50
53
|
|
51
54
|
def construct_query_string(self, params):
|
52
55
|
params = "&".join(params)
|
File without changes
|
@@ -0,0 +1,80 @@
|
|
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="imio.smartweb">
|
6
|
+
|
7
|
+
<browser:page
|
8
|
+
name="view"
|
9
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
10
|
+
class=".view.CampaignViewView"
|
11
|
+
template="view.pt"
|
12
|
+
permission="zope2.View"
|
13
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
14
|
+
/>
|
15
|
+
|
16
|
+
<plone:service
|
17
|
+
name="@results"
|
18
|
+
method="GET"
|
19
|
+
accept="application/json"
|
20
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
21
|
+
factory=".endpoint.CampaignEndpointGet"
|
22
|
+
permission="zope2.View"
|
23
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
24
|
+
/>
|
25
|
+
|
26
|
+
<plone:service
|
27
|
+
name="@auth"
|
28
|
+
method="GET"
|
29
|
+
accept="text/plain"
|
30
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
31
|
+
factory=".endpoint.AuthCampaignEndpointGet"
|
32
|
+
permission="zope.Public"
|
33
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
34
|
+
/>
|
35
|
+
|
36
|
+
<plone:service
|
37
|
+
name="@zones"
|
38
|
+
method="GET"
|
39
|
+
accept="application/json"
|
40
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
41
|
+
factory=".endpoint.ZonesEndpointGet"
|
42
|
+
permission="zope2.View"
|
43
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
44
|
+
/>
|
45
|
+
|
46
|
+
|
47
|
+
<!-- endpoint to get topics from TS -->
|
48
|
+
<plone:service
|
49
|
+
name="@ts_topics"
|
50
|
+
method="GET"
|
51
|
+
accept="application/json"
|
52
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
53
|
+
factory=".endpoint.TsTopicsEndpointGet"
|
54
|
+
permission="zope2.View"
|
55
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
56
|
+
/>
|
57
|
+
|
58
|
+
<!-- endpoint to expose smartweb topics to TS -->
|
59
|
+
<plone:service
|
60
|
+
name="@topics"
|
61
|
+
method="GET"
|
62
|
+
accept="application/json"
|
63
|
+
for="plone.dexterity.interfaces.IDexterityContent"
|
64
|
+
factory=".endpoint.TopicsEndpointGet"
|
65
|
+
permission="zope2.View"
|
66
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
67
|
+
/>
|
68
|
+
|
69
|
+
<!-- endpoint to expose smartweb AND TS topics to campaign view -->
|
70
|
+
<plone:service
|
71
|
+
name="@all_topics"
|
72
|
+
method="GET"
|
73
|
+
accept="application/json"
|
74
|
+
for="imio.smartweb.core.contents.ICampaignView"
|
75
|
+
factory=".endpoint.AllTopicsEndpointGet"
|
76
|
+
permission="zope2.View"
|
77
|
+
layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
|
78
|
+
/>
|
79
|
+
|
80
|
+
</configure>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
from collective.instancebehavior.interfaces import IInstanceBehaviorAssignableContent
|
4
|
+
from imio.smartweb.core.contents import RestView
|
5
|
+
from imio.smartweb.core.utils import get_basic_auth_json
|
6
|
+
from imio.smartweb.core.utils import get_ts_api_url
|
7
|
+
from imio.smartweb.core.utils import get_value_from_registry
|
8
|
+
from imio.smartweb.locales import SmartwebMessageFactory as _
|
9
|
+
from plone import api
|
10
|
+
from plone.app.content.namechooser import NormalizingNameChooser
|
11
|
+
from plone.i18n.normalizer import idnormalizer
|
12
|
+
from plone.supermodel import model
|
13
|
+
from zope import schema
|
14
|
+
from zope.component import getUtility
|
15
|
+
from zope.container.interfaces import INameChooser
|
16
|
+
from zope.interface import implementer
|
17
|
+
|
18
|
+
import logging
|
19
|
+
|
20
|
+
logger = logging.getLogger("imio.smartweb.core")
|
21
|
+
|
22
|
+
|
23
|
+
class ICampaignView(model.Schema):
|
24
|
+
""" """
|
25
|
+
|
26
|
+
linked_campaign = schema.Choice(
|
27
|
+
vocabulary="imio.smartweb.vocabulary.PublikCampaigns",
|
28
|
+
title=_("E-Guichet campaign"),
|
29
|
+
required=False,
|
30
|
+
default=None,
|
31
|
+
)
|
32
|
+
|
33
|
+
propose_project_url = schema.TextLine(
|
34
|
+
title=_("Propose project URL"),
|
35
|
+
description=_("URL to propose a project"),
|
36
|
+
required=False,
|
37
|
+
)
|
38
|
+
|
39
|
+
nb_results = schema.Int(
|
40
|
+
title=_("Number of items to display"), default=20, required=True
|
41
|
+
)
|
42
|
+
|
43
|
+
display_map = schema.Bool(
|
44
|
+
title=_("Display map"),
|
45
|
+
description=_("If selected, map will be displayed"),
|
46
|
+
required=False,
|
47
|
+
default=True,
|
48
|
+
)
|
49
|
+
|
50
|
+
|
51
|
+
@implementer(ICampaignView, IInstanceBehaviorAssignableContent)
|
52
|
+
class CampaignView(RestView):
|
53
|
+
"""Campaign class"""
|
54
|
+
|
55
|
+
|
56
|
+
@implementer(INameChooser)
|
57
|
+
class CampaignNameChooser(NormalizingNameChooser):
|
58
|
+
def chooseName(self, name, obj):
|
59
|
+
"""Génère un ID basé sur le titre récupéré de l'API."""
|
60
|
+
if ICampaignView.providedBy(obj):
|
61
|
+
if not obj.title:
|
62
|
+
# Récupération du titre via l'API
|
63
|
+
wcs_api = get_ts_api_url("wcs")
|
64
|
+
ts_campaign_endpoint = "imio-ideabox-campagne"
|
65
|
+
url = f"{wcs_api}/cards/{ts_campaign_endpoint}/{obj.linked_campaign}"
|
66
|
+
user = get_value_from_registry("smartweb.iaideabox_api_username")
|
67
|
+
pwd = get_value_from_registry("smartweb.iaideabox_api_password")
|
68
|
+
json_campaign = get_basic_auth_json(url, user, pwd)
|
69
|
+
|
70
|
+
if json_campaign and "fields" in json_campaign:
|
71
|
+
obj.title = json_campaign["fields"].get(
|
72
|
+
"titre", "campagne-sans-nom"
|
73
|
+
)
|
74
|
+
else:
|
75
|
+
obj.title = "campaign-without-name"
|
76
|
+
|
77
|
+
# Normaliser l'ID en utilisant le titre
|
78
|
+
normalized_id = idnormalizer.normalize(obj.title)
|
79
|
+
|
80
|
+
# Vérifier que l'ID généré est bien unique dans le conteneur
|
81
|
+
return super().chooseName(normalized_id, obj)
|
82
|
+
|
83
|
+
return super().chooseName(name, obj)
|