imio.smartweb.core 1.2.11__py3-none-any.whl → 1.2.19__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 (99) hide show
  1. imio/smartweb/core/browser/configure.zcml +1 -1
  2. imio/smartweb/core/browser/dashboards/configure.zcml +0 -2
  3. imio/smartweb/core/browser/dashboards/plausible.py +4 -4
  4. imio/smartweb/core/browser/static/smartweb-edit-compiled.js +1 -1
  5. imio/smartweb/core/browser/static/src/edit.js +5 -0
  6. imio/smartweb/core/browser/utils.py +4 -30
  7. imio/smartweb/core/contents/__init__.py +2 -0
  8. imio/smartweb/core/contents/rest/base.py +12 -0
  9. imio/smartweb/core/contents/rest/configure.zcml +7 -0
  10. imio/smartweb/core/contents/rest/directory/content.py +2 -2
  11. imio/smartweb/core/contents/rest/directory/view.pt +2 -1
  12. imio/smartweb/core/contents/rest/directory/view.py +3 -0
  13. imio/smartweb/core/contents/rest/events/content.py +2 -2
  14. imio/smartweb/core/contents/rest/events/view.pt +2 -1
  15. imio/smartweb/core/contents/rest/events/view.py +3 -0
  16. imio/smartweb/core/contents/rest/news/content.py +2 -2
  17. imio/smartweb/core/contents/rest/news/view.pt +2 -1
  18. imio/smartweb/core/contents/rest/news/view.py +3 -0
  19. imio/smartweb/core/contents/rest/search/endpoint.py +1 -1
  20. imio/smartweb/core/contents/rest/traversal.py +18 -0
  21. imio/smartweb/core/contents/rest/view.py +7 -0
  22. imio/smartweb/core/contents/sections/events/view.py +1 -1
  23. imio/smartweb/core/contents/sections/news/view.py +1 -1
  24. imio/smartweb/core/interfaces.py +4 -0
  25. imio/smartweb/core/profiles/default/actions.xml +15 -0
  26. imio/smartweb/core/profiles/default/metadata.xml +1 -1
  27. imio/smartweb/core/rest/authentic_sources.py +47 -10
  28. imio/smartweb/core/rest/configure.zcml +54 -0
  29. imio/smartweb/core/tests/test_rest.py +120 -0
  30. imio/smartweb/core/tests/utils.py +15 -0
  31. imio/smartweb/core/upgrades/configure.zcml +18 -0
  32. imio/smartweb/core/upgrades/profiles/1051_to_1052/actions.xml +20 -0
  33. imio/smartweb/core/utils.py +31 -0
  34. imio/smartweb/core/viewlets/configure.zcml +11 -0
  35. imio/smartweb/core/viewlets/httpheaders.py +13 -0
  36. imio/smartweb/core/viewlets/ogp_tag_header.pt +10 -0
  37. imio/smartweb/core/viewlets/ogptags.py +8 -0
  38. imio/smartweb/core/webcomponents/build/css/54.smartweb-webcomponents-compiled.css +1 -0
  39. imio/smartweb/core/webcomponents/build/css/647.smartweb-webcomponents-compiled.css +1 -0
  40. imio/smartweb/core/webcomponents/build/js/3.smartweb-webcomponents-compiled.js +2 -0
  41. imio/smartweb/core/webcomponents/build/js/323.smartweb-webcomponents-compiled.js +1 -1
  42. imio/smartweb/core/webcomponents/build/js/363.smartweb-webcomponents-compiled.js +2 -0
  43. imio/smartweb/core/webcomponents/build/js/493.smartweb-webcomponents-compiled.js +1 -0
  44. imio/smartweb/core/webcomponents/build/js/54.smartweb-webcomponents-compiled.js +1 -0
  45. imio/smartweb/core/webcomponents/build/js/647.smartweb-webcomponents-compiled.js +2 -0
  46. imio/smartweb/core/webcomponents/build/js/647.smartweb-webcomponents-compiled.js.LICENSE.txt +1 -0
  47. imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
  48. imio/smartweb/core/webcomponents/package.json +14 -17
  49. imio/smartweb/core/webcomponents/src/assets/contentIcon/download.svg +1 -0
  50. imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.jsx +85 -84
  51. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactCard/ContactCard.jsx +22 -23
  52. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactContent/ContactContent.jsx +109 -93
  53. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactContent/download.svg +1 -0
  54. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactList/ContactList.jsx +7 -7
  55. imio/smartweb/core/webcomponents/src/components/Events/EventCard/EventCard.jsx +43 -0
  56. imio/smartweb/core/webcomponents/src/components/Events/{ContactContent/ContactContent.jsx → EventContent/EventContent.jsx} +76 -81
  57. imio/smartweb/core/webcomponents/src/components/Events/{ContactList/ContactList.jsx → EventList/EventList.jsx} +9 -9
  58. imio/smartweb/core/webcomponents/src/components/Events/Events.jsx +99 -98
  59. imio/smartweb/core/webcomponents/src/components/Events/Events.scss +1 -1
  60. imio/smartweb/core/webcomponents/src/components/News/News.jsx +23 -25
  61. imio/smartweb/core/webcomponents/src/components/News/News.scss +3 -5
  62. imio/smartweb/core/webcomponents/src/components/News/{ContactCard/ContactCard.jsx → NewsCard/NewsCard.jsx} +14 -27
  63. imio/smartweb/core/webcomponents/src/components/News/{ContactContent/ContactContent.jsx → NewsContent/NewsContent.jsx} +37 -40
  64. imio/smartweb/core/webcomponents/src/components/News/{ContactList/ContactList.jsx → NewsList/NewsList.jsx} +9 -9
  65. imio/smartweb/core/webcomponents/src/components/Search/ContactResult/ContactResult.jsx +5 -5
  66. imio/smartweb/core/webcomponents/src/components/Search/EventsResult/EventsResult.jsx +5 -5
  67. imio/smartweb/core/webcomponents/src/components/Search/NewsResult/NewsResult.jsx +5 -5
  68. imio/smartweb/core/webcomponents/src/components/Search/WebResult/WebResult.jsx +3 -3
  69. imio/smartweb/core/webcomponents/src/{components/Events/ContactMap/ContactMap.jsx → utils/Map.jsx} +60 -64
  70. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/METADATA +72 -1
  71. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/RECORD +81 -83
  72. imio/smartweb/core/webcomponents/build/css/267.smartweb-webcomponents-compiled.css +0 -1
  73. imio/smartweb/core/webcomponents/build/css/779.smartweb-webcomponents-compiled.css +0 -1
  74. imio/smartweb/core/webcomponents/build/js/267.smartweb-webcomponents-compiled.js +0 -1
  75. imio/smartweb/core/webcomponents/build/js/552.smartweb-webcomponents-compiled.js +0 -2
  76. imio/smartweb/core/webcomponents/build/js/565.smartweb-webcomponents-compiled.js +0 -1
  77. imio/smartweb/core/webcomponents/build/js/612.smartweb-webcomponents-compiled.js +0 -2
  78. imio/smartweb/core/webcomponents/build/js/779.smartweb-webcomponents-compiled.js +0 -1
  79. imio/smartweb/core/webcomponents/pnpm-lock.yaml +0 -7066
  80. imio/smartweb/core/webcomponents/src/components/Annuaire/ContactMap/ContactMap.jsx +0 -156
  81. imio/smartweb/core/webcomponents/src/components/Annuaire/Skeleton/LoaderCss.jsx +0 -7
  82. imio/smartweb/core/webcomponents/src/components/Annuaire/Skeleton/Skeleton.jsx +0 -20
  83. imio/smartweb/core/webcomponents/src/components/Events/ContactCard/ContactCard.jsx +0 -49
  84. imio/smartweb/core/webcomponents/src/components/Events/ContactMap/ContactMap.scss +0 -0
  85. imio/smartweb/core/webcomponents/src/components/Events/Skeleton/Skeleton.jsx +0 -20
  86. imio/smartweb/core/webcomponents/src/components/News/ContactMap/ContactMap.jsx +0 -127
  87. imio/smartweb/core/webcomponents/src/components/News/ContactMap/ContactMap.scss +0 -4
  88. imio/smartweb/core/webcomponents/src/components/News/Skeleton/Skeleton.jsx +0 -20
  89. imio/smartweb/core/webcomponents/src/components/Search/Skeleton/Skeleton.jsx +0 -20
  90. /imio/smartweb/core/webcomponents/build/css/{552.smartweb-webcomponents-compiled.css → 363.smartweb-webcomponents-compiled.css} +0 -0
  91. /imio/smartweb/core/webcomponents/build/js/{552.smartweb-webcomponents-compiled.js.LICENSE.txt → 3.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  92. /imio/smartweb/core/webcomponents/build/js/{612.smartweb-webcomponents-compiled.js.LICENSE.txt → 363.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
  93. /imio/smartweb/core/webcomponents/src/{components/Annuaire/ContactMap/ContactMap.scss → utils/Map.scss} +0 -0
  94. /imio.smartweb.core-1.2.11-py3.10-nspkg.pth → /imio.smartweb.core-1.2.19-py3.10-nspkg.pth +0 -0
  95. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/LICENSE.GPL +0 -0
  96. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/LICENSE.rst +0 -0
  97. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/WHEEL +0 -0
  98. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/namespace_packages.txt +0 -0
  99. {imio.smartweb.core-1.2.11.dist-info → imio.smartweb.core-1.2.19.dist-info}/top_level.txt +0 -0
@@ -57,7 +57,7 @@
57
57
  for="*"
58
58
  class=".utils.UtilsView"
59
59
  permission="zope2.View"
60
- allowed_attributes="is_previewable_content map_configuration"
60
+ allowed_attributes="is_previewable_content map_configuration is_plausible_set"
61
61
  layer="imio.smartweb.core.interfaces.IImioSmartwebCoreLayer"
62
62
  />
63
63
 
@@ -5,9 +5,7 @@
5
5
  <include package="plone.app.contentmenu" />
6
6
  <browser:page
7
7
  name="stats"
8
- title="Plausible dashboard"
9
8
  template="plausible.pt"
10
- menu="plone_displayviews"
11
9
  for="plone.base.interfaces.siteroot.IPloneSiteRoot"
12
10
  class=".plausible.PlausibleView"
13
11
  permission="cmf.ModifyPortalContent"
@@ -1,18 +1,18 @@
1
1
  from Products.Five.browser import BrowserView
2
- from imio.smartweb.core.browser.utils import get_plausible_vars
2
+ from imio.smartweb.core.utils import get_plausible_vars
3
3
 
4
4
 
5
5
  class PlausibleView(BrowserView):
6
6
  @property
7
7
  def is_plausible_set(self):
8
- return True if get_plausible_vars(self) else False
8
+ return True if get_plausible_vars() else False
9
9
 
10
10
  @property
11
11
  def get_embedhostjs_src(self):
12
- vars = get_plausible_vars(self)
12
+ vars = get_plausible_vars()
13
13
  return f"https://{vars['plausible_url']}/js/embed.host.js"
14
14
 
15
15
  @property
16
16
  def get_iframe_src(self):
17
- vars = get_plausible_vars(self)
17
+ vars = get_plausible_vars()
18
18
  return f"https://{vars['plausible_url']}/share/{vars['plausible_site']}?auth={vars['plausible_token']}&embed=true&theme=light&background=transparent"
@@ -1 +1 @@
1
- (()=>{"use strict";jQuery(document).ready((function(e){e("#contentview-preview a").click((function(o){e(".hide-in-preview, #section-byline, #global_statusmessage").toggle("fast"),o.preventDefault()})),e("#formfield-form-widgets-svg_icon input").click((function(o){var s=e(this);e(this).attr("checked")?(e(this).prop("checked",!1),e(this).removeAttr("checked"),e(this).css("box-shadow","none"),e(this).css("border-color","#DEE2ED")):e("#formfield-form-widgets-svg_icon input").each((function(o,t){s[0]===t?(e(this).prop("checked",!0),e(this).attr("checked","checked"),e(this).css("border-color","#007a99"),e(this).css("box-shadow","0 0 0 0.25rem rgb(0 122 153 / 25%)")):(e(this).prop("checked",!1),e(this).removeAttr("checked"),e(this).css("box-shadow","none"),e(this).css("border-color","#DEE2ED"))}))}))})),jQuery(window).on("load",(function(e){var o=$("#plone-authentic-sources-menu").wrap("<ul class='plonetoolbar-authentic-sources-menu'>").parent();$(".personaltools-wrapper").prepend(o);var s=$("#plone-smartweb-help-menu").wrap("<ul class='plonetoolbar-smartweb-help-menu'>").parent();$(".personaltools-wrapper").prepend(s)}))})();
1
+ (()=>{"use strict";jQuery(document).ready((function(e){e("#contentview-preview a").click((function(o){e(".hide-in-preview, #section-byline, #global_statusmessage").toggle("fast"),o.preventDefault()})),e("#formfield-form-widgets-svg_icon input").click((function(o){var s=e(this);e(this).attr("checked")?(e(this).prop("checked",!1),e(this).removeAttr("checked"),e(this).css("box-shadow","none"),e(this).css("border-color","#DEE2ED")):e("#formfield-form-widgets-svg_icon input").each((function(o,t){s[0]===t?(e(this).prop("checked",!0),e(this).attr("checked","checked"),e(this).css("border-color","#007a99"),e(this).css("box-shadow","0 0 0 0.25rem rgb(0 122 153 / 25%)")):(e(this).prop("checked",!1),e(this).removeAttr("checked"),e(this).css("box-shadow","none"),e(this).css("border-color","#DEE2ED"))}))}));var o=e("li:has(a[href*='@@stats'])");e("#collapse-personaltools li:eq(0)").after(o)})),jQuery(window).on("load",(function(e){var o=$("#plone-authentic-sources-menu").wrap("<ul class='plonetoolbar-authentic-sources-menu'>").parent();$(".personaltools-wrapper").prepend(o);var s=$("#plone-smartweb-help-menu").wrap("<ul class='plonetoolbar-smartweb-help-menu'>").parent();$(".personaltools-wrapper").prepend(s)}))})();
@@ -32,6 +32,11 @@ jQuery(document).ready(function ($) {
32
32
  })
33
33
  }
34
34
  });
