imio.smartweb.core 1.2.74__py3-none-any.whl → 1.2.76__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 (23) hide show
  1. imio/smartweb/core/browser/static/smartweb-view-compiled.css +1 -1
  2. imio/smartweb/core/browser/static/src/view.less +106 -57
  3. imio/smartweb/core/contents/pages/configure.zcml +1 -0
  4. imio/smartweb/core/contents/pages/views.py +44 -0
  5. imio/smartweb/core/contents/sections/contact/macros.pt +28 -3
  6. imio/smartweb/core/contents/sections/contact/view.py +28 -12
  7. imio/smartweb/core/contents/sections/events/view.py +1 -1
  8. imio/smartweb/core/contents/sections/news/view.py +1 -1
  9. imio/smartweb/core/tests/test_section_contact.py +35 -10
  10. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.scss +364 -378
  11. imio/smartweb/core/webcomponents/src/components/Events/Events.scss +401 -417
  12. imio/smartweb/core/webcomponents/src/components/Filters/MainFilter.scss +174 -172
  13. imio/smartweb/core/webcomponents/src/components/News/News.scss +145 -130
  14. imio/smartweb/core/webcomponents/src/components/News/NewsContent/NewsContent.jsx +35 -14
  15. imio/smartweb/core/webcomponents/src/components/Search/Search.scss +117 -118
  16. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/METADATA +20 -1
  17. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/RECORD +23 -23
  18. /imio.smartweb.core-1.2.74-py3.12-nspkg.pth → /imio.smartweb.core-1.2.76-py3.12-nspkg.pth +0 -0
  19. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/LICENSE.GPL +0 -0
  20. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/LICENSE.rst +0 -0
  21. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/WHEEL +0 -0
  22. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/namespace_packages.txt +0 -0
  23. {imio.smartweb.core-1.2.74.dist-info → imio.smartweb.core-1.2.76.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- *{background-position:50%;background-size:cover}body,html{max-width:100%}body{overflow-x:hidden}.table_schedule--active{display:block!important}.card-img-top{padding-top:56.25%}.template-folder_contents table .actionmenu a.action.set-default-page{display:none}#banner{background-size:cover;grid-column-end:-1;grid-column-start:1;height:200px}.hidden-banner{height:55px!important}.pat-structure .pagination>.active>a{z-index:0}.carousel-image{padding-bottom:50%}.swiper-slide .swiper-image{padding-bottom:60%}.swiper-wrapper{padding-bottom:50px}.template-taxonomy-edit-data .taxonomy-tree{border:0 solid #fff}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_item{border:none;font-size:1.25rem;padding:0 0 1rem;text-transform:uppercase}.template-taxonomy-edit-data .super-text{display:none}.template-taxonomy-edit-data .editable-divs{display:none!important}.template-taxonomy-edit-data div.info .super-text+.editable-divs:nth-child(2),.template-taxonomy-edit-data span .super-text+.editable-divs:nth-child(2){display:inline!important}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.info,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_item{border-bottom:2px solid #555}.template-taxonomy-edit-data .info,.template-taxonomy-edit-data .tree-view_item{border-bottom:1px dashed #d2d2d2}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.info input,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_item input{color:#303030;padding-top:.5rem!important;text-shadow:0 1px 0 #303030}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.info:before,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_item:before{content:"⤷";float:left;font-weight:700;margin-top:.3rem}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.info:before,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_item:before{content:"•";float:left;font-size:1.5rem;font-weight:700;margin-top:1px}.template-taxonomy-edit-data .taxonomy-tree .tree-view_arrow{display:none}.template-taxonomy-edit-data .taxonomy-tree .tree-view_children{margin-left:2rem}.smartweb_herobanner .section-slide,.smartweb_herobanner .section-slide .swiper-banner-image{height:100%}#portal-globalnav-collapse .nav_index_html,#subsite-navigation .nav_index_html{display:none}.block-menu-element,.list-menu-element{list-style:none}
1
+ @import url(https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css);*{background-position:50%;background-size:cover}body,html{max-width:100%}body{overflow-x:hidden}.table_schedule--active{display:block!important}.card-img-top{padding-top:56.25%}.template-folder_contents table .actionmenu a.action.set-default-page{display:none}#banner{background-size:cover;grid-column-end:-1;grid-column-start:1;height:200px}.hidden-banner{height:55px!important}.pat-structure .pagination>.active>a{z-index:0}.carousel-image{padding-bottom:50%}.swiper-slide .swiper-image{padding-bottom:60%}.swiper-wrapper{padding-bottom:50px}.template-taxonomy-edit-data .taxonomy-tree{border:0 solid #fff}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_item{border:none;font-size:1.25rem;padding:0 0 1rem;text-transform:uppercase}.template-taxonomy-edit-data .super-text{display:none}.template-taxonomy-edit-data .editable-divs{display:none!important}.template-taxonomy-edit-data div.info .super-text+.editable-divs:nth-child(2),.template-taxonomy-edit-data span .super-text+.editable-divs:nth-child(2){display:inline!important}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.info,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_item{border-bottom:2px solid #555}.template-taxonomy-edit-data .info,.template-taxonomy-edit-data .tree-view_item{border-bottom:1px dashed #d2d2d2}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.info input,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_item input{color:#303030;padding-top:.5rem!important;text-shadow:0 1px 0 #303030}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.info:before,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_item:before{content:"⤷";float:left;font-weight:700;margin-top:.3rem}.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.info:before,.template-taxonomy-edit-data .taxonomy-tree>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_children>.tree-view>.tree-view_item:before{content:"•";float:left;font-size:1.5rem;font-weight:700;margin-top:1px}.template-taxonomy-edit-data .taxonomy-tree .tree-view_arrow{display:none}.template-taxonomy-edit-data .taxonomy-tree .tree-view_children{margin-left:2rem}.smartweb_herobanner .section-slide,.smartweb_herobanner .section-slide .swiper-banner-image{height:100%}#portal-globalnav-collapse .nav_index_html,#subsite-navigation .nav_index_html{display:none}.block-menu-element,.list-menu-element{list-style:none}.contact_informations_social{display:flex;flex-wrap:wrap;gap:8px}.contact_informations_social .website{width:100%}
@@ -1,18 +1,21 @@
1
- *{
1
+ @import url("https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css");
2
+
3
+ * {
2
4
  background-size: cover;
3
5
  background-position: center;
4
6
  }
5
- html, body {
7
+ html,
8
+ body {
6
9
  max-width: 100%;
7
10
  }
8
- body{
11
+ body {
9
12
  overflow-x: hidden;
10
13
  }
11
- .table_schedule--active{
12
- display: block!important;
14
+ .table_schedule--active {
15
+ display: block !important;
13
16
  }
14
17
 
15
- .card-img-top{
18
+ .card-img-top {
16
19
  padding-top: 56.25%;
17
20
  }
18
21
  // for edition
@@ -21,14 +24,14 @@ body{
21
24
  }
22
25
  //
23
26
  // banner
24
- #banner{
27
+ #banner {
25
28
  grid-column-start: 1;
26
29
  grid-column-end: -1;
27
- height:200px;
30
+ height: 200px;
28
31
  background-size: cover;
29
32
  }
30
- .hidden-banner{
31
- height: 55px!important;
33
+ .hidden-banner {
34
+ height: 55px !important;
32
35
  }
33
36
 
34
37
  .pat-structure .pagination > .active > a {
@@ -38,86 +41,132 @@ body{
38
41
  //// slidier
39
42
 
40
43
  .carousel-image {
41
- padding-bottom: 50%;
44
+ padding-bottom: 50%;
42
45
  }
43
46
 
44
- .swiper-slide .swiper-image{
45
- padding-bottom: 60%;
47
+ .swiper-slide .swiper-image {
48
+ padding-bottom: 60%;
46
49
  }
47
- .swiper-wrapper{
48
- padding-bottom: 50px;
50
+ .swiper-wrapper {
51
+ padding-bottom: 50px;
49
52
  }
50
53
 
51
54
  /* si identifiant numérique on cache l'identifiant */
52
- .template-taxonomy-edit-data{
55
+ .template-taxonomy-edit-data {
53
56
  .taxonomy-tree {
54
- border:0px solid white;
55
- & > .tree-view > .tree-view_item {
56
- font-size: 1.25rem;
57
- padding: 0rem 0 1rem;
58
- text-transform: uppercase;
59
- border: none;
57
+ border: 0px solid white;
58
+ & > .tree-view > .tree-view_item {
59
+ font-size: 1.25rem;
60
+ padding: 0rem 0 1rem;
61
+ text-transform: uppercase;
62
+ border: none;
60
63
  }
61
64
  }
62
- .super-text{
63
- display:none;
65
+ .super-text {
66
+ display: none;
64
67
  }
65
68
  .editable-divs {
66
- display: none !important;
69
+ display: none !important;
67
70
  }
68
- span .super-text +.editable-divs:nth-child(2),
69
- div.info .super-text +.editable-divs:nth-child(2) {
70
- display: inline !important;
71
+ span .super-text + .editable-divs:nth-child(2),
72
+ div.info .super-text + .editable-divs:nth-child(2) {
73
+ display: inline !important;
71
74
  }
72
75
  .taxonomy-tree > .tree-view > .tree-view_children > .info,
73
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_item{
74
- border-bottom:2px solid #555;
76
+ .taxonomy-tree
77
+ > .tree-view
78
+ > .tree-view_children
79
+ > .tree-view
80
+ > .tree-view_item {
81
+ border-bottom: 2px solid #555;
75
82
  }
76
83
  .tree-view_item,
77
84
  .info {
78
- border-bottom: 1px dashed #D2D2D2;
85
+ border-bottom: 1px dashed #d2d2d2;
79
86
  }
80
87
  .taxonomy-tree > .tree-view > .tree-view_children > .info input,
81
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_item input{
82
- text-shadow: 0px 1px 0px #303030;
83
- padding-top: 0.5rem !important;
84
- color: #303030;
88
+ .taxonomy-tree
89
+ > .tree-view
90
+ > .tree-view_children
91
+ > .tree-view
92
+ > .tree-view_item
93
+ input {
94
+ text-shadow: 0px 1px 0px #303030;
95
+ padding-top: 0.5rem !important;
96
+ color: #303030;
85
97
  }
86
98
 
87
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .info:before,
88
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .tree-view > .tree-view_item:before{
89
- content: "⤷";
90
- font-weight:bold;
91
- float: left;
92
- margin-top: 0.3rem;
99
+ .taxonomy-tree
100
+ > .tree-view
101
+ > .tree-view_children
102
+ > .tree-view
103
+ > .tree-view_children
104
+ > .info:before,
105
+ .taxonomy-tree
106
+ > .tree-view
107
+ > .tree-view_children
108
+ > .tree-view
109
+ > .tree-view_children
110
+ > .tree-view
111
+ > .tree-view_item:before {
112
+ content: "⤷";
113
+ font-weight: bold;
114
+ float: left;
115
+ margin-top: 0.3rem;
93
116
  }
94
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .info:before,
95
- .taxonomy-tree > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .tree-view > .tree-view_children > .tree-view > .tree-view_item:before{
96
- font-weight:bold;
97
- float: left;
98
- margin-top: 1px;
99
- content: "•";
100
- font-size: 1.5rem;
117
+ .taxonomy-tree
118
+ > .tree-view
119
+ > .tree-view_children
120
+ > .tree-view
121
+ > .tree-view_children
122
+ > .tree-view
123
+ > .tree-view_children
124
+ > .info:before,
125
+ .taxonomy-tree
126
+ > .tree-view
127
+ > .tree-view_children
128
+ > .tree-view
129
+ > .tree-view_children
130
+ > .tree-view
131
+ > .tree-view_children
132
+ > .tree-view
133
+ > .tree-view_item:before {
134
+ font-weight: bold;
135
+ float: left;
136
+ margin-top: 1px;
137
+ content: "•";
138
+ font-size: 1.5rem;
101
139
  }
102
140
  .taxonomy-tree .tree-view_arrow {
103
- display: none;
141
+ display: none;
104
142
  }
105
143
  .taxonomy-tree .tree-view_children {
106
- margin-left: 2rem;
144
+ margin-left: 2rem;
107
145
  }
108
146
  }
109
- .smartweb_herobanner{
110
- .section-slide{
147
+ .smartweb_herobanner {
148
+ .section-slide {
111
149
  height: 100%;
112
- .swiper-banner-image{
150
+ .swiper-banner-image {
113
151
  height: 100%;
114
152
  }
115
153
  }
116
154
  }
117
- #portal-globalnav-collapse .nav_index_html, #subsite-navigation .nav_index_html {
118
- display: none;
155
+ #portal-globalnav-collapse .nav_index_html,
156
+ #subsite-navigation .nav_index_html {
157
+ display: none;
119
158
  }
120
159
 
121
- .block-menu-element, .list-menu-element {
160
+ .block-menu-element,
161
+ .list-menu-element {
122
162
  list-style: none;
123
- }
163
+ }
164
+
165
+ .contact_informations_social {
166
+ display: flex;
167
+ flex-wrap: wrap;
168
+ gap: 8px;
169
+ .website {
170
+ width: 100%;
171
+ }
172
+ }
@@ -15,6 +15,7 @@
15
15
  template="view.pt"
16
16
  class=".views.PagesView"
17
17
  permission="zope2.View"
18
+ allowed_attributes="get_page_contacts"
18
19
  layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
19
20
  />
20
21
 
@@ -1,9 +1,11 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from Acquisition import aq_inner
4
+ from imio.smartweb.core.config import DIRECTORY_URL
4
5
  from imio.smartweb.core.utils import get_scale_url
5
6
  from imio.smartweb.core.interfaces import IHtmxViewUtils
6
7
  from imio.smartweb.core.interfaces import IViewWithoutLeadImage
8
+ from imio.smartweb.core.utils import get_json
7
9
  from imio.smartweb.locales import SmartwebMessageFactory as _
8
10
  from Products.CMFPlone.resources import add_bundle_on_request
9
11
  from plone import api
@@ -11,11 +13,14 @@ from plone.app.content.browser.contents.rearrange import OrderContentsBaseAction
11
13
  from plone.app.content.utils import json_loads
12
14
  from plone.app.contenttypes.browser.folder import FolderView
13
15
  from plone.app.contenttypes.browser.full_view import FullViewItem as BaseFullViewItem
16
+ from plone.memoize.view import memoize
14
17
  from Products.CMFPlone import utils
15
18
  from Products.CMFPlone.browser.navigation import PhysicalNavigationBreadcrumbs
16
19
  from zope.component import getMultiAdapter
17
20
  from zope.interface import implementer
18
21
 
22
+ import itertools
23
+
19
24
 
20
25
  @implementer(IViewWithoutLeadImage)
21
26
  @implementer(IHtmxViewUtils)
@@ -46,6 +51,45 @@ class PagesView(FolderView):
46
51
  add_bundle_on_request(self.request, "flexbin")
47
52
  return self.index()
48
53
 
54
+ @memoize
55
+ def get_page_contacts(self):
56
+ # TODO We need to check every tests to be sure to avoid caching that
57
+ # creates false positive assertions
58
+ sections_contacts = self.context.listFolderContents(
59
+ contentFilter={
60
+ "portal_type": [
61
+ "imio.smartweb.SectionContact",
62
+ ]
63
+ }
64
+ )
65
+ if len(sections_contacts) == 0:
66
+ return None
67
+ nested_contact_list = [
68
+ section_contacts.related_contacts
69
+ for section_contacts in sections_contacts
70
+ if section_contacts.related_contacts is not None
71
+ ]
72
+ if nested_contact_list == []:
73
+ return None
74
+ # Make a "set" to simplifying request in url (avoid duplicate uid)
75
+ # Sometimes we have duplicate uid because some pages were build with contact attributes
76
+ # in a section and for layout issues,for the same contact, others attributes are in another section.
77
+ page_contacts = list(
78
+ set(list(itertools.chain.from_iterable(nested_contact_list)))
79
+ )
80
+ uids = "&UID=".join(page_contacts)
81
+ bsize = len(page_contacts)
82
+ url = "{}/@search?UID={}&fullobjects=1&b_size={}".format(
83
+ DIRECTORY_URL, uids, bsize
84
+ )
85
+ current_lang = api.portal.get_current_language()[:2]
86
+ if current_lang != "fr":
87
+ url = f"{url}&translated_in_{current_lang}=1"
88
+ json_data = get_json(url)
89
+ if json_data is None or len(json_data.get("items", [])) == 0:
90
+ return
91
+ return json_data
92
+
49
93
  def results(self, **kwargs):
50
94
  """
51
95
  Gets results for folder listings without taking care of friendly_types
@@ -61,7 +61,8 @@
61
61
  i18n:translate="">Contact</h3>
62
62
 
63
63
  <span tal:replace="python:contact.vat_number"></span>
64
- <ul tal:define="phones python:contact.phones;
64
+ <ul class="contact_informations_genral"
65
+ tal:define="phones python:contact.phones;
65
66
  mails python:contact.mails;
66
67
  urls python:contact.urls">
67
68
  <li class="phones"
@@ -78,13 +79,37 @@
78
79
  <a tal:attributes="href python:'mailto:{}'.format(mail.get('mail_address'))"
79
80
  tal:content="python:'{}'.format(mail.get('mail_address'))" />
80
81
  </li>
82
+ </ul>
83
+ <ul class="contact_informations_social"
84
+ tal:define="urls python:contact.urls">
81
85
  <li class="urls"
82
86
  tal:repeat="url urls"
83
87
  tal:attributes="class python:url.get('type') or ''">
84
88
  <a tal:attributes="href python:url.get('url');
85
89
  title python:contact.get_translated_url_type(url.get('type'))"
86
- tal:content="python:url.get('url')"
87
- target="_blank" />
90
+ target="_blank">
91
+ <tal:condition tal:condition="python:url.get('type') == 'facebook'">
92
+ <i class="bi bi-facebook"></i>
93
+ </tal:condition>
94
+ <tal:condition tal:condition="python:url.get('type') == 'twitter'">
95
+ <i class="bi bi-twitter"></i>
96
+ </tal:condition>
97
+ <tal:condition tal:condition="python:url.get('type') == 'instagram'">
98
+ <i class="bi bi-instagram"></i>
99
+ </tal:condition>
100
+ <tal:condition tal:condition="python:url.get('type') == 'youtube'">
101
+ <i class="bi bi-youtube"></i>
102
+ </tal:condition>
103
+ <tal:condition tal:condition="python:url.get('type') == 'pinterest'">
104
+ <i class="bi bi-pinterest"></i>
105
+ </tal:condition>
106
+ <tal:condition tal:condition="python:url.get('type') == 'linkedin'">
107
+ <i class="bi bi-linkedin"></i>
108
+ </tal:condition>
109
+
110
+ <span tal:attributes="class python:'sr-only' if url.get('type') != 'website' else ''"
111
+ tal:content="python:url.get('url')"/>
112
+ </a>
88
113
  </li>
89
114
  </ul>
90
115
  </div>
@@ -4,30 +4,46 @@ from imio.smartweb.core.config import DIRECTORY_URL
4
4
  from imio.smartweb.core.contents.sections.contact.utils import ContactProperties
5
5
  from imio.smartweb.core.contents.sections.views import HashableJsonSectionView
6
6
  from imio.smartweb.core.utils import batch_results
7
- from imio.smartweb.core.utils import get_json
8
7
  from plone import api
8
+ from zope.component import queryMultiAdapter
9
9
 
10
10
 
11
11
  class ContactView(HashableJsonSectionView):
12
12
  """Contact Section view"""
13
13
 
14
14
  def contacts(self):
15
- if self.context.related_contacts is None:
16
- return
17
- related_contacts = self.context.related_contacts
18
- uids = "&UID=".join(related_contacts)
15
+ # Firstly, try to get contact from the container view
16
+ container_view = queryMultiAdapter(
17
+ (self.context.aq_parent, self.request), name="full_view"
18
+ )
19
+ self.json_data = container_view.get_page_contacts()
20
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0:
21
+ return []
22
+
23
+ container_contacts = self.json_data.get("items")
24
+ results_items = [
25
+ contact
26
+ for contact in container_contacts
27
+ if contact["UID"] in self.context.related_contacts
28
+ ]
29
+ index_map = {
30
+ value: index for index, value in enumerate(self.context.related_contacts)
31
+ }
32
+ results_items = sorted(results_items, key=lambda x: index_map[x["UID"]])
33
+
34
+ # construct JSON data as before WEBBDC-1265 to avoid hash differences
35
+ uids = "&UID=".join(self.context.related_contacts)
19
36
  url = "{}/@search?UID={}&fullobjects=1".format(DIRECTORY_URL, uids)
20
37
  current_lang = api.portal.get_current_language()[:2]
21
38
  if current_lang != "fr":
22
39
  url = f"{url}&translated_in_{current_lang}=1"
23
- self.json_data = get_json(url)
40
+ self.json_data = {
41
+ "@id": url,
42
+ "items": results_items,
43
+ "items_total": len(results_items),
44
+ }
24
45
  self.refresh_modification_date()
25
- if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
26
- return
27
- results = self.json_data.get("items")
28
- index_map = {value: index for index, value in enumerate(related_contacts)}
29
- results = sorted(results, key=lambda x: index_map[x["UID"]])
30
- return batch_results(results, self.context.nb_contact_by_line)
46
+ return batch_results(results_items, self.context.nb_contact_by_line)
31
47
 
32
48
  def get_contact_properties(self, json_dict):
33
49
  return ContactProperties(json_dict, self.context)
@@ -51,7 +51,7 @@ class EventsView(CarouselOrTableSectionView, HashableJsonSectionView):
51
51
  url = "{}/@events?{}".format(EVENTS_URL, "&".join(params))
52
52
  self.json_data = get_json(url)
53
53
  self.refresh_modification_date()
54
- if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
54
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0:
55
55
  return []
56
56
  linking_view_url = self.context.linking_rest_view.to_object.absolute_url()
57
57
  image_scale = self.image_scale
@@ -47,7 +47,7 @@ class NewsView(CarouselOrTableSectionView, HashableJsonSectionView):
47
47
  url = "{}/@search?{}".format(NEWS_URL, "&".join(params))
48
48
  self.json_data = get_json(url)
49
49
  self.refresh_modification_date()
50
- if self.json_data is None or len(self.json_data.get("items", [])) == 0: # NOQA
50
+ if self.json_data is None or len(self.json_data.get("items", [])) == 0:
51
51
  return []
52
52
  linking_view_url = self.context.linking_rest_view.to_object.absolute_url()
53
53
  image_scale = self.image_scale
@@ -8,6 +8,7 @@ from imio.smartweb.common.contact_utils import formatted_schedule
8
8
  from imio.smartweb.common.contact_utils import get_schedule_for_today
9
9
  from imio.smartweb.core.contents.sections.contact.utils import ContactProperties
10
10
  from imio.smartweb.core.contents.sections.views import SECTION_ITEMS_HASH_KEY
11
+ from imio.smartweb.core.tests.utils import clear_cache
11
12
  from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_FUNCTIONAL_TESTING
12
13
  from imio.smartweb.core.testing import ImioSmartwebTestCase
13
14
  from imio.smartweb.core.tests.utils import get_json
@@ -57,7 +58,8 @@ class TestSectionContact(ImioSmartwebTestCase):
57
58
  view = queryMultiAdapter((self.page, self.request), name="full_view")
58
59
  self.assertIn("My contact", view())
59
60
  contact_view = queryMultiAdapter((contact, self.request), name="view")
60
- self.assertIsNone(contact_view.contacts())
61
+ self.assertEqual(contact_view.contacts(), [])
62
+
61
63
  authentic_contact_uid = "2dc381f0fb584381b8e4a19c84f53b35"
62
64
  contact.related_contacts = [authentic_contact_uid]
63
65
  contact_search_url = (
@@ -69,12 +71,13 @@ class TestSectionContact(ImioSmartwebTestCase):
69
71
  authentic_contact_uid
70
72
  )
71
73
  m.get(contact_search_url, exc=requests.exceptions.ConnectTimeout)
72
- self.assertIsNone(contact_view.contacts())
74
+ self.assertEqual(contact_view.contacts(), [])
73
75
  m.get(contact_search_url, status_code=404)
74
- self.assertIsNone(contact_view.contacts())
76
+ self.assertEqual(contact_view.contacts(), [])
75
77
  m.get(contact_search_url, text=json.dumps(self.json_no_contact))
76
- self.assertIsNone(contact_view.contacts())
78
+ self.assertEqual(contact_view.contacts(), [])
77
79
  m.get(contact_search_url, text=json.dumps(self.json_contact))
80
+ clear_cache(self.request)
78
81
  self.assertIsNotNone(contact_view.contacts())
79
82
  json_contact = ContactProperties(self.json_contact.get("items")[0], contact)
80
83
  self.assertEqual(json_contact.contact_type_class, "contact-type-organization")
@@ -137,6 +140,18 @@ class TestSectionContact(ImioSmartwebTestCase):
137
140
  images = json_contact.images(contact.image_scale, contact.nb_results_by_batch)
138
141
  self.assertIsNone(images)
139
142
 
143
+ @requests_mock.Mocker()
144
+ def test_sorted_contacts_are_empty(self, m):
145
+ # TODO Separate test test_sorted_contacts_is_none /
146
+ # test_sorted_contacts 'cause of Memoize ??!!
147
+ contact = api.content.create(
148
+ container=self.page,
149
+ type="imio.smartweb.SectionContact",
150
+ title="My contact",
151
+ )
152
+ contact_view = queryMultiAdapter((contact, self.request), name="view")
153
+ self.assertEqual(contact_view.contacts(), [])
154
+
140
155
  @requests_mock.Mocker()
141
156
  def test_sorted_contacts(self, m):
142
157
  contact = api.content.create(
@@ -145,7 +160,6 @@ class TestSectionContact(ImioSmartwebTestCase):
145
160
  title="My contact",
146
161
  )
147
162
  contact_view = queryMultiAdapter((contact, self.request), name="view")
148
- self.assertIsNone(contact_view.contacts())
149
163
  authentic_contact_uid = [
150
164
  "2dc381f0fb584381b8e4a19c84f53b35",
151
165
  "af7bd1f547034b24a2e0da16c0ba0358",
@@ -508,7 +522,9 @@ class TestSectionContact(ImioSmartwebTestCase):
508
522
  "afternoonend": "",
509
523
  "comments": "",
510
524
  }
525
+ clear_cache(self.request)
511
526
  m.get(contact_search_url, text=json.dumps(json_contact_empty_schedule))
527
+ view = queryMultiAdapter((self.page, self.request), name="full_view")
512
528
  json_contact = ContactProperties(
513
529
  json_contact_empty_schedule.get("items")[0], contact
514
530
  )
@@ -556,7 +572,6 @@ class TestSectionContact(ImioSmartwebTestCase):
556
572
 
557
573
  annotations = IAnnotations(contact)
558
574
  self.assertIsNone(annotations.get(SECTION_ITEMS_HASH_KEY))
559
-
560
575
  self.assertIsNotNone(contact_view.contacts())
561
576
  hash_1 = annotations.get(SECTION_ITEMS_HASH_KEY)
562
577
  self.assertIsNotNone(hash_1)
@@ -564,15 +579,25 @@ class TestSectionContact(ImioSmartwebTestCase):
564
579
 
565
580
  sleep(1)
566
581
  m.get(contact_search_url, text=json.dumps(self.json_no_contact))
567
- self.assertIsNone(contact_view.contacts())
582
+ clear_cache(self.request)
583
+ contact_view = queryMultiAdapter((contact, self.request), name="view")
584
+ self.assertEqual(contact_view.contacts(), [])
585
+ # refresh_modification_date doesn't calculate when json_data is None
586
+ # For this section, this is the case
587
+ # For other sections, we get json_data with empty "items"
588
+ # Refactoring needed to ensure clarity ?
568
589
  next_modification = self.page.ModificationDate()
569
590
  hash_2 = annotations.get(SECTION_ITEMS_HASH_KEY)
570
- self.assertNotEqual(hash_1, hash_2)
571
- self.assertNotEqual(first_modification, next_modification)
591
+ self.assertEqual(hash_1, hash_2)
592
+ self.assertEqual(first_modification, next_modification)
572
593
 
573
594
  sleep(1)
574
- self.assertIsNone(contact_view.contacts())
595
+ contact_view = queryMultiAdapter((contact, self.request), name="view")
596
+ self.assertEqual(contact_view.contacts(), [])
575
597
  last_modification = self.page.ModificationDate()
576
598
  hash_3 = annotations.get(SECTION_ITEMS_HASH_KEY)
577
599
  self.assertEqual(hash_2, hash_3)
578
600
  self.assertEqual(next_modification, last_modification)
601
+
602
+ # TODO we should test with various contact sections containing
603
+ # contacts