imio.smartweb.core 1.3__py3-none-any.whl → 1.3.2__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 (39) 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 +162 -110
  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/profiles/default/metadata.xml +1 -1
  13. imio/smartweb/core/profiles/default/types/imio.smartweb.SectionTimestampedPublications.xml +4 -0
  14. imio/smartweb/core/profiles/default/types.xml +1 -0
  15. imio/smartweb/core/profiles/default/workflows.xml +1 -0
  16. imio/smartweb/core/tests/test_ideabox.py +33 -1
  17. imio/smartweb/core/tests/test_rest.py +1 -3
  18. imio/smartweb/core/tests/test_sitemap.py +98 -40
  19. imio/smartweb/core/tests/test_vocabulary.py +18 -0
  20. imio/smartweb/core/upgrades/configure.zcml +19 -0
  21. imio/smartweb/core/upgrades/profiles/1061_to_1062/types/imio.smartweb.SectionTimestampedPublications.xml +1 -5
  22. imio/smartweb/core/upgrades/profiles/1066_to_1067/types/imio.smartweb.SectionTimestampedPublications.xml +39 -0
  23. imio/smartweb/core/viewlets/offcanvas.pt +2 -0
  24. imio/smartweb/core/webcomponents/build/css/919.smartweb-webcomponents-compiled.css +1 -1
  25. imio/smartweb/core/webcomponents/build/js/373.smartweb-webcomponents-compiled.js +1 -1
  26. imio/smartweb/core/webcomponents/build/js/666.smartweb-webcomponents-compiled.js +1 -1
  27. imio/smartweb/core/webcomponents/build/js/919.smartweb-webcomponents-compiled.js +1 -1
  28. imio/smartweb/core/webcomponents/build/js/922.smartweb-webcomponents-compiled.js +1 -1
  29. imio/smartweb/core/webcomponents/src/components/Search/Search.jsx +54 -9
  30. imio/smartweb/core/webcomponents/src/components/Search/Search.scss +9 -0
  31. imio/smartweb/core/webcomponents/src/utils/translation.js +12 -0
  32. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/METADATA +27 -1
  33. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/RECORD +39 -38
  34. /imio.smartweb.core-1.3-py3.12-nspkg.pth → /imio.smartweb.core-1.3.2-py3.12-nspkg.pth +0 -0
  35. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/LICENSE.GPL +0 -0
  36. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/LICENSE.rst +0 -0
  37. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/WHEEL +0 -0
  38. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/namespace_packages.txt +0 -0
  39. {imio.smartweb.core-1.3.dist-info → imio.smartweb.core-1.3.2.dist-info}/top_level.txt +0 -0
@@ -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({}))
@@ -3,8 +3,12 @@
3
3
  from freezegun import freeze_time
4
4
  from gzip import GzipFile
5
5
  from io import BytesIO
6
+ from imio.smartweb.core.browser.sitemap import CatalogSiteMap
7
+ from imio.smartweb.core.browser.sitemap import get_endpoint_data
8
+ from imio.smartweb.core.browser.sitemap import cache_key
6
9
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
7
10
  from imio.smartweb.core.testing import ImioSmartwebTestCase
11
+ from imio.smartweb.core.tests.utils import clear_cache
8
12
  from imio.smartweb.core.tests.utils import get_json
9
13
  from imio.smartweb.core.tests.utils import make_named_image
10
14
  from plone import api
@@ -12,11 +16,13 @@ from plone.app.testing import setRoles
12
16
  from plone.app.testing import TEST_USER_ID
13
17
  from plone.app.textfield.value import RichTextValue
14
18
  from plone.base.utils import safe_text
19
+ from plone.memoize.ram import choose_cache
15
20
  from plone.namedfile.file import NamedBlobImage
16
21
  from unittest.mock import patch
22
+ from unittest.mock import Mock
23
+ from zope.annotation import IAnnotations
17
24
  from zope.component import getMultiAdapter
18
25
 
19
- import json
20
26
  import requests_mock
21
27
 
22
28
 
@@ -76,6 +82,10 @@ class TestPage(ImioSmartwebTestCase):
76
82
  title="news view",
77
83
  )
78
84
  self.rest_news.selected_news_folder = "64f4cbee9a394a018a951f6d94452914"
85
+ self.json_rest_directory = get_json("resources/json_rest_directory.json")
86
+ self.json_rest_events = get_json("resources/json_rest_events.json")
87
+ self.json_rest_news = get_json("resources/json_rest_news.json")
88
+
79
89
  api.content.transition(self.rest_directory, "publish")
