imio.smartweb.core 1.3__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.
Files changed (32) hide show
  1. imio/smartweb/core/browser/configure.zcml +16 -0
  2. imio/smartweb/core/browser/search/search.py +15 -0
  3. imio/smartweb/core/browser/sitemap.py +155 -107
  4. imio/smartweb/core/contents/rest/base.py +5 -2
  5. imio/smartweb/core/contents/rest/campaign/endpoint.py +3 -3
  6. imio/smartweb/core/contents/rest/directory/endpoint.py +11 -3
  7. imio/smartweb/core/contents/rest/events/endpoint.py +11 -3
  8. imio/smartweb/core/contents/rest/news/endpoint.py +11 -3
  9. imio/smartweb/core/contents/rest/search/endpoint.py +4 -1
  10. imio/smartweb/core/contents/rest/utils.py +3 -3
  11. imio/smartweb/core/interfaces.py +2 -0
  12. imio/smartweb/core/tests/test_ideabox.py +33 -1
  13. imio/smartweb/core/tests/test_rest.py +1 -3
  14. imio/smartweb/core/tests/test_sitemap.py +81 -42
  15. imio/smartweb/core/tests/test_vocabulary.py +18 -0
  16. imio/smartweb/core/viewlets/offcanvas.pt +2 -0
  17. imio/smartweb/core/webcomponents/build/css/919.smartweb-webcomponents-compiled.css +1 -1
  18. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  19. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -1
  20. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  21. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -1
  22. imio/smartweb/core/webcomponents/src/components/Search/Search.jsx +54 -9
  23. imio/smartweb/core/webcomponents/src/components/Search/Search.scss +9 -0
  24. imio/smartweb/core/webcomponents/src/utils/translation.js +12 -0
  25. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/METADATA +17 -1
  26. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/RECORD +32 -32
  27. /imio.smartweb.core-1.3-py3.12-nspkg.pth → /imio.smartweb.core-1.3.1-py3.12-nspkg.pth +0 -0
  28. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.GPL +0 -0
  29. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/LICENSE.rst +0 -0
  30. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/WHEEL +0 -0
  31. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.1.dist-info}/namespace_packages.txt +0 -0
  32. {imio.smartweb.core-1.3.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="*"
@@ -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.utils import get_auth_sources_response
6
- from imio.smartweb.core.contents.rest.utils import get_entity_id
7
- from plone import api
8
- from plone.base.interfaces import IPloneSiteRoot
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.registry.interfaces import IRegistry
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 getUtility
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
- utils = getToolByName(self.context, "plone_utils")
42
- query["portal_type"] = utils.getUserFriendlyTypes(friendlytypes)
43
- registry = getUtility(IRegistry)
44
- typesUseViewActionInListings = frozenset(
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
- # Comparison must be on GMT value
64
- modified = (date.micros(), date.ISO8601())
65
- default_modified = default_page_modified.get(loc, None)
66
- if default_modified is not None:
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
- # Comparison must be on GMT value
82
- modified = (date.micros(), date.ISO8601())
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
- if auth_source_uid is None:
125
- return self.request.response.setStatus(
126
- 404, "No default authentic source found"
127
- )
128
- obj = api.content.get(UID=auth_source_uid)
129
- if obj is None:
130
- logger.warning(
131
- f"Seems that a main authentic view (for {auth_source_key}) is not found"
132
- )
133
- continue
134
- auth_source_view_url = obj.absolute_url()
135
- results = get_auth_sources_response(
136
- auth_source_key, normalizeString(entity_id), (60 * 60 * 24)
137
- ).json()
138
- if results is None or results.get("type") == "ValueError":
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
- for item in results.get("items"):
141
- item_id = normalizeString(item.get("title"))
142
- item_uid = item.get("id")
143
- loc = f"{auth_source_view_url}/{item_id}?u={item_uid}"
144
- lastmod = item.get("modified")
145
- yield {
146
- "loc": loc,
147
- "lastmod": lastmod,
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
@@ -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
- del item[field]
52
+ item.pop(field, None)
50
53
 
51
54
  def construct_query_string(self, params):
52
55
  params = "&".join(params)
@@ -107,7 +107,7 @@ class CampaignEndpoint(BaseTsEndpoint):
107
107
  extra_params = [f"{k}={v}" for k, v in self.request.form.items()]
108
108
  extra_params = "&".join(extra_params)
109
109
  campaign_id = self.context.linked_campaign
110
- url = f"{wcs_api}/cards/imio-ideabox-projet/list?campagne={campaign_id}&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&{extra_params}"
110
+ url = f"{wcs_api}/cards/imio-ideabox-projet/list?filter-campagne={campaign_id}&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&{extra_params}"
111
111
  return url
112
112
 
113
113
 
@@ -124,7 +124,7 @@ class ZonesEndpoint(BaseTsEndpoint):
124
124
  def query_url(self):
125
125
  wcs_api = get_ts_api_url("wcs")
126
126
  campaign_id = self.context.linked_campaign
127
- return f"{wcs_api}/cards/imio-ideabox-zone/list?campagne={campaign_id}"
127
+ return f"{wcs_api}/cards/imio-ideabox-zone/list?filter-campagne={campaign_id}"
128
128
 
129
129
 
130
130
  @implementer(IExpandableElement)
@@ -140,7 +140,7 @@ class TsTopicsEndpoint(BaseTsEndpoint):
140
140
  def query_url(self):
141
141
  wcs_api = get_ts_api_url("wcs")
142
142
  campaign_id = self.context.linked_campaign
143
- return f"{wcs_api}/cards/imio-ideabox-theme/list?campagne={campaign_id}"
143
+ return f"{wcs_api}/cards/imio-ideabox-theme/list?filter-campagne={campaign_id}"
144
144
 
145
145
 
146
146
  @implementer(IExpandableElement)
@@ -13,7 +13,7 @@ from zope.interface import Interface
13
13
 
14
14
  class BaseDirectoryEndpoint(BaseEndpoint):
15
15
  def __call__(self):
16
- results = super(BaseDirectoryEndpoint, self).__call__()
16
+ results = super(BaseDirectoryEndpoint, self).__call__() or {}
17
17
  if not results.get("items"):
18
18
  return results
19
19
  orientation = self.context.orientation
@@ -45,10 +45,13 @@ class BaseDirectoryEndpoint(BaseEndpoint):
45
45
  "metadata_fields=taxonomy_contact_category",
46
46
  "metadata_fields=topics",
47
47
  "metadata_fields=has_leadimage",
48
- "fullobjects=1",
48
+ "fullobjects={}".format(self.fullobjects),
49
49
  "sort_on=sortable_title",
50
- "b_size={}".format(self.context.nb_results),
51
50
  ]
51
+ if self.batch_size == 0:
52
+ params.append("b_size={}".format(self.context.nb_results))
53
+ else:
54
+ params.append("b_size={}".format(self.batch_size))
52
55
  if self.context.selected_categories is not None:
53
56
  for category in self.context.selected_categories:
54
57
  params.append(f"taxonomy_contact_category.query={category}")
@@ -74,6 +77,11 @@ class DirectoryEndpointGet(BaseService):
74
77
  def reply(self):
75
78
  return DirectoryEndpoint(self.context, self.request)()
76
79
 
80
+ def reply_for_given_object(self, obj, request, fullobjects=1, batch_size=0):
81
+ return DirectoryEndpoint(
82
+ obj, request, fullobjects=fullobjects, batch_size=batch_size
83
+ )()
84
+
77
85
 
78
86
  class DirectoryFiltersEndpointGet(BaseService):
79
87
  def reply(self):
@@ -12,7 +12,7 @@ from zope.interface import Interface
12
12
 
13
13
  class BaseEventsEndpoint(BaseEndpoint):
14
14
  def __call__(self):
15
- results = super(BaseEventsEndpoint, self).__call__()
15
+ results = super(BaseEventsEndpoint, self).__call__() or {}
16
16
  if not results or not results.get("items"):
17
17
  return results
18
18
  orientation = self.context.orientation
@@ -43,9 +43,12 @@ class BaseEventsEndpoint(BaseEndpoint):
43
43
  "metadata_fields=has_leadimage",
44
44
  "metadata_fields=UID",
45
45
  "sort_on=event_dates",
46
- "fullobjects=1",
47
- "b_size={}".format(self.context.nb_results),
46
+ "fullobjects={}".format(self.fullobjects),
48
47
  ]
48
+ if self.batch_size == 0:
49
+ params.append("b_size={}".format(self.context.nb_results))
50
+ else:
51
+ params.append("b_size={}".format(self.batch_size))
49
52
  if self.context.selected_event_types is not None:
50
53
  for event_type in self.context.selected_event_types:
51
54
  params.append(f"event_type={event_type}")
@@ -70,6 +73,11 @@ class EventsEndpointGet(BaseService):
70
73
  def reply(self):
71
74
  return EventsEndpoint(self.context, self.request)()
72
75
 
76
+ def reply_for_given_object(self, obj, request, fullobjects=1, batch_size=0):
77
+ return EventsEndpoint(
78
+ obj, request, fullobjects=fullobjects, batch_size=batch_size
79
+ )()
80
+
73
81
 
74
82
  class EventsFiltersEndpointGet(BaseService):
75
83
  def reply(self):
@@ -12,7 +12,7 @@ from zope.interface import Interface
12
12
 
13
13
  class BaseNewsEndpoint(BaseEndpoint):
14
14
  def __call__(self):
15
- results = super(BaseNewsEndpoint, self).__call__()
15
+ results = super(BaseNewsEndpoint, self).__call__() or {}
16
16
  if not results.get("items"):
17
17
  return results
18
18
  orientation = self.context.orientation
@@ -46,9 +46,12 @@ class BaseNewsEndpoint(BaseEndpoint):
46
46
  "metadata_fields=UID",
47
47
  "sort_on=effective",
48
48
  "sort_order=descending",
49
- "b_size={}".format(self.context.nb_results),
50
- "fullobjects=1",
49
+ "fullobjects={}".format(self.fullobjects),
51
50
  ]
