src/pyams_content/shared/common/zmi/types.py
changeset 276 78422a1c4228
child 288 3f7f7a1624f0
equal deleted inserted replaced
275:0c63253d75bd 276:78422a1c4228
       
     1 #
       
     2 # Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
       
     3 # All Rights Reserved.
       
     4 #
       
     5 # This software is subject to the provisions of the Zope Public License,
       
     6 # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
       
     7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
       
     8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
       
     9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
       
    10 # FOR A PARTICULAR PURPOSE.
       
    11 #
       
    12 
       
    13 __docformat__ = 'restructuredtext'
       
    14 
       
    15 # import standard library
       
    16 import json
       
    17 
       
    18 # import interfaces
       
    19 from pyams_content.interfaces import MANAGE_TOOL_PERMISSION
       
    20 from pyams_content.shared.common.interfaces.types import ITypedSharedTool, ITypedDataManager, \
       
    21     IBaseDataType, IDataType, ISubType
       
    22 from pyams_i18n.interfaces import II18n
       
    23 from pyams_skin.interfaces.container import ITableElementName
       
    24 from pyams_skin.interfaces.viewlet import IWidgetTitleViewletManager
       
    25 from pyams_skin.layer import IPyAMSLayer
       
    26 from pyams_viewlet.interfaces import IViewletManager
       
    27 from pyams_zmi.interfaces.menu import IPropertiesMenu
       
    28 from pyams_zmi.layer import IAdminLayer
       
    29 from z3c.form.interfaces import DISPLAY_MODE, IDataExtractedEvent
       
    30 from z3c.table.interfaces import IValues, IColumn
       
    31 
       
    32 # import packages
       
    33 from pyams_content.shared.common.types import DataType, SubType
       
    34 from pyams_form.form import AJAXAddForm, AJAXEditForm
       
    35 from pyams_form.security import ProtectedFormObjectMixin
       
    36 from pyams_pagelet.pagelet import pagelet_config
       
    37 from pyams_skin.table import BaseTable, SorterColumn, TrashColumn, NameColumn, ActionColumn
       
    38 from pyams_skin.viewlet.menu import MenuItem
       
    39 from pyams_skin.viewlet.toolbar import ToolbarAction
       
    40 from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter, ContextRequestAdapter
       
    41 from pyams_utils.traversing import get_parent
       
    42 from pyams_utils.unicode import translate_string
       
    43 from pyams_utils.url import absolute_url
       
    44 from pyams_viewlet.viewlet import viewlet_config
       
    45 from pyams_zmi.form import AdminDialogAddForm, AdminDialogEditForm
       
    46 from pyams_zmi.view import ContainerAdminView
       
    47 from pyramid.decorator import reify
       
    48 from pyramid.events import subscriber
       
    49 from pyramid.exceptions import NotFound
       
    50 from pyramid.view import view_config
       
    51 from z3c.form import field
       
    52 from zope.interface import Invalid
       
    53 
       
    54 from pyams_content import _
       
    55 
       
    56 
       
    57 @viewlet_config(name='data-types.menu', context=ITypedSharedTool, layer=IAdminLayer,
       
    58                 manager=IPropertiesMenu, permission=MANAGE_TOOL_PERMISSION, weight=20)
       
    59 class TypedSharedToolTypesMenu(MenuItem):
       
    60     """Typed shared tool types menu"""
       
    61 
       
    62     label = _("Data types")
       
    63     icon_class = 'fa-folder-o'
       
    64     url = '#data-types.html'
       
    65 
       
    66 
       
    67 #
       
    68 # Typed shared data types manager target views
       
    69 #
       
    70 
       
    71 class TypedSharedToolTypesTable(ProtectedFormObjectMixin, BaseTable):
       
    72     """Typed shared tool types table"""
       
    73 
       
    74     id = 'types_list'
       
    75     hide_header = True
       
    76     sortOn = None
       
    77 
       
    78     @property
       
    79     def cssClasses(self):
       
    80         classes = ['table', 'table-bordered', 'table-striped', 'table-hover', 'table-tight']
       
    81         permission = self.permission
       
    82         if (not permission) or self.request.has_permission(permission, self.context):
       
    83             classes.append('table-dnd')
       
    84         return {'table': ' '.join(classes)}
       
    85 
       
    86     @property
       
    87     def data_attributes(self):
       
    88         attributes = super(TypedSharedToolTypesTable, self).data_attributes
       
    89         attributes['table'] = {'id': self.id,
       
    90                                'data-ams-plugins': 'pyams_content',
       
    91                                'data-ams-plugin-pyams_content-src':
       
    92                                    '/--static--/pyams_content/js/pyams_content{MyAMS.devext}.js',
       
    93                                'data-ams-location': absolute_url(ITypedDataManager(self.context), self.request),
       
    94                                'data-ams-tablednd-drag-handle': 'td.sorter',
       
    95                                'data-ams-tablednd-drop-target': 'set-types-order.json'}
       
    96         return attributes
       
    97 
       
    98     @reify
       
    99     def values(self):
       
   100         return list(super(TypedSharedToolTypesTable, self).values)
       
   101 
       
   102     def render(self):
       
   103         if not self.values:
       
   104             translate = self.request.localizer.translate
       
   105             return translate(_("No currently defined data type."))
       
   106         return super(TypedSharedToolTypesTable, self).render()
       
   107 
       
   108 
       
   109 @adapter_config(context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable), provides=IValues)
       
   110 class TypedSharedToolTypesValues(ContextRequestViewAdapter):
       
   111     """Typed shared tool types table values adapter"""
       
   112 
       
   113     @property
       
   114     def values(self):
       
   115         return ITypedDataManager(self.context).values()
       
   116 
       
   117 
       
   118 @adapter_config(name='sorter', context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable),
       
   119                 provides=IColumn)
       
   120 class TypedSharedToolTypesSorterColumn(ProtectedFormObjectMixin, SorterColumn):
       
   121     """Typed shared tool types sorter column"""
       
   122 
       
   123 
       
   124 @adapter_config(name='name', context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable),
       
   125                 provides=IColumn)
       
   126 class TypedSharedToolTypesNameColumn(NameColumn):
       
   127     """Typed shared tool types name column"""
       
   128 
       
   129     _header = _("Data type label")
       
   130 
       
   131     def renderCell(self, item):
       
   132         return '<span data-ams-stop-propagation="true" ' \
       
   133                '      data-ams-click-handler="PyAMS_content.types.switchSubtypes">' \
       
   134                '    <span class="small hint" title="{hint}" data-ams-hint-gravity="e">' \
       
   135                '        <i class="fa fa-plus-square-o switch"></i>' \
       
   136                '    </span>' \
       
   137                '</span>&nbsp;&nbsp;&nbsp;<span class="title">{title}</span>' \
       
   138                '<div class="inner-table-form subtypes margin-x-10 margin-bottom-0 padding-left-5"></div>'.format(
       
   139             hint=self.request.localizer.translate(_("Click to see subtypes")),
       
   140             title=super(TypedSharedToolTypesNameColumn, self).renderCell(item))
       
   141 
       
   142 
       
   143 @adapter_config(name='paragraphs', context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable),
       
   144                 provides=IColumn)
       
   145 class TypedSharedToolTypesParagraphsColumn(ActionColumn):
       
   146     """Typed shared tool types paragraphs column"""
       
   147 
       
   148     weight = 100
       
   149 
       
   150     icon_class = 'fa fa-fw fa-paragraph'
       
   151     icon_hint = _("Default paragraphs")
       
   152 
       
   153     url = 'paragraphs-dialog.html'
       
   154     modal_target = True
       
   155 
       
   156     permission = MANAGE_TOOL_PERMISSION
       
   157 
       
   158 
       
   159 @adapter_config(name='associations', context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable),
       
   160                 provides=IColumn)
       
   161 class TypedSharedToolTypesAssociationsColumn(ActionColumn):
       
   162     """Typed shared tool types associations column"""
       
   163 
       
   164     weight = 110
       
   165 
       
   166     icon_class = 'fa fa-fw fa-link'
       
   167     icon_hint = _("Default associations")
       
   168 
       
   169     url = 'associations-dialog.html'
       
   170     modal_target = True
       
   171 
       
   172     permission = MANAGE_TOOL_PERMISSION
       
   173 
       
   174 
       
   175 @adapter_config(name='trash', context=(ITypedSharedTool, IPyAMSLayer, TypedSharedToolTypesTable),
       
   176                 provides=IColumn)
       
   177 class TypedSharedToolTypesTrashColumn(TrashColumn):
       
   178     """Typed shared tool types trash column"""
       
   179 
       
   180     permission = MANAGE_TOOL_PERMISSION
       
   181 
       
   182 
       
   183 @pagelet_config(name='data-types.html', context=ITypedSharedTool, layer=IPyAMSLayer,
       
   184                 permission=MANAGE_TOOL_PERMISSION)
       
   185 class TypedSharedToolTypesView(ContainerAdminView):
       
   186     """Typed shared tool types view"""
       
   187 
       
   188     title = _("Content data types")
       
   189     table_class = TypedSharedToolTypesTable
       
   190 
       
   191 
       
   192 #
       
   193 # Typed shared data types manager views
       
   194 #
       
   195 
       
   196 @view_config(name='delete-element.json', context=ITypedDataManager, request_type=IPyAMSLayer,
       
   197              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   198 def delete_data_type(request):
       
   199     """Data type delete view"""
       
   200     translate = request.localizer.translate
       
   201     name = request.params.get('object_name')
       
   202     if not name:
       
   203         return {'status': 'message',
       
   204                 'messagebox': {'status': 'error',
       
   205                                'content': translate(_("No provided object_name argument!"))}}
       
   206     if name not in request.context:
       
   207         return {'status': 'message',
       
   208                 'messagebox': {'status': 'error',
       
   209                                'content': translate(_("Given data type doesn't exist!"))}}
       
   210     del request.context[name]
       
   211     return {'status': 'success'}
       
   212 
       
   213 
       
   214 @view_config(name='set-types-order.json', context=ITypedDataManager, request_type=IPyAMSLayer,
       
   215              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   216 def set_data_types_order(request):
       
   217     """Update data types order"""
       
   218     order = list(map(str, json.loads(request.params.get('names'))))
       
   219     request.context.updateOrder(order)
       
   220     return {'status': 'success'}
       
   221 
       
   222 
       
   223 #
       
   224 # Data type views
       
   225 #
       
   226 
       
   227 @adapter_config(context=(IBaseDataType, IPyAMSLayer), provides=ITableElementName)
       
   228 class DataTypeElementNameAdapter(ContextRequestAdapter):
       
   229     """Types shared tool types name adapter"""
       
   230 
       
   231     @property
       
   232     def name(self):
       
   233         return II18n(self.context).query_attribute('label', request=self.request)
       
   234 
       
   235 
       
   236 @viewlet_config(name='add-data-type.action', context=ITypedSharedTool, layer=IAdminLayer,
       
   237                 view=TypedSharedToolTypesView, manager=IWidgetTitleViewletManager,
       
   238                 permission=MANAGE_TOOL_PERMISSION, weight=1)
       
   239 class DataTypeAddAction(ToolbarAction):
       
   240     """Data type adding action"""
       
   241 
       
   242     label = _("Add data type")
       
   243     label_css_class = 'fa fa-fw fa-plus'
       
   244     url = 'add-data-type.html'
       
   245     modal_target = True
       
   246 
       
   247 
       
   248 @pagelet_config(name='add-data-type.html', context=ITypedSharedTool, layer=IPyAMSLayer,
       
   249                 permission=MANAGE_TOOL_PERMISSION)
       
   250 class DataTypeAddForm(AdminDialogAddForm):
       
   251     """Data type add form"""
       
   252 
       
   253     legend = _("Add new data type")
       
   254     icon_css_class = 'fa fa-fw fa-folder-o'
       
   255     label_css_class = 'control-label col-md-4'
       
   256     input_css_class = 'col-md-8'
       
   257 
       
   258     fields = field.Fields(IDataType).omit('__parent__', '__name__')
       
   259 
       
   260     ajax_handler = 'add-data-type.json'
       
   261     edit_permission = MANAGE_TOOL_PERMISSION
       
   262 
       
   263     def create(self, data):
       
   264         return DataType()
       
   265 
       
   266     def add(self, object):
       
   267         name = translate_string(object.name, spaces='-')
       
   268         ITypedDataManager(self.context)[name] = object
       
   269 
       
   270     def nextURL(self):
       
   271         return absolute_url(self.context, self.request, 'admin#data-types.html')
       
   272 
       
   273 
       
   274 @subscriber(IDataExtractedEvent, form_selector=DataTypeAddForm)
       
   275 def handle_datatype_add_form_data_extraction(event):
       
   276     """Check new data type for existing name"""
       
   277     context = event.form.context
       
   278     manager = ITypedDataManager(context)
       
   279     name = event.data.get('name')
       
   280     if translate_string(name, spaces='-') in manager:
       
   281         event.form.widgets.errors += (Invalid(_("Specified type name is already used!")),)
       
   282 
       
   283 
       
   284 @view_config(name='add-data-type.json', context=ITypedSharedTool, request_type=IPyAMSLayer,
       
   285              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   286 class DataTypeAJAXAddForm(AJAXAddForm, DataTypeAddForm):
       
   287     """Data type add form, JSON renderer"""
       
   288 
       
   289     def nextURL(self):
       
   290         return '#data-types.html'
       
   291 
       
   292 
       
   293 @pagelet_config(name='properties.html', context=IDataType, layer=IPyAMSLayer, permission=MANAGE_TOOL_PERMISSION)
       
   294 class DataTypeEditForm(AdminDialogEditForm):
       
   295     """Data type edit form"""
       
   296 
       
   297     legend = _("Data type properties")
       
   298     icon_css_class = 'fa fa-fw fa-folder-o'
       
   299     label_css_class = 'control-label col-md-4'
       
   300     input_css_class = 'col-md-8'
       
   301 
       
   302     fields = field.Fields(IDataType).omit('__parent__', '__name__')
       
   303 
       
   304     ajax_handler = 'properties.json'
       
   305     edit_permission = MANAGE_TOOL_PERMISSION
       
   306 
       
   307     def updateWidgets(self, prefix=None):
       
   308         super(DataTypeEditForm, self).updateWidgets(prefix)
       
   309         if 'name' in self.widgets:
       
   310             self.widgets['name'].mode = DISPLAY_MODE
       
   311 
       
   312 
       
   313 @view_config(name='properties.json', context=IDataType, request_type=IPyAMSLayer,
       
   314              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   315 class DataTypeAJAXEditForm(AJAXEditForm, DataTypeEditForm):
       
   316     """Data type edit form, JSON renderer"""
       
   317 
       
   318 
       
   319 #
       
   320 # Subtypes views
       
   321 #
       
   322 
       
   323 class DatatypeSubtypesTable(BaseTable):
       
   324     """Data type subtypes table"""
       
   325 
       
   326     @property
       
   327     def id(self):
       
   328         return 'subtypes_{0}_list'.format(self.context.__name__)
       
   329 
       
   330     hide_header = True
       
   331     sortOn = None
       
   332 
       
   333     widget_class = 'ams-widget margin-top-5'
       
   334     cssClasses = {'table': 'table table-bordered table-striped table-hover table-tight table-dnd'}
       
   335 
       
   336     @property
       
   337     def data_attributes(self):
       
   338         attributes = super(DatatypeSubtypesTable, self).data_attributes
       
   339         attributes['table'] = {'id': self.id,
       
   340                                'data-ams-plugins': 'pyams_content',
       
   341                                'data-ams-plugin-pyams_content-src':
       
   342                                    '/--static--/pyams_content/js/pyams_content{MyAMS.devext}.js',
       
   343                                'data-ams-location': absolute_url(self.context, self.request),
       
   344                                'data-ams-tablednd-drag-handle': 'td.sorter',
       
   345                                'data-ams-tablednd-drop-target': 'set-subtypes-order.json'}
       
   346         attributes.setdefault('tr', {}).setdefault('data-ams-stop-propagation', 'true')
       
   347         return attributes
       
   348 
       
   349     @reify
       
   350     def values(self):
       
   351         return list(super(DatatypeSubtypesTable, self).values)
       
   352 
       
   353 
       
   354 @adapter_config(context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable), provides=IValues)
       
   355 class DatatypeSubtypesTableValues(ContextRequestViewAdapter):
       
   356     """Data type subtypes table values adapter"""
       
   357 
       
   358     @property
       
   359     def values(self):
       
   360         return self.context.values()
       
   361 
       
   362 
       
   363 @adapter_config(name='sorter', context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable), provides=IColumn)
       
   364 class DatatypeSubtypesTableSorterColumn(SorterColumn):
       
   365     """Data type subtypes table sorter column"""
       
   366 
       
   367 
       
   368 @adapter_config(name='name', context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable), provides=IColumn)
       
   369 class DatatypeSubtypesTableNameColumn(NameColumn):
       
   370     """Data type subtypes table name column"""
       
   371 
       
   372     _header = _("Subtype label")
       
   373 
       
   374     def renderHeadCell(self):
       
   375         result = super(DatatypeSubtypesTableNameColumn, self).renderHeadCell()
       
   376         registry = self.request.registry
       
   377         viewlet = registry.queryMultiAdapter((self.context, self.request, self.table), IViewletManager,
       
   378                                              name='pyams.widget_title')
       
   379         if viewlet is not None:
       
   380             viewlet.update()
       
   381             result += viewlet.render()
       
   382         return result
       
   383 
       
   384 
       
   385 @adapter_config(name='paragraphs', context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable),
       
   386                 provides=IColumn)
       
   387 class DatatypeSubtypesTableParagraphsColumn(ActionColumn):
       
   388     """Data type subtypes paragraphs column"""
       
   389 
       
   390     weight = 100
       
   391 
       
   392     icon_class = 'fa fa-fw fa-paragraph'
       
   393     icon_hint = _("Default paragraphs")
       
   394 
       
   395     url = 'paragraphs-dialog.html'
       
   396     modal_target = True
       
   397 
       
   398     permission = MANAGE_TOOL_PERMISSION
       
   399 
       
   400 
       
   401 @adapter_config(name='associations', context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable),
       
   402                 provides=IColumn)
       
   403 class DatatypeSubtypesTableAssociationsColumn(ActionColumn):
       
   404     """Data type subtypes associations column"""
       
   405 
       
   406     weight = 110
       
   407 
       
   408     icon_class = 'fa fa-fw fa-link'
       
   409     icon_hint = _("Default associations")
       
   410 
       
   411     url = 'associations-dialog.html'
       
   412     modal_target = True
       
   413 
       
   414     permission = MANAGE_TOOL_PERMISSION
       
   415 
       
   416 
       
   417 @adapter_config(name='trash', context=(IDataType, IPyAMSLayer, DatatypeSubtypesTable), provides=IColumn)
       
   418 class DatatypeSubtypesTableTrashColumn(TrashColumn):
       
   419     """Data type subtypes table trash column"""
       
   420 
       
   421     permission = MANAGE_TOOL_PERMISSION
       
   422 
       
   423 
       
   424 @view_config(name='get-subtypes-table.json', context=ITypedDataManager, request_type=IPyAMSLayer,
       
   425              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   426 def get_subtypes_table(request):
       
   427     """Get subtypes table"""
       
   428     datatype = request.context.get(str(request.params.get('object_name')))
       
   429     if datatype is None:
       
   430         raise NotFound()
       
   431     table = DatatypeSubtypesTable(datatype, request)
       
   432     table.update()
       
   433     return table.render()
       
   434 
       
   435 
       
   436 @view_config(name='set-subtypes-order.json', context=IDataType, request_type=IPyAMSLayer,
       
   437              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   438 def set_subtypes_order(request):
       
   439     """Update subtypes order"""
       
   440     order = list(map(str, json.loads(request.params.get('names'))))
       
   441     request.context.updateOrder(order)
       
   442     return {'status': 'success'}
       
   443 
       
   444 
       
   445 @view_config(name='delete-element.json', context=IDataType, request_type=IPyAMSLayer,
       
   446              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   447 def delete_subtype(request):
       
   448     """Data subtype delete view"""
       
   449     translate = request.localizer.translate
       
   450     name = request.params.get('object_name')
       
   451     if not name:
       
   452         return {'status': 'message',
       
   453                 'messagebox': {'status': 'error',
       
   454                                'content': translate(_("No provided object_name argument!"))}}
       
   455     if name not in request.context:
       
   456         return {'status': 'message',
       
   457                 'messagebox': {'status': 'error',
       
   458                                'content': translate(_("Given data subtype doesn't exist!"))}}
       
   459     del request.context[name]
       
   460     return {'status': 'success'}
       
   461 
       
   462 
       
   463 #
       
   464 # Data sub-types views
       
   465 #
       
   466 
       
   467 
       
   468 @viewlet_config(name='add-data-subtype.action', context=IDataType, layer=IPyAMSLayer,
       
   469                 view=DatatypeSubtypesTable, manager=IWidgetTitleViewletManager,
       
   470                 permission=MANAGE_TOOL_PERMISSION, weight=1)
       
   471 class DataSubtypeAddAction(ToolbarAction):
       
   472     """Data subtype adding action"""
       
   473 
       
   474     label = _("Add subtype")
       
   475     label_css_class = 'fa fa-fw fa-plus'
       
   476     url = 'add-data-subtype.html'
       
   477     modal_target = True
       
   478 
       
   479 
       
   480 @pagelet_config(name='add-data-subtype.html', context=IDataType, layer=IPyAMSLayer,
       
   481                 permission=MANAGE_TOOL_PERMISSION)
       
   482 class DataSubtypeAddForm(AdminDialogAddForm):
       
   483     """Data subtype add form"""
       
   484 
       
   485     legend = _("Add new subtype")
       
   486     icon_css_class = 'fa fa-fw fa-folder-o'
       
   487     label_css_class = 'control-label col-md-4'
       
   488     input_css_class = 'col-md-8'
       
   489 
       
   490     fields = field.Fields(ISubType).omit('__parent__', '__name__')
       
   491 
       
   492     ajax_handler = 'add-data-subtype.json'
       
   493     edit_permission = MANAGE_TOOL_PERMISSION
       
   494 
       
   495     def create(self, data):
       
   496         return SubType()
       
   497 
       
   498     def add(self, object):
       
   499         name = translate_string(object.name, spaces='-')
       
   500         IDataType(self.context)[name] = object
       
   501 
       
   502     def nextURL(self):
       
   503         return absolute_url(self.context, self.request, 'admin#data-types.html')
       
   504 
       
   505 
       
   506 @subscriber(IDataExtractedEvent, form_selector=DataSubtypeAddForm)
       
   507 def handle_subtype_add_form_data_extraction(event):
       
   508     """Check new data subtype for existing name"""
       
   509     context = event.form.context
       
   510     manager = IDataType(context)
       
   511     name = event.data.get('name')
       
   512     if translate_string(name, spaces='-') in manager:
       
   513         event.form.widgets.errors += (Invalid(_("Specified subtype name is already used!")),)
       
   514 
       
   515 
       
   516 @view_config(name='add-data-subtype.json', context=IDataType, request_type=IPyAMSLayer,
       
   517              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   518 class DataSubtypeAJAXAddForm(AJAXAddForm, DataSubtypeAddForm):
       
   519     """Data subtype add form, JSON renderer"""
       
   520 
       
   521     def get_ajax_output(self, changes):
       
   522         subtypes_table = DatatypeSubtypesTable(self.context, self.request)
       
   523         subtypes_table.update()
       
   524         return {'status': 'success',
       
   525                 'message': self.request.localizer.translate(_("Subtype was correctly added.")),
       
   526                 'events': [{
       
   527                     'event': 'PyAMS_content.changed_item',
       
   528                     'options': {
       
   529                         'handler': 'PyAMS_content.types.refreshSubtypes',
       
   530                         'object_name': subtypes_table.id,
       
   531                         'table': subtypes_table.render()
       
   532                     }
       
   533                 }]}
       
   534 
       
   535 
       
   536 @pagelet_config(name='properties.html', context=ISubType, layer=IPyAMSLayer, permission=MANAGE_TOOL_PERMISSION)
       
   537 class DataSubtypeEditForm(AdminDialogEditForm):
       
   538     """Data subtype edit form"""
       
   539 
       
   540     legend = _("Data subtype properties")
       
   541     icon_css_class = 'fa fa-fw fa-folder-o'
       
   542     label_css_class = 'control-label col-md-4'
       
   543     input_css_class = 'col-md-8'
       
   544 
       
   545     fields = field.Fields(ISubType).omit('__parent__', '__name__')
       
   546 
       
   547     ajax_handler = 'properties.json'
       
   548     edit_permission = MANAGE_TOOL_PERMISSION
       
   549 
       
   550     def updateWidgets(self, prefix=None):
       
   551         super(DataSubtypeEditForm, self).updateWidgets(prefix)
       
   552         if 'name' in self.widgets:
       
   553             self.widgets['name'].mode = DISPLAY_MODE
       
   554 
       
   555 
       
   556 @view_config(name='properties.json', context=ISubType, request_type=IPyAMSLayer,
       
   557              permission=MANAGE_TOOL_PERMISSION, renderer='json', xhr=True)
       
   558 class DataSubtypeAJAXEditForm(AJAXEditForm, DataSubtypeEditForm):
       
   559     """Data subtype edit form, JSON renderer"""
       
   560 
       
   561     def get_ajax_output(self, changes):
       
   562         if 'label' in changes.get(IBaseDataType, ()):
       
   563             target = get_parent(self.context, IDataType)
       
   564             subtypes_table = DatatypeSubtypesTable(target, self.request)
       
   565             subtypes_table.update()
       
   566             return {'status': 'success',
       
   567                     'message': self.request.localizer.translate(self.successMessage),
       
   568                     'events': [{
       
   569                         'event': 'PyAMS_content.changed_item',
       
   570                         'options': {
       
   571                             'handler': 'PyAMS_content.types.refreshSubtypes',
       
   572                             'object_name': subtypes_table.id,
       
   573                             'table': subtypes_table.render()
       
   574                         }
       
   575                     }]}
       
   576         else:
       
   577             return super(DataSubtypeAJAXEditForm, self).get_ajax_output(changes)