35
+
36
+ // Move statistics action menu entry as the first element in personaltools menu
37
+ var $stat_link = $("li:has(a[href*='@@stats'])");
38
+ $("#collapse-personaltools li:eq(0)").after($stat_link);
39
+
35
40
  });
36
41
 
37
42
  jQuery(window).on("load", function(e) {
@@ -2,6 +2,7 @@
2
2
  from Products.Five.browser import BrowserView
3
3
  from imio.smartweb.core.contents import IPages
4
4
  from imio.smartweb.core.contents.pages.procedure.utils import sign_url
5
+ from imio.smartweb.core.utils import get_plausible_vars
5
6
  from imio.smartweb.locales import SmartwebMessageFactory as _
6
7
  from plone import api
7
8
  from plone.api.portal import get_registry_record
@@ -75,33 +76,6 @@ class UtilsView(BrowserView):
75
76
  }
76
77
  )
77
78
 
78
-
79
- def get_plausible_vars(self):
80
- env_plausible_url = os.getenv("SMARTWEB_PLAUSIBLE_URL", "")
81
- env_plausible_site = os.getenv("SMARTWEB_PLAUSIBLE_SITE", "")
82
- env_plausible_token = os.getenv("SMARTWEB_PLAUSIBLE_TOKEN", "")
83
-
84
- plausible_url = (
85
- env_plausible_url
86
- if (env_plausible_url and env_plausible_url != "")
87
- else api.portal.get_registry_record("smartweb.plausible_url")
88
- )
89
- plausible_site = (
90
- env_plausible_site
91
- if (env_plausible_site and env_plausible_site != "")
92
- else api.portal.get_registry_record("smartweb.plausible_site")
93
- )
94
- plausible_token = (
95
- env_plausible_token
96
- if (env_plausible_token and env_plausible_token != "")
97
- else api.portal.get_registry_record("smartweb.plausible_token")
98
- )
99
- if all([plausible_site, plausible_url, plausible_token]):
100
- plausible_vars = {
101
- "plausible_url": plausible_url,
102
- "plausible_site": plausible_site,
103
- "plausible_token": plausible_token,
104
- }
105
- return plausible_vars
106
- else:
107
- return None
79
+ def is_plausible_set(self):
80
+ """ """
81
+ return True if get_plausible_vars() else False
@@ -17,6 +17,8 @@ from .pages.portal_page.content import IPortalPage # NOQA
17
17
  from .pages.portal_page.content import PortalPage # NOQA