80
90
  api.content.transition(self.rest_agenda, "publish")
81
91
  api.content.transition(self.rest_news, "publish")
@@ -111,60 +121,108 @@ class TestPage(ImioSmartwebTestCase):
111
121
  (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
112
122
  )
113
123
  xml = self.uncompress(sitemap())
114
- self.assertIn(
115
- "<loc>http://nohost/plone/folder/page1/gallery/image/view</loc>", xml
116
- )
124
+ self.assertIn("<loc>http://nohost/plone/folder/page1/gallery/image</loc>", xml)
117
125
  # Gallery and image created 2024-02-02 10:00:00
118
126
  self.assertIn(
119
- "<loc>http://nohost/plone/folder/page1/gallery/image/view</loc>\n <lastmod >2024-02-02T10:00:00",
127
+ "<loc>http://nohost/plone/folder/page1/gallery/image</loc>\n <lastmod >2024-02-02T10:00:00",
120
128
  xml,
121
129
  )
122
130
 
123
- rest_views = {
124
- "directory": self.rest_directory,
125
- "events": self.rest_agenda,
126
- "news": self.rest_news,
127
- }
128
- contact_search_url = news_search_url = events_search_url = (
129
- "http://localhost:8080/Plone/@querystring-search"
130
- )
131
- for k, v in rest_views.items():
132
- api.portal.set_registry_record(f"smartweb.default_{k}_view", v.UID())
131
+ cache = choose_cache("imio.smartweb.core.browser.sitemap.get_endpoint_data")
132
+ cache.ramcache.invalidateAll()
133
+
133
134
  with patch(
134
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
135
- return_value="kamoulox",
136
- ):
137
- self.json_contacts = get_json("resources/json_contacts_raw_mock.json")
138
- m.post(contact_search_url, text=json.dumps(self.json_contacts))
139
- sitemap = getMultiAdapter(
140
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
135
+ "imio.smartweb.core.contents.rest.news.endpoint.BaseNewsEndpoint.__call__",
136
+ return_value=self.json_rest_news,
137
+ ) as mypatch:
138
+ xml = self.uncompress(sitemap())
139
+ self.assertIn(
140
+ "<loc>http://nohost/plone/news-view/ceci-est-une-deuxieme-actualite",
141
+ xml,
141
142
  )
143
+
144
+ cache = choose_cache("imio.smartweb.core.browser.sitemap.get_endpoint_data")
145
+ cache.ramcache.invalidateAll()
146
+
147
+ with patch(
148
+ "imio.smartweb.core.contents.rest.directory.endpoint.BaseDirectoryEndpoint.__call__",
149
+ return_value=self.json_rest_directory,
150
+ ) as mypatch:
142
151
  xml = self.uncompress(sitemap())
143
- self.assertIn("<loc>http://nohost/plone/directory-view/contact1-title", xml)
152
+ self.assertIn(
153
+ "<loc>http://nohost/plone/directory-view/service-communication-de-ladministration-communale",
154
+ xml,
155
+ )
156
+
157
+ cache = choose_cache("imio.smartweb.core.browser.sitemap.get_endpoint_data")
158
+ cache.ramcache.invalidateAll()
144
159
 
145
160
  with patch(
146
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
147
- return_value="kamoulox",
161
+ "imio.smartweb.core.contents.rest.events.endpoint.BaseEventsEndpoint.__call__",
162
+ return_value=self.json_rest_events,
148
163
  ):
149
- self.json_news = get_json("resources/json_rest_news.json")
150
- m.post(news_search_url, text=json.dumps(self.json_news))
151
- sitemap = getMultiAdapter(
152
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
153
- )
154
164
  xml = self.uncompress(sitemap())
155
- self.assertIn("<loc>http://nohost/plone/news-view/", xml)
165
+ self.assertIn(
166
+ "<loc>http://nohost/plone/agenda-view/evenement-recurrent-tous-les-samedi",
167
+ xml,
168
+ )
169
+
170
+ def test_site_map_for_user_display(self):
171
+ sitemap = CatalogSiteMap(self.portal, self.request)
172
+ # 3 authentic sources
173
+ self.assertEqual(len(sitemap.siteMap().get("children")), 3)
174
+ self.assertNotIn(
175
+ "Folder",
176
+ [child.get("Title") for child in sitemap.siteMap().get("children")],
177
+ )
156
178
 
