# HG changeset patch # User Thierry Florac # Date 1520763402 -3600 # Node ID c68bcd7f6fe139192546f952e5a45cf4c05ec8b5 # Parent 0b12851171717312ecedf88dcf86b1ccf8c201bc Added ".zmi" sub-package diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/admin.py --- a/src/pyams_zmi/admin.py Sun Mar 11 11:16:23 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -# -# Copyright (c) 2008-2015 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_skin.layer import IPyAMSLayer -from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION -from pyams_zmi.layer import IAdminLayer - -# import packages -from pyams_pagelet.pagelet import pagelet_config -from pyams_template.template import template_config -from pyams_zmi.view import AdminView -from zope.interface import Interface - - -@pagelet_config(name='admin', context=Interface, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) -@template_config(template='templates/admin-index.pt', layer=IAdminLayer) -class MainAdminPage(AdminView): - """Main administration page""" diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/control_panel.py --- a/src/pyams_zmi/control_panel.py Sun Mar 11 11:16:23 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -# -# Copyright (c) 2008-2015 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 -from html import escape - -# import interfaces -from pyams_skin.interfaces import IInnerPage, IPageHeader, IContentHelp -from pyams_skin.interfaces.container import ITableWithActions -from pyams_skin.layer import IPyAMSLayer -from pyams_utils.interfaces import MANAGE_SYSTEM_PERMISSION -from pyams_utils.interfaces.site import IOptionalUtility -from pyams_zmi.interfaces.menu import IControlPanelMenu, IUtilitiesMenu -from pyams_zmi.layer import IAdminLayer -from z3c.table.interfaces import IValues, IColumn -from zope.component.interfaces import ISite - -# import packages -from pyams_pagelet.pagelet import pagelet_config -from pyams_skin.container import ContainerView -from pyams_skin.help import ContentHelp -from pyams_skin.page import DefaultPageHeaderAdapter -from pyams_skin.table import BaseTable, TrashColumn -from pyams_skin.viewlet.menu import MenuItem -from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config -from pyams_utils.registry import registered_utilities -from pyams_utils.text import text_to_html -from pyams_utils.url import absolute_url -from pyams_viewlet.manager import viewletmanager_config -from pyams_viewlet.viewlet import viewlet_config -from pyams_zmi.view import AdminView -from pyramid.view import view_config -from z3c.table.column import GetAttrColumn -from zope.interface import implementer, Interface - -from pyams_zmi import _ - - -# -# Utilities views and adapters -# - -@viewlet_config(name='utilities.menu', layer=IAdminLayer, context=ISite, manager=IControlPanelMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=1) -@viewletmanager_config(name='utilities.menu', layer=IAdminLayer, context=ISite, provides=IUtilitiesMenu) -@implementer(IUtilitiesMenu) -class UtilitiesMenuItem(MenuItem): - """Utilities menu""" - - label = _("Utilities") - icon_class = 'fa-codepen' - url = '#utilities.html' - - -@implementer(ITableWithActions) -class UtilitiesTable(BaseTable): - """Utilities table""" - - id = 'utilities_table' - title = _("Site utilities") - - @property - def data_attributes(self): - attributes = super(UtilitiesTable, self).data_attributes - attributes['table'] = {'data-ams-location': absolute_url(self.context, self.request), - 'data-ams-delete-target': 'delete-utility.json'} - return attributes - - -@adapter_config(name='trash', context=(Interface, IAdminLayer, UtilitiesTable), provides=IColumn) -class UtilitiesTrashColumn(TrashColumn): - """Utilities trash column""" - - icon_hint = _("Delete utility") - permission = MANAGE_SYSTEM_PERMISSION - - checker = lambda col, x: IOptionalUtility.providedBy(x) - - -@adapter_config(context=(ISite, IAdminLayer, UtilitiesTable), provides=IValues) -class UtilitiesValuesAdapter(ContextRequestViewAdapter): - """Utilities values adapter""" - - @property - def values(self): - return list(self.context.getSiteManager().values()) - - -@pagelet_config(name='utilities.html', context=ISite, layer=IPyAMSLayer, permission=MANAGE_SYSTEM_PERMISSION) -@implementer(IInnerPage) -class UtilitiesView(AdminView, ContainerView): - """Control panel view""" - - table_class = UtilitiesTable - - def __init__(self, context, request): - super(UtilitiesView, self).__init__(context, request) - - -@adapter_config(context=(ISite, IAdminLayer, UtilitiesView), provides=IPageHeader) -class UtilitiesHeaderAdapter(DefaultPageHeaderAdapter): - """Utilities header adapter""" - - icon_class = 'fa fa-fw fa-codepen' - - -@view_config(name='delete-utility.json', context=ISite, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -def delete_utility(request): - """Delete utility from site manager""" - translate = request.localizer.translate - name = request.params.get('object_name') - if not name: - return {'status': 'message', - 'messagebox': {'status': 'error', - 'content': translate(_("No provided object_name argument!"))}} - manager = request.context.getSiteManager() - if name not in manager: - return {'status': 'message', - 'messagebox': {'status': 'error', - 'content': translate(_("Given utility name doesn't exist!"))}} - del manager[name] - return {'status': 'success'} - - -# -# Common registrations views and adapters -# - -class IRegistrationsTable(Interface): - """Registrations view marker interface""" - - -@adapter_config(name='component', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) -class RegistrationsComponentColumn(GetAttrColumn): - """Registrations component column""" - - _header = _("Component") - weight = 1 - - @property - def header(self): - return self.request.localizer.translate(self._header) - - def getValue(self, obj): - component = obj.component - if component is not None: - name = getattr(component, '__name__', None) - if not name: - name = str(component.__class__) - else: - name = str(obj.factory) - return escape(name) - - -@adapter_config(name='interface', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) -class RegistrationsInterfaceColumn(GetAttrColumn): - """Registrations interface column""" - - _header = _("Registered interface") - weight = 5 - - @property - def header(self): - return self.request.localizer.translate(self._header) - - def getValue(self, obj): - return text_to_html(str(obj.provided)) - - -@adapter_config(name='name', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) -class RegistrationsNameColumn(GetAttrColumn): - """Registrations name column""" - - _header = _("Name") - weight = 10 - - @property - def header(self): - return self.request.localizer.translate(self._header) - - def getValue(self, obj): - return obj.name or _('< no name >') - - -# -# Local registrations views -# - -@viewlet_config(name='local-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=1) -class LocalRegistrationsMenuItem(MenuItem): - """Local registrations menu""" - - label = _("Local registrations") - url = '#local-registrations.html' - - -@implementer(IRegistrationsTable) -class LocalRegistrationsTable(BaseTable): - """Local utilities registrations table""" - - id = 'local_registrations_table' - title = _("Local utilities registrations") - - data_attributes = {} - - -@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsTable), provides=IValues) -class LocalRegistrationsValuesAdapter(ContextRequestViewAdapter): - """Local utilities values adapter""" - - @property - def values(self): - return list(self.context.getSiteManager().registeredUtilities()) - - -@pagelet_config(name='local-registrations.html', context=ISite, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -@implementer(IInnerPage) -class LocalRegistrationsView(AdminView, ContainerView): - """Registrations view""" - - table_class = LocalRegistrationsTable - - def __init__(self, context, request): - super(LocalRegistrationsView, self).__init__(context, request) - - -@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IPageHeader) -class LocalRegistrationsHeaderAdapter(DefaultPageHeaderAdapter): - """Local registrations header adapter""" - - icon_class = 'fa fa-fw fa-codepen' - - -@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IContentHelp) -class LocalRegistrationsHelpAdapter(ContentHelp): - """Local registrations help adapter""" - - header = _("Local registry utilities") - message = _("""A local registry is a registry defining utilities stored into -site's Object Database (ZODB). - -You can manage these utilities and modify their properties and site's behaviour without -modifying the application.""") - message_format = 'rest' - - -# -# Global registrations views -# - -@viewlet_config(name='global-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=2) -class GlobalRegistrationsMenuItem(MenuItem): - """Global registrations menu""" - - label = _("Global registrations") - url = '#global-registrations.html' - - -@implementer(IRegistrationsTable) -class GlobalRegistrationsTable(BaseTable): - """Utilities global registrations table""" - - id = 'global_registrations_table' - title = _("Global utilities registrations") - - data_attributes = {} - - -@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsTable), provides=IValues) -class GlobalRegistrationsValuesAdapter(ContextRequestViewAdapter): - """Global utilities values adapter""" - - @property - def values(self): - return list(registered_utilities()) - - -@pagelet_config(name='global-registrations.html', context=ISite, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -@implementer(IInnerPage) -class GlobalRegistrationsView(AdminView, ContainerView): - """Global registrations view""" - - table_class = GlobalRegistrationsTable - - def __init__(self, context, request): - super(GlobalRegistrationsView, self).__init__(context, request) - - -@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IPageHeader) -class GlobalRegistrationsHeaderAdapter(DefaultPageHeaderAdapter): - """Global registrations header adapter""" - - icon_class = 'fa fa-fw fa-codepen' - - -@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IContentHelp) -class GlobalRegistrationsHelpAdapter(ContentHelp): - """Global registrations help adapter""" - - header = _("Global registry utilities") - message = _("""The global registry groups local utilities as well as utilities registered outside -site's Object Database (ZODB). - -These utilities are declared statically (generally using include or ZCML directives) and can't be setup -without modifying site configuration.""") - message_format = 'rest' diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/extension.py --- a/src/pyams_zmi/extension.py Sun Mar 11 11:16:23 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -# -# Copyright (c) 2008-2015 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_skin.interfaces.extension import IGoogleTagManagerInfo, IGoogleAnalyticsInfo, IUserReportInfo -from pyams_skin.layer import IPyAMSLayer -from pyams_utils.interfaces import MANAGE_SYSTEM_PERMISSION -from pyams_utils.interfaces.site import ISiteRoot -from pyams_zmi.interfaces.menu import IPropertiesMenu -from pyams_zmi.layer import IAdminLayer - -# import packages -from pyams_form.form import AJAXEditForm -from pyams_pagelet.pagelet import pagelet_config -from pyams_skin.viewlet.menu import MenuItem -from pyams_viewlet.viewlet import viewlet_config -from pyams_zmi.form import AdminDialogEditForm -from pyramid.view import view_config -from z3c.form import field - -from pyams_zmi import _ - - -# -# Google Tag Manager views -# - -@viewlet_config(name='tag-manager-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=10) -class GoogleTagManagerPropertiesMenuItem(MenuItem): - """Google Tag Manager properties menu""" - - label = _("Google Tag Manager...") - icon_class = 'fa-tags' - url = 'tag-manager-properties.html' - modal_target = True - - -@pagelet_config(name='tag-manager-properties.html', context=ISiteRoot, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -class GoogleTagManagerPropertiesEditForm(AdminDialogEditForm): - """Google Tag Manager properties edit form""" - - legend = _("Update Google Tag Manager properties") - ajax_handler = 'tag-manager-properties.json' - edit_permission = MANAGE_SYSTEM_PERMISSION - - fields = field.Fields(IGoogleTagManagerInfo) - - label_css_class = 'control-label col-md-4' - input_css_class = 'col-md-8' - - -@view_config(name='tag-manager-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -class GoogleTagManagerPropertiesAJAXEditForm(AJAXEditForm, GoogleTagManagerPropertiesEditForm): - """Google Tag Manager properties edit form, JSON renderer""" - - -# -# Google Analytics views -# - -@viewlet_config(name='analytics-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=15) -class GoogleAnalyticsPropertiesMenuItem(MenuItem): - """Google Analytics properties menu""" - - label = _("Google Analytics...") - icon_class = 'fa-line-chart' - url = 'analytics-properties.html' - modal_target = True - - -@pagelet_config(name='analytics-properties.html', context=ISiteRoot, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -class GoogleAnalyticsPropertiesEditForm(AdminDialogEditForm): - """Google Analytics properties edit form""" - - legend = _("Update Google Analytics properties") - ajax_handler = 'analytics-properties.json' - edit_permission = MANAGE_SYSTEM_PERMISSION - - fields = field.Fields(IGoogleAnalyticsInfo) - - label_css_class = 'control-label col-md-4' - input_css_class = 'col-md-8' - - -@view_config(name='analytics-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -class GoogleAnalyticsPropertiesAJAXEditForm(AJAXEditForm, GoogleAnalyticsPropertiesEditForm): - """Google Analytics properties edit form, JSON renderer""" - - -# -# UserReport views -# - -@viewlet_config(name='user-report.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=20) -class UserReportPropertiesMenuItem(MenuItem): - """UserReport properties menu""" - - label = _("UserReport settings...") - icon_class = 'fa-comments' - url = 'user-report.html' - modal_target = True - - -@pagelet_config(name='user-report.html', context=ISiteRoot, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -class UserReportPropertiesEditForm(AdminDialogEditForm): - """UserReport properties edit form""" - - legend = _("Update UserReport service properties") - ajax_handler = 'user-report.json' - edit_permission = MANAGE_SYSTEM_PERMISSION - - fields = field.Fields(IUserReportInfo) - - label_css_class = 'control-label col-md-4' - input_css_class = 'col-md-8' - - -@view_config(name='user-report.json', context=ISiteRoot, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -class UserReportPropertiesAJAXEditForm(AJAXEditForm, UserReportPropertiesEditForm): - """UserReport properties edit form, JSON renderer""" diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/site.py --- a/src/pyams_zmi/site.py Sun Mar 11 11:16:23 2018 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,180 +0,0 @@ -# -# Copyright (c) 2008-2015 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_form.interfaces.form import IWidgetForm -from pyams_skin.interfaces import IInnerPage, IPageHeader, IContentTitle -from pyams_skin.interfaces.configuration import IConfiguration, IBackOfficeConfiguration -from pyams_skin.layer import IPyAMSLayer -from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION, MANAGE_SYSTEM_PERMISSION -from pyams_utils.interfaces.site import ISiteRoot -from pyams_zmi.interfaces.menu import ISiteManagementMenu, IPropertiesMenu -from pyams_zmi.layer import IAdminLayer - -# import packages -from pyams_form.form import AJAXEditForm -from pyams_pagelet.pagelet import pagelet_config -from pyams_skin.page import DefaultPageHeaderAdapter -from pyams_skin.viewlet.menu import MenuItem -from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter -from pyams_viewlet.manager import viewletmanager_config -from pyams_viewlet.viewlet import viewlet_config -from pyams_zmi.form import AdminEditForm, AdminDialogEditForm -from pyramid.decorator import reify -from pyramid.view import view_config -from z3c.form import field -from zope.interface import implementer, implementedBy, Interface - -from pyams_zmi import _ - - -@adapter_config(context=(ISiteRoot, IAdminLayer, Interface), provides=IContentTitle) -class SiteRootTitleAdapter(ContextRequestViewAdapter): - """Site root title adapter""" - - @property - def title(self): - return IBackOfficeConfiguration(self.context).title - - -# -# Configuration properties -# - -@viewlet_config(name='properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=ISiteManagementMenu, - permission=VIEW_SYSTEM_PERMISSION, weight=1) -@viewletmanager_config(name='properties.menu', context=ISiteRoot, layer=IAdminLayer, provides=IPropertiesMenu) -@implementer(IPropertiesMenu) -class PropertiesMenuItem(MenuItem): - """Properties menu""" - - label = _("Properties") - icon_class = 'fa-edit' - url = '#properties.html' - - -@pagelet_config(name='properties.html', context=ISiteRoot, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) -@implementer(IWidgetForm, IInnerPage) -class PropertiesEditForm(AdminEditForm): - """Properties edit form""" - - legend = _("Update main site properties") - ajax_handler = 'properties.json' - edit_permission = MANAGE_SYSTEM_PERMISSION - - @reify - def fields(self): - - def get_configuration_interface(context): - for interface in implementedBy(context.__class__).interfaces(): - if issubclass(interface, IConfiguration): - return interface - - content = self.getContent() - return field.Fields(get_configuration_interface(content)).omit('__name__') - - def getContent(self): - return IConfiguration(self.context) - - -@view_config(name='properties.json', context=ISiteRoot, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -class PropertiesAJAXEditForm(AJAXEditForm, PropertiesEditForm): - """Properties edit form, AJAX renderer""" - - def get_ajax_output(self, changes): - if changes: - return {'status': 'reload', - 'location': '#properties.html', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - else: - return AJAXEditForm.get_ajax_output(self, changes) - - -@adapter_config(context=(Interface, IPyAMSLayer, PropertiesEditForm), provides=IPageHeader) -class PropertiesEditFormHeaderAdapter(DefaultPageHeaderAdapter): - """Utilities header adapter""" - - @property - def title(self): - return IBackOfficeConfiguration(self.context).title - - icon_class = 'fa fa-fw fa-twitch' - - -# -# Back-office configuration properties -# - -@viewlet_config(name='back-office-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, - permission=MANAGE_SYSTEM_PERMISSION, weight=1) -class BackOfficePropertiesMenuItem(MenuItem): - """Back-office properties menu""" - - label = _("Back-office properties...") - icon_class = 'fa-tachometer' - url = 'back-office-properties.html' - modal_target = True - - -@pagelet_config(name='back-office-properties.html', context=ISiteRoot, layer=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION) -class BackOfficePropertiesEditForm(AdminDialogEditForm): - """Back-office properties edit form""" - - legend = _("Update site back-office properties") - ajax_handler = 'back-office-properties.json' - edit_permission = MANAGE_SYSTEM_PERMISSION - - dialog_class = 'modal-large' - - @reify - def fields(self): - - def get_configuration_interface(context): - for interface in implementedBy(context.__class__).interfaces(): - if issubclass(interface, IBackOfficeConfiguration): - return interface - - content = self.getContent() - return field.Fields(get_configuration_interface(content)).omit('__name__') - - def getContent(self): - return IBackOfficeConfiguration(self.context) - - def updateWidgets(self, prefix=None): - super(BackOfficePropertiesEditForm, self).updateWidgets(prefix) - if 'login_header' in self.widgets: - self.widgets['login_header'].widget_css_class = 'textarea' - if 'login_footer' in self.widgets: - self.widgets['login_footer'].widget_css_class = 'textarea' - - -@view_config(name='back-office-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, - permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) -class BackOfficePropertiesAJAXEditForm(AJAXEditForm, BackOfficePropertiesEditForm): - """Back-office properties edit form, JSON renderer""" - - def get_ajax_output(self, changes): - if changes: - return {'status': 'reload', - 'location': '#properties.html', - 'smallbox': self.request.localizer.translate(self.successMessage), - 'smallbox_status': 'success'} - else: - return AJAXEditForm.get_ajax_output(self, changes) diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/__init__.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,19 @@ +# +# 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 + +# import packages diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/control_panel.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/control_panel.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,323 @@ +# +# Copyright (c) 2008-2015 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 +from html import escape + +# import interfaces +from pyams_skin.interfaces import IInnerPage, IPageHeader, IContentHelp +from pyams_skin.interfaces.container import ITableWithActions +from pyams_skin.layer import IPyAMSLayer +from pyams_utils.interfaces import MANAGE_SYSTEM_PERMISSION +from pyams_utils.interfaces.site import IOptionalUtility +from pyams_zmi.interfaces.menu import IControlPanelMenu, IUtilitiesMenu +from pyams_zmi.layer import IAdminLayer +from z3c.table.interfaces import IValues, IColumn +from zope.component.interfaces import ISite + +# import packages +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.container import ContainerView +from pyams_skin.help import ContentHelp +from pyams_skin.page import DefaultPageHeaderAdapter +from pyams_skin.table import BaseTable, TrashColumn +from pyams_skin.viewlet.menu import MenuItem +from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config +from pyams_utils.registry import registered_utilities +from pyams_utils.text import text_to_html +from pyams_utils.url import absolute_url +from pyams_viewlet.manager import viewletmanager_config +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.view import AdminView +from pyramid.view import view_config +from z3c.table.column import GetAttrColumn +from zope.interface import implementer, Interface + +from pyams_zmi import _ + + +# +# Utilities views and adapters +# + +@viewlet_config(name='utilities.menu', layer=IAdminLayer, context=ISite, manager=IControlPanelMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=1) +@viewletmanager_config(name='utilities.menu', layer=IAdminLayer, context=ISite, provides=IUtilitiesMenu) +@implementer(IUtilitiesMenu) +class UtilitiesMenuItem(MenuItem): + """Utilities menu""" + + label = _("Utilities") + icon_class = 'fa-codepen' + url = '#utilities.html' + + +@implementer(ITableWithActions) +class UtilitiesTable(BaseTable): + """Utilities table""" + + id = 'utilities_table' + title = _("Site utilities") + + @property + def data_attributes(self): + attributes = super(UtilitiesTable, self).data_attributes + attributes['table'] = {'data-ams-location': absolute_url(self.context, self.request), + 'data-ams-delete-target': 'delete-utility.json'} + return attributes + + +@adapter_config(name='trash', context=(Interface, IAdminLayer, UtilitiesTable), provides=IColumn) +class UtilitiesTrashColumn(TrashColumn): + """Utilities trash column""" + + icon_hint = _("Delete utility") + permission = MANAGE_SYSTEM_PERMISSION + + checker = lambda col, x: IOptionalUtility.providedBy(x) + + +@adapter_config(context=(ISite, IAdminLayer, UtilitiesTable), provides=IValues) +class UtilitiesValuesAdapter(ContextRequestViewAdapter): + """Utilities values adapter""" + + @property + def values(self): + return list(self.context.getSiteManager().values()) + + +@pagelet_config(name='utilities.html', context=ISite, layer=IPyAMSLayer, permission=MANAGE_SYSTEM_PERMISSION) +@implementer(IInnerPage) +class UtilitiesView(AdminView, ContainerView): + """Control panel view""" + + table_class = UtilitiesTable + + def __init__(self, context, request): + super(UtilitiesView, self).__init__(context, request) + + +@adapter_config(context=(ISite, IAdminLayer, UtilitiesView), provides=IPageHeader) +class UtilitiesHeaderAdapter(DefaultPageHeaderAdapter): + """Utilities header adapter""" + + icon_class = 'fa fa-fw fa-codepen' + + +@view_config(name='delete-utility.json', context=ISite, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +def delete_utility(request): + """Delete utility from site manager""" + translate = request.localizer.translate + name = request.params.get('object_name') + if not name: + return {'status': 'message', + 'messagebox': {'status': 'error', + 'content': translate(_("No provided object_name argument!"))}} + manager = request.context.getSiteManager() + if name not in manager: + return {'status': 'message', + 'messagebox': {'status': 'error', + 'content': translate(_("Given utility name doesn't exist!"))}} + del manager[name] + return {'status': 'success'} + + +# +# Common registrations views and adapters +# + +class IRegistrationsTable(Interface): + """Registrations view marker interface""" + + +@adapter_config(name='component', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) +class RegistrationsComponentColumn(GetAttrColumn): + """Registrations component column""" + + _header = _("Component") + weight = 1 + + @property + def header(self): + return self.request.localizer.translate(self._header) + + def getValue(self, obj): + component = obj.component + if component is not None: + name = getattr(component, '__name__', None) + if not name: + name = str(component.__class__) + else: + name = str(obj.factory) + return escape(name) + + +@adapter_config(name='interface', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) +class RegistrationsInterfaceColumn(GetAttrColumn): + """Registrations interface column""" + + _header = _("Registered interface") + weight = 5 + + @property + def header(self): + return self.request.localizer.translate(self._header) + + def getValue(self, obj): + return text_to_html(str(obj.provided)) + + +@adapter_config(name='name', context=(ISite, IAdminLayer, IRegistrationsTable), provides=IColumn) +class RegistrationsNameColumn(GetAttrColumn): + """Registrations name column""" + + _header = _("Name") + weight = 10 + + @property + def header(self): + return self.request.localizer.translate(self._header) + + def getValue(self, obj): + return obj.name or _('< no name >') + + +# +# Local registrations views +# + +@viewlet_config(name='local-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=1) +class LocalRegistrationsMenuItem(MenuItem): + """Local registrations menu""" + + label = _("Local registrations") + url = '#local-registrations.html' + + +@implementer(IRegistrationsTable) +class LocalRegistrationsTable(BaseTable): + """Local utilities registrations table""" + + id = 'local_registrations_table' + title = _("Local utilities registrations") + + data_attributes = {} + + +@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsTable), provides=IValues) +class LocalRegistrationsValuesAdapter(ContextRequestViewAdapter): + """Local utilities values adapter""" + + @property + def values(self): + return list(self.context.getSiteManager().registeredUtilities()) + + +@pagelet_config(name='local-registrations.html', context=ISite, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +@implementer(IInnerPage) +class LocalRegistrationsView(AdminView, ContainerView): + """Registrations view""" + + table_class = LocalRegistrationsTable + + def __init__(self, context, request): + super(LocalRegistrationsView, self).__init__(context, request) + + +@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IPageHeader) +class LocalRegistrationsHeaderAdapter(DefaultPageHeaderAdapter): + """Local registrations header adapter""" + + icon_class = 'fa fa-fw fa-codepen' + + +@adapter_config(context=(ISite, IAdminLayer, LocalRegistrationsView), provides=IContentHelp) +class LocalRegistrationsHelpAdapter(ContentHelp): + """Local registrations help adapter""" + + header = _("Local registry utilities") + message = _("""A local registry is a registry defining utilities stored into +site's Object Database (ZODB). + +You can manage these utilities and modify their properties and site's behaviour without +modifying the application.""") + message_format = 'rest' + + +# +# Global registrations views +# + +@viewlet_config(name='global-registrations.menu', layer=IAdminLayer, context=ISite, manager=IUtilitiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=2) +class GlobalRegistrationsMenuItem(MenuItem): + """Global registrations menu""" + + label = _("Global registrations") + url = '#global-registrations.html' + + +@implementer(IRegistrationsTable) +class GlobalRegistrationsTable(BaseTable): + """Utilities global registrations table""" + + id = 'global_registrations_table' + title = _("Global utilities registrations") + + data_attributes = {} + + +@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsTable), provides=IValues) +class GlobalRegistrationsValuesAdapter(ContextRequestViewAdapter): + """Global utilities values adapter""" + + @property + def values(self): + return list(registered_utilities()) + + +@pagelet_config(name='global-registrations.html', context=ISite, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +@implementer(IInnerPage) +class GlobalRegistrationsView(AdminView, ContainerView): + """Global registrations view""" + + table_class = GlobalRegistrationsTable + + def __init__(self, context, request): + super(GlobalRegistrationsView, self).__init__(context, request) + + +@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IPageHeader) +class GlobalRegistrationsHeaderAdapter(DefaultPageHeaderAdapter): + """Global registrations header adapter""" + + icon_class = 'fa fa-fw fa-codepen' + + +@adapter_config(context=(ISite, IAdminLayer, GlobalRegistrationsView), provides=IContentHelp) +class GlobalRegistrationsHelpAdapter(ContentHelp): + """Global registrations help adapter""" + + header = _("Global registry utilities") + message = _("""The global registry groups local utilities as well as utilities registered outside +site's Object Database (ZODB). + +These utilities are declared statically (generally using include or ZCML directives) and can't be setup +without modifying site configuration.""") + message_format = 'rest' diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/extension.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/extension.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,149 @@ +# +# Copyright (c) 2008-2015 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_skin.interfaces.extension import IGoogleTagManagerInfo, IGoogleAnalyticsInfo, IUserReportInfo +from pyams_skin.layer import IPyAMSLayer +from pyams_utils.interfaces import MANAGE_SYSTEM_PERMISSION +from pyams_utils.interfaces.site import ISiteRoot +from pyams_zmi.interfaces.menu import IPropertiesMenu +from pyams_zmi.layer import IAdminLayer + +# import packages +from pyams_form.form import AJAXEditForm +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.viewlet.menu import MenuItem, MenuDivider +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.form import AdminDialogEditForm +from pyramid.view import view_config +from z3c.form import field + +from pyams_zmi import _ + + +@viewlet_config(name='extensions-divider.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=9) +class ExtensionsMenuDivider(MenuDivider): + """Extensions menu divider""" + + +# +# Google Tag Manager views +# + +@viewlet_config(name='tag-manager-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=10) +class GoogleTagManagerPropertiesMenuItem(MenuItem): + """Google Tag Manager properties menu""" + + label = _("Google Tag Manager...") + icon_class = 'fa-tags' + url = 'tag-manager-properties.html' + modal_target = True + + +@pagelet_config(name='tag-manager-properties.html', context=ISiteRoot, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +class GoogleTagManagerPropertiesEditForm(AdminDialogEditForm): + """Google Tag Manager properties edit form""" + + legend = _("Update Google Tag Manager properties") + ajax_handler = 'tag-manager-properties.json' + edit_permission = MANAGE_SYSTEM_PERMISSION + + fields = field.Fields(IGoogleTagManagerInfo) + + label_css_class = 'control-label col-md-4' + input_css_class = 'col-md-8' + + +@view_config(name='tag-manager-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class GoogleTagManagerPropertiesAJAXEditForm(AJAXEditForm, GoogleTagManagerPropertiesEditForm): + """Google Tag Manager properties edit form, JSON renderer""" + + +# +# Google Analytics views +# + +@viewlet_config(name='analytics-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=15) +class GoogleAnalyticsPropertiesMenuItem(MenuItem): + """Google Analytics properties menu""" + + label = _("Google Analytics...") + icon_class = 'fa-line-chart' + url = 'analytics-properties.html' + modal_target = True + + +@pagelet_config(name='analytics-properties.html', context=ISiteRoot, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +class GoogleAnalyticsPropertiesEditForm(AdminDialogEditForm): + """Google Analytics properties edit form""" + + legend = _("Update Google Analytics properties") + ajax_handler = 'analytics-properties.json' + edit_permission = MANAGE_SYSTEM_PERMISSION + + fields = field.Fields(IGoogleAnalyticsInfo) + + label_css_class = 'control-label col-md-4' + input_css_class = 'col-md-8' + + +@view_config(name='analytics-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class GoogleAnalyticsPropertiesAJAXEditForm(AJAXEditForm, GoogleAnalyticsPropertiesEditForm): + """Google Analytics properties edit form, JSON renderer""" + + +# +# UserReport views +# + +@viewlet_config(name='user-report.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=20) +class UserReportPropertiesMenuItem(MenuItem): + """UserReport properties menu""" + + label = _("UserReport settings...") + icon_class = 'fa-comments' + url = 'user-report.html' + modal_target = True + + +@pagelet_config(name='user-report.html', context=ISiteRoot, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +class UserReportPropertiesEditForm(AdminDialogEditForm): + """UserReport properties edit form""" + + legend = _("Update UserReport service properties") + ajax_handler = 'user-report.json' + edit_permission = MANAGE_SYSTEM_PERMISSION + + fields = field.Fields(IUserReportInfo) + + label_css_class = 'control-label col-md-4' + input_css_class = 'col-md-8' + + +@view_config(name='user-report.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class UserReportPropertiesAJAXEditForm(AJAXEditForm, UserReportPropertiesEditForm): + """UserReport properties edit form, JSON renderer""" diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/index.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/index.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,33 @@ +# +# Copyright (c) 2008-2015 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_skin.layer import IPyAMSLayer +from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION +from pyams_zmi.layer import IAdminLayer + +# import packages +from pyams_pagelet.pagelet import pagelet_config +from pyams_template.template import template_config +from pyams_zmi.view import AdminView +from zope.interface import Interface + + +@pagelet_config(name='admin', context=Interface, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) +@template_config(template='templates/admin-index.pt', layer=IAdminLayer) +class MainAdminPage(AdminView): + """Main administration page""" diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/site.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/site.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,223 @@ +# +# Copyright (c) 2008-2015 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_form.interfaces.form import IWidgetForm +from pyams_skin.interfaces import IInnerPage, IPageHeader, IContentTitle +from pyams_skin.interfaces.configuration import IConfiguration, IBackOfficeConfiguration +from pyams_skin.layer import IPyAMSLayer +from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION, MANAGE_SYSTEM_PERMISSION +from pyams_utils.interfaces.site import ISiteRoot +from pyams_zmi.interfaces import IZMIConfiguration +from pyams_zmi.interfaces.menu import ISiteManagementMenu, IPropertiesMenu +from pyams_zmi.layer import IAdminLayer + +# import packages +from pyams_form.form import AJAXEditForm +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.page import DefaultPageHeaderAdapter +from pyams_skin.viewlet.menu import MenuItem +from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter +from pyams_viewlet.manager import viewletmanager_config +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.form import AdminEditForm, AdminDialogEditForm +from pyramid.decorator import reify +from pyramid.view import view_config +from z3c.form import field +from zope.interface import implementer, implementedBy, Interface + +from pyams_zmi import _ + + +@adapter_config(context=(ISiteRoot, IAdminLayer, Interface), provides=IContentTitle) +class SiteRootTitleAdapter(ContextRequestViewAdapter): + """Site root title adapter""" + + @property + def title(self): + return IBackOfficeConfiguration(self.context).title + + +# +# Configuration properties +# + +@viewlet_config(name='properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=ISiteManagementMenu, + permission=VIEW_SYSTEM_PERMISSION, weight=1) +@viewletmanager_config(name='properties.menu', context=ISiteRoot, layer=IAdminLayer, provides=IPropertiesMenu) +@implementer(IPropertiesMenu) +class PropertiesMenuItem(MenuItem): + """Properties menu""" + + label = _("Properties") + icon_class = 'fa-edit' + url = '#properties.html' + + +@pagelet_config(name='properties.html', context=ISiteRoot, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION) +@implementer(IWidgetForm, IInnerPage) +class PropertiesEditForm(AdminEditForm): + """Properties edit form""" + + legend = _("Update main site properties") + ajax_handler = 'properties.json' + edit_permission = MANAGE_SYSTEM_PERMISSION + + @reify + def fields(self): + + def get_configuration_interface(context): + for interface in implementedBy(context.__class__).interfaces(): + if issubclass(interface, IConfiguration): + return interface + + content = self.getContent() + return field.Fields(get_configuration_interface(content)).omit('__name__') + + def getContent(self): + return IConfiguration(self.context) + + +@view_config(name='properties.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class PropertiesAJAXEditForm(AJAXEditForm, PropertiesEditForm): + """Properties edit form, AJAX renderer""" + + def get_ajax_output(self, changes): + if changes: + return {'status': 'reload', + 'location': '#properties.html', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + else: + return AJAXEditForm.get_ajax_output(self, changes) + + +@adapter_config(context=(Interface, IPyAMSLayer, PropertiesEditForm), provides=IPageHeader) +class PropertiesEditFormHeaderAdapter(DefaultPageHeaderAdapter): + """Utilities header adapter""" + + @property + def title(self): + return IBackOfficeConfiguration(self.context).title + + icon_class = 'fa fa-fw fa-twitch' + + +# +# Back-office configuration properties +# + +@viewlet_config(name='back-office-properties.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=1) +class BackOfficePropertiesMenuItem(MenuItem): + """Back-office properties menu""" + + label = _("Back-office properties...") + icon_class = 'fa-tachometer' + url = 'back-office-properties.html' + modal_target = True + + +@pagelet_config(name='back-office-properties.html', context=ISiteRoot, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +class BackOfficePropertiesEditForm(AdminDialogEditForm): + """Back-office properties edit form""" + + legend = _("Update site back-office properties") + ajax_handler = 'back-office-properties.json' + edit_permission = MANAGE_SYSTEM_PERMISSION + + dialog_class = 'modal-large' + + @reify + def fields(self): + + def get_configuration_interface(context): + for interface in implementedBy(context.__class__).interfaces(): + if issubclass(interface, IBackOfficeConfiguration): + return interface + + content = self.getContent() + return field.Fields(get_configuration_interface(content)).omit('__name__') + + def getContent(self): + return IBackOfficeConfiguration(self.context) + + def updateWidgets(self, prefix=None): + super(BackOfficePropertiesEditForm, self).updateWidgets(prefix) + if 'login_header' in self.widgets: + self.widgets['login_header'].widget_css_class = 'textarea' + if 'login_footer' in self.widgets: + self.widgets['login_footer'].widget_css_class = 'textarea' + + +@view_config(name='back-office-properties.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class BackOfficePropertiesAJAXEditForm(AJAXEditForm, BackOfficePropertiesEditForm): + """Back-office properties edit form, JSON renderer""" + + def get_ajax_output(self, changes): + if changes: + return {'status': 'reload', + 'location': '#properties.html', + 'smallbox': self.request.localizer.translate(self.successMessage), + 'smallbox_status': 'success'} + else: + return AJAXEditForm.get_ajax_output(self, changes) + + +# +# ZMI configuration properties +# + +@viewlet_config(name='zmi-configuration.menu', context=ISiteRoot, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SYSTEM_PERMISSION, weight=2) +class ZMIConfigurationMenuItem(MenuItem): + """ZMI configuration menu""" + + label = _("ZMI configuration...") + icon_class = 'fa-window-restore' + url = 'zmi-configuration.html' + modal_target = True + + +@pagelet_config(name='zmi-configuration.html', context=ISiteRoot, layer=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION) +class ZMIConfigurationEditForm(AdminDialogEditForm): + """ZMI configuration edit form""" + + legend = _("Update ZMI configuration") + label_css_class = 'control-label col-md-4' + input_css_class = 'col-md-8' + + ajax_handler = "zmi-configuration.json" + edit_permission = MANAGE_SYSTEM_PERMISSION + + fields = field.Fields(IZMIConfiguration) + + +@view_config(name='zmi-configuration.json', context=ISiteRoot, request_type=IPyAMSLayer, + permission=MANAGE_SYSTEM_PERMISSION, renderer='json', xhr=True) +class ZMIConfigurationAJAXEditForm(AJAXEditForm, ZMIConfigurationEditForm): + """ZMI configuration edit form, JSON renderer""" + + def get_ajax_output(self, changes): + if changes: + return {'status': 'redirect'} + else: + return super(ZMIConfigurationAJAXEditForm, self).get_ajax_output(changes) diff -r 0b1285117171 -r c68bcd7f6fe1 src/pyams_zmi/zmi/skin.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pyams_zmi/zmi/skin.py Sun Mar 11 11:16:42 2018 +0100 @@ -0,0 +1,81 @@ +# +# Copyright (c) 2008-2015 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_skin.interfaces import IUserSkinnable +from pyams_skin.layer import IPyAMSLayer +from pyams_utils.interfaces import MANAGE_SKIN_PERMISSION +from pyams_zmi.interfaces.menu import IPropertiesMenu +from pyams_zmi.layer import IAdminLayer + +# import packages +from pyams_form.form import AJAXEditForm +from pyams_pagelet.pagelet import pagelet_config +from pyams_skin.viewlet.menu import MenuItem, MenuDivider +from pyams_viewlet.viewlet import viewlet_config +from pyams_zmi.form import AdminDialogEditForm +from pyramid.view import view_config +from z3c.form import field + +from pyams_zmi import _ + + +# +# User skinnable properties configuration +# + +@viewlet_config(name='user-skin-properties.divider', context=IUserSkinnable, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SKIN_PERMISSION, weight=199) +class UserSkinnablePropertiesMenuDivider(MenuDivider): + """User skin properties menu divider""" + + +@viewlet_config(name='user-skin-properties.menu', context=IUserSkinnable, layer=IAdminLayer, manager=IPropertiesMenu, + permission=MANAGE_SKIN_PERMISSION, weight=200) +class UserSkinnablePropertiesMenuItem(MenuItem): + """User skin properties menu""" + + label = _("Graphic theme...") + icon_class = 'fa-paint-brush' + url = 'user-skin-properties.html' + modal_target = True + + +@pagelet_config(name='user-skin-properties.html', context=IUserSkinnable, layer=IPyAMSLayer, + permission=MANAGE_SKIN_PERMISSION) +class UserSkinnablePropertiesEditForm(AdminDialogEditForm): + """User skin properties edit form""" + + legend = _("Graphic theme elements") + label_css_class = 'control-label col-md-4' + input_css_class = 'col-md-8' + + @property + def fields(self): + fields = field.Fields(IUserSkinnable) + if not self.context.can_inherit_skin: + fields = fields.omit('inherit_skin') + return fields + + ajax_handler = 'user-skin-properties.json' + edit_permission = MANAGE_SKIN_PERMISSION + + +@view_config(name='user-skin-properties.json', context=IUserSkinnable, request_type=IPyAMSLayer, + permission=MANAGE_SKIN_PERMISSION, renderer='json', xhr=True) +class UserSkinnablePropertiesAJAXEditForm(AJAXEditForm, UserSkinnablePropertiesEditForm): + """User skin properties edit form, JSON renderer"""