18
18
  from .pages.procedure.content import IProcedure # NOQA
19
19
  from .pages.procedure.content import Procedure # NOQA
20
+ from .rest.base import RestView # NOQA
21
+ from .rest.base import IRestView # NOQA
20
22
  from .rest.directory.content import DirectoryView # NOQA
21
23
  from .rest.directory.content import IDirectoryView # NOQA
22
24
  from .rest.events.content import EventsView # NOQA
@@ -2,7 +2,10 @@
2
2
 
3
3
  from imio.smartweb.core.utils import get_json
4
4
  from plone import api
5
+ from plone.dexterity.content import Container
5
6
  from plone.rest import Service
7
+ from zope.interface import implementer
8
+ from zope.interface import Interface
6
9
 
7
10
  import json
8
11
 
@@ -71,3 +74,12 @@ class BaseService(Service):
71
74
  indent=2,
72
75
  separators=(", ", ": "),
73
76
  )
77
+
78
+
79
+ class IRestView(Interface):
80
+ """"""
81
+
82
+
83
+ @implementer(IRestView)
84
+ class RestView(Container):
85
+ """Shared base class for REST views contents"""
@@ -6,4 +6,11 @@
6
6
  <include package=".news" />
7
7
  <include package=".search" />
8
8
 
9
+ <adapter
10
+ for="imio.smartweb.core.contents.IRestView
11
+ zope.publisher.interfaces.http.IHTTPRequest"
12
+ provides="zope.publisher.interfaces.IPublishTraverse"
13
+ factory=".traversal.RestViewTraversable"
14
+ />
15
+
9
16
  </configure>
