class IRelatedDocuments(form.Schema): """The relatedDocument behvavior is a opengever.document specific relateditems behavior. Only allows opengever.documents """ relatedItems = RelationList( title=_(u'label_related_documents', default=u'Related Documents'), default=[], value_type=RelationChoice( title=u"Related", source=RepositoryPathSourceBinder( portal_type=("opengever.document.document", "ftw.mail.mail"), navigation_tree_query={ 'object_provides': [ 'opengever.repository.repositoryroot.IRepositoryRoot', 'opengever.repository.repositoryfolder.' + 'IRepositoryFolderSchema', 'opengever.dossier.behaviors.dossier.IDossierMarker', 'opengever.document.document.IDocumentSchema', 'ftw.mail.mail.IMail', ] }), ), required=False, ) form.fieldset( u'common', label=_(u'fieldset_common', default=u'Common'), fields=[ u'relatedItems', ], )
def get_items(self): return [ { "class": "document_author", "label": _("label_by_author", default="by"), "content": self.context.document_author, "replace": False, }, { "class": "documentModified", "label": _("label_start_byline", default="from"), "content": self.document_date(), "replace": False, }, { "class": "sequenceNumber", "label": _("label_sequence_number", default="Sequence Number"), "content": self.sequence_number(), "replace": False, }, { "class": "referenceNumber", "label": _("label_reference_number", default="Reference Number"), "content": self.reference_number(), "replace": False, }, ]
def cancel(self, obj): """Cancels a single document checkout. """ if IMail.providedBy(obj): msg = _(u'msg_cancel_checkout_on_mail_not_possible', default=u'Could not cancel checkout on document ${title}, ' 'mails does not support the checkin checkout process.', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message( message=msg, request=self.request, type='error') return # check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is cancel allowed for this document? if not manager.is_cancel_allowed(): msg = _(u'Could not cancel checkout on document ${title}', mapping=dict(title=obj.Title().decode('utf-8'))) api.portal.show_message( message=msg, request=self.request, type='error') else: manager.cancel() # notify the user msg = _(u'Cancel checkout: ${title}', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message( message=msg, request=self.request, type='info')
def validate(self, value): """An mail upload as og.document should't be possible, it should be added as Mail object (see opengever.mail). Only .docx files are accepted into proposal documents. Removing a file is not an option for proposal documents. """ if self.request.form.get('form.widgets.file.action') == 'remove': if self.is_proposal_upload(): raise Invalid(_( u'error_proposal_no_document', default=(u"It's not possible to have no file in proposal documents.") )) if not value: return if not value.filename: return if self.is_email_upload(value.filename): self.raise_invalid() if self.is_proposal_upload(): if not os.path.splitext(value.filename)[1].lower() == '.docx': raise Invalid(_( u'error_proposal_document_type', default=(u"It's not possible to have non-.docx documents as proposal documents.") ))
def get_items(self): return [{ 'class': 'document_author', 'label': _('label_by_author', default='by'), 'content': self.context.document_author, 'replace': False }, { 'class': 'documentModified', 'label': _('label_start_byline', default='from'), 'content': self.document_date(), 'replace': False }, { 'class': 'sequenceNumber', 'label': _('label_sequence_number', default='Sequence Number'), 'content': self.sequence_number(), 'replace': False }, { 'class': 'referenceNumber', 'label': _('label_reference_number', default='Reference Number'), 'content': self.reference_number(), 'replace': False }]
def validate(self, value): """An mail upload as og.document should't be possible, it should be added as Mail object (see opengever.mail). Only .docx files are accepted into proposal documents. Removing a file is not an option for proposal documents. """ if self.request.form.get('form.widgets.file.action') == 'remove': if self.is_proposal_upload(): raise Invalid( _(u'error_proposal_no_document', default= (u"It's not possible to have no file in proposal documents." ))) if not value: return if not value.filename: return if self.is_email_upload(value.filename): self.raise_invalid() if self.is_proposal_upload(): if not os.path.splitext(value.filename)[1].lower() == '.docx': raise Invalid( _(u'error_proposal_document_type', default= (u"It's not possible to have non-.docx documents as proposal documents." )))
class IDocumentSchema(model.Schema): """Document Schema Interface.""" model.fieldset( u'common', label=_(u'fieldset_common', u'Common'), fields=[ u'title', u'file', ], ) dexteritytextindexer.searchable('title') form.order_before(title='IDocumentMetadata.description') title = schema.TextLine(title=_(u'label_title', default=u'Title'), required=False) model.primary('file') form.order_after(file='IDocumentMetadata.document_author') file = field.NamedBlobFile( title=_(u'label_file', default='File'), description=_(u'help_file', default=''), required=False, ) @invariant def title_or_file_required(data): if not data.title and not data.file: raise Invalid( _(u'error_title_or_file_required', default=u'Either the title or the file is ' 'required.'))
def __call__(self): if not self.request.get('paths'): msg = _(u'error_no_items', default=u'You have not selected any Items') IStatusMessage(self.request).addStatusMessage(msg, type='error') return_temp = self.request.get('orig_template', self.context.absolute_url()) return self.request.RESPONSE.redirect(return_temp) documents = self.get_selected_documents() # generate the xls data with the XLSReporter reporter = XLSReporter(self.request, self.get_document_attributes(), documents) data = reporter() if not data: msg = _(u'Could not generate the report.') IStatusMessage(self.request).addStatusMessage(msg, type='error') return self.request.RESPONSE.redirect(self.context.absolute_url()) response = self.request.RESPONSE response.setHeader( 'Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) set_attachment_content_disposition(self.request, "document_report.xlsx") return data
def _columns(self): return [ {'id': 'reference', 'title': _(u'label_document_reference_number')}, {'id': 'sequence_number', 'title': _(u'label_document_sequence_number')}, {'id': 'Title', 'sort_index': 'sortable_title', 'title': _(u'label_title', default=u'Title')}, {'id': 'document_author', 'title': _(u'label_author', default=u'Author'), 'sort_index': 'sortable_author', 'transform': readable_author}, {'id': 'document_date', 'title': _(u'label_document_date', default=u'Document Date'), 'transform': readable_date}, {'id': 'receipt_date', 'title': _(u'label_document_receipt_date'), 'transform': readable_date}, {'id': 'delivery_date', 'title': _(u'label_document_delivery_date'), 'transform': readable_date}, {'id': 'checked_out', 'title': _(u'label_document_checked_out_by'), 'transform': readable_author}, {'id': 'public_trial', 'title': _(u'label_public_trial'), 'transform': StringTranslater( self.request, 'opengever.base').translate}, {'id': 'containing_dossier', 'title': _(u'label_dossier_title')}, ]
def __call__(self): if not self.request.get('paths'): msg = _( u'error_no_items', default=u'You have not selected any Items') IStatusMessage(self.request).addStatusMessage(msg, type='error') return_temp = self.request.get( 'orig_template', self.context.absolute_url()) return self.request.RESPONSE.redirect(return_temp) documents = self.get_selected_documents() # generate the xls data with the XLSReporter reporter = XLSReporter( self.request, self.get_document_attributes(), documents) data = reporter() if not data: msg = _(u'Could not generate the report.') IStatusMessage(self.request).addStatusMessage( msg, type='error') return self.request.RESPONSE.redirect(self.context.absolute_url()) response = self.request.RESPONSE response.setHeader( 'Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') set_attachment_content_disposition(self.request, "document_report.xlsx") return data
def get_items(self): return [ { 'class': 'document_author', 'label': _('label_by_author', default='by'), 'content': self.context.document_author, 'replace': False }, { 'class': 'documentModified', 'label': _('label_start_byline', default='from'), 'content': self.document_date(), 'replace': False }, { 'class': 'sequenceNumber', 'label': _('label_sequence_number', default='Sequence Number'), 'content': self.sequence_number(), 'replace': False }, { 'class': 'referenceNumber', 'label': _('label_reference_number', default='Reference Number'), 'content': self.reference_number(), 'replace': False } ]
class CheckinContextCommentForm(form.Form): """Form to checkin one document, the form's context.""" fields = field.Fields(IContextCheckinCommentSchema) ignoreContext = True label = _(u'heading_checkin_comment_form', u'Checkin Documents') def __init__(self, context, request): super(CheckinContextCommentForm, self).__init__(context, request) self.checkin_controller = CheckinController(self.request) @button.buttonAndHandler(_(u'button_checkin', default=u'Checkin')) def checkin_button_handler(self, action): data, errors = self.extractData() self.checkin_controller.checkin_document(self.context, comment=data['comment']) return self.redirect() @button.buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def cancel(self, action): return self.redirect() def redirect(self): return self.request.RESPONSE.redirect(self.context.absolute_url())
def translations(self): return json.dumps({ 'msg_pdf_generation_succesfull': translate( _(u'msg_pdf_generation_succesfull', default=u'PDF generated successfully'), context=self.request), 'msg_pdf_generation_error': translate( _(u'msg_pdf_generation_error', default=u'PDF generation error'), context=self.request), 'msg_pdf_generation_in_progress': translate( _(u'msg_pdf_generation_in_progress', default=u'PDF is being generated'), context=self.request), 'msg_pdf_generation_failed': translate( _(u'msg_pdf_generation_failed', default=u'PDF generation failed'), context=self.request), 'msg_pdf_generation_timeout': translate( _(u'msg_pdf_generation_timeout', default=u'PDF generation timed out'), context=self.request), 'label_button_destination_document': translate( _(u'label_button_destination_document', default=u'Go to destination document'), context=self.request), 'label_button_error': translate( _(u'label_button_error', default=u'Error'), context=self.request), 'label_button_creation_in_progress': translate( _(u'label_button_creation_in_progress', default=u'Generating'), context=self.request), 'label_backlink_to_source_document': translate( _(u'label_backlink_to_source_document', default=u'Back to source document'), context=self.request), 'label_error': translate( _(u'label_error', default=u'Error'), context=self.request), })
class IRelatedDocuments(model.Schema): """The 'Related documents' behvavior is an opengever.document specific 'Related items' behavior. Only allows references to opengever.documents. """ form.order_after(relatedItems='IDocumentMetadata.preserved_as_paper') relatedItems = RelationList( title=_(u'label_related_documents', default=u'Related Documents'), default=[], missing_value=[], value_type=RelationChoice( title=u"Related", source=RepositoryPathSourceBinder( portal_type=("opengever.document.document", "ftw.mail.mail"), navigation_tree_query={ 'object_provides': ['opengever.repository.repositoryroot.IRepositoryRoot', 'opengever.repository.repositoryfolder.' + 'IRepositoryFolderSchema', 'opengever.dossier.behaviors.dossier.IDossierMarker', 'opengever.document.document.IDocumentSchema', 'ftw.mail.mail.IMail', ] }), ), required=False, ) model.fieldset( u'common', label=_(u'fieldset_common', default=u'Common'), fields=[ u'relatedItems', ], )
class ISaveAsPdfSchema(Interface): destination_folder = RelationChoice( title=_('label_destination', default="Destination"), description=_('help_destination', default="Live Search: search for the dossier"), source=RepositoryPathSourceBinder( object_provides=[ 'opengever.dossier.behaviors.dossier.IDossierMarker', ], navigation_tree_query={ 'object_provides': [ 'opengever.repository.repositoryroot.IRepositoryRoot', 'opengever.repository.repositoryfolder.IRepositoryFolderSchema', 'opengever.dossier.behaviors.dossier.IDossierMarker', ], 'review_state': DOSSIER_STATES_OPEN + [ 'repositoryfolder-state-active', 'repositoryroot-state-active' ] }), required=True, ) version_id = Int( title=_('version_id', default='Document Version'), required=False, )
def cancel(self, obj): """Cancels a single document checkout. """ if IMail.providedBy(obj): msg = _(u'msg_cancel_checkout_on_mail_not_possible', default=u'Could not cancel checkout on document ${title}, ' 'mails does not support the checkin checkout process.', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message(message=msg, request=self.request, type='error') return # check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is cancel allowed for this document? if not manager.is_cancel_allowed(): msg = _(u'Could not cancel checkout on document ${title}.', mapping=dict(title=obj.Title().decode('utf-8'))) api.portal.show_message(message=msg, request=self.request, type='error') else: manager.cancel() # notify the user msg = _(u'Cancel checkout: ${title}', mapping={'title': obj.Title().decode('utf-8')}) api.portal.show_message(message=msg, request=self.request, type='info')
def get_document_attributes(self): return [ {'id': 'reference', 'title': _(u'label_document_reference_number')}, {'id': 'sequence_number', 'title': _(u'label_document_sequence_number')}, {'id': 'Title', 'title': _(u'label_title', default=u'Title')}, {'id': 'document_author', 'title': _(u'label_author', default=u'Author'), 'transform': readable_author}, {'id': 'document_date', 'title': _(u'label_document_date', default=u'Document Date'), 'transform': readable_date}, {'id': 'receipt_date', 'title': _(u'label_document_receipt_date'), 'transform': readable_date}, {'id': 'delivery_date', 'title': _(u'label_document_delivery_date'), 'transform': readable_date}, {'id': 'checked_out', 'title': _(u'label_document_checked_out_by'), 'transform': readable_author}, {'id': 'public_trial', 'title': _(u'label_public_trial'), 'transform': StringTranslater( self.request, 'opengever.base').translate}, {'id': 'containing_dossier', 'title': _(u'label_dossier_title')}, ]
def render(self): # check whether we have paths or not paths = self.request.get('paths') # using "paths" is mandantory on any objects except for a document if not paths and not IDocumentSchema.providedBy(self.context): msg = _(u'You have not selected any documents') IStatusMessage(self.request).addStatusMessage(msg, type='error') # we assume the request came from the tabbed_view "documents" # tab on the dossier return self.request.RESPONSE.redirect('%s#documents' % self.context.absolute_url()) elif paths: # lookup the objects to be handled using the catalog catalog = getToolByName(self.context, 'portal_catalog') objects = [] for path in paths: query = dict(path={'query': path, 'depth': 0}) obj = catalog(query)[0].getObject() objects.append(obj) else: # the context is the document objects = [self.context] # now, lets checkout every document for obj in objects: if not IDocumentSchema.providedBy(obj): # notify the user. we have a no-checkoutable object msg = _( u'Could not check out object: ${title}, ' 'it is not a document', mapping={'title': obj.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='error') continue self.checkout(obj) # lets register a redirector for starting external # editor - if requested external_edit = self.request.get('mode') == 'external' if len(objects) == 1 and external_edit: redirector = IRedirector(self.request) redirector.redirect('%s/external_edit' % objects[0].absolute_url(), target='_self', timeout=1000) # now lets redirect to an appropriate target.. if len(objects) == 1: return self.request.RESPONSE.redirect(objects[0].absolute_url()) else: return self.request.RESPONSE.redirect('%s#documents' % self.context.absolute_url())
def __call__(self): # check whether we have paths or not paths = self.request.get('paths') # using "paths" is mandantory on any objects except for a document if not paths and not IDocumentSchema.providedBy(self.context): msg = _(u'You have not selected any documents.') IStatusMessage(self.request).addStatusMessage( msg, type='error') # we assume the request came from the tabbed_view "documents" # tab on the dossier return self.request.RESPONSE.redirect( '%s#documents' % self.context.absolute_url()) elif paths: # lookup the objects to be handled using the catalog catalog = getToolByName(self.context, 'portal_catalog') objects = [] for path in paths: query = dict(path={'query': path, 'depth': 0}) obj = catalog(query)[0].getObject() objects.append(obj) else: # the context is the document objects = [self.context] # now, lets checkout every document if not self.request.get('reauth') == '1': for obj in objects: if not IDocumentSchema.providedBy(obj): # notify the user. we have a no-checkoutable object msg = _( u'Could not check out object: ${title}, ' 'it is not a document.', mapping={'title': obj.Title().decode('utf-8')}) IStatusMessage( self.request).addStatusMessage(msg, type='error') continue self.checkout(obj) # lets register a redirector for starting external # editor - if requested external_edit = self.request.get('mode') == 'external' # now lets redirect to an appropriate target.. if len(objects) == 1: if external_edit: objects[0].setup_external_edit_redirect(self.request) return self.request.RESPONSE.redirect( objects[0].absolute_url()) else: return self.request.RESPONSE.redirect( '%s#documents' % self.context.absolute_url())
def render(self): # have the document a file if not self.context.file: msg = _(u"The Document ${title} has no File", mapping={"title": self.context.Title().decode("utf-8")}) IStatusMessage(self.request).addStatusMessage(msg, type="error") return self.request.RESPONSE.redirect(get_redirect_url(self.context)) # check out the document manager = getMultiAdapter((self.context, self.request), ICheckinCheckoutManager) # check if the document is allready checked out by the actual user userid = getToolByName(self.context, "portal_membership").getAuthenticatedMember().getId() if manager.checked_out() == userid: # check if the document is locked # otherwies only open with the ext. editor info = getMultiAdapter((self.context, self.request), name="plone_lock_info") if info.is_locked(): msg = _(u"Can't edit the document at moment, " "beacuse it's locked.") IStatusMessage(self.request).addStatusMessage(msg, type="error") return self.request.RESPONSE.redirect(get_redirect_url(self.context)) elif manager.checked_out() is not None: info = getUtility(IContactInformation) msg = _( u"The Document is allready checked out by: ${userid}", mapping={"userid": info.describe(manager.checked_out())}, ) IStatusMessage(self.request).addStatusMessage(msg, type="error") return self.request.RESPONSE.redirect(get_redirect_url(self.context)) elif not manager.is_checkout_allowed(): msg = _(u"Could not check out document ${title}", mapping={"title": self.context.Title().decode("utf-8")}) IStatusMessage(self.request).addStatusMessage(msg, type="error") return self.request.RESPONSE.redirect(get_redirect_url(self.context)) else: # check it out manager.checkout() # notify the user msg = _(u"Checked out: ${title}", mapping={"title": self.context.Title().decode("utf-8")}) IStatusMessage(self.request).addStatusMessage(msg, type="info") # lets register a redirector for starting external # editor - if requested redirector = IRedirector(self.request) redirector.redirect("%s/external_edit" % self.context.absolute_url(), target="_self", timeout=1000) # now lets redirect to an appropriate target.. return self.request.RESPONSE.redirect(self.context.absolute_url())
class IContextCheckinCommentSchema(Interface): """Form schema to enter a journal comment for checkin.""" comment = schema.Text( title=_(u'label_checkin_journal_comment', default=u'Journal Comment'), description=_(u'help_checkin_journal_comment', default=u'Describe, why you checkin the ' 'selected documents'), required=False)
class CheckinContextCommentForm(form.Form): """Form to checkin one document, the form's context.""" fields = field.Fields(IContextCheckinCommentSchema) ignoreContext = True label = _(u'heading_checkin_comment_form', u'Checkin Documents') def __init__(self, context, request): super(CheckinContextCommentForm, self).__init__(context, request) if self.is_document_locked(): # Add a warning onto a locked document checkin view msg = _( u'label_warn_checkout_locked', default=u' '.join(( 'This document is currently being worked on.', 'When you check it in manually you will lose the changes.', 'Please allow for the process to be finished first.')), ) IStatusMessage(self.request).addStatusMessage(msg, type=u'warning') self.checkin_controller = CheckinController(self.request) def is_document_locked(self): return IRefreshableLockable(self.context).locked() def checkin_document(self, force=False): # Errors are handled by the checkin data = self.extractData()[0] self.checkin_controller.checkin_document(self.context, comment=data['comment'], force=force) return self.redirect() @button.buttonAndHandler( _(u'button_checkin', default=u'Checkin'), condition=lambda form: not form.is_document_locked()) def checkin_button_handler(self, action): return self.checkin_document() @button.buttonAndHandler(_(u'button_checkin_anyway', default=u'Checkin anyway'), condition=lambda form: form.is_document_locked()) def checkin_anyway_button_handler(self, action): return self.checkin_document(force=True) @button.buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def cancel(self, action): return self.redirect() def redirect(self): return self.request.RESPONSE.redirect(self.context.absolute_url())
def get_metadata_config(self): rows = [ FieldRow('title'), FieldRow('IDocumentMetadata.document_date'), TemplateRow(self.file_template, label=_('label_file', default='File')), CustomRow(self.get_creation_date, label=_('label_created', default='Created')), CustomRow(self.get_modification_date, label=_('label_modified', default='Modified')), FieldRow('IDocumentMetadata.document_type'), FieldRow('IDocumentMetadata.document_author'), CustomRow(self.render_creator_link, label=_('label_creator', default='creator')), WebIntelligentFieldRow('IDocumentMetadata.description'), TemplateRow(self.keywords_template, label=_(u'label_keywords', default=u'Keywords')), FieldRow('IDocumentMetadata.foreign_reference'), CustomRow(self.render_checked_out_link, label=_('label_checked_out', default='Checked out')), FieldRow('IDocumentMetadata.digitally_available'), FieldRow('IDocumentMetadata.preserved_as_paper'), FieldRow('IDocumentMetadata.receipt_date'), FieldRow('IDocumentMetadata.delivery_date'), TemplateRow(self.related_documents_template, label=_(u'label_related_documents', default=u'Related Documents')), FieldRow('IClassification.classification'), FieldRow('IClassification.privacy_layer'), TemplateRow(self.public_trial_template, label=ogbmf('label_public_trial', default='Public Trial')), FieldRow('IClassification.public_trial_statement') ] if self.is_archivale_file_visible(): row = TemplateRow(self.archival_file_template, label=_(u'label_archival_file', default='Archival File')) rows.append(row) row = CustomRow(self.render_archival_file_state, label=_('label_archival_file_state', default='Archival file state')) rows.append(row) if is_meeting_feature_enabled(): rows.append( TemplateRow(self.submitted_with_template, label=_('Submitted with'))) return rows
class ICheckinCommentFormSchema(Interface): """ Form schema for entering a journal comment in checkin procedure """ # hidden by form paths = schema.TextLine(title=u'Selected Items') comment = schema.Text(title=_(u'label_checkin_journal_comment', default=u'Journal Comment'), description=_( u'help_checkin_journal_comment', default=u'Describe, why you checkin the ' 'selected documents'), required=False)
def get_metadata_config(self): rows = [ FieldRow('title'), FieldRow('IDocumentMetadata.document_date'), TemplateRow(self.file_template, label=_('label_file', default='File')), CustomRow(self.get_creation_date, label=_('label_created', default='Created')), CustomRow(self.get_modification_date, label=_('label_modified', default='Modified')), FieldRow('IDocumentMetadata.document_type'), FieldRow('IDocumentMetadata.document_author'), CustomRow(self.render_creator_link, label=_('label_creator', default='creator')), WebIntelligentFieldRow('IDocumentMetadata.description'), TemplateRow(self.keywords_template, label=_(u'label_keywords', default=u'Keywords')), FieldRow('IDocumentMetadata.foreign_reference'), CustomRow(self.render_checked_out_link, label=_('label_checked_out', default='Checked out')), FieldRow('IDocumentMetadata.digitally_available'), FieldRow('IDocumentMetadata.preserved_as_paper'), FieldRow('IDocumentMetadata.receipt_date'), FieldRow('IDocumentMetadata.delivery_date'), TemplateRow(self.related_documents_template, label=_( u'label_related_documents', default=u'Related Documents')), FieldRow('IClassification.classification'), FieldRow('IClassification.privacy_layer'), TemplateRow(self.public_trial_template, label=ogbmf('label_public_trial', default='Public Trial')), FieldRow('IClassification.public_trial_statement') ] if self.is_archivale_file_visible(): row = TemplateRow( self.archival_file_template, label=_(u'label_archival_file', default='Archival File')) rows.append(row) row = CustomRow(self.render_archival_file_state, label=_('label_archival_file_state', default='Archival file state')) rows.append(row) if is_meeting_feature_enabled(): rows.append(TemplateRow(self.submitted_with_template, label=_('Submitted with'))) return rows
def revert_link(self): """Returns a formatted link to revert to this particular version if reverting is allowed, an inactive label otherwise. """ if self.is_revert_allowed: url = '{}/revert-file-to-version?version_id={}' url = url.format(self.url, self.version_id) url = addTokenToUrl(url) link = translate_link( url, _(u'label_revert', default=u'Revert'), css_class='standalone function-revert') return link else: label = translate_text(_(u'label_revert', default=u'Revert')) return u'<span class="discreet">{}</span>'.format(label)
def raise_invalid(self): if IDossierMarker.providedBy(self.context): mail_address = IEmailAddress( self.request).get_email_for_object(self.context) else: parent = aq_parent(aq_inner(self.context)) mail_address = IEmailAddress( self.request).get_email_for_object(parent) # Remove widget value in order to disable that the widget renders # radio-buttons (nochange/remove/replace) once a file has been # uploaded. # This is a special case since we are an additional validator # for the file field that may block an otherwise valid file upload. # The widget does not expect this to happen though. if getattr(self.view.parentForm, '_nullify_file_on_error', False): self.widget.value = None raise Invalid(_( u'error_mail_upload', default=(u"It's not possible to add E-mails here, please " "send it to ${mailaddress} or drag it to the dossier " "(Dragn'n'Drop)."), mapping={'mailaddress': mail_address} ))
def get_html_tag(self, additional_classes=[], url_extension='', viewname='download', include_token=False): file_url = self.context.absolute_url() # Do not display a download confirmation for mail items if self.is_active() and not IOGMailMarker.providedBy(self.context): viewname = 'file_download_confirmation' clazz = (('link-overlay ' 'modal ' '{0}').format(' '.join(additional_classes))) else: clazz = ' '.join(additional_classes) url = '{0}/{1}{2}'.format(file_url, viewname, url_extension) if include_token: url = addTokenToUrl(url) label = translate(_(u'label_download_copy', default='Download copy'), context=self.request).encode('utf-8') return ('<a href="{0}" ' 'id="action-download" ' 'class="{1}">{2}</a>').format(url, clazz, label)
def report_cannot_checkin_non_document(self, obj): title = obj.Title() if not isinstance(title, unicode): title = title.decode('utf-8') msg = _(u'Could not check in ${title}, it is not a document.', mapping=dict(title=title)) IStatusMessage(self.request).addStatusMessage(msg, type=u'error')
def validate(self, value): """The document must either have a digital file or be preserved in paper form. XXX: This validator is a hack, since it validates field values across schemata using request.form instead of `value`. """ # Bail if not called during a regular add form if self.request.form == {}: return # Mails are always available in digital form if IMail.providedBy(self.context): return form = self.view.parentForm if getattr(form, 'skip_validate_file_field', False): return if not any([ self.has_file(), self.is_preserved_as_paper(), self.has_referenced_document() ]): raise Invalid( _(u'error_file_and_preserved_as_paper', default=u"You don't select a file and document is also not " u"preserved in paper_form, please correct it."))
def revert_link(self): """Returns a formatted link to revert to this particular version if reverting is allowed, an inactive label otherwise. """ if self.is_revert_allowed: url = '{}/revert-file-to-version?version_id={}' url = url.format(self.url, self.version_id) url = addTokenToUrl(url) link = translate_link(url, _(u'label_revert', default=u'Revert'), css_class='standalone function-revert') return link else: label = translate_text(_(u'label_revert', default=u'Revert')) return u'<span class="discreet">{}</span>'.format(label)
def get_save_pdf_title(self): return _(u'title_save_pdf', default=u'Save PDF of ${title} under ${destination}', mapping={ 'title': self.source_document.title, 'destination': self.destination.title })
def revert_to_version(self, version_id, create_version=True): """Reverts the adapted document to a specific version. We only revert the file field, since we do not wan't to version the metadata on the document. If `create_version` is set to `True`, a new version is created after reverting. """ version = self.repository.retrieve(self.context, version_id) old_obj = version.object if old_obj.file: # Create a new NamedBlobFile instance instead of using # a reference in order to avoid the version being reverted # to being overwritten later old_file_copy = NamedBlobFile(old_obj.file.data, filename=old_obj.file.filename, contentType=old_obj.file.contentType) self.context.file = old_file_copy else: self.context.file = None if create_version: # let's create a version comment = _(u'Reverted file to version ${version_id}', mapping=dict(version_id=version_id)) self.repository.save(obj=self.context, comment=comment) # event notify(ObjectRevertedToVersion(self.context, version_id, create_version))
def revert_to_version(self, version_id, create_version=True): """Reverts the adapted document to a specific version. We only revert the file field, since we do not wan't to version the metadata on the document. If `create_version` is set to `True`, a new version is created after reverting. """ version = self.repository.retrieve(self.context, version_id) old_obj = version.object if old_obj.file: # Create a new NamedBlobFile instance instead of using # a reference in order to avoid the version being reverted # to being overwritten later old_file_copy = NamedBlobFile(old_obj.file.data, filename=old_obj.file.filename, contentType=old_obj.file.contentType) self.context.file = old_file_copy else: self.context.file = None if create_version: # let's create a version comment = _(u'Reverted file to version ${version_id}', mapping=dict(version_id=version_id)) self.repository.save(obj=self.context, comment=comment) # event notify( ObjectRevertedToVersion(self.context, version_id, create_version))
def validate(self, value): """The document must either have a digital file or be preserved in paper form. XXX: This validator is a hack, since it validates field values across schemata using request.form instead of `value`. """ # Bail if not called during a regular add form if self.request.form == {}: return # Mails are always available in digital form if IMail.providedBy(self.context): return form = self.view.parentForm if getattr(form, 'skip_validate_file_field', False): return if not any([self.has_file(), self.is_preserved_as_paper(), self.has_referenced_document()]): raise Invalid( _(u'error_file_and_preserved_as_paper', default=u"You don't select a file and document is also not " u"preserved in paper_form, please correct it."))
def report_cannot_checkin_non_document(self, obj): title = obj.Title() if not isinstance(title, unicode): title = title.decode('utf-8') msg = _( u'Could not check in ${title}, it is not a document.', mapping=dict(title=title)) IStatusMessage(self.request).addStatusMessage(msg, type=u'error')
def __call__(self, *args, **kwargs): try: return layout.FormWrapper.__call__(self, *args, **kwargs) except NoItemsSelected: msg = _(u'You have not selected any documents') IStatusMessage(self.request).addStatusMessage(msg, type='error') return get_containg_document_tab_url(self.context)
def create_destination_document(self): # get all the metadata that will be set on the created file. # We blacklist some fields that should not be copied fields_to_skip = set(("file", "archival_file", "archival_file_state", "thumbnail", "preview", "digitally_available", "changeNote", "changed", "relatedItems",)) metadata = {} for schema in iterSchemataForType(self.context.portal_type): for name, schema_field in getFieldsInOrder(schema): if name in fields_to_skip: continue field_instance = schema_field.bind(self.context) metadata[name] = field_instance.get(self.context) command = CreateDocumentCommand(self.destination, None, None, **metadata) destination_document = command.execute() # We make it in shadow state until its file is set by the callback view destination_document.as_shadow_document() # Add marker interface. This should be useful in the future for # cleanup jobs, retries if the PDF was not delivered and so on. alsoProvides(destination_document, IDocumentSavedAsPDFMarker) # Add annotations needed for the SavePDFDocumentUnder view. annotations = IAnnotations(destination_document) annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context) annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id # The missing_value attribute of a z3c-form field is used # as soon as an object has no default_value i.e. after creating # an object trough the command-line. # # Because the relatedItems field needs a list as a missing_value, # we will fall into the "mutable keyword argument"-python gotcha. # The relatedItems will be shared between the object-instances. # # Unfortunately the z3c-form field does not provide a # missing_value-factory (like the defaultFactory) which would be # necessary to fix this issue properly. # # As a workaround we make sure that the new document's relatedItems # is different object from the source document's. IRelatedDocuments(destination_document).relatedItems = list( IRelatedDocuments(destination_document).relatedItems) IRelatedDocuments(destination_document).relatedItems.append( RelationValue(getUtility(IIntIds).getId(self.context))) msg = _(u'Document ${document} was successfully created in ${destination}', mapping={"document": destination_document.title, "destination": self.destination.title}) api.portal.show_message(msg, self.request, type='info') return destination_document
class MultiCheckoutCancelForm(form.Form): """Form to confirm cancelation of checkout for mutliple documents.""" fields = field.Fields(IMultiCheckoutCancelSchema) ignoreContext = True def __init__(self, context, request): super(MultiCheckoutCancelForm, self).__init__(context, request) def cancel_checkout(self, force=False): self.request.set("paths", self.get_document_paths()) return CancelDocuments(self.context, self.request).__call__() @button.buttonAndHandler(_(u'Cancel checkout')) def cancel_checkout_button(self, action): return self.cancel_checkout() @button.buttonAndHandler(_(u'button_cancel', default=u'Cancel')) def cancel(self, action): return self.redirect() def redirect(self): return self.request.RESPONSE.redirect( get_containing_document_tab_url(self.context)) def get_document_paths(self): if self.widgets: field_name = self.prefix + self.widgets.prefix + 'paths' value = self.request.get(field_name, False) if value: return value.split(';;') return self.request.get('paths', []) def get_filenames(self): portal = api.portal.get() paths = self.get_document_paths() return [ portal.unrestrictedTraverse(path.split("/")).title_or_id() for path in paths ] def updateWidgets(self): super(MultiCheckoutCancelForm, self).updateWidgets() self.widgets['paths'].mode = HIDDEN_MODE self.widgets['paths'].value = ';;'.join(self.get_document_paths())
def __call__(self, *args, **kwargs): try: return layout.FormWrapper.__call__(self, *args, **kwargs) except NoItemsSelected: msg = _(u'You have not selected any documents') IStatusMessage(self.request).addStatusMessage( msg, type='error') return get_containg_document_tab_url(self.context)
def file_or_preserved_as_paper(data): """ When no digital file exist, the document must be preserved in paper. """ if not data.file and not data.preserved_as_paper: raise Invalid( _(u'error_file_and_preserved_as_paper', default=u"You don't select a file and document is also not \ preserved in paper_form, please correct it."))
def perform_checkin(self, document, comment): manager = getMultiAdapter((document, self.request), ICheckinCheckoutManager) if not manager.is_checkin_allowed(): msg = _( u'Could not check in document ${title}', mapping=dict(title=document.Title().decode('utf-8'))) IStatusMessage(self.request).addStatusMessage( msg, type='error') else: manager.checkin(comment) msg = _( u'Checked in: ${title}', mapping=dict(title=document.Title().decode('utf-8'))) IStatusMessage(self.request).addStatusMessage( msg, type='info')
def set_copyname(doc, event): """Documents wich are copied, should be renamed to copy of filename.""" key = 'prevent-copyname-on-document-copy' request = getRequest() if request.get(key, False): return doc.title = u'%s %s' % (translate(_('copy_of', default="copy of"), context=request), doc.title)
def checkout(self, obj): """Checks out a single document object.""" # Check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is checkout allowed for this document? if not manager.is_checkout_allowed(): msg = _(u'Could not check out document ${title}.', mapping={'title': obj.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='error') else: # check it out manager.checkout() # notify the user msg = _(u'Checked out: ${title}', mapping={'title': obj.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='info')
def validate(self, value): super(DestinationValidator, self).validate(value) # Allowed contenttypes for destination-folder allowed_types = [t.getId() for t in value.allowedContentTypes()] if self.context.portal_type not in allowed_types: raise NotInContentTypes( _(u"error_NotInContentTypes", default=u"User is not allowed to add a document there."))
def checkin(self): try: self.checkin_controller.checkin_documents( self.request.get('paths'), ) except NoItemsSelected: msg = _(u'You have not selected any documents.') IStatusMessage(self.request).addStatusMessage(msg, type=u'error') return self.request.RESPONSE.redirect( get_containing_document_tab_url(self.context))
def set_copyname(doc, event): """Documents wich are copied, should be renamed to copy of filename.""" key = 'prevent-copyname-on-document-copy' request = getRequest() if request.get(key, False): return doc.title = u'%s %s' % ( translate(_('copy_of', default="copy of"), context=request), doc.title)
def checkin(self): try: self.checkin_controller.checkin_documents(self.request.get('paths')) except NoItemsSelected: msg = _(u'You have not selected any documents') IStatusMessage(self.request).addStatusMessage( msg, type='error') return self.request.RESPONSE.redirect( get_containing_document_tab_url(self.context))
def save_pdf_under_link(self): """Returns a formatted link to save this particular version as PDF. """ url = '{}/save_pdf_under?version_id={}' url = url.format(self.url, self.version) url = addTokenToUrl(url) link = translate_link( url, _(u'label_save_pdf', default=u'Save PDF'), css_class='standalone function-save-pdf') return link
def comment(self): """Comment for this version. """ versioner = Versioner(self.obj) if versioner.get_custom_initial_version_comment(): return versioner.get_custom_initial_version_comment() return translate( _(u'initial_document_version_change_note', default=u'Initial version'), context=getRequest())
def get_checkout_cancel_tag(self): if not self.has_file() or not self.is_checkout_cancel_available(): return None clazz = 'link-overlay modal function-revert' url = u'{}/@@cancel_document_checkout_confirmation'.format( self.context.absolute_url()) label = translate(_(u'Cancel checkout'), context=self.request).encode('utf-8') return ('<a href="{0}" ' 'id="action-cancel-checkout" ' 'class="{1}">{2}</a>').format(url, clazz, label)
def pdf_preview_link(self): """Returns a formatted link to download the PDF preview for this version (only rendered if opengever.pdfconverter is available). """ url = '{}/download_pdf_version?version_id={}' url = url.format(self.url, self.version_id) url = addTokenToUrl(url) link = translate_link( url, _(u'button_pdf', default=u'PDF'), css_class='standalone function-download-pdf') return link
def checkin_button_handler(self, action): """Handle checkin """ data, errors = self.extractData() if len(errors) == 0: # check in each document for obj in self.objects: if IDocumentSchema.providedBy(obj): manager = getMultiAdapter((obj, obj.REQUEST), ICheckinCheckoutManager) if not manager.is_checkin_allowed(): msg = _( u'Could not check in document ${title}', mapping=dict(title=obj.Title().decode('utf-8'))) IStatusMessage(self.request).addStatusMessage( msg, type='error') else: manager.checkin(data['comment']) msg = _( u'Checked in: ${title}', mapping=dict(title=obj.Title().decode('utf-8'))) IStatusMessage(self.request).addStatusMessage( msg, type='info') else: title = obj.Title() if not isinstance(title, unicode): title = title.decode('utf-8') msg = _( u'Could not check in ${title}, it is not a document.', mapping=dict(title=title)) IStatusMessage(self.request).addStatusMessage( msg, type='error') # redirect to dossier return self.request.RESPONSE.redirect( get_containg_document_tab_url(self.context))
def cancel(self, obj): """Cancels a single document checkout. """ # check out the document manager = getMultiAdapter((obj, self.request), ICheckinCheckoutManager) # is cancel allowed for this document? if not manager.is_cancel_allowed(): msg = _(u'Could not cancel checkout on document ${title}', mapping=dict(title=obj.Title().decode('utf-8'))) IStatusMessage(self.request).addStatusMessage(msg, type='error') else: manager.cancel() # notify the user msg = _(u'Cancel checkout: ${title}', mapping={'title': obj.Title().decode('utf-8')}) IStatusMessage(self.request).addStatusMessage(msg, type='info')
def render(self): mtool = getToolByName(self.context, "portal_membership") if mtool.checkPermission("Modify portal content", self.context): return self.response.redirect("%s/edit" % (self.context.absolute_url())) else: msg = _( u"You are not authorized to edit the document ${title}", mapping={"title": self.context.Title().decode("utf-8")}, ) IStatusMessage(self.request).addStatusMessage(msg, type="error") return self.request.RESPONSE.redirect(get_redirect_url(self.context))