def test_proposaltemplate_checked_out_suffix(self): self.login(self.dossier_responsible) self.assertEquals('icon-docx', get_css_class(self.proposal_template)) self.checkout_document(self.proposal_template) self.assertEquals('icon-docx is-checked-out-by-current-user', get_css_class(obj2brain(self.proposal_template)))
def test_document_obj_checked_out_suffix(self): self.login(self.dossier_responsible) self.assertEquals('icon-docx', get_css_class(self.document)) self.checkout_document(self.document) self.assertEquals('icon-docx is-checked-out-by-current-user', get_css_class(self.document))
def test_document_obj_checked_out_in_context_of_another_users_id(self): self.login(self.dossier_responsible) self.assertEquals('icon-docx', get_css_class(self.document)) self.checkout_document(self.document) self.assertEquals( 'icon-docx is-checked-out-by-current-user', get_css_class(self.document, for_user=self.dossier_responsible.id)) self.assertEquals( 'icon-docx is-checked-out', get_css_class(self.document, for_user=self.regular_user.id))
def test_remote_task_globalindex(self): obj = GlobalindexTask(1231, 'client1') obj.assigned_client = 'client2' obj.is_subtask = False self.replay() self.assertEquals(get_css_class(obj), 'icon-task-remote-task')
def get_chains(self): repository = [] chain = [] for obj in aq_chain(self.context): if INavigationRoot.providedBy(obj): break if IHideFromBreadcrumbs.providedBy(obj): continue if ISQLObjectWrapper.providedBy(obj): data = obj.get_breadcrumb() else: data = { 'absolute_url': obj.absolute_url(), 'title': obj.Title(), 'css_class': get_css_class(obj, type_icon_only=True) } if self.is_part_of_repo(obj): repository.append(data) else: chain.append(data) chain.reverse() return repository, chain
def test_obj(self): obj = self.stub() self.expect(obj.portal_type).result('ftw.obj.obj') self.replay() self.assertEquals(get_css_class(obj), 'contenttype-ftw-obj-obj')
def linked(item, value, with_tooltip=True): """Takes an item (object or brain) and returns a HTML snippet that contains a link to the item, it's icon and breadcrumbs in the tooltip. """ if isinstance(value, unicode): value = value.encode('utf-8') # Determine URL and UID url = get_url(item) if ICatalogBrain.providedBy(item) or isinstance(item, SolrDocument): uid = item.UID else: uid = IUUID(item) # Construct CSS class css_class = get_css_class(item) # Make sure all data used in the HTML snippet is properly escaped value = escape_html(value) if with_tooltip: css_class = "rollover-breadcrumb " + css_class link = '<a class="%s" href="%s" data-uid="%s"><span>%s</span></a>' % ( css_class, url, uid, value) wrapper = '<span class="linkWrapper">%s</span>' % link return wrapper
def test_proposaltemplate_checked_out_by_other_suffix(self): self.login(self.dossier_responsible) self.checkout_document(self.proposal_template) self.login(self.regular_user) self.assertEquals('icon-docx is-checked-out', get_css_class(obj2brain(self.proposal_template)))
def documents(self): """ Get documents and mails that are directly contained in the inbox, but not in forwardings. """ catalog = api.portal.get_tool(name='portal_catalog') query = {'isWorkingCopy': 0, 'path': {'depth': 1, 'query': '/'.join(self.context.getPhysicalPath())}, 'object_provides': [ 'opengever.document.behaviors.IBaseDocument', ], 'sort_on': 'modified', 'sort_order': 'reverse'} documents = catalog(query)[:10] document_list = [{ 'Title': document.Title, 'getURL': document.getURL, 'alt': document.document_date and document.document_date.strftime('%d.%m.%Y') or '', 'css_class': get_css_class(document), 'portal_type': document.portal_type, } for document in documents] return document_list
def test_document_obj_checked_out_by_other_suffix(self): self.login(self.dossier_responsible) self.checkout_document(self.document) self.login(self.regular_user) self.assertEquals('icon-docx is-checked-out', get_css_class(self.document))
def linked(item, value): """Takes an item (object or brain) and returns a HTML snippet that contains a link to the item, it's icon and breadcrumbs in the tooltip. """ if isinstance(value, unicode): value = value.encode('utf-8') # Determine URL method url_method = lambda: '#' if hasattr(item, 'getURL'): url_method = item.getURL elif hasattr(item, 'absolute_url'): url_method = item.absolute_url # Construct CSS class css_class = get_css_class(item) # Construct breadcrumbs breadcrumb_titles = _breadcrumbs_from_item(item) link_title = " > ".join(t for t in breadcrumb_titles) # Make sure all data used in the HTML snippet is properly escaped link_title = cgi.escape(link_title, quote=True) value = cgi.escape(value, quote=True) link = '<a class="rollover-breadcrumb %s" href="%s" title="%s">%s</a>' % ( css_class, url_method(), link_title, value) wrapper = '<span class="linkWrapper">%s</span>' % link return wrapper
def linked(item, value): """Takes an item (object or brain) and returns a HTML snippet that contains a link to the item, it's icon and breadcrumbs in the tooltip. """ if isinstance(value, unicode): value = value.encode('utf-8') # Determine URL and UID url = get_url(item) if ICatalogBrain.providedBy(item): uid = item.UID else: uid = IUUID(item) # Construct CSS class css_class = get_css_class(item) # Make sure all data used in the HTML snippet is properly escaped value = escape_html(value) link = '<a class="rollover-breadcrumb %s" href="%s" data-uid="%s">%s</a>' % ( css_class, url, uid, value) wrapper = '<span class="linkWrapper">%s</span>' % link return wrapper
def linked(item, value): """Takes an item (object or brain) and returns a HTML snippet that contains a link to the item, it's icon and breadcrumbs in the tooltip. """ if isinstance(value, unicode): value = value.encode('utf-8') # Determine URL method and UID url_method = lambda: '#' if hasattr(item, 'getURL'): url_method = item.getURL uid = item.UID elif hasattr(item, 'absolute_url'): url_method = item.absolute_url uid = IUUID(item) # Construct CSS class css_class = get_css_class(item) # Make sure all data used in the HTML snippet is properly escaped value = escape_html(value) link = '<a class="rollover-breadcrumb %s" href="%s" data-uid="%s">%s</a>' % ( css_class, url_method(), uid, value) wrapper = '<span class="linkWrapper">%s</span>' % link return wrapper
def _get_recently_touched(self, user_id): """Get the list of recently touched objects, minus checked out docs. This list is compiled by reading recently touched log for the given user_id, subtracting any checked out documents (because those are already displayed in the other list), and combining them with catalog brains (by UID) for any information other than the timestamp. Timestamps used for display and ordering are fully based on the recently touched log, the catalog's 'modified' timestamp isn't being used here. This is because 'modified' is a very technical timestamp, and it's very hard to control when it does or does not get updated. Therefore we use our separate timestamp when an object gets tagged as "touched" so we control the semantics. """ portal = api.portal.get() catalog = api.portal.get_tool('portal_catalog') recently_touched_log = IAnnotations(portal).get( RECENTLY_TOUCHED_KEY, {}).get(user_id, []) # Subtract checked out docs from recently touched list checked_out_brains = self._get_checked_out_brains(user_id) checked_out_uids = [b.UID for b in checked_out_brains] touched_only_uids = [m['uid'] for m in recently_touched_log if m['uid'] not in checked_out_uids] touched_brains = catalog( UID=touched_only_uids, object_provides=[i.__identifier__ for i in RECENTLY_TOUCHED_INTERFACES_TO_TRACK], ) touched_brains_by_uid = {b.UID: b for b in touched_brains} entries = [] for entry in recently_touched_log: brain = touched_brains_by_uid.get(entry['uid']) if brain is None: # Might have checked out docs in storage, or items that don't # match the currently tracked types continue data = { "icon_class": get_css_class(brain), "last_touched": entry['last_touched'].isoformat(), "target_url": brain.getURL(), "title": brain.Title, } entries.append(data) # Truncate list to currently configured limit (storage might still # contain more entries until they get rotated out). limit = get_registry_record('limit', IRecentlyTouchedSettings) entries = entries[:limit] return entries
def indexed_task_link(item, display_client=False): """Renders a indexed task item (globalindex sqlalchemy object) either with a link to the effective task (if the user has access) or just with the title. """ site = getSite() css_class = get_css_class(item) # get the contact information utlity and the client info = queryUtility(IContactInformation) if info: client = info.get_client_by_id(item.client_id) if not info or not client: return '<span class="%s">%s</span>' % (css_class, item.title) # has the user access to the target task? has_access = False mtool = getToolByName(site, 'portal_membership') member = mtool.getAuthenticatedMember() if member: principals = set(member.getGroups() + [member.getId()]) allowed_principals = set(item.principals) # Administrators always have access, but the global role 'Administrator' # doesn't get indexed in task.principals in task indexer. # TODO: Avoid hardcoding 'og_administratoren' allowed_principals.add(u'og_administratoren') has_access = len(principals & allowed_principals) > 0 # is the target on a different client? we need to make a popup if # it is... if item.client_id != get_client_id(): link_target = ' target="_blank"' url = '%s/%s' % (client.public_url, item.physical_path) else: link_target = '' url = client.public_url + '/' + item.physical_path # embed the client if display_client: client_html = ' <span class="discreet">(%s)</span>' % client.title else: client_html = '' # create breadcrumbs including the (possibly remote) client title breadcrumb_titles = "[%s] > %s" % (client.title, item.breadcrumb_title) # render the full link if he has acccess inner_html = ''.join(('<span class="rollover-breadcrumb %s" \ title="%s">%s</span>' % \ (css_class, breadcrumb_titles, item.title), client_html)) if has_access: return '<a href="%s"%s>%s</a>' % (url, link_target, inner_html) else: return inner_html
def for_object(self, obj): self.arguments['oguid'] = Oguid.for_object(obj) self.arguments['title'] = obj.title self.arguments['portal_type'] = obj.portal_type self.arguments['icon_class'] = get_css_class(obj) self.arguments['plone_uid'] = IUUID(obj) return self
def test_task_globalindex(self): obj = GlobalindexTask(1231, 'client1') obj.assigned_client = 'client1' obj.is_subtask = False self.replay() self.assertEquals(get_css_class(obj), 'contenttype-opengever-task-task')
def test_forwarding_globalindex(self): obj = GlobalindexTask(1232, 'client1') obj.task_type = 'forwarding_task_type' obj.is_subtask = False self.replay() self.assertEquals(get_css_class(obj), 'contenttype-opengever-inbox-forwarding')
def test_forwarding(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.inbox.forwarding') self.replay() self.assertEquals(get_css_class(obj), 'contenttype-opengever-inbox-forwarding')
def test_sablontemplate_obj_with_icon(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.meeting.sablontemplate') self.expect(getattr(obj, '_v__is_relation', False)).result(False) self.expect(obj.getIcon()).result('icon_dokument_word.gif') self.replay() self.assertEquals(get_css_class(obj), 'icon-dokument_word')
def test_document_obj_with_relation_flag(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.document.document') self.expect(getattr(obj, '_v__is_relation', False)).result(True) obj._v__is_relation = False self.replay() self.assertEquals(get_css_class(obj), 'icon-dokument_verweis')
def test_document_brain_with_icon(self): brain = self.stub() self.expect(brain.portal_type).result('opengever.document.document') self.expect(getattr(brain, '_v__is_relation', False)).result(False) self.expect(brain.getIcon).result('icon_dokument_pdf.gif') self.replay() self.assertEquals(get_css_class(brain), 'icon-dokument_pdf')
def _update_favorites_icon_class(context): """Event handler which updates the icon_class of all existing favorites for the current context. """ favorites_query = Favorite.query.filter( Favorite.oguid == Oguid.for_object(context)) for favorite in favorites_query.all(): favorite.icon_class = get_css_class(context, for_user=favorite.userid)
def get_infos_for(self, obj): return { 'title': obj.Title(), 'overlay_url': obj.absolute_url() + '/@@bumblebee-overlay-listing', 'uid': IUUID(obj), 'checksum': IBumblebeeDocument(obj).get_checksum(), 'mime_type_css_class': get_css_class(obj), 'preview_image_url': bumblebee.get_service_v3().get_representation_url( obj, 'thumbnail')}
def byline_items(self): meeting = self.context.model yield { 'class': 'byline-meeting-wf-state-{}'.format(meeting.workflow_state), 'label': _('meeting_byline_workflow_state', default='State'), 'content': meeting.get_state().title } yield { 'label': _('meeting_byline_start', default='Start'), 'content': meeting.get_start() } if meeting.get_end(): yield { 'label': _('meeting_byline_end', default='End'), 'content': meeting.get_end() } yield self.get_role_item( 'byline-presidency', _('meeting_byline_presidency', default='Presidency'), meeting.presidency) yield self.get_role_item( 'byline-secretary', _('meeting_byline_secretary', default='Secretary'), meeting.secretary) if meeting.location: yield { 'label': _('meeting_byline_location', default='Location'), 'content': meeting.location } dossier = meeting.get_dossier() if api.user.has_permission('View', obj=dossier): dossier_html = linked(dossier, dossier.Title()) else: no_access_tooltip = safe_unicode( translate( _(u'You are not allowed to view the meeting dossier.'), context=self.request)) dossier_html = ( u'<span class="{classes}">' u'<span class="no_access" title="{no_access_tooltip}">' u'{title}</span></span>').format( classes=safe_unicode(get_css_class(dossier)), no_access_tooltip=escape_html(no_access_tooltip), title=escape_html(safe_unicode(dossier.Title()))) yield { 'label': _('meeting_byline_meetin_dossier', default='Meeting dossier'), 'content': dossier_html, 'replace': True }
def dossier_link(item, value): dossier = item.get_dossier() if not dossier: return url = dossier.absolute_url() link = u'<a href="{0}" title="{1}" class="{2}">{1}</a>'.format( url, escape_html(dossier.title), get_css_class(dossier)) return link
def get_infos_for(self, brain): return { 'title': brain.Title, 'overlay_url': brain.getURL() + '/@@bumblebee-overlay-listing', 'uid': brain.UID, 'checksum': brain.bumblebee_checksum, 'mime_type_css_class': get_css_class(brain), 'preview_image_url': bumblebee.get_service_v3().get_representation_url( brain, 'thumbnail')}
def test_document_obj_with_icon(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.document.document') self.expect(getattr(obj, '_v__is_relation', False)).result(False) self.expect(obj.getIcon()).result('icon_dokument_word.gif') self.replay() self.assertEquals(get_css_class(obj), 'icon-dokument_word')
def test_remote_subtask_globalindex__responsible(self): # Tests task which is both, remote and subtask, from the # perspective of the responsible (on responsible's client). obj = GlobalindexTask(1231, 'client2') obj.assigned_client = 'client1' obj.is_subtask = True # current-client: client1 self.replay() self.assertEquals(get_css_class(obj), 'icon-task-remote-task')
def test_remote_successor_task_brain(self): brain = self.stub() self.expect(brain.portal_type).result('opengever.task.task') self.expect(brain.is_subtask).result(False) self.expect(brain.client_id).result('client1') self.expect(brain.assigned_client).result('client1') self.expect(brain.predecessor).result('client2:12345') self.replay() self.assertEquals(get_css_class(brain), 'icon-task-remote-task')
def test_subtask_brain(self): brain = self.stub() self.expect(brain.portal_type).result('opengever.task.task') self.expect(brain.predecessor).result(None) self.expect(brain.is_subtask).result(True) self.expect(brain.client_id).result('client1') self.expect(brain.assigned_client).result('client1') self.replay() self.assertEquals(get_css_class(brain), 'icon-task-subtask')
def test_task_brain(self): brain = self.stub() self.expect(brain.portal_type).result('opengever.task.task') self.expect(brain.predecessor).result(None) self.expect(brain.is_subtask).result(False) self.expect(brain.client_id).result('client1') self.expect(brain.assigned_client).result('client1') self.replay() self.assertEquals(get_css_class(brain), 'contenttype-opengever-task-task')
def add(self, userid, obj): favorite = Favorite(userid=userid, oguid=Oguid.for_object(obj), title=obj.Title().decode('utf-8'), portal_type=obj.portal_type, icon_class=get_css_class(obj), plone_uid=IUUID(obj), position=self.get_next_position(userid)) create_session().add(favorite) create_session().flush() return favorite
def documents(self): documents = self.catalog( ['opengever.document.document', 'ftw.mail.mail', ])[:10] document_list = [{ 'Title': document.Title, 'getURL': document.getURL, 'alt': document.document_date and document.document_date.strftime('%d.%m.%Y') or '', 'css_class': get_css_class(document), 'portal_type': document.portal_type, } for document in documents] return document_list
def get_infos_for(self, obj): return { 'title': obj.Title(), 'overlay_url': obj.absolute_url() + '/@@bumblebee-overlay-listing', 'uid': IUUID(obj), 'mime_type_css_class': get_css_class(obj), 'preview_image_url': bumblebee.get_service_v3().get_representation_url( obj, 'thumbnail') }
def decoratorFactory(self, node): new_node = super(OpengeverNavtreeStrategy, self).decoratorFactory(node) portal_type = new_node.get('portal_type', '') if portal_type == 'opengever.document.document': brain = new_node.get('item_icon').brain new_node['normalized_portal_type'] = ' {}'.format( get_css_class(brain)) new_node['item_icon'] = None elif portal_type == 'opengever.meeting.sablontemplate': new_node['item_icon'] = None return new_node
def get_infos_for(self, brain): return { 'title': brain.Title, 'overlay_url': brain.getURL() + '/@@bumblebee-overlay-listing', 'uid': brain.UID, 'mime_type_css_class': get_css_class(brain), 'preview_image_url': bumblebee.get_service_v3().get_representation_url( brain, 'thumbnail') }
def test_remote_successor_task_obj(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.task.task') self.expect(obj.responsible_client).result('client1') self.expect(obj.predecessor).result('client2:123456') parent = self.stub() self.set_parent(obj, parent) # parent is dossier -> obj is not subtask self.expect(parent.portal_type).result('opengever-dossier') self.replay() self.assertEquals(get_css_class(obj), 'icon-task-remote-task')
def serialize_brain(self, brain, last_touched): """Serialize the brain with the summary serialization from plone restapi and extend the result with the two additional data `icon_class` and `last_touched`. """ result = getMultiAdapter((brain, self.request), ISerializeToJsonSummary)() result.update({ "icon_class": get_css_class(brain), "last_touched": last_touched }) return result
def add(self, userid, obj): truncated_title = Favorite.truncate_title(obj.Title().decode('utf-8')) favorite = Favorite( userid=userid, oguid=Oguid.for_object(obj), title=truncated_title, portal_type=obj.portal_type, icon_class=get_css_class(obj), plone_uid=IUUID(obj), position=self.get_next_position(userid)) create_session().add(favorite) create_session().flush() return favorite
def test_task_obj(self): obj = self.stub() self.expect(obj.portal_type).result('opengever.task.task') self.expect(obj.predecessor).result(None) self.expect(obj.responsible_client).result('client1') parent = self.stub() self.set_parent(obj, parent) # parent is dossier -> obj is not subtask self.expect(parent.portal_type).result('opengever-dossier') self.replay() self.assertEquals(get_css_class(obj), 'contenttype-opengever-task-task')