@@ -1,9 +1,9 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from imio.smartweb.core.contents import RestView
3
4
  from imio.smartweb.locales import SmartwebMessageFactory as _
4
5
  from plone.app.z3cform.widget import SelectFieldWidget
5
6
  from plone.autoform import directives
6
- from plone.dexterity.content import Container
7
7
  from plone.supermodel import model
8
8
  from zope import schema
9
9
  from zope.interface import implementer
@@ -34,5 +34,5 @@ class IDirectoryView(model.Schema):
34
34
 
35
35
 
36
36
  @implementer(IDirectoryView)
37
- class DirectoryView(Container):
37
+ class DirectoryView(RestView):
38
38
  """DirectoryView class"""
@@ -10,7 +10,8 @@
10
10
  propose-url view/propose_url;
11
11
  orientation view/orientation;
12
12
  current-language view/current_language;
13
- display-map view/display_map;"></smartweb-annuaire>
13
+ display-map view/display_map;
14
+ view-path view/view_path;"></smartweb-annuaire>
14
15
  </div>
15
16
  </metal:main>
16
17
  </body>
@@ -1,9 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from imio.smartweb.core.contents.rest.view import BaseRestView
4
+ from imio.smartweb.core.interfaces import IOgpViewUtils
4
5
  from plone import api
