class IProgressPortlet(IPortletDataProvider): """ Progress bar portlet """ label = schema.TextLine( title=_(u"Porlet title"), description=_(u"Title of the portlet. Leave empty if you don't want " "to display a title for this portlet"), default=u"% Done", required=False)
class AddForm(base.AddForm): """ Add portlet """ form_fields = form.Fields(IMetadataPortlet) label = _(u"Add Editing progress portlet") description = _(u"This portlet shows editing progress information") def create(self, data): """ Create """ return Assignment(label=data.get('label', u"Editing progress"))
class AddForm(base.AddForm): """ Add portlet """ form_fields = form.Fields(IProgressPortlet) label = _(u"Add Workflow Percentage Bar portlet") description = _(u"This portlet shows workflow progress information (%)") def create(self, data): """ Create """ return Assignment(label=data.get('label', u'% Done'))
class AddForm(base.AddForm): """ Add portlet """ form_fields = form.Fields(ITrailPortlet) label = _(u"Add Workflow states trail portlet") description = _(u"This portlet shows workflow states trail information") def create(self, data): """ Create """ return Assignment(label=data.get('label', u'Status'))
def nextUrl(self): """ Redirect to view as next_url """ status = queryAdapter(self.request, IStatusMessage) status.addStatusMessage(_('Changes saved'), type='info') next_url = self.parent.absolute_url() self.request.response.redirect(next_url)
def reset(self, action, data): """ Handle save action """ storage = queryAdapter(self.parent, IStorage) storage.delete_field(self.prefix) name = action.__name__.encode('utf-8') value = self.request.form.get(name, '') if value == 'ajax': return _(u"Changes saved") return self.nextUrl
def edit_reset(self, **kwargs): """ Reorder fields """ form = self.request.form form.update(kwargs) storage = queryAdapter(self.context, IStorage) storage.delete_fields() if form.get('ajax', False): return _('Reset complete') self.request.response.redirect(self.context.absolute_url())
def edit_reset(self, **kwargs): """ Reorder fields """ form = self.request.form form.update(kwargs) storage = queryAdapter(self.context, IStorage) storage.delete_fields() if form.get('ajax', False): return _('Reset complete') self.request.response.redirect(self.context.absolute_url())
def edit_reorder(self, **kwargs): """ Reorder fields """ form = self.request.form form.update(kwargs) order = form.get('order', []) storage = queryAdapter(self.context, IStorage) storage.reorder(order) if form.get('ajax', False): return _('Items reordered') self.request.response.redirect(self.context.absolute_url())
def edit_reorder(self, **kwargs): """ Reorder fields """ form = self.request.form form.update(kwargs) order = form.get('order', []) storage = queryAdapter(self.context, IStorage) storage.reorder(order) if form.get('ajax', False): return _('Items reordered') self.request.response.redirect(self.context.absolute_url())
def import_xml(self, **kwargs): """ Export """ upload_file = kwargs.get('import_file', None) if getattr(upload_file, 'read', None): upload_file = upload_file.read() xml = upload_file or '' if not xml.startswith('<?xml version="1.0"'): return _('Please provide a valid xml file') environ = SnapshotImportContext(self.context, 'utf-8') importer = queryMultiAdapter((self.context, environ), IBody, name='metadata.progress.xml') importer.body = xml return None
def import_xml(self, **kwargs): """ Export """ upload_file = kwargs.get('import_file', None) if getattr(upload_file, 'read', None): upload_file = upload_file.read() xml = upload_file or '' if not xml.startswith('<?xml version="1.0"'): return _('Please provide a valid xml file') environ = SnapshotImportContext(self.context, 'utf-8') importer = queryMultiAdapter((self.context, environ), IBody, name='metadata.progress.xml') importer.body = xml return None
def __call__(self, *args, **kwargs): if self.request.method != 'POST': return self.index() form = self.request.form form.update(kwargs) error = self.import_xml(**form) if error: to = self.__name__ msg = error else: to = '' msg = _('Configuration imported sucesfully') return self._redirect(msg=msg, to=to)
def __call__(self, *args, **kwargs): if self.request.method != 'POST': return self.index() form = self.request.form form.update(kwargs) error = self.import_xml(**form) if error: to = self.__name__ msg = error else: to = '' msg = _('Configuration imported sucesfully') return self._redirect(msg=msg, to=to)
class IProgressWidgetView(IProgressWidget): """ Common interface for widget in view mode """ prefix = schema.TextLine( title=_(u'Prefix'), description=_(u"Usually a schema field name") ) custom = schema.Bool( title=_(u"Custom"), description=_(u"Is this widget customized?"), readonly=True ) hidden = schema.Bool( title=_(u"Hidden"), description=_(u"Is this widget hidden?"), readonly=True ) def setPrefix(prefix): """ Update prefix """ def default(name): """ Get default value of a property given by name """ def ready(context): """ For the given context was this property correctly set """ def get(name, default): """ Get widget configuration by given name or return the default value """ def translate(message): """ Use zope.i18n to translate message """ def __call__(args, kwargs): """ Render widget
class IWorkflowProgress(Interface): """ These adapters provides progress information for an object By default, if you don't manually define any progress via ZMI the system tries to guess the progress using a very simple algorithm: - private = 33% - pending = 66% - published = 100% >>> IWorkflowProgress(sandbox).hasProgress False >>> IWorkflowProgress(sandbox).progress 33 >>> portal.portal_workflow.doActionFor(sandbox, 'submit') >>> IWorkflowProgress(sandbox).progress 66 >>> portal.portal_workflow.doActionFor(sandbox, 'publish') >>> IWorkflowProgress(sandbox).progress 100 You can also get a list of steps and their percentage: >>> IWorkflowProgress(sandbox).steps [(['private'], 33, ['Private'], ...), ...(['published'], 100, ['Published']...)] And % done (on a simple item it's the same as progress). This is useful within Collections >>> IWorkflowProgress(sandbox).done 100 You can always change progress values per state via ZMI: >>> wf = portal.portal_workflow.simple_publication_workflow >>> wf.states.pending.progress = 60 >>> wf.states.published.progress = 90 >>> IWorkflowProgress(sandbox).hasProgress True >>> IWorkflowProgress(sandbox).progress 90 Changing at least one state will disable the auto-detection mechanism. So don't forget to manually set progress for all possible states within your workflow: >>> portal.portal_workflow.doActionFor(sandbox, 'retract') >>> IWorkflowProgress(sandbox).progress 0 >>> portal.portal_workflow.doActionFor(sandbox, 'submit') >>> IWorkflowProgress(sandbox).progress 60 >>> IWorkflowProgress(sandbox).done 60 >>> IWorkflowProgress(sandbox).steps [(['pending'], 60, ['Pending review'],... (['published'], 90, ['Published']...)] """ progress = schema.Int( title=_(u"Progress"), description=_(u"For a folderish item, this can be the sum of all items" "with progress 100% / total items possible progress"), readonly=True, default=0) done = schema.Int( title=_(u"% Done"), description=_(u"For a folderish item, this can be the sum of all items" "progress / total items possible progress"), readonly=True, default=0) steps = schema.List( title=_(u"Steps"), description=_(u"A list of workflow steps with percetage"), readonly=True)
class ISimpleWidgetEdit(IProgressWidgetEdit): """ Simple widget edit """ labelEmpty = schema.Text( title=_(u'Message (not set)'), description=_(u'Message to be used when property is NOT filled'), required=False, default=u"Please set the {label} of this {context.portal_type}") labelReady = schema.Text( title=_(u'Message (ready)'), description=_(u'Message to be used when property is filled'), required=False, default=u"You added the {label}") iconEmpty = schema.TextLine( title=_(u'Icon (not set)'), description=_(u'Icon to be used when property is NOT filled'), required=False, default=u'eea-icon eea-icon-edit') iconReady = schema.TextLine( title=_(u"Icon (ready)"), description=_(u"Icon to be used when property is filled"), required=False, default=u'eea-icon eea-icon-check') link = schema.Text(title=_(u'Edit link'), description=_(u'Link where to edit this property'), required=False, default=u'edit#fieldsetlegend-default') linkLabel = schema.Text( title=_(u'Edit link label'), description=_(u'Human readable label for edit link'), required=False, default=u'Add {label}') condition = schema.Text( title=_(u'Condition (ready)'), description=_(u"Tal condition to mark this as ready"), required=False, default=u"python:value") hideReady = schema.Bool( title=_(u'Hide (ready)'), description=_(u"Hide this if it's ready (completed)"), required=False, default=False) states = schema.List( title=_(u'Workflow states'), description=_(u"Select workflow states where this will be visible"), required=False, default=[u'all'], value_type=schema.Choice( vocabulary=u"eea.progressbar.vocabulary.WorkflowStates"))
class EditForm(base.EditForm): """ Portlet edit """ form_fields = form.Fields(IProgressPortlet) label = _(u"Edit Workflow Percentage Bar portlet") description = _(u"This portlet shows workflow progress information (%)")
class EditForm(SubPageForm): """ Basic layer to edit progress widgets Assign these attributes in your subclass: - form_fields: Fields(Interface) """ form_fields = None def __init__(self, context, request): super(EditForm, self).__init__(context, request) self.parent = self.context.getParentNode() for key in self.request.form: if key.endswith('.labelEmpty'): self.prefix = key.split('.')[0] break @property def _data(self): """ Return view """ storage = queryAdapter(self.parent, IStorage) return storage.field(self.prefix, {}) def setUpWidgets(self, ignore_request=False): """ Sets up widgets """ self.adapters = {} for key, value in self.request.form.items(): if isinstance(value, str): value = value.decode('utf-8') self.request.form[key] = value self.widgets = setUpWidgets( self.form_fields, self.prefix, self.context, self.request, form=self, data=self._data, adapters=self.adapters, ignore_request=ignore_request) @formAction(_('Save'), condition=haveInputWidgets) def save(self, action, data): """ Handle save action """ storage = queryAdapter(self.parent, IStorage) storage.edit_field(self.prefix, **data) name = action.__name__.encode('utf-8') value = self.request.form.get(name, '') if value == 'ajax': return _(u"Changes saved") return self.nextUrl @formAction(_('Reset'), condition=haveInputWidgets) def reset(self, action, data): """ Handle save action """ storage = queryAdapter(self.parent, IStorage) storage.delete_field(self.prefix) name = action.__name__.encode('utf-8') value = self.request.form.get(name, '') if value == 'ajax': return _(u"Changes saved") return self.nextUrl @property def nextUrl(self): """ Redirect to view as next_url """ status = queryAdapter(self.request, IStatusMessage) status.addStatusMessage(_('Changes saved'), type='info') next_url = self.parent.absolute_url() self.request.response.redirect(next_url)
class EditForm(base.EditForm): """ Portlet edit """ form_fields = form.Fields(ITrailPortlet) label = _(u"Edit Workflow State Trail portlet") description = _(u"This portlet shows workflow states trail information")
class IWidgetDirective(IPageDirective): """ Progress bar widget directive """ for_ = fields.GlobalObject( title=u"The interface or class this view is for.", required=False ) view = fields.GlobalObject( title=_(u"View"), description=_(u"A class that provides attributes used by the view."), required=True, ) edit = fields.GlobalObject( title=_(u"Edit"), description=_(u"A class that provides attributes used by the edit."), required=True, ) name = schema.TextLine( title=u"The name of the field from ctype Schema", description=_(u"" u"E.g. prgressbar.widget.title or progressbar.widget.relatedItems"), required=False ) layer = fields.GlobalInterface( title=_(u"The layer the view is in."), description=_(u""" A skin is composed of layers. It is common to put skin specific views in a layer named after the skin. If the 'layer' attribute is not supplied, it defaults to 'default'."""), required=False, ) edit_permission = zcml.Permission( title=_(u"Edit Permission"), description=_(u"The permission needed to edit this widget."), required=False, ) view_permission = zcml.Permission( title=_(u"View Permission"), description=_(u"The permission needed to view this widget."), required=False, ) permission = zcml.Permission( title=_(u"Permission"), description=_(u"The permission needed to use the view or edit"), required=False )
class ISettings(Interface): """ Alchemy settings >>> ptool = queryUtility(IProgressTool) >>> settings = queryAdapter(ptool, ISettings) >>> settings <eea.progressbar.controlpanel.settings.ControlPanelAdapter object at...> >>> settings.viewletVisibleFor [u'Document', u'Collection', u'Folder', u'News Item', u'Event'] >>> settings.viewletVisibleFor = [u'Folder'] >>> settings.viewletVisibleFor [u'Folder'] >>> settings.trailViewletVisibleFor [u'Document', u'Collection', u'Folder', u'News Item', u'Event'] >>> settings.trailViewletVisibleFor = [u'Document'] >>> settings.trailViewletVisibleFor [u'Document'] >>> settings.metadataViewletVisibleFor [] >>> settings.metadataViewletVisibleFor = [u'Event'] >>> settings.metadataViewletVisibleFor [u'Event'] >>> settings.hidedStatesPercentage 0 >>> settings.hidedStatesPercentage = -1 >>> settings.hidedStatesPercentage -1 """ viewletVisibleFor = schema.List( title=_(u"Enable workflow percentage bar viewlet"), description=_(u"Workflow percentage bar viewlet is visible for the " u"following content-types"), required=False, default=[u"Document", u"Collection", u"Folder", u"News Item", u"Event"], value_type=schema.Choice( vocabulary="plone.app.vocabularies.ReallyUserFriendlyTypes") ) trailViewletVisibleFor = schema.List( title=_(u"Enable workflow steps trail viewlet"), description=_(u"Workflow steps trail viewlet is visible for the " u"following content-types"), required=False, default=[u"Document", u"Collection", u"Folder", u"News Item", u"Event"], value_type=schema.Choice( vocabulary="plone.app.vocabularies.ReallyUserFriendlyTypes") ) metadataViewletVisibleFor = schema.List( title=_(u"Enable editing progress viewlet"), description=_(u"Editing progress viewlet is visible for the " u"following content-types"), required=False, default=[], value_type=schema.Choice( vocabulary="plone.app.vocabularies.ReallyUserFriendlyTypes") ) hidedStatesPercentage = schema.Int( title=_(u"Ignore states lower than or equal to"), description=_(u"Ignore states that have a " u"defined percentage lower than or equal to"), required=False, default=0 )
class EditForm(base.EditForm): """ Portlet edit """ form_fields = form.Fields(IMetadataPortlet) label = _(u"Edit Editing progress portlet") description = _(u"This portlet shows editing progress information")
class IStorage(Interface): """ Annotations Storage >>> ptool = queryUtility(IProgressTool) >>> cid = ptool.invokeFactory('ProgressContentType', id='document') >>> sandbox = ptool[cid] >>> from eea.progressbar.interfaces import IStorage >>> storage = IStorage(sandbox) >>> storage <eea.progressbar.storage.handler.Storage object at ...> >>> storage.fields {} >>> storage.order [] """ fields = schema.Dict(title=_(u"Custom fields settings"), readonly=True) order = schema.List(title=_(u"Custom order of fields"), readonly=True) def add_field(name, kwargs): """ Add new field configuration >>> storage.add_field('title', icon='eea-icon', ready='Title added') 'title' >>> storage.add_field('effectiveDate') 'effectiveDate' >>> storage.add_field('expirationDate') 'expirationDate' """ def field(name, default): """ Get field by given name >>> storage.field('description', {}) {} >>> storage.field('title') {...'name': 'title'...} """ def edit_field(name, kwargs): """ Edit field configuration >>> storage.edit_field('description', icon="eea-icon-pencil") 'description' >>> storage.field('description') {...'name': 'description'...} """ def delete_field(name): """ Delete field configuration >>> storage.delete_field('relatedItems') Traceback (most recent call last): ... KeyError: 'relatedItems' >>> storage.delete_field('description') {...'name': 'description'...} >>> 'description' in storage.fields False """ def reorder(order): """ Reorder fields >>> storage.reorder(('effectiveDate', 'expirationDate', 'title')) >>> storage.order ['effectiveDate', 'expirationDate', 'title'] """ def delete_fields(): """ Delete all fields
""" EEA Relations Content Type """ from zope.interface import implements from Products.Archetypes import atapi from Products.ATContentTypes.content.folder import ATFolder from eea.progressbar.content.interfaces import IContentType from eea.progressbar.config import EEAMessageFactory as _ EditSchema = atapi.Schema(( atapi.StringField('ctype', schemata="default", vocabulary_factory='plone.app.vocabularies.ReallyUserFriendlyTypes', required=True, widget=atapi.SelectionWidget( label=_('Portal type'), description=_('Select portal type'), i18n_domain="eea" ) ), )) SCHEMA = ATFolder.schema.copy() + EditSchema.copy() def finalize_schema(schema=SCHEMA): """ Update schema """ for field in schema.fields(): field.write_permission = 'Manage portal' if field.schemata != 'default': field.required = False
def state_title(self): """ Current state title """ return _('Total progress')
def state_title(self): """ Current state title """ return _('Total progress')
class EEASchemaExtender(object): """ Schema extender for progress bar fields """ implements(ISchemaExtender, IBrowserLayerAwareExtender) layer = IProgressBarLayer fieldsProgress = (EEABooleanField( name='disableProgressBarViewlet', schemata='settings', default=False, searchable=False, widget=BooleanWidget( label=_('Hide Workflow Percentage Bar Viewlet'), description=_('Hide Workflow Percentage Bar viewlet for ' 'this context/page'), )), ) fieldsTrail = (EEABooleanField( name='disableProgressTrailViewlet', schemata='settings', default=False, searchable=False, widget=BooleanWidget( label=_('Hide Workflow Steps Trail Viewlet'), description=_('Hide Workflow Steps Trail viewlet for ' 'this context/page'), )), ) fieldsMetadata = (EEABooleanField( name='disableMetadataViewletVisibleFor', schemata='settings', default=False, searchable=False, widget=BooleanWidget( label=_('Hide Editing Progress Viewlet'), description=_('Hide Editing Progress viewlet for ' 'this context/page'), )), ) def __init__(self, context): self.context = context def getFields(self): """ Returns provenance list field """ ptool = queryUtility(IProgressTool) settings = queryAdapter(ptool, ISettings) ctype = getattr(self.context, 'portal_type', '') fields = () if not settings: return fields allowed = settings.viewletVisibleFor or [] if ctype in allowed: fields += self.fieldsProgress allowed = settings.trailViewletVisibleFor or [] if ctype in allowed: fields += self.fieldsTrail allowed = settings.metadataViewletVisibleFor or [] if ctype in allowed: fields += self.fieldsMetadata return fields