imio.smartweb.core 1.2.12__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.
- imio/smartweb/core/browser/configure.zcml +1 -1
- imio/smartweb/core/browser/dashboards/configure.zcml +0 -2
- imio/smartweb/core/browser/dashboards/plausible.py +4 -4
- imio/smartweb/core/browser/static/smartweb-edit-compiled.js +1 -1
- imio/smartweb/core/browser/static/src/edit.js +5 -0
- imio/smartweb/core/browser/utils.py +4 -30
- imio/smartweb/core/contents/__init__.py +2 -0
- imio/smartweb/core/contents/rest/base.py +12 -0
- imio/smartweb/core/contents/rest/configure.zcml +7 -0
- imio/smartweb/core/contents/rest/directory/content.py +2 -2
- imio/smartweb/core/contents/rest/directory/view.pt +2 -1
- imio/smartweb/core/contents/rest/directory/view.py +3 -0
- imio/smartweb/core/contents/rest/events/content.py +2 -2
- imio/smartweb/core/contents/rest/events/view.pt +2 -1
- imio/smartweb/core/contents/rest/events/view.py +3 -0
- imio/smartweb/core/contents/rest/news/content.py +2 -2
- imio/smartweb/core/contents/rest/news/view.pt +2 -1
- imio/smartweb/core/contents/rest/news/view.py +3 -0
- imio/smartweb/core/contents/rest/search/endpoint.py +1 -1
- imio/smartweb/core/contents/rest/traversal.py +18 -0
- imio/smartweb/core/contents/rest/view.py +7 -0
- imio/smartweb/core/contents/sections/events/view.py +1 -1
- imio/smartweb/core/contents/sections/news/view.py +1 -1
- imio/smartweb/core/interfaces.py +4 -0
- imio/smartweb/core/profiles/default/actions.xml +15 -0
- imio/smartweb/core/profiles/default/metadata.xml +1 -1
- imio/smartweb/core/rest/authentic_sources.py +21 -11
- imio/smartweb/core/tests/test_rest.py +120 -0
- imio/smartweb/core/tests/utils.py +15 -0
- imio/smartweb/core/upgrades/configure.zcml +18 -0
- imio/smartweb/core/upgrades/profiles/1051_to_1052/actions.xml +20 -0
- imio/smartweb/core/utils.py +31 -0
- imio/smartweb/core/viewlets/configure.zcml +11 -0
- imio/smartweb/core/viewlets/httpheaders.py +13 -0
- imio/smartweb/core/viewlets/ogp_tag_header.pt +10 -0
- imio/smartweb/core/viewlets/ogptags.py +8 -0
- imio/smartweb/core/webcomponents/build/css/54.smartweb-webcomponents-compiled.css +1 -0
- imio/smartweb/core/webcomponents/build/css/647.smartweb-webcomponents-compiled.css +1 -0
- imio/smartweb/core/webcomponents/build/js/3.smartweb-webcomponents-compiled.js +2 -0
- imio/smartweb/core/webcomponents/build/js/323.smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/build/js/363.smartweb-webcomponents-compiled.js +2 -0
- imio/smartweb/core/webcomponents/build/js/493.smartweb-webcomponents-compiled.js +1 -0
- imio/smartweb/core/webcomponents/build/js/54.smartweb-webcomponents-compiled.js +1 -0
- imio/smartweb/core/webcomponents/build/js/647.smartweb-webcomponents-compiled.js +2 -0
- imio/smartweb/core/webcomponents/build/js/647.smartweb-webcomponents-compiled.js.LICENSE.txt +1 -0
- imio/smartweb/core/webcomponents/build/js/smartweb-webcomponents-compiled.js +1 -1
- imio/smartweb/core/webcomponents/package.json +14 -17
- imio/smartweb/core/webcomponents/src/assets/contentIcon/download.svg +1 -0
- imio/smartweb/core/webcomponents/src/components/Annuaire/Annuaire.jsx +85 -84
- imio/smartweb/core/webcomponents/src/components/Annuaire/ContactCard/ContactCard.jsx +22 -23
- imio/smartweb/core/webcomponents/src/components/Annuaire/ContactContent/ContactContent.jsx +109 -93
- imio/smartweb/core/webcomponents/src/components/Annuaire/ContactContent/download.svg +1 -0
- imio/smartweb/core/webcomponents/src/components/Annuaire/ContactList/ContactList.jsx +7 -7
- imio/smartweb/core/webcomponents/src/components/Events/EventCard/EventCard.jsx +43 -0
- imio/smartweb/core/webcomponents/src/components/Events/{ContactContent/ContactContent.jsx → EventContent/EventContent.jsx} +76 -81
- imio/smartweb/core/webcomponents/src/components/Events/{ContactList/ContactList.jsx → EventList/EventList.jsx} +9 -9
- imio/smartweb/core/webcomponents/src/components/Events/Events.jsx +99 -98
- imio/smartweb/core/webcomponents/src/components/Events/Events.scss +1 -1
- imio/smartweb/core/webcomponents/src/components/News/News.jsx +23 -25
- imio/smartweb/core/webcomponents/src/components/News/News.scss +3 -5
- imio/smartweb/core/webcomponents/src/components/News/{ContactCard/ContactCard.jsx → NewsCard/NewsCard.jsx} +14 -27
- imio/smartweb/core/webcomponents/src/components/News/{ContactContent/ContactContent.jsx → NewsContent/NewsContent.jsx} +37 -40
- imio/smartweb/core/webcomponents/src/components/News/{ContactList/ContactList.jsx → NewsList/NewsList.jsx} +9 -9
- imio/smartweb/core/webcomponents/src/components/Search/ContactResult/ContactResult.jsx +5 -5
- imio/smartweb/core/webcomponents/src/components/Search/EventsResult/EventsResult.jsx +5 -5
- imio/smartweb/core/webcomponents/src/components/Search/NewsResult/NewsResult.jsx +5 -5
- imio/smartweb/core/webcomponents/src/components/Search/WebResult/WebResult.jsx +3 -3
- imio/smartweb/core/webcomponents/src/{components/Events/ContactMap/ContactMap.jsx → utils/Map.jsx} +60 -64
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/METADATA +59 -1
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/RECORD +80 -82
- imio/smartweb/core/webcomponents/build/css/267.smartweb-webcomponents-compiled.css +0 -1
- imio/smartweb/core/webcomponents/build/css/779.smartweb-webcomponents-compiled.css +0 -1
- imio/smartweb/core/webcomponents/build/js/267.smartweb-webcomponents-compiled.js +0 -1
- imio/smartweb/core/webcomponents/build/js/552.smartweb-webcomponents-compiled.js +0 -2
- imio/smartweb/core/webcomponents/build/js/565.smartweb-webcomponents-compiled.js +0 -1
- imio/smartweb/core/webcomponents/build/js/612.smartweb-webcomponents-compiled.js +0 -2
- imio/smartweb/core/webcomponents/build/js/779.smartweb-webcomponents-compiled.js +0 -1
- imio/smartweb/core/webcomponents/pnpm-lock.yaml +0 -7066
- imio/smartweb/core/webcomponents/src/components/Annuaire/ContactMap/ContactMap.jsx +0 -156
- imio/smartweb/core/webcomponents/src/components/Annuaire/Skeleton/LoaderCss.jsx +0 -7
- imio/smartweb/core/webcomponents/src/components/Annuaire/Skeleton/Skeleton.jsx +0 -20
- imio/smartweb/core/webcomponents/src/components/Events/ContactCard/ContactCard.jsx +0 -49
- imio/smartweb/core/webcomponents/src/components/Events/ContactMap/ContactMap.scss +0 -0
- imio/smartweb/core/webcomponents/src/components/Events/Skeleton/Skeleton.jsx +0 -20
- imio/smartweb/core/webcomponents/src/components/News/ContactMap/ContactMap.jsx +0 -127
- imio/smartweb/core/webcomponents/src/components/News/ContactMap/ContactMap.scss +0 -4
- imio/smartweb/core/webcomponents/src/components/News/Skeleton/Skeleton.jsx +0 -20
- imio/smartweb/core/webcomponents/src/components/Search/Skeleton/Skeleton.jsx +0 -20
- /imio/smartweb/core/webcomponents/build/css/{552.smartweb-webcomponents-compiled.css → 363.smartweb-webcomponents-compiled.css} +0 -0
- /imio/smartweb/core/webcomponents/build/js/{552.smartweb-webcomponents-compiled.js.LICENSE.txt → 3.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
- /imio/smartweb/core/webcomponents/build/js/{612.smartweb-webcomponents-compiled.js.LICENSE.txt → 363.smartweb-webcomponents-compiled.js.LICENSE.txt} +0 -0
- /imio/smartweb/core/webcomponents/src/{components/Annuaire/ContactMap/ContactMap.scss → utils/Map.scss} +0 -0
- /imio.smartweb.core-1.2.12-py3.10-nspkg.pth → /imio.smartweb.core-1.2.19-py3.10-nspkg.pth +0 -0
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/LICENSE.GPL +0 -0
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/LICENSE.rst +0 -0
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/WHEEL +0 -0
- {imio.smartweb.core-1.2.12.dist-info → imio.smartweb.core-1.2.19.dist-info}/namespace_packages.txt +0 -0
- {imio.smartweb.core-1.2.12.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.
|
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(
|
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(
|
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(
|
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
|
-
|
80
|
-
|
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(
|
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;
|
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(
|
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;
|
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(
|
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;
|
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}
|
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}
|
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}
|
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
|
}
|
imio/smartweb/core/interfaces.py
CHANGED
@@ -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>
|
@@ -39,34 +39,44 @@ class BaseRequestForwarder(Service):
|
|
39
39
|
token = get_wca_token(self.client_id, self.client_secret)
|
40
40
|
headers = {"Accept": "application/json", "Authorization": token}
|
41
41
|
params = self.request.form
|
42
|
-
|
42
|
+
if method == "GET":
|
43
|
+
params = self.add_missing_metadatas(params)
|
43
44
|
data = json_body(self.request)
|
44
45
|
|
45
46
|
# Forward the request to the authentic source
|
46
47
|
auth_source_response = requests.request(
|
47
|
-
method, url, params=params, headers=headers,
|
48
|
+
method, url, params=params, headers=headers, json=data
|
48
49
|
)
|
49
|
-
|
50
50
|
response = self.request.response
|
51
51
|
# Set the status code and headers from the authentic source server response
|
52
52
|
response.setStatus(auth_source_response.status_code)
|
53
53
|
for header, value in auth_source_response.headers.items():
|
54
54
|
response.setHeader(header, value)
|
55
55
|
|
56
|
+
if auth_source_response.status_code == 204 or auth_source_response.text == "":
|
57
|
+
# Empty response
|
58
|
+
return ""
|
59
|
+
|
56
60
|
return auth_source_response.json()
|
57
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
|
+
|
58
70
|
def add_smartweb_urls(self, json_data):
|
59
|
-
if "items" not in 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)
|
60
76
|
return json_data
|
61
77
|
for item in json_data.get("items", []):
|
62
78
|
if "@id" in item and "UID" in item:
|
63
|
-
|
64
|
-
# TODO: handle other views & translations (use/refactor code in
|
65
|
-
# search endpoint)
|
66
|
-
default_view_url = get_default_view_url(self.request_type)
|
67
|
-
item_uid = item["UID"]
|
68
|
-
item_id = item["id"]
|
69
|
-
item["smartweb_url"] = f"{default_view_url}#/{item_id}?u={item_uid}"
|
79
|
+
self.construct_url(default_view_url, item)
|
70
80
|
return json_data
|
71
81
|
|
72
82
|
def add_missing_metadatas(self, params):
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
|
3
|
+
from base64 import b64encode
|
3
4
|
from freezegun import freeze_time
|
4
5
|
from imio.smartweb.core import config
|
5
6
|
from imio.smartweb.core.contents.rest.base import BaseEndpoint
|
@@ -8,16 +9,20 @@ from imio.smartweb.core.contents.rest.events.endpoint import EventsEndpoint
|
|
8
9
|
from imio.smartweb.core.contents.rest.news.endpoint import NewsEndpoint
|
9
10
|
from imio.smartweb.core.testing import IMIO_SMARTWEB_CORE_ACCEPTANCE_TESTING
|
10
11
|
from imio.smartweb.core.testing import ImioSmartwebTestCase
|
12
|
+
from imio.smartweb.core.tests.utils import FakeResponse
|
11
13
|
from imio.smartweb.core.tests.utils import get_json
|
12
14
|
from plone import api
|
13
15
|
from plone.app.testing import setRoles
|
14
16
|
from plone.app.testing import TEST_USER_ID
|
17
|
+
from plone.app.testing import TEST_USER_PASSWORD
|
15
18
|
from plone.restapi.testing import RelativeSession
|
16
19
|
from unittest.mock import patch
|
17
20
|
from urllib.parse import urlparse
|
18
21
|
from urllib.parse import parse_qs
|
19
22
|
from zope.component import queryMultiAdapter
|
23
|
+
from zope.event import notify
|
20
24
|
from zope.publisher.browser import TestRequest
|
25
|
+
from ZPublisher.pubevents import PubStart
|
21
26
|
|
22
27
|
import json
|
23
28
|
import requests_mock
|
@@ -73,6 +78,21 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
|
|
73
78
|
def tearDown(self):
|
74
79
|
self.api_session.close()
|
75
80
|
|
81
|
+
def traverse(self, path="/plone", method="GET"):
|
82
|
+
request = self.layer["request"]
|
83
|
+
request.environ["PATH_INFO"] = path
|
84
|
+
request.environ["PATH_TRANSLATED"] = path
|
85
|
+
request.environ["HTTP_ACCEPT"] = "application/json"
|
86
|
+
request.environ["REQUEST_METHOD"] = method
|
87
|
+
request.other["ACTUAL_URL"] = ""
|
88
|
+
request.other["URL"] = ""
|
89
|
+
request.method = method
|
90
|
+
request.form = {}
|
91
|
+
auth = f"{TEST_USER_ID}:{TEST_USER_PASSWORD}"
|
92
|
+
request._auth = "Basic %s" % b64encode(auth.encode("utf8")).decode("utf8")
|
93
|
+
notify(PubStart(request))
|
94
|
+
return request.traverse(path)
|
95
|
+
|
76
96
|
@freeze_time("2021-09-14 8:00:00")
|
77
97
|
def test_convert_cached_image_scales(self):
|
78
98
|
endpoint = BaseEndpoint(self.portal, self.request)
|
@@ -366,3 +386,103 @@ class SectionsFunctionalTest(ImioSmartwebTestCase):
|
|
366
386
|
self.rest_events.display_map = True
|
367
387
|
view = queryMultiAdapter((self.rest_events, self.request), name="view")
|
368
388
|
self.assertIn('display-map="True"', view())
|
389
|
+
|
390
|
+
@patch("imio.smartweb.core.rest.authentic_sources.get_wca_token")
|
391
|
+
@patch("imio.smartweb.core.rest.authentic_sources.requests.request")
|
392
|
+
@patch("imio.smartweb.core.rest.authentic_sources.get_default_view_url")
|
393
|
+
def test_request_forwarder(self, mock_view_url, mock_request, mock_get_wca_token):
|
394
|
+
mock_view_url.return_value = "http://view-url"
|
395
|
+
mock_get_wca_token.return_value = "kamoulox"
|
396
|
+
mock_request.return_value = FakeResponse(
|
397
|
+
status_code=200,
|
398
|
+
headers={"test-header": "True"},
|
399
|
+
)
|
400
|
+
|
401
|
+
# traversal stack
|
402
|
+
service = self.traverse("/plone/@news_request_forwarder/belleville/@search")
|
403
|
+
self.assertListEqual(service.traversal_stack, ["belleville", "@search"])
|
404
|
+
|
405
|
+
# add_smartweb_urls
|
406
|
+
json_data = {}
|
407
|
+
self.assertEqual(service.add_smartweb_urls(json_data), json_data)
|
408
|
+
json_data = {"foo": "bar"}
|
409
|
+
self.assertEqual(service.add_smartweb_urls(json_data), json_data)
|
410
|
+
json_data = {"@id": "http://news/my-news"}
|
411
|
+
self.assertEqual(service.add_smartweb_urls(json_data), json_data)
|
412
|
+
json_data = {"@id": "http://news/my-news", "UID": "12345678"}
|
413
|
+
json_result = service.add_smartweb_urls(json_data)
|
414
|
+
self.assertEqual(
|
415
|
+
json_result["smartweb_url"], "http://view-url/content?u=12345678"
|
416
|
+
)
|
417
|
+
json_data = {"items": []}
|
418
|
+
self.assertEqual(service.add_smartweb_urls(json_data), json_data)
|
419
|
+
json_data = {"items": [{"@id": "http://news/my-news"}]}
|
420
|
+
self.assertEqual(service.add_smartweb_urls(json_data), json_data)
|
421
|
+
json_data = {"items": [{"@id": "http://news/my-news", "UID": "12345678"}]}
|
422
|
+
json_result = service.add_smartweb_urls(json_data)
|
423
|
+
self.assertIn("smartweb_url", json_result["items"][0])
|
424
|
+
self.assertEqual(
|
425
|
+
json_data["items"][0]["smartweb_url"], "http://view-url/content?u=12345678"
|
426
|
+
)
|
427
|
+
|
428
|
+
# add_missing_metadatas
|
429
|
+
params = {}
|
430
|
+
self.assertEqual(
|
431
|
+
service.add_missing_metadatas(params), {"metadata_fields": ["id", "UID"]}
|
432
|
+
)
|
433
|
+
params = {"fullobjects": 1}
|
434
|
+
self.assertEqual(service.add_missing_metadatas(params), params)
|
435
|
+
params = {"metadata_fields": ["other", "UID"]}
|
436
|
+
self.assertEqual(
|
437
|
+
service.add_missing_metadatas(params),
|
438
|
+
{"metadata_fields": ["other", "UID", "id"]},
|
439
|
+
)
|
440
|
+
params = {"metadata_fields": ["other", "id"]}
|
441
|
+
self.assertEqual(
|
442
|
+
service.add_missing_metadatas(params),
|
443
|
+
{"metadata_fields": ["other", "id", "UID"]},
|
444
|
+
)
|
445
|
+
|
446
|
+
# reply
|
447
|
+
response = service.reply()
|
448
|
+
mock_request.assert_called_with(
|
449
|
+
"GET",
|
450
|
+
"http://localhost:8080/Plone/belleville/@search",
|
451
|
+
params={"metadata_fields": ["id", "UID"]},
|
452
|
+
headers={"Accept": "application/json", "Authorization": "kamoulox"},
|
453
|
+
json={},
|
454
|
+
)
|
455
|
+
self.assertEqual(response, {})
|
456
|
+
self.assertEqual(self.request.response.status, 200)
|
457
|
+
self.assertEqual(self.request.response.headers, {"test-header": "True"})
|
458
|
+
|
459
|
+
service = self.traverse(
|
460
|
+
"/plone/@events_request_forwarder/belleville/", method="POST"
|
461
|
+
)
|
462
|
+
service.reply()
|
463
|
+
mock_request.assert_called_with(
|
464
|
+
"POST",
|
465
|
+
"http://localhost:8080/Plone/belleville",
|
466
|
+
params={},
|
467
|
+
headers={"Accept": "application/json", "Authorization": "kamoulox"},
|
468
|
+
json={},
|
469
|
+
)
|
470
|
+
|
471
|
+
mock_request.side_effect = None
|
472
|
+
mock_request.return_value = FakeResponse(status_code=204)
|
473
|
+
service = self.traverse(
|
474
|
+
"/plone/@events_request_forwarder/belleville/", method="PATCH"
|
475
|
+
)
|
476
|
+
response = service.reply()
|
477
|
+
self.assertEqual(response, "")
|
478
|
+
self.assertEqual(self.request.response.status, 204)
|
479
|
+
|
480
|
+
self.assertEqual(
|
481
|
+
self.api_session.get("/@directory_request_forwarder/foo/bar").text, ""
|
482
|
+
)
|
483
|
+
self.assertEqual(
|
484
|
+
self.api_session.get("/@events_request_forwarder/foo/bar").text, ""
|
485
|
+
)
|
486
|
+
self.assertEqual(
|
487
|
+
self.api_session.get("/@news_request_forwarder/foo/bar").text, ""
|
488
|
+
)
|
@@ -94,3 +94,18 @@ def make_named_image(filename="plone.png"):
|
|
94
94
|
with open(path, "rb") as f:
|
95
95
|
image_data = f.read()
|
96
96
|
return {"filename": filename, "data": image_data}
|
97
|
+
|
98
|
+
|
99
|
+
class FakeResponse:
|
100
|
+
status_code = 404
|
101
|
+
headers = {}
|
102
|
+
text = "{}"
|
103
|
+
|
104
|
+
def __init__(self, status_code=None, headers=None):
|
105
|
+
if status_code:
|
106
|
+
self.status_code = status_code
|
107
|
+
if headers:
|
108
|
+
self.headers = headers
|
109
|
+
|
110
|
+
def json(self):
|
111
|
+
return json.loads(self.text)
|