6
+ from zope.interface import implementer
5
7
 
6
8
 
9
+ @implementer(IOgpViewUtils)
7
10
  class DirectoryViewView(BaseRestView):
8
11
  """DirectoryView view"""
9
12
 
@@ -1,8 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from imio.smartweb.core.contents import RestView
3
4
  from imio.smartweb.locales import SmartwebMessageFactory as _
4
5
  from plone.autoform import directives
5
- from plone.dexterity.content import Container
6
6
  from plone.supermodel import model
7
7
  from z3c.form.browser.checkbox import CheckBoxFieldWidget
8
8
  from zope import schema
@@ -39,5 +39,5 @@ class IEventsView(model.Schema):
39
39
 
40
40
 
41
41
  @implementer(IEventsView)
42
- class EventsView(Container):
42
+ class EventsView(RestView):
43
43
  """EventsView class"""
@@ -11,7 +11,8 @@
11
11
  propose-url view/propose_url;
12
12
  orientation view/orientation;
13
13
  current-language view/current_language;
14
- display-map view/display_map;"></smartweb-events>
14
+ display-map view/display_map;
15
+ view-path view/view_path;"></smartweb-events>
15
16
  </div>
16
17
  </metal:main>
17
18
  </body>
@@ -1,9 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from imio.smartweb.core.contents.rest.view import BaseRestView
4
+ from imio.smartweb.core.interfaces import IOgpViewUtils
4
5
  from plone import api
6
+ from zope.interface import implementer
5
7
 
6
8
 
9
+ @implementer(IOgpViewUtils)
7
10
  class EventsViewView(BaseRestView):
8
11
  """EventsView view"""
9
12
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
+ from imio.smartweb.core.contents import RestView
3
4
  from imio.smartweb.locales import SmartwebMessageFactory as _
4
- from plone.dexterity.content import Container
5
5
  from plone.supermodel import model
6
6
  from zope import schema
7
7
  from zope.interface import implementer
@@ -23,5 +23,5 @@ class INewsView(model.Schema):
23
23
 
24
24
 
25
25
  @implementer(INewsView)