179
+ # Publish folder and page (private content don't appear in sitemap)
180
+ api.content.transition(self.folder, "publish")
181
+ api.content.transition(self.page, "publish")
182
+ sitemap = CatalogSiteMap(self.portal, self.request)
183
+ self.assertEqual(len(sitemap.siteMap().get("children")), 4)
184
+ self.assertIn(
185
+ "Folder",
186
+ [child.get("Title") for child in sitemap.siteMap().get("children")],
187
+ )
188
+ folder_entry = [
189
+ child
190
+ for child in sitemap.siteMap().get("children")
191
+ if child.get("Title") == "Folder"
192
+ ][0]
193
+ self.assertIn(
194
+ "Page 1", [child.get("Title") for child in folder_entry.get("children")]
195
+ )
196
+
197
+ directory_entry = [
198
+ child
199
+ for child in sitemap.siteMap().get("children")
200
+ if child.get("Title") == "directory view"
201
+ ][0]
202
+ self.assertEqual(len(directory_entry.get("children")), 0)
203
+
204
+ cache = choose_cache("imio.smartweb.core.browser.sitemap.get_endpoint_data")
205
+ cache.ramcache.invalidateAll()
206
+
207
+ # Populate directory view with 6 contacts
157
208
  with patch(
158
- "imio.smartweb.core.contents.rest.utils.get_wca_token",
159
- return_value="kamoulox",
209
+ "imio.smartweb.core.contents.rest.directory.endpoint.BaseDirectoryEndpoint.__call__",
210
+ return_value=self.json_rest_directory,
160
211
  ):
161
- self.json_events = get_json("resources/json_rest_events.json")
162
- m.post(events_search_url, text=json.dumps(self.json_events))
163
- sitemap = getMultiAdapter(
164
- (self.portal, self.portal.REQUEST), name="sitemap.xml.gz"
165
- )
166
- xml = self.uncompress(sitemap())
167
- self.assertIn("<loc>http://nohost/plone/agenda-view/", xml)
212
+ sitemap = CatalogSiteMap(self.portal, self.request)
213
+ directory_entry = [
214
+ child
215
+ for child in sitemap.siteMap().get("children")
216
+ if child.get("Title") == "directory view"
217
+ ][0]
218
+ self.assertEqual(len(directory_entry.get("children")), 6)
219
+
220
+ def test_bad_portal_type(self):
221
+ obj = Mock()
222
+ obj.portal_type = None
223
+ request = Mock()
224
+ result = get_endpoint_data(obj, request)
225
+ assert result == {}
168
226
 
169
227
  def uncompress(self, sitemapdata):
170
228
  sio = BytesIO(sitemapdata)
@@ -41,3 +41,21 @@ class TestVocabulary(ImioSmartwebTestCase):
41
41
  self.assertEqual(
42
42
  result["results"][0]["text"], "Activités et divertissement"
43
43
  )
44
+
45
+ self.page = api.content.create(
46
+ container=self.portal,
47
+ type="imio.smartweb.Page",
48
+ title="My Page",
49
+ )
50
+ self.contacts = api.content.create(
51
+ container=self.page,
52
+ type="imio.smartweb.SectionContact",
53
+ title="My contancts",
54
+ )
55
+ self.request.form = {
56
+ "name": "imio.smartweb.vocabulary.RemoteContacts",
57
+ "field": "related_contacts",
58
+ }
59
+ view = queryMultiAdapter((self.contacts, self.request), name="getVocabulary")
60
+ result = json.loads(view())
61
+ self.assertEqual(result["results"], [])
@@ -291,6 +291,14 @@
291
291
  provides="Products.GenericSetup.interfaces.EXTENSION"
292
292
  />
293
293
 
294
+ <genericsetup:registerProfile
295
+ name="upgrade_1066_to_1067"
296
+ title="Upgrade core from 1066 to 1067"
297
+ directory="profiles/1066_to_1067"
298
+ description="BLA BLA BLA"
299
+ provides="Products.GenericSetup.interfaces.EXTENSION"
300
+ />
301
+
294
302
  <genericsetup:upgradeStep
295
303
  title="Configure first official release"
296
304
  description="Run needed profiles steps and reindex catalog"
@@ -961,6 +969,17 @@
961
969
  profile="imio.smartweb.core:default"
962
970
  />
963
971
 
972
+ <genericsetup:upgradeSteps
973
+ source="1066"
974
+ destination="1067"
975
+ profile="imio.smartweb.core:default">
976
+ <genericsetup:upgradeDepends
977
+ title="BLA BLA BLA"
978
+ import_profile="imio.smartweb.core.upgrades:upgrade_1066_to_1067"
979
+ />
980
+ </genericsetup:upgradeSteps>
981
+
982
+
964
983
  <!--genericsetup:upgradeStep