51
+ if self.batch_size == 0:
52
+ params.append("b_size={}".format(self.context.nb_results))
53
+ else:
54
+ params.append("b_size={}".format(self.batch_size))
52
55
  params = self.construct_query_string(params)
53
56
  url = f"{NEWS_URL}/{self.remote_endpoint}?{params}"
54
57
  return url
@@ -70,6 +73,11 @@ class NewsEndpointGet(BaseService):
70
73
  def reply(self):
71
74
  return NewsEndpoint(self.context, self.request)()
72
75
 
76
+ def reply_for_given_object(self, obj, request, fullobjects=1, batch_size=0):
77
+ return NewsEndpoint(
78
+ obj, request, fullobjects=fullobjects, batch_size=batch_size
79
+ )()
80
+
73
81
 
74
82
  class NewsFiltersEndpointGet(BaseService):
75
83
  def reply(self):
@@ -57,7 +57,10 @@ def get_default_view_url(view_type):
57
57
  if not record:
58
58
  return ""
59
59
  with api.env.adopt_user(username="admin"):
60
- return api.content.get(UID=record).absolute_url()
60
+ obj = api.content.get(UID=record)
61
+ if not obj:
62
+ return ""
63
+ return obj.absolute_url()
61
64
 
62
65
 
63
66
  def get_views_mapping(navigation_root):