26
- class NewsView(Container):
26
+ class NewsView(RestView):
27
27
  """NewsView class"""
@@ -10,7 +10,8 @@
10
10
  batch-size view/batch_size;
11
11
  propose-url view/propose_url;
12
12
  orientation view/orientation;
13
- current-language view/current_language;"></smartweb-news>
13
+ current-language view/current_language;
14
+ view-path view/view_path;"></smartweb-news>
14
15
  </div>
15
16
  </metal:main>
16
17
  </body>
@@ -1,9 +1,12 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  from imio.smartweb.core.contents.rest.view import BaseRestView
4
+ from imio.smartweb.core.interfaces import IOgpViewUtils
4
5
  from plone import api
6
+ from zope.interface import implementer
5
7
 
6
8
 
9
+ @implementer(IOgpViewUtils)
7
10
  class NewsViewView(BaseRestView):
8
11
  """NewsView view"""
9
12
 
@@ -153,7 +153,7 @@ class ExtendedSearchHandler(SearchHandler):
153
153
  del item[fname]
154
154
  type_mapping = mapping[item["@type"]]
155
155
  base_url = type_mapping.get(item["container_uid"], type_mapping["default"])
156
- item["_url"] = "{base}#/content?u={item_uid}".format(
156
+ item["_url"] = "{base}/content?u={item_uid}".format(
157
157
  base=base_url,
158
158
  item_uid=item["UID"],
159
159
  )
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from imio.smartweb.core.contents import IRestView
4
+ from ZPublisher.BaseRequest import DefaultPublishTraverse
5
+ from zope.component import adapts
6
+ from zope.publisher.interfaces.http import IHTTPRequest
7
+
8
+
9
+ class RestViewTraversable(DefaultPublishTraverse):
10
+ """ """
11
+
12
+ adapts(IRestView, IHTTPRequest)
13
+
14
+ def publishTraverse(self, request, name):
15
+ if "u" in self.request.form and name != "view":
16
+ return self.context
17
+
18
+ return super(RestViewTraversable, self).publishTraverse(request, name)
@@ -3,6 +3,7 @@
3
3
  from imio.smartweb.core.interfaces import IViewWithoutLeadImage
4
4
  from plone import api
5
5
  from Products.Five import BrowserView
6
+ from urllib.parse import urlsplit
6
7
  from zope.interface import implementer
7
8
 
8
9
 
@@ -29,3 +30,9 @@ class BaseRestView(BrowserView):
29
30
  @property
30
31
  def current_language(self):
31
32
  return api.portal.get_current_language()[:2]
33
+
34
+ @property
35
+ def view_path(self):
36
+ url = self.context.absolute_url()
37
+ parsed = urlsplit(url)
38
+ return url.replace(f"{parsed.scheme}://{parsed.netloc}", "")
@@ -68,7 +68,7 @@ class EventsView(CarouselOrTableSectionView, HashableJsonSectionView):
68
68
  "description": item["description"],
69
69
  "category": item["category_title"],
70
70
  "event_date": date_dict,
71
- "url": f"{linking_view_url}#/{item_id}?u={item_uid}",
71
+ "url": f"{linking_view_url}/{item_id}?u={item_uid}",
72
72
  "has_image": item["has_leadimage"],
73
73
  "image": f"{item_url}/@@images/image/{orientation}_{image_scale}?cache_key={modified_hash}",
74
74
  }
@@ -61,7 +61,7 @@ class NewsView(CarouselOrTableSectionView, HashableJsonSectionView):
61
61
  "description": item["description"],
62
62
  "category": item["category_title"],
63
63
  "effective": item["effective"],
64
- "url": f"{linking_view_url}#/{item_id}?u={item_uid}",
64
+ "url": f"{linking_view_url}/{item_id}?u={item_uid}",
65
65
  "has_image": item["has_leadimage"],
66
66
  "image": f"{item_url}/@@images/image/{orientation}_{image_scale}?cache_key={modified_hash}",
67
67
  }
@@ -31,3 +31,7 @@ class IArcgisViewUtils(Interface):
31
31
 
32
32
  def get_portal_item_id():
33
33
  """Return id of a map"""
34
+
35
+
36
+ class IOgpViewUtils(Interface):
37
+ """ """
@@ -88,6 +88,21 @@
88
88
  </object>
89
89
  </object>
90
90
 
91
+ <object meta_type="CMF Action Category" name="user">
92
+ <object meta_type="CMF Action" name="dashboard" i18n:domain="plone" remove="True" />
93
+ <object meta_type="CMF Action" name="statistics" i18n:domain="imio.smartweb">
94
+ <property name="title" i18n:translate="">Statistics</property>
95
+ <property name="description" i18n:translate=""/>
96
+ <property name="url_expr">string:$portal_url/@@stats</property>
97
+ <property name="icon_expr">string:activity</property>
98
+ <property name="available_expr">portal/@@utils/is_plausible_set</property>
99
+ <property name="permissions">
100
+ <element value="Add portal content"/>
101
+ </property>
102
+ <property name="visible">True</property>
103
+ </object>
104
+ </object>
105
+
91
106
  <object name="header_actions" meta_type="CMF Action Category">
92
107
  <object name="account" meta_type="CMF Action" i18n:domain="imio.smartweb">
93
108
  <property name="title" i18n:translate="">My account</property>
@@ -1,6 +1,6 @@
1
1
  <?xml version='1.0' encoding='UTF-8'?>
2
2
  <metadata>
3
- <version>1051</version>
3
+ <version>1052</version>
4
4
  <dependencies>
5
5
  <dependency>profile-plone.app.dexterity:default</dependency>
6
6
  <dependency>profile-plone.app.imagecropping:default</dependency>
@@ -4,11 +4,15 @@ from imio.smartweb.core.config import DIRECTORY_URL
4
4
  from imio.smartweb.core.config import EVENTS_URL
5
5
  from imio.smartweb.core.config import NEWS_URL
6
6
  from imio.smartweb.core.contents.rest.search.endpoint import get_default_view_url
7
+ from imio.smartweb.core.utils import get_wca_token
8
+ from plone.protect.interfaces import IDisableCSRFProtection
7
9
  from plone.restapi.deserializer import json_body
8
10
  from plone.restapi.services import Service
11
+ from zope.interface import alsoProvides
9
12
  from zope.interface import implementer
10
13
  from zope.publisher.interfaces import IPublishTraverse
11
14
 
15
+ import os
12
16
  import requests
13
17
 
14
18
 
@@ -19,6 +23,7 @@ class BaseRequestForwarder(Service):
19
23
  self.traversal_stack = []
20
24
 
21
25
  def reply(self):
26
+ alsoProvides(self.request, IDisableCSRFProtection)
22
27
  url = "/".join(self.traversal_stack)
23
28
  auth_source_url = f"{self.base_url}/{url}"
24
29
  response = self.forward_request(auth_source_url)
@@ -31,46 +36,78 @@ class BaseRequestForwarder(Service):
31
36
 
32
37
  def forward_request(self, url):
33
38
  method = self.request.method
34
- headers = {"Accept": "application/json"}
39
+ token = get_wca_token(self.client_id, self.client_secret)
40
+ headers = {"Accept": "application/json", "Authorization": token}
35
41
  params = self.request.form
42
+ if method == "GET":
43
+ params = self.add_missing_metadatas(params)
36
44
  data = json_body(self.request)
37
45
 
38
46
  # Forward the request to the authentic source
39
47
  auth_source_response = requests.request(
40
- method, url, params=params, headers=headers, data=data
48
+ method, url, params=params, headers=headers, json=data
41
49
  )
42
-
43
50
  response = self.request.response
44
51
  # Set the status code and headers from the authentic source server response
45
52
  response.setStatus(auth_source_response.status_code)
46
53
  for header, value in auth_source_response.headers.items():
47
54
  response.setHeader(header, value)
48
55
 
56
+ if auth_source_response.status_code == 204 or auth_source_response.text == "":
57
+ # Empty response
58
+ return ""
59
+
49
60
  return auth_source_response.json()
50
61
 
62
+ def construct_url(self, view_url, item):
63
+ # we can construct a Smartweb-related URL for item
64
+ # TODO: handle other views & translations (use/refactor code in
65
+ # search endpoint)
66
+ item_uid = item["UID"]
67
+ item_id = item.get("id", "content")
68
+ item["smartweb_url"] = f"{view_url}/{item_id}?u={item_uid}"
69
+
51
70
  def add_smartweb_urls(self, json_data):
71
+ if "items" not in json_data and "@id" not in json_data:
72
+ return json_data
73
+ default_view_url = get_default_view_url(self.request_type)
74
+ if "@id" in json_data and "UID" in json_data:
75
+ self.construct_url(default_view_url, json_data)
76
+ return json_data
52
77
  for item in json_data.get("items", []):