965
984
  title="Check contact itinerary if address was checked in visible blocks"
966
985
  description=""
@@ -16,11 +16,7 @@
16
16
 
17
17
  <!-- Hierarchy control -->
18
18
  <property name="global_allow">False</property>
19
- <property name="filter_content_types">True</property>
20
- <property name="allowed_content_types">
21
- <element value="imio.smartweb.SectionTimestampedPublications" />
22
- </property>
23
-
19
+ <property name="filter_content_types">True</property>
24
20
  <!-- Schema, class and security -->
25
21
  <!-- if we can add a page, we can add a page section -->
26
22
  <property name="add_permission">imio.smartweb.core.AddPage</property>
@@ -0,0 +1,39 @@
1
+ <?xml version="1.0"?>
2
+ <object xmlns:i18n="http://xml.zope.org/namespaces/i18n"
3
+ name="imio.smartweb.SectionTimestampedPublications"
4
+ meta_type="Dexterity FTI"
5
+ i18n:domain="imio.smartweb">
6
+
7
+ <!-- Basic properties -->
8
+ <property
9
+ i18n:translate=""
10
+ name="title">Timestamped publications section</property>
11
+ <property
12
+ i18n:translate=""
13
+ name="description">Timestamped publication section for a page</property>
14
+
15
+ <property name="icon_expr">string:newspaper</property>
16
+
17
+ <!-- Hierarchy control -->
18
+ <property name="global_allow">False</property>
19
+ <property name="filter_content_types">True</property>
20
+ <!-- Schema, class and security -->
21
+ <!-- if we can add a page, we can add a page section -->
22
+ <property name="add_permission">imio.smartweb.core.AddPage</property>
23
+ <property name="klass">imio.smartweb.core.contents.SectionTimestampedPublications</property>
24
+ <property name="schema">imio.smartweb.core.contents.ISectionTimestampedPublications</property>
25
+
26
+ <!-- Enabled behaviors -->
27
+ <property name="behaviors" purge="false">
28
+ <element value="plone.namefromtitle"/>
29
+ <element value="plone.locking"/>
30
+ <element value="plone.shortname"/>
31
+ <element value="imio.smartweb.category_display"/>
32
+ <element value="imio.smartweb.orientation"/>
33
+ </property>
34
+
35
+ <property name="default_view">table_view</property>
36
+ <property name="default_view_fallback">False</property>
37
+ <property name="immediate_view">view</property>
38
+
39
+ </object>
@@ -7,6 +7,8 @@
7
7
  <template id="search-template">
8
8
  <smartweb-search tal:attributes="current-language view/current_language;
9
9
  query-url view/navroot_url;
10
+ context-user-has-roles view/context_user_has_roles;
11
+ are-views-available view/are_views_available;
10
12
  result-option view/get_search_result_option">
11
13
  </smartweb-search>
12
14
  </template>