@@ -69,10 +69,10 @@ def get_auth_sources_response(
69
69
  "v": wf_status,
70
70
  },
71
71
  ],
72
- "metadata_fields": ["title", "modified"],
72
+ "metadata_fields": ["title", "modified", "id"],
73
73
  "sort_on": "effective",
74
74
  "sort_order": "descending",
75
- "fullobjects": True,
75
+ "fullobjects": False,
76
76
  "b_start": 0,
77
77
  "b_size": 4000,
78
78
  }
@@ -81,7 +81,7 @@ def get_auth_sources_response(
81
81
  auth = get_wca_token(client_id, client_secret)
82
82
  headers = {
83
83
  "Accept": "application/json",
84
- "Content-Type": "text/plain",
84
+ "Content-Type": "application/json",
85
85
  "Authorization": auth,
86
86
  }
87
87
  url = f"{url}/@querystring-search"
@@ -5,6 +5,7 @@ from collective.messagesviewlet.interfaces import ICollectiveMessagesviewletLaye
5
5
  from collective.solr.browser.interfaces import IThemeSpecific
6
6
  from imio.smartweb.common.interfaces import IImioSmartwebCommonLayer
7
7
  from plone.app.contenttypes.interfaces import IPloneAppContenttypesLayer
8
+ from Products.CMFPlone.browser.interfaces import ISiteMap
8
9
  from zope.interface import Interface
9
10
 
10
11
 
@@ -22,6 +23,7 @@ class IImioSmartwebCoreLayer(
22
23
  ILayerSpecific,
23
24
  IThemeSpecific,
24
25
  ICollectiveMessagesviewletLayer,
26
+ ISiteMap,
25
27
  ):
26
28
  """Marker interface that defines a browser layer."""
27
29
 
@@ -85,6 +85,38 @@ class TestIdeabox(ImioSmartwebTestCase):
85
85
  self.assertEqual(campaign_view.title, "Sprint iMio Fall 2024")
86
86
  self.assertEqual(campaign_view.id, "sprint-imio-fall-2024")
87
87
 
88
+ # CampaignNameChooser : Give th Title to our object thanks to e-guichet object Title.
89
+ @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
90
+ @patch("imio.smartweb.core.subscribers.get_value_from_registry")
91
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_basic_auth_json")
92
+ @patch("imio.smartweb.core.contents.rest.campaign.content.get_value_from_registry")
93
+ def test_campaign_name_chooser(
94
+ self,
95
+ m_get_value_from_registry_namechooser,
96
+ m_get_basic_auth_json_namechooser,
97
+ m_get_value_from_registry,
98
+ m_get_basic_auth_json,
99
+ ):
100
+ from imio.smartweb.core.contents.rest.campaign.content import CampaignView
101
+ from zope.component import queryAdapter
102
+ from zope.container.interfaces import INameChooser
103
+
104
+ m_get_value_from_registry.return_value = (
105
+ "https://staging3-formulaires.guichet-citoyen.be/api"
106
+ )
107
+ m_get_basic_auth_json.return_value = self.json_campaign_raw_mock
108
+
109
+ m_get_value_from_registry_namechooser.return_value = (
110
+ "https://staging3-formulaires.guichet-citoyen.be/api"
111
+ )
112
+ m_get_basic_auth_json_namechooser.return_value = self.json_campaign_raw_mock
113
+ campaign_view = CampaignView(id="test-campaign", title=None)
114
+ campaign_view.linked_campaign = "2"
115
+ name_chooser = queryAdapter(self.folder, INameChooser)
116
+ generated_id = name_chooser.chooseName(None, campaign_view)
117
+ self.assertEqual(campaign_view.title, "Sprint iMio Fall 2024")
118
+ self.assertEqual(generated_id, "sprint-imio-fall-2024")
119
+
88
120
  @requests_mock.Mocker()
89
121
  @patch("imio.smartweb.core.subscribers.get_basic_auth_json")
90
122
  @patch("imio.smartweb.core.subscribers.get_value_from_registry")
@@ -110,7 +142,7 @@ class TestIdeabox(ImioSmartwebTestCase):
110
142
  url = endpoint.query_url
111
143
  self.assertEqual(
112
144
  url,
113
- "https://demo-formulaires.guichet-citoyen.be/api/cards/imio-ideabox-projet/list?campagne=2&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&",
145
+ "https://demo-formulaires.guichet-citoyen.be/api/cards/imio-ideabox-projet/list?filter-campagne=2&full=on&filter-statut=Vote|Enregistr%C3%A9e&filter-statut-operator=in&",
114
146
  )
115
147
 
116
148
  m.get(url, text=json.dumps({}))
@@ -18,7 +18,6 @@ from plone.app.testing import TEST_USER_ID
18
18
  from plone.app.testing import TEST_USER_PASSWORD
19
19
  from plone.namedfile.file import NamedBlobImage
20
20
  from plone.restapi.testing import RelativeSession
21
- from unittest import mock
22
21
  from unittest.mock import patch
23
22
  from urllib.parse import urlparse
24
23
  from urllib.parse import parse_qs
@@ -29,7 +28,6 @@ from ZPublisher.pubevents import PubStart
29
28
  from imio.smartweb.core.viewlets.ogptags import OgpTagsViewlet
30
29
 
31
30
  import json
32
- import os
33
31
  import requests_mock
34
32
  import transaction
35
33
 
@@ -444,8 +442,8 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
444
442
  "metadata_fields=UID&"
445
443
  "sort_on=effective&"
446
444
  "sort_order=descending&"
447
- "b_size=20&"
448
445
  "fullobjects=1&"
446
+ "b_size=20&"
449
447
  "translated_in_en=1".format(self.rest_news.selected_news_folder),
450
448
  )
451
449
  m.get(url, text=json.dumps({}))