53
78
  if "@id" in item and "UID" in item:
54
- # we can construct a Smartweb-related URL for item
55
- # TODO: handle other views & translations (use/refactor code in
56
- # search endpoint)
57
- # TODO 2: always get UID and ID to construct URL ?
58
- default_view_url = get_default_view_url(self.request_type)
59
- item_uid = item["UID"]
60
- item["smartweb_url"] = f"{default_view_url}/#content?u={item_uid}"
79
+ self.construct_url(default_view_url, item)
61
80
  return json_data
62
81
 
82
+ def add_missing_metadatas(self, params):
83
+ if "fullobjects" in params:
84
+ return params
85
+ if "metadata_fields" not in params:
86
+ params["metadata_fields"] = ["id", "UID"]
87
+ else:
88
+ if "id" not in params["metadata_fields"]:
89
+ params["metadata_fields"].append("id")
90
+ if "UID" not in params["metadata_fields"]:
91
+ params["metadata_fields"].append("UID")
92
+ return params
93
+
63
94
 
64
95
  class DirectoryRequestForwarder(BaseRequestForwarder):
65
96
  request_type = "directory"
97
+ client_id = os.environ.get("RESTAPI_DIRECTORY_CLIENT_ID")
98
+ client_secret = os.environ.get("RESTAPI_DIRECTORY_CLIENT_SECRET")
66
99
  base_url = DIRECTORY_URL
67
100
 
68
101
 
69
102
  class EventsRequestForwarder(BaseRequestForwarder):
70
103
  request_type = "events"
104
+ client_id = os.environ.get("RESTAPI_EVENTS_CLIENT_ID")
105
+ client_secret = os.environ.get("RESTAPI_EVENTS_CLIENT_SECRET")
71
106
  base_url = EVENTS_URL
72
107
 
73
108
 
74
109
  class NewsRequestForwarder(BaseRequestForwarder):
75
110
  request_type = "news"
111
+ client_id = os.environ.get("RESTAPI_NEWS_CLIENT_ID")
112
+ client_secret = os.environ.get("RESTAPI_NEWS_CLIENT_SECRET")
76
113
  base_url = NEWS_URL
@@ -22,6 +22,24 @@
22
22
  name="@directory_request_forwarder"
23
23
  />
24
24
 
25
+ <plone:service
26
+ method="PATCH"
27
+ accept="application/json"
28
+ factory=".authentic_sources.DirectoryRequestForwarder"
29
+ for="*"
30
+ permission="zope2.View"
31
+ name="@directory_request_forwarder"
32
+ />
33
+
34
+ <plone:service
35
+ method="DELETE"
36
+ accept="application/json"
37
+ factory=".authentic_sources.DirectoryRequestForwarder"
38
+ for="*"
39
+ permission="zope2.View"
40
+ name="@directory_request_forwarder"
41
+ />
42
+
25
43
 
26
44
  <!-- Events -->
27
45
  <plone:service
@@ -42,6 +60,24 @@
42
60
  name="@events_request_forwarder"
43
61
  />
44
62
 
63
+ <plone:service
64
+ method="PATCH"
65
+ accept="application/json"
66
+ factory=".authentic_sources.EventsRequestForwarder"
67
+ for="*"
68
+ permission="zope2.View"
69
+ name="@events_request_forwarder"
70
+ />
71
+
72
+ <plone:service
73
+ method="DELETE"
74
+ accept="application/json"
75
+ factory=".authentic_sources.EventsRequestForwarder"
76
+ for="*"
77
+ permission="zope2.View"
78
+ name="@events_request_forwarder"
79
+ />
80
+
45
81
 
46
82
  <!-- News -->
47
83
  <plone:service
@@ -62,4 +98,22 @@
62
98
  name="@news_request_forwarder"
63
99
  />
64
100
 
101
+ <plone:service
102
+ method="PATCH"
103
+ accept="application/json"
104
+ factory=".authentic_sources.NewsRequestForwarder"
105
+ for="*"
106
+ permission="zope2.View"
107
+ name="@news_request_forwarder"
108
+ />
109
+
110
+ <plone:service
111
+ method="DELETE"
112
+ accept="application/json"
113
+ factory=".authentic_sources.NewsRequestForwarder"
114
+ for="*"
115
+ permission="zope2.View"
116
+ name="@news_request_forwarder"
117
+ />
118
+
65
119
  </configure>