@@ -1 +1 @@
1
- .userrole-authenticated .r-search-container{padding:0 20px 0 123px}.r-search-container{margin:0 auto;max-width:1330px;padding:0 20px}.r-search-container .full-width{left:50%;margin-left:-50vw;margin-right:-50vw;position:relative;right:50%;width:100vw}.r-search-container .r-search-highlighter{background:#0000;border-bottom:2px solid #f9b300;font-weight:700;padding:0;position:relative}.r-search-container .r-search-header{border-bottom:1px solid #000}.r-search-container .r-search-header-title{font-size:15px;font-weight:700;text-transform:uppercase}.r-search-container .r-search-header-count{color:gray;font-size:10px;text-transform:uppercase}.r-search-container .r-search-result{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));margin-top:2rem}.r-search-container .r-search.search-bar-filter,.r-search-container .r-search.search-bar-filter form{position:relative}.r-search-container .r-search.search-bar-filter input,.r-search-container .r-search.search-bar-filter label{width:100%}.r-search-container .r-search.search-bar-filter input{border:1px solid #ccc;color:#000;font-weight:700;height:50px;letter-spacing:1.2px;line-height:50px;padding:0 10px}.r-search-container .r-search.search-bar-filter input::placeholder{color:#000;font-size:12px;letter-spacing:1.2px;opacity:1;text-transform:uppercase}.r-search-container .r-search.search-bar-filter button{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg data-name='Calque 2'%3E%3Cpath d='M11.08 6.77a4.31 4.31 0 1 0-4.31 4.31 4.32 4.32 0 0 0 4.31-4.31m4.92 8A1.24 1.24 0 0 1 14.77 16a1.17 1.17 0 0 1-.86-.37l-3.3-3.28a6.77 6.77 0 1 1 1.74-1.74l3.3 3.3a1.25 1.25 0 0 1 .35.86' data-name='Calque 1' style='fill:%23141414;fill-rule:evenodd'/%3E%3C/g%3E%3C/svg%3E") no-repeat;background-position:50%;background-size:80%;border:none;bottom:0;position:absolute;right:10px;top:0;width:20px}.r-search-container .r-search-select{border-radius:0;height:50px}.r-search-container .r-search-list{margin-top:20px;overflow-y:scroll}@media screen and (min-width:992px){.r-search-container .r-search-list{max-height:375px}}.r-search-container .r-search-list .r-search-item{border-bottom:1px solid #00000040;display:flex;font-size:14px;gap:10px;list-style:none;padding:1rem 0}.r-search-container .r-search-list .r-search-item .r-search-img{background-repeat:no-repeat;background-size:cover;flex-basis:100%;flex-basis:91px;flex-grow:0;flex-shrink:0;height:61px;width:91px}.offcanvas-header .btn-close{position:absolute;right:10px;top:10px}.search-contact .r-search-img,.search-events .r-search-img,.search-news .r-search-img{float:left;margin-right:.5rem}.r-search-result mark{display:initial}
1
+ .userrole-authenticated .r-search-container{padding:0 20px 0 123px}.r-search-container{margin:0 auto;max-width:1330px;padding:0 20px}.r-search-container .full-width{left:50%;margin-left:-50vw;margin-right:-50vw;position:relative;right:50%;width:100vw}.r-search-container .r-search-highlighter{background:#0000;border-bottom:2px solid #f9b300;font-weight:700;padding:0;position:relative}.r-search-container .r-search-header{border-bottom:1px solid #000}.r-search-container .r-search-header-title{font-size:15px;font-weight:700;text-transform:uppercase}.r-search-container .r-search-header-count{color:gray;font-size:10px;text-transform:uppercase}.r-search-container .r-search-result{display:grid;gap:1.5rem;grid-template-columns:repeat(auto-fit,minmax(250px,1fr));margin-top:2rem}.r-search-container .r-search.search-bar-filter,.r-search-container .r-search.search-bar-filter form{position:relative}.r-search-container .r-search.search-bar-filter input,.r-search-container .r-search.search-bar-filter label{width:100%}.r-search-container .r-search.search-bar-filter input{border:1px solid #ccc;color:#000;font-weight:700;height:50px;letter-spacing:1.2px;line-height:50px;padding:0 10px}.r-search-container .r-search.search-bar-filter input::placeholder{color:#000;font-size:12px;letter-spacing:1.2px;opacity:1;text-transform:uppercase}.r-search-container .r-search.search-bar-filter button{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cg data-name='Calque 2'%3E%3Cpath d='M11.08 6.77a4.31 4.31 0 1 0-4.31 4.31 4.32 4.32 0 0 0 4.31-4.31m4.92 8A1.24 1.24 0 0 1 14.77 16a1.17 1.17 0 0 1-.86-.37l-3.3-3.28a6.77 6.77 0 1 1 1.74-1.74l3.3 3.3a1.25 1.25 0 0 1 .35.86' data-name='Calque 1' style='fill:%23141414;fill-rule:evenodd'/%3E%3C/g%3E%3C/svg%3E") no-repeat;background-position:50%;background-size:80%;border:none;bottom:0;position:absolute;right:10px;top:0;width:20px}.r-search-container .r-search-select{border-radius:0;height:50px}.r-search-container .r-search-list{margin-top:20px;overflow-y:scroll}@media screen and (min-width:992px){.r-search-container .r-search-list{max-height:375px}}.r-search-container .r-search-list .r-search-item{border-bottom:1px solid #00000040;display:flex;font-size:14px;gap:10px;list-style:none;padding:1rem 0}.r-search-container .r-search-list .r-search-item .r-search-img{background-repeat:no-repeat;background-size:cover;flex-basis:100%;flex-basis:91px;flex-grow:0;flex-shrink:0;height:61px;width:91px}.offcanvas-header .btn-close{position:absolute;right:10px;top:10px}.search-contact .r-search-img,.search-events .r-search-img,.search-news .r-search-img{float:left;margin-right:.5rem}.r-search-result mark{display:initial}.search-disabled-message{background-color:#f8f9fa;border:1px solid #dee2e6;border-radius:4px;color:#6c757d;margin:1rem 0;padding:1rem}