# HG changeset patch # User Thierry Florac # Date 1530613113 -7200 # Node ID 6c410c0ee25c88102c22f0c86501aa50a5d5d646 # Parent 4ced68ece1581f87a2ed8f28585f9365e1439f3e Added PyAMS simple header diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/features/header/__init__.py --- a/src/pyams_default_theme/features/header/__init__.py Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/features/header/__init__.py Tue Jul 03 12:18:33 2018 +0200 @@ -17,11 +17,21 @@ # import interfaces from pyams_content.features.header.interfaces import IHeaderTarget, IHeaderSettings +from pyams_content.features.menu.interfaces import IMenuLinksContainerTarget, IMenuLinksContainer +from pyams_default_theme.features.header.interfaces import ISimpleHeaderRendererSettings, ISimpleHeaderTabsMenu from pyams_default_theme.layer import IPyAMSDefaultLayer +from zope.location.interfaces import ISublocations # import packages +from persistent import Persistent +from pyams_content.component.association.interfaces import ASSOCIATION_CONTAINER_KEY +from pyams_content.features.menu import Menu +from pyams_file.property import FileProperty +from pyams_utils.adapter import get_annotation_adapter, adapter_config, ContextAdapter from pyams_utils.traversing import get_parent from pyams_viewlet.viewlet import contentprovider_config, ViewContentProvider +from zope.interface import implementer +from zope.location import Location, locate @contentprovider_config(name='pyams.header', layer=IPyAMSDefaultLayer) @@ -42,3 +52,37 @@ if renderer is None: return '' return renderer.render() + + +# +# Simple header renderer settings +# + +SIMPLE_HEADER_TABS_KEY = '{0}::tabs'.format(ASSOCIATION_CONTAINER_KEY) + + +@implementer(ISimpleHeaderRendererSettings, IMenuLinksContainerTarget) +class SimpleHeaderRendererSettings(Persistent, Location): + """Simple header renderer settings""" + + banner = FileProperty(ISimpleHeaderRendererSettings['banner']) + logo = FileProperty(ISimpleHeaderRendererSettings['logo']) + + @property + def tabs(self): + return get_annotation_adapter(self, SIMPLE_HEADER_TABS_KEY, Menu, + markers=ISimpleHeaderTabsMenu, name='++ass++tabs') + + +@adapter_config(name='tabs', context=ISimpleHeaderRendererSettings, provides=IMenuLinksContainer) +def simple_header_tabs_links_adapter(context): + """Simple header tabs links adapter""" + return context.tabs + + +@adapter_config(name='links', context=ISimpleHeaderRendererSettings, provides=ISublocations) +class SimpleHeaderRendererSettingsSublocations(ContextAdapter): + """Simple header renderer settings sub-locations adapter""" + + def sublocations(self): + return self.context.tabs.values() diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/features/header/interfaces.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_default_theme/features/header/interfaces.py Tue Jul 03 12:18:33 2018 +0200 @@ -0,0 +1,43 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + + +# import standard library + +# import interfaces +from pyams_content.features.header.interfaces import IHeaderRendererSettings + +# import packages +from pyams_file.schema import ImageField +from zope.interface import Interface, Attribute + +from pyams_default_theme import _ + + +class ISimpleHeaderRendererSettings(IHeaderRendererSettings): + """Simple header renderer settings""" + + banner = ImageField(title=_("Banner image"), + description=_("Image displayed as header background"), + required=False) + + logo = ImageField(title=_("Logo"), + description=_("Logo displayed in header"), + required=False) + + tabs = Attribute("Top tabs list") + + +class ISimpleHeaderTabsMenu(Interface): + """Simple header menu marker interface""" diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/features/header/skin/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_default_theme/features/header/skin/__init__.py Tue Jul 03 12:18:33 2018 +0200 @@ -0,0 +1,62 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + + +# import standard library + +# import interfaces +from pyams_content.component.association.interfaces import IAssociationInfo +from pyams_content.features.header.interfaces import IHeaderTarget, IHeaderRenderer, IHeaderSettings, \ + IHeaderRendererSettings +from pyams_default_theme.features.header.interfaces import ISimpleHeaderRendererSettings +from pyams_skin.layer import IPyAMSLayer + +# import packages +from pyams_content.features.header.skin import BaseHeaderRenderer +from pyams_default_theme.features.header import SimpleHeaderRendererSettings +from pyams_template.template import template_config +from pyams_utils.adapter import adapter_config + +from pyams_default_theme import _ + + +SIMPLE_HEADER_RENDERER_NAME = 'PyAMS simple header' + + +# +# Simple header renderer +# + +@adapter_config(name=SIMPLE_HEADER_RENDERER_NAME, context=(IHeaderTarget, IPyAMSLayer), provides=IHeaderRenderer) +@adapter_config(name=SIMPLE_HEADER_RENDERER_NAME, context=(IHeaderSettings, IPyAMSLayer), provides=IHeaderRenderer) +@template_config(template='templates/simple-header.pt', layer=IPyAMSLayer) +class SimpleHeaderRenderer(BaseHeaderRenderer): + """Simple header renderer""" + + name = SIMPLE_HEADER_RENDERER_NAME + label = _("PyAMS simple header with banner and tabs") + weight = 1 + + settings_key = 'PyAMS::simple' + settings_interface = ISimpleHeaderRendererSettings + + @staticmethod + def get_link_info(link): + return IAssociationInfo(link) + + +@adapter_config(context=SimpleHeaderRenderer, provides=IHeaderRendererSettings) +def simple_header_renderer_settings_factory(context): + """Simple header renderer settings factory""" + return SimpleHeaderRendererSettings() diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/features/header/skin/templates/simple-header.pt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_default_theme/features/header/skin/templates/simple-header.pt Tue Jul 03 12:18:33 2018 +0200 @@ -0,0 +1,24 @@ +
+ + + Link
+
+
diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/features/header/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_default_theme/features/header/zmi/__init__.py Tue Jul 03 12:18:33 2018 +0200 @@ -0,0 +1,84 @@ +# +# Copyright (c) 2008-2018 Thierry Florac +# All Rights Reserved. +# +# This software is subject to the provisions of the Zope Public License, +# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. +# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED +# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS +# FOR A PARTICULAR PURPOSE. +# + +__docformat__ = 'restructuredtext' + + +# import standard library + +# import interfaces +from pyams_default_theme.features.header import ISimpleHeaderRendererSettings, ISimpleHeaderTabsMenu +from pyams_form.interfaces.form import IInnerSubForm +from pyams_portal.interfaces import MANAGE_TEMPLATE_PERMISSION +from pyams_skin.layer import IPyAMSLayer +from transaction.interfaces import ITransactionManager + +# import packages +from pyams_content.features.header.zmi import HeaderSettingsRendererSettingsEditForm +from pyams_content.features.menu.zmi import LinksTable, IMenuLinksView, MenuLinksView +from pyams_skin.event import get_json_widget_refresh_event +from pyams_utils.adapter import adapter_config +from pyams_zmi.form import InnerAdminEditForm +from z3c.form import field + +from pyams_default_theme import _ + + +@adapter_config(name='simple-header-properties', + context=(ISimpleHeaderRendererSettings, IPyAMSLayer, HeaderSettingsRendererSettingsEditForm), + provides=IInnerSubForm) +class SimpleHeaderPropertiesEditForm(InnerAdminEditForm): + """Simple header properties edit form""" + + legend = None + edit_permission = MANAGE_TEMPLATE_PERMISSION + weight = 1 + + fields = field.Fields(ISimpleHeaderRendererSettings) + + def get_ajax_output(self, changes): + output = super(SimpleHeaderPropertiesEditForm, self).get_ajax_output(changes) + updated = changes.get(ISimpleHeaderRendererSettings, ()) + if updated: + ITransactionManager(self.context).commit() + if 'banner' in updated: + output.setdefault('events', []).append( + get_json_widget_refresh_event(self.context, self.request, + SimpleHeaderPropertiesEditForm, 'banner')) + if 'logo' in updated: + output.setdefault('events', []).append( + get_json_widget_refresh_event(self.context, self.request, + SimpleHeaderPropertiesEditForm, 'logo')) + return output + + +# +# Header top tabs table view +# + +class TabsAssociationsTable(LinksTable): + """Simple header tabs associations table""" + + associations_name = 'tabs' + + +@adapter_config(name='simple-header-tabs', + context=(ISimpleHeaderRendererSettings, IPyAMSLayer, HeaderSettingsRendererSettingsEditForm), + provides=IInnerSubForm) +@adapter_config(name='++ass++tabs', context=(ISimpleHeaderTabsMenu, IPyAMSLayer), provides=IMenuLinksView) +class SimpleHeaderTabsView(MenuLinksView): + """Simple header tabs view""" + + title = _("Top tabs") + + table_class = TabsAssociationsTable + weight = 10 diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.mo Binary file src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.mo has changed diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.po --- a/src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.po Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/locales/fr/LC_MESSAGES/pyams_default_theme.po Tue Jul 03 12:18:33 2018 +0200 @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-06-20 14:40+0200\n" +"POT-Creation-Date: 2018-07-03 09:32+0200\n" "PO-Revision-Date: 2017-06-07 12:41+0200\n" "Last-Translator: Thierry Florac \n" "Language-Team: French\n" @@ -248,6 +248,30 @@ msgid "Label associated with second level options menu" msgstr "Libellé associé au second niveau de sélection" +#: src/pyams_default_theme/features/header/interfaces.py:31 +msgid "Banner image" +msgstr "Bandeau" + +#: src/pyams_default_theme/features/header/interfaces.py:32 +msgid "Image displayed as header background" +msgstr "Image affichée en tête de page" + +#: src/pyams_default_theme/features/header/interfaces.py:35 +msgid "Logo" +msgstr "Logo" + +#: src/pyams_default_theme/features/header/interfaces.py:36 +msgid "Logo displayed in header" +msgstr "Logo superposé au bandeau" + +#: src/pyams_default_theme/features/header/zmi/__init__.py:81 +msgid "Top tabs" +msgstr "Onglets de navigation" + +#: src/pyams_default_theme/features/header/skin/__init__.py:48 +msgid "PyAMS simple header with banner and tabs" +msgstr "PyAMS: en-tête simple avec bandeau et onglets de navigation" + #~ msgid "Search..." #~ msgstr "Chercher..." diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/locales/pyams_default_theme.pot --- a/src/pyams_default_theme/locales/pyams_default_theme.pot Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/locales/pyams_default_theme.pot Tue Jul 03 12:18:33 2018 +0200 @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE 1.0\n" -"POT-Creation-Date: 2018-06-20 14:40+0200\n" +"POT-Creation-Date: 2018-07-03 09:32+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" @@ -230,3 +230,27 @@ #: ./src/pyams_default_theme/features/menu/portlet/navigation/interfaces.py:35 msgid "Label associated with second level options menu" msgstr "" + +#: ./src/pyams_default_theme/features/header/interfaces.py:31 +msgid "Banner image" +msgstr "" + +#: ./src/pyams_default_theme/features/header/interfaces.py:32 +msgid "Image displayed as header background" +msgstr "" + +#: ./src/pyams_default_theme/features/header/interfaces.py:35 +msgid "Logo" +msgstr "" + +#: ./src/pyams_default_theme/features/header/interfaces.py:36 +msgid "Logo displayed in header" +msgstr "" + +#: ./src/pyams_default_theme/features/header/zmi/__init__.py:81 +msgid "Top tabs" +msgstr "" + +#: ./src/pyams_default_theme/features/header/skin/__init__.py:48 +msgid "PyAMS simple header with banner and tabs" +msgstr "" diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/resources/css/pyams-default.css --- a/src/pyams_default_theme/resources/css/pyams-default.css Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/resources/css/pyams-default.css Tue Jul 03 12:18:33 2018 +0200 @@ -1,3 +1,19 @@ +body { + max-width: 950px; + margin: 0 auto; +} +body .header-simple .banner { + position: relative; +} +body .header-simple .banner img.banner { + width: 100%; +} +body .header-simple .banner img.logo { + position: absolute; + top: 10px; + left: 10px; + max-height: calc(80%); +} @media only screen and (min-width: 1200px) { .portal-page .slot.col-lg-0 { display: none; @@ -18,3 +34,4 @@ display: none; } } +/*# sourceMappingURL=pyams-default.css.map */ \ No newline at end of file diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/resources/css/pyams-default.css.map --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_default_theme/resources/css/pyams-default.css.map Tue Jul 03 12:18:33 2018 +0200 @@ -0,0 +1,1 @@ +{"version":3,"sources":["../less/pyams-default.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;EACA,cAAA;;AAFD,IAIC,eACC;EACC,kBAAA;;AAGC,IALH,eACC,QAGC,IACE;EACA,WAAA;;AAED,IARH,eACC,QAGC,IAIE;EACA,kBAAA;EACA,SAAA;EACA,UAAA;EACA,YAAY,SAAZ;;AAUH,wBAA2C;EAC1C,YAFF,MAEG;IACA,aAAA;;;AAGF,wBAA0C,uBAAwB;EACjE,YAPF,MAOG;IACA,aAAA;;;AAGF,wBAA0C,uBAAuB;EAChE,YAZF,MAYG;IACA,aAAA;;;AAGF,wBAA0C;EACzC,YAjBF,MAiBG;IACA,aAAA","file":"pyams-default.css"} \ No newline at end of file diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/resources/css/pyams-default.min.css --- a/src/pyams_default_theme/resources/css/pyams-default.min.css Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/resources/css/pyams-default.min.css Tue Jul 03 12:18:33 2018 +0200 @@ -1,1 +1,1 @@ -@media only screen and (min-width:1200px){.portal-page .slot.col-lg-0{display:none}}@media only screen and (min-width:992px) and (max-width:1199px){.portal-page .slot.col-md-0{display:none}}@media only screen and (min-width:768px) and (max-width:991px){.portal-page .slot.col-sm-0{display:none}}@media only screen and (max-width:767px){.portal-page .slot.col-xs-0{display:none}} \ No newline at end of file +body{max-width:950px;margin:0 auto}body .header-simple .banner{position:relative}body .header-simple .banner img.banner{width:100%}body .header-simple .banner img.logo{position:absolute;top:10px;left:10px;max-height:calc(80%)}@media only screen and (min-width:1200px){.portal-page .slot.col-lg-0{display:none}}@media only screen and (min-width:992px) and (max-width:1199px){.portal-page .slot.col-md-0{display:none}}@media only screen and (min-width:768px) and (max-width:991px){.portal-page .slot.col-sm-0{display:none}}@media only screen and (max-width:767px){.portal-page .slot.col-xs-0{display:none}} diff -r 4ced68ece158 -r 6c410c0ee25c src/pyams_default_theme/resources/less/pyams-default.less --- a/src/pyams_default_theme/resources/less/pyams-default.less Mon Jul 02 17:13:16 2018 +0200 +++ b/src/pyams_default_theme/resources/less/pyams-default.less Tue Jul 03 12:18:33 2018 +0200 @@ -1,3 +1,26 @@ +body { + max-width: 950px; + margin: 0 auto; + + .header-simple { + .banner { + position: relative; + + img { + &.banner { + width: 100%; + } + &.logo { + position: absolute; + top: 10px; + left: 10px; + max-height: calc(100% - 20px); + } + } + } + } +} + .portal-page { .slot {