Пример #1
0
 def inspectContentObject(self):
     """ Display detailed information about the current content object """
     logger.debug("in inspectViewlet")
     
     context_state = getMultiAdapter((self.context, self.request), name=u'plone_context_state')
     
     template = ViewPageTemplateFile('panel_inspect_content_object.pt')
     # Wrap it so that Zope knows in what context it's being called
     # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
     template = template.__of__(self)
     out = template(contentObject = self.context,
                    parent = context_state.parent(),
                    skinName = self.context.getCurrentSkinName(),
                    templateName = context_state.view_template_id()
                   )
     
     # Dump the output to the inspector panel
     self.updatePanelBodyContent(out)
     
     # Highlight the element
     ksscore = self.getCommandSet('core')
     self.highlightElement(ksscore.getCssSelector('#glowormPageWrapper'))
     
     # And in the nav tree (Should this be here or in the nav tree viewlet code?)
     self.highlightInNavTree(ksscore.getCssSelector('#glowormPanelNavTree .inspectContentObject'))
     
     return self.render()
Пример #2
0
 def inspectField(self, fieldname):
     """ Display detailed information about one of current content object's fields
     """
     field = self.context.getField(fieldname)
     template = ViewPageTemplateFile('panel_inspect_field.pt')
     # Wrap it so that Zope knows in what context it's being called
     # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
     template = template.__of__(self)
     out = template(fieldName = fieldname,
                    type = field.type,
                    widget = type(field.widget).__name__,
                    accessor = field.accessor,
                    mutator = field.mutator,
                    readPermission = field.read_permission,
                    writePermission = field.write_permission
                   )
     
     # Dump the output to the inspector panel
     self.updatePanelBodyContent(out)
     
     # Highlight the element
     ksscore = self.getCommandSet('core')
     self.highlightElement(ksscore.getCssSelector('.kssattr-atfieldname-%s' % fieldname))
     
     return self.render()
Пример #3
0
 def showMoveViewletForm(self, viewlethash):
     """ Show the form for moving a viewlet between managers. """
     
     unhashedViewletInfo = unhashViewletInfo(viewlethash)
     reg = findTemplateViewRegistrationFromHash(viewlethash)
     viewRegistrationInfo = list(registration.templateViewRegistrationInfos([reg]))[0]
     
     managerName = unhashedViewletInfo['managerName']
     managerNames = self._getAllViewletManagerNames()
     managerNames.sort()
     # Remove the viewlet's current viewlet manager and the gloworm panel from the choices.
     managerNames.remove(unhashedViewletInfo['managerName'])
     managerNames.remove('gloworm.glowormPanel')
     
     template = ViewPageTemplateFile('panel_move_viewlet.pt')
     # Wrap it so that Zope knows in what context it's being called
     # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
     template = template.__of__(self)
     
     out = template(viewlethash=viewlethash,
                    viewletName = unhashedViewletInfo['viewletName'],
                    managerNames = managerNames)
     # Dump the output to the inspector panel
     self.updatePanelBodyContent(out)
     
     return self.render()
Пример #4
0
 def test_cook_zope3_page_templates_using_format(self):
     from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
     pt = ViewPageTemplateFile('using_format_zope3_page_template.pt')
     hack_pt(pt)
     # Need to pass a namespace.
     namespace = {'context': self.app}
     # Even when one of the accessed items requires a role that we do
     # not have, we get no Unauthorized, because this is a filesystem
     # template.
     self.app.test_folder_1_.__roles__ = ['Manager']
     self.assertEqual(
         pt.pt_render(namespace).strip(),
         u"<p>class of &lt;application at &gt; is "
         u"&lt;class 'ofs.application.application'&gt;</p>\n"
         u"<p>CLASS OF &lt;APPLICATION AT &gt; IS "
         u"&lt;CLASS 'OFS.APPLICATION.APPLICATION'&gt;</p>\n"
         u"<p>{'foo': &lt;Folder at /test_folder_1_&gt;} has "
         u"foo=&lt;Folder at test_folder_1_&gt;</p>\n"
         u"<p>{'foo': &lt;Folder at /test_folder_1_&gt;} has "
         u"foo=&lt;Folder at test_folder_1_&gt;</p>\n"
         u"<p>[&lt;Folder at /test_folder_1_&gt;] has "
         u"first item &lt;Folder at test_folder_1_&gt;</p>\n"
         u"<p>[&lt;Folder at /test_folder_1_&gt;] has "
         u"first item &lt;Folder at test_folder_1_&gt;</p>"
     )
def default_html_handler(webdav_handle, filename, view_name, request):

    html_template = ViewPageTemplateFile('html_view.pt')

    # exist-db base url
    base_url = '{}/view/{}'.format(request.context.absolute_url(1),
                                   '/'.join(request.subpath[:-1]))

    # get HTML
    html = webdav_handle.open('.', 'rb').read()
    root = lxml.html.fromstring(html)

    # rewrite relative image urls
    for img in root.xpath('//img'):
        src = img.attrib['src']
        if not src.startswith('http'):
            img.attrib['src'] = '{}/{}'.format(base_url, src)

    # rewrite relative image urls
    for link in root.xpath('//link'):
        src = link.attrib['href']
        if not src.startswith('http'):
            link.attrib['href'] = '{}/{}'.format(base_url, src)

    html = lxml.html.tostring(root)
    return html_template.pt_render(dict(
        template='html_view',
        request=request,
        context=request.context,
        options=dict(
            base_url=base_url,
            html=html)))
Пример #6
0
 def inspectViewlet(self, viewlethash):
     """ Display detailed information about a particular viewlet. """
     logger.debug("in inspectViewlet")
     
     # Unhash the viewlet info
     unhashedViewletInfo = unhashViewletInfo(viewlethash)
     # Get the registration information for this viewlet
     reg = findTemplateViewRegistrationFromHash(viewlethash)
     
     viewName = unhashedViewletInfo['viewletName']
     managerName = unhashedViewletInfo['managerName']
     cls = registration.getViewClassFromRegistration(reg)
     className = "%s.%s" % (cls.__module__, cls.__name__)
     try:
         viewRegistrationInfo = list(registration.templateViewRegistrationInfos([reg]))[0]
     except IndexError:
         # For some reason, there's no registration with portal_view_cusomtizations,
         # this appears to happen when there's no template defined for the viewlet and it instead
         # uses a "render" method.
         customizationExists = False
         customizationAllowed = False
         templatePath = ""
     else:
         template = viewRegistrationInfo['zptfile']
         templatePath = registration.generateIdFromRegistration(reg)
         container = queryUtility(IViewTemplateContainer)
         customizationExists = templatePath in container
         customizationAllowed = True
     
     # Get the names of the hidden viewlets
     storage = getUtility(IViewletSettingsStorage)
     hiddenViewlets = frozenset(storage.getHidden(managerName, self.context.getCurrentSkinName()))
     isVisible = viewName not in hiddenViewlets
     
     template = ViewPageTemplateFile('panel_inspect_viewlet.pt')
     # Wrap it so that Zope knows in what context it's being called
     # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
     template = template.__of__(self)
     out = template(viewName = viewName,
                    managerName = managerName,
                    template = template,
                    className = className,
                    templatePath = templatePath,
                    customizationExists = customizationExists,
                    customizationAllowed = customizationAllowed,
                    visible = isVisible,
                    viewletHash = viewlethash)
     
     # Dump the output to the output panel
     self.updatePanelBodyContent(out)
     
     # Highlight this element
     ksscore = self.getCommandSet('core')
     self.highlightElement(ksscore.getCssSelector('.kssattr-viewlethash-%s' % viewlethash))
     
     # And in the nav tree (Should this be here or in the nav tree viewlet code?)
     self.highlightInNavTree(ksscore.getCssSelector('#glowormPanelNavTree .kssattr-forviewlet-%s' % viewlethash))
     
     return self.render()
Пример #7
0
 def test_cook_zope3_page_templates_normal(self):
     from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
     pt = ViewPageTemplateFile('normal_zope3_page_template.pt')
     hack_pt(pt)
     # Need to pass a namespace.
     namespace = {'context': self.app}
     self.assertEqual(
         pt.pt_render(namespace).strip(),
         u'<p>&lt;application at &gt;</p>\n'
         u'<p>&lt;APPLICATION AT &gt;</p>')
 def test_cook_zope3_page_templates_normal(self):
     from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
     # Note: on Plone 3.3 this is actually a ZopeTwoPageTemplateFile.
     pt = ViewPageTemplateFile('normal_zope3_page_template.pt')
     hack_pt(pt)
     # Need to pass a namespace.
     namespace = {'context': self.portal}
     self.assertEqual(
         pt.pt_render(namespace).strip(),
         u'<p>&lt;plonesite at plone&gt;</p>\n'
         u'<p>&lt;PLONESITE AT PLONE&gt;</p>')
 def test_cook_zope3_page_templates_using_format(self):
     from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
     # Note: on Plone 3.3 this is actually a ZopeTwoPageTemplateFile.
     pt = ViewPageTemplateFile('using_format_zope3_page_template.pt')
     hack_pt(pt)
     # Need to pass a namespace.
     namespace = {'context': self.portal}
     self.assertEqual(
         pt.pt_render(namespace).strip(),
         u"<p>class of &lt;plonesite at plone&gt; is "
         u"&lt;class 'products.cmfplone.portal.plonesite'&gt;</p>\n"
         u"<p>CLASS OF &lt;PLONESITE AT PLONE&gt; IS "
         u"&lt;CLASS 'PRODUCTS.CMFPLONE.PORTAL.PLONESITE'&gt;</p>\n"
         u"<p>{'foo': 42} has foo=42</p>\n"
         u"<p>{'foo': 42} has foo=42</p>\n"
         u"<p>['ni'] has first item ni</p>\n"
         u"<p>['ni'] has first item ni</p>"
     )
def ace_editor(webdav_handle, filename, view_name, request,
               readonly=False, template_name='ace_editor.pt'):
    """ Default handler for showing/editing textish content through the ACE editor """

    mt, encoding = mimetypes.guess_type(filename)
    content = webdav_handle.open('.', 'rb').read()
    ace_mode = config.ACE_MODES.get(mt, 'text')
    template = ViewPageTemplateFile(template_name)
    action_url = '{}/view-editor/{}'.format(request.context.absolute_url(),
                                            '/'.join(request.subpath))
    return template.pt_render(dict(
        template='ace_editor.pt',
        request=request,
        context=request.context,
        options=dict(content=content,
                     action_url=action_url,
                     readonly=readonly,
                     ace_readonly=str(readonly).lower(),  # JS
                     ace_mode=ace_mode)))
Пример #11
0
    def customizeViewlet(self, viewlethash):
        """ Display an edit form for modifiying a viewlet's template """
        logger.debug("in customizeViewlet")
        
        # Unhash the viewlet info
        unhashedViewletInfo = unhashViewletInfo(viewlethash)
        
        # Get the viewlet's registration information from portal_view_customizations
        container = queryUtility(IViewTemplateContainer)
        reg = findTemplateViewRegistrationFromHash(viewlethash)
        regInfo = list(registration.templateViewRegistrationInfos([reg]))[0]
        
        # TODO We should be looking at regInfo['customized'] to determine whether or not a customization exists.
        # It never seems to have a value though... check on this.
        templateName = registration.generateIdFromRegistration(reg)
        
        # Check to see if the viewlet has already been customized. Get the template code accordingly.
        if templateName not in container.objectIds():
            viewzpt = registration.customizeTemplate(reg)
            sm = getSiteManager(self.context)
            sm.registerAdapter(viewzpt, required= reg.required, provided = reg.provided, name=reg.name)
        else:
            viewzpt = container[templateName]
        templateCode = viewzpt.read()
        template = ViewPageTemplateFile('panel_customize_viewlet.pt')
        # Wrap it so that Zope knows in what context it's being called
        # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
        template = template.__of__(self)
        out = template(templateURL = viewzpt.absolute_url(),
                       viewletHash = viewlethash,
                       templateCode = templateCode)
        
        # Dump the output to the output panel
        self.updatePanelBodyContent(out)
        
        # Force a resize update of the panel so that the form elements are sized to the dimensions of the panel.
        kssglo = self.getCommandSet('gloWorm')
        kssglo.forceGlowormPanelResize()

        return self.render()
Пример #12
0
def default_html_handler(get_handle, filename, view_name, request):

    html_template = ViewPageTemplateFile('html_view.pt')

    # exist-db base url
    base_url = '{}/@@view/{}'.format(
        request.context.absolute_url(1),
        '/'.join(request.subpath[:-1]))
    # get HTML
    html = get_handle.open(get_handle.leaf_filename, 'rb').read()
    html = unicode(html, 'utf8')
    if html.startswith(u'<?xml'):
        pos = html.find('?>')
        html = html[pos+3:]
    root = lxml.html.fromstring(html)

    # rewrite relative image urls
    for img in root.xpath('//img'):
        src = img.attrib['src']
        if not src.startswith('http'):
            img.attrib['src'] = '{}/{}'.format(base_url, src)

    # rewrite relative image urls
    for link in root.xpath('//link'):
        src = link.attrib['href']
        if not src.startswith('http'):
            link.attrib['href'] = '{}/{}'.format(base_url, src)

    html = lxml.html.tostring(root, encoding=unicode)

    return html_template.pt_render(dict(
        template='html_view',
        request=request,
        context=request.context,
        options=dict(
            base_url=base_url,
            html=html)))
Пример #13
0
class SidebarViewlet(ViewletBase):
    index = ViewPageTemplateFile('templates/sidebar.pt')

    def get_mouse_activated(self):
        """Pass in values to be used in JavaScript
        """
        mouse = api.portal.get_registry_record(
            name='collective.sidebar.mouse',
            default=True,
        )
        if mouse:
            return 'true'
        else:
            return 'false'

    def get_mouse_area(self):
        """Pass in values to be used in JavaScript
        """
        mouse_area = api.portal.get_registry_record(
            name='collective.sidebar.mouse_area',
            default=30,
        )
        return str(mouse_area)

    def get_sidebar_position(self):
        position = api.portal.get_registry_record(
            name='collective.sidebar.sidebar_position',
            default='left',
        )
        css_class = 'sidebar-' + position
        return css_class

    def _contentCanBeAdded(self, addContext, request):
        """
        Find out if content can be added either by local constraints on the
        current context or by allowed_content_types on the FTI.
        """
        constrain = IConstrainTypes(addContext, None)
        if constrain is None:
            return _allowedTypes(request, addContext)
        return constrain.getLocallyAllowedTypes()

    def is_anonymous(self):
        """
        Check if the user is anonymous.
        """
        return api.user.is_anonymous()

    def get_portal_url(self):
        """
        Return the portal URL.
        """
        return api.portal.get().absolute_url()

    def get_static_links(self):
        """
        Return sidebar links from portal_actions.
        """
        links = self.context.portal_actions.listFilteredActionsFor(self.context)  # noqa: 501
        sidebar_links = links.get('sidebar_links', [])
        return sidebar_links

    def get_user_data(self):
        user = get_user()
        mtool = api.portal.get_tool('portal_membership')
        portrait = mtool.getPersonalPortrait(id=user[1])
        user_info = mtool.getMemberInfo(user[1])
        portal_url = self.get_portal_url()
        data = {
            'user_info': user_info,
            'portrait': portrait.absolute_url(),
            'user_url': portal_url + '/@@personal-information',
        }
        return data

    def get_navigation_root_url(self):
        """
        Return navigation root URL based on the language.
        """
        navigation_root = api.portal.get_navigation_root(self.context)
        return navigation_root.absolute_url()

    def get_back(self):
        """
        Get link to parent.
        """
        context = self.context
        portal = api.portal.get()
        parent = context.aq_parent
        root_nav = api.portal.get_registry_record(
            name='collective.sidebar.root_nav',
            default=False,
        )
        if context == portal or context.portal_type == 'LRF' or root_nav:
            return None
        try:
            if parent.default_page == context.id:
                if parent == api.portal.get_navigation_root(context):
                    return None
                return parent.aq_parent.absolute_url()
        except AttributeError:
            pass
        return parent.absolute_url()

    def can_edit(self):
        """
        Check if the user can modify content.
        """
        permission = permissions.ModifyPortalContent
        if api.user.has_permission(permission, obj=self.context):
            return True
        return False

    def can_manage_portal(self):
        """
        Check is user can manage the portal.
        """
        permission = permissions.ManagePortal
        if api.user.has_permission(permission, obj=self.context):
            return True
        return False

    def check_displayed_types(self, item):
        """
        Check settings if content type should be displayed in navigation.
        """
        types = api.portal.get_registry_record(name='plone.displayed_types')
        if item.portal_type not in types:
            return True

    def check_filter_on_workflow(self, item):
        """
        Check workflow settings if item should be displayed in navigation.
        """
        filter = api.portal.get_registry_record(
            name='plone.filter_on_workflow',
        )
        states = api.portal.get_registry_record(
            name='plone.workflow_states_to_show',
        )
        if filter:
            state = api.content.get_state(obj=item.getObject())
            if state not in states:
                return True

    def check_item(self, item):
        """
        Check if we want to have the given item in the navigation.
        """
        if self.check_displayed_types(item):
            return False
        if self.check_filter_on_workflow(item):
            return False
        if item.exclude_from_nav:
            return False
        try:
            if self.context.default_page == item.id:
                return False
        except AttributeError:
            pass
        return True

    def get_items(self):
        """
        Get folder contents and return.
        """
        context = self.context
        root_nav = api.portal.get_registry_record(
            name='collective.sidebar.root_nav',
            default=False,
        )
        if root_nav:
            context = api.portal.get_navigation_root(context)
        contents = []
        if IFolderish.providedBy(context):
            contents = context.getFolderContents()
        else:
            # Can not remember what edgecase we catch here.
            try:
                parent = context.aq_parent
                contents = parent.getFolderContents()
            except Exception:  # noqa: 902
                pass
        items = []
        for item in contents:
            if self.check_item(item):
                data = {
                    'title': item.Title,
                    'title_cropped': crop(item.Title, 100),
                    'url': item.getURL(),
                }
                items.append(data)
        return items

    def get_folder_contents_url(self):
        """
        Get URL to folder_contents.
        """
        context = self.context
        parent = context.aq_parent
        context_url = context.absolute_url() + '/folder_contents'
        parent_url = parent.absolute_url() + '/folder_contents'
        try:
            if parent.default_page == context.id:
                return parent_url
        except AttributeError:
            pass
        if IFolderish.providedBy(context):
            return context_url
        else:
            return parent_url

    def get_workflow_state_title(self):
        """
        Returns the workflow state title.
        """
        state = self.get_workflow_state()
        tools = getMultiAdapter(
            (self.context, self.request),
            name='plone_tools',
        )
        workflows = tools.workflow().getWorkflowsFor(self.context)
        if workflows:
            for w in workflows:
                if state in w.states:
                    return w.states[state].title or state

    def has_workflow(self):
        """
        Check if there is a workflow for the current context.
        """
        state = self.get_workflow_state()
        return state is not None

    def has_workflow_state_color(self):
        """
        Returns a CSS class for workflow state:
            - with-state-color
            - without-state-color
        TODO: This should be a switch in the backend # noqa: T000
              to enable colored states.
        """
        return 'with-state-color'

    def get_workflow_state(self):
        """
        Return the workflow state for the current context.
        """
        return api.content.get_state(self.context, None)

    def get_workflow_actions(self):
        """
        Return menu item entries in a TAL-friendly form.
        """
        from plone.app.contentmenu import PloneMessageFactory as _
        context = self.context
        request = context.REQUEST
        try:
            pkg_resources.get_distribution('Products.CMFPlacefulWorkflow')
            from Products.CMFPlacefulWorkflow.permissions import ManageWorkflowPolicies  # noqa: 501
        except pkg_resources.DistributionNotFound:
            from Products.CMFCore.permissions import ManagePortal as ManageWorkflowPolicies  # noqa: 501
        results = []
        locking_info = queryMultiAdapter(
            (context, request),
            name='plone_lock_info',
        )
        if locking_info and locking_info.is_locked_for_current_user():
            return []
        wf_tool = api.portal.get_tool('portal_workflow')
        workflowActions = wf_tool.listActionInfos(object=context)
        for action in workflowActions:
            if action['category'] != 'workflow':
                continue
            cssClass = ''
            actionUrl = action['url']
            if actionUrl == '':
                actionUrl = '{0}/content_status_modify?workflow_action={1}'
                actionUrl = actionUrl.format(
                    context.absolute_url(),
                    action['id'],
                )
                cssClass = ''
            description = ''
            transition = action.get('transition', None)
            if transition is not None:
                description = transition.description
            if action['allowed']:
                results.append({
                    'title': action['title'],
                    'description': description,
                    'action': addTokenToUrl(actionUrl, request),
                    'selected': False,
                    'icon': None,
                    'extra': {
                        'id': 'workflow-transition-{0}'.format(action['id']),
                        'separator': None,
                        'class': cssClass,
                    },
                    'submenu': None,
                })
        url = context.absolute_url()

        try:
            pw = api.portal.get_tool('portal_placeful_workflow')
        except InvalidParameterError:
            pw = None

        if pw is not None:
            permission = 'ManageWorkflowPolicies'
            if api.user.has_permission(permission, obj=self.context):
                results.append({
                    'title': _(u'workflow_policy', default=u'Policy...'),
                    'description': '',
                    'action': url + '/placeful_workflow_configuration',
                    'selected': False,
                    'icon': None,
                    'extra': {
                        'id': 'workflow-transition-policy',
                        'separator': None,
                        'class': '',
                    },
                    'submenu': None,
                })
        return results

    @staticmethod
    def is_actions_enabled():
        """
        Should actions be shown
        """
        return api.portal.get_registry_record(
            name='collective.sidebar.enable_actions',
            default=True,
        )

    def cookies_enabled(self):
        """
        Should cookie support be enabled
        """
        return api.portal.get_registry_record(
            'collective.sidebar.enable_cookies',
            default=False,
        )

    def collapse_enabled(self):
        """
        Should collapsible sections be enabled
        """
        return api.portal.get_registry_record(
            'collective.sidebar.enable_collapse',
            default=False,
        )

    def get_section_state(self, section_name=''):
        """
        Return section 'collapsed' state
        """
        if self.cookies_enabled() and self.collapse_enabled():
            sections = self.request.get('sections', '')
            if sections:
                sections = sections.split(',')
                if section_name in sections:
                    return 'menu-section collapsed'
        return 'menu-section'

    def get_actions(self):
        """
        Returns registred object_actions like cut, copy, paste, ...
        """
        portal = api.portal.get()
        actions = portal.portal_actions.listFilteredActionsFor(self.context)
        buttons = list()
        if actions:
            buttons = actions.get('object_buttons', list())
            for action in buttons:
                if not action.get('icon', None):
                    action.icon = self.get_icon(action.get('id', None))
                if action.get('url', None):
                    action.url = addTokenToUrl(action.get('url'), self.request)
        return buttons

    def get_addable_items(self):
        """
        Return menu item entries in a TAL-friendly form.
        """
        context = self.context
        request = self.request
        factories_view = getMultiAdapter(
            (context, request),
            name='folder_factories',
        )
        include = None
        addContext = factories_view.add_context()
        constraints = IConstrainTypes(addContext, None)
        if constraints is not None:
            include = constraints.getImmediatelyAddableTypes()
        results = factories_view.addable_types(include=include)
        results_with_icons = []
        for result in results:
            result['icon'] = 'menu-item-icon {0}'.format(self.get_icon('plus'))
            results_with_icons.append(result)
        results = results_with_icons
        constraints = ISelectableConstrainTypes(addContext, None)
        if constraints is not None:
            if constraints.canSetConstrainTypes() and \
                    constraints.getDefaultAddableTypes():
                url = '{0}/folder_constraintypes_form'.format(
                    addContext.absolute_url(),
                )
                results.append({
                    'title': _(u'folder_add_settings',
                               default=u'Restrictions'),
                    'description': _(
                        u'title_configure_addable_content_types',
                        default=u'Configure which content types can be '
                                u'added here',
                    ),
                    'action': url,
                    'selected': False,
                    'icon': 'menu-item-icon {0}'.format(self.get_icon('cog')),
                    'id': 'settings',
                    'extra': {
                        'id': 'plone-contentmenu-settings',
                        'separator': None,
                        'class': '',
                    },
                    'submenu': None,
                })
        # Also add a menu item to add items to the default page
        context_state = getMultiAdapter(
            (context, request),
            name='plone_context_state',
        )
        if context_state.is_structural_folder() and \
                context_state.is_default_page() and \
                self._contentCanBeAdded(context, request):
            results.append({
                'title': _(u'default_page_folder',
                           default=u'Add item to default page'),
                'description': _(
                    u'desc_default_page_folder',
                    default=u'If the default page is also a folder, '
                            u'add items to it from here.',
                ),
                'action': context.absolute_url() + '/@@folder_factories',
                'selected': False,
                'icon': 'menu-item-icon {0}'.format(self.get_icon('cog')),
                'id': 'special',
                'extra': {
                    'id': 'plone-contentmenu-add-to-default-page',
                    'separator': None,
                    'class': 'pat-plone-modal',
                },
                'submenu': None,
            })
        return results

    def _get_context_state(self):
        return getMultiAdapter((self.context, self.request),
                               name='plone_context_state')

    def get_default_view_link(self):
        context_state = self._get_context_state()
        if context_state.is_default_page():
            parent = context_state.parent()
            return parent.absolute_url() + '/select_default_view'
        else:
            return self.context.absolute_url() + '/select_default_view'

    def get_default_page_link(self):
        context_state = self._get_context_state()
        if context_state.is_default_page():
            parent = context_state.parent()
            return parent.absolute_url() + '/select_default_page'
        else:
            return self.context.absolute_url() + '/select_default_page'

    def get_icon(self, icon):
        return get_icon(icon)

    def get_navigation_class(self):
        """
        Check if dynamic navigation is enabled
        """
        root_nav = api.portal.get_registry_record(
            name='collective.sidebar.root_nav',
            default=False,
        )
        dynamic = api.portal.get_registry_record(
            name='collective.sidebar.dynamic_navigation',
            default=False,
        )

        if root_nav:
            return 'navigation-static'

        if dynamic:
            return 'navigation-dynamic'
        else:
            return 'navigation-static'
Пример #14
0
class FolderPdfBody (BrowserView):
    """ Override folder pdf body
    """
    template = ViewPageTemplateFile("pt/folder.body.pt")

    def __init__(self, context, request):
        super(FolderPdfBody, self).__init__(context, request)
        self._macro = "content-core"
        self._theme = None
        self._maxdepth = None
        self._maxbreadth = None
        self._maxitems = None
        self._depth = 0
        self._count = 1

    def theme(self, context=None):
        """ PDF Theme
        """

        if context:
            tool = queryUtility(IPDFTool)

            return tool.theme(context)

        if self._theme is None:
            tool = queryUtility(IPDFTool)
            self._theme = tool.theme(self.context)

        return self._theme

    def getValue(self, name, context='', default=None):
        """ Get value
        """

        if context == '':
            context = self.context

        getField = getattr(context, 'getField', lambda name: None)
        field = getField(name)

        if not field:
            return default

        value = field.getAccessor(context)()

        return value or default

    @property
    def macro(self):
        """ ZPT macro to use while rendering PDF
        """

        return self._macro

    @property
    def maxdepth(self):
        """ Maximum depth
        """

        if self._maxdepth is None:
            self._maxdepth = self.getValue(
                'pdfMaxDepth', default=self.getValue('maxdepth',
                                                     self.theme(), default=0))

        return self._maxdepth

    @property
    def maxbreadth(self):
        """ Maximum breadth
        """

        if self._maxbreadth is None:
            self._maxbreadth = self.getValue(
                'pdfMaxBreadth', default=self.getValue(
                    'maxbreadth', self.theme(), default=0))

        return self._maxbreadth

    @property
    def maxitems(self):
        """ Maximum items
        """

        if self._maxitems is None:
            self._maxitems = self.getValue(
                'pdfMaxItems', default=self.getValue('maxitems',
                                                     self.theme(), default=0))

        return self._maxitems

    @property
    def depth(self):
        """ Current depth
        """

        return self._depth

    @property
    def count(self):
        """ Current counter
        """

        return self._count

    @property
    def brains(self):
        """ Brains
        """

        return self.context.getFolderContents()[:self.maxbreadth]

    def show_limit_page(self):
        """ Returns the pdf limit page
        """
        pdf = self.context.restrictedTraverse("@@pdf.limit")

        return pdf()

    @property
    def pdfs(self):
        """ Folder children
        """
        self._depth += 1

        if not self.request.get('pdf_last_brain_url'):
            brains = self.context.getFolderContents(
                contentFilter={
                    'portal_type': ['Folder', 'Collection', 'Topic']
                })

            if brains:
                self.request['pdf_last_brain_url'] = brains[-1].getURL()
                # 31424 in case there is only one result from the content
                # filter then we need to reset the depth in order to
                # get the content of the brain

                if len(brains) == 1:
                    self._depth -= 1

        if self.depth > self.maxdepth:
            if self.context.absolute_url() == \
                    self.request.get('pdf_last_brain_url'):
                yield self.show_limit_page()

            return

        ajax_load = self.request.get('ajax_load', True)
        self.request.form['ajax_load'] = ajax_load

        for brain in self.brains:
            if self.count > self.maxitems:
                if not self.request.get('pdflimit'):
                    self.request['pdflimit'] = "reached"
                    yield self.show_limit_page()

                break

            doc = brain.getObject()
            theme = self.theme(doc)
            body = getattr(theme, 'body', '')

            if not body:
                continue

            if isinstance(body, unicode):
                body = body.encode('utf-8')

            if (self.theme(self.context).id == theme.id and
                    self.depth == self.maxdepth):

                if brain.getURL() == self.request.get('pdf_last_brain_url'):
                    if not self.request.get('pdflimit'):
                        self.request['pdflimit'] = "reached"
                        yield self.show_limit_page()

                continue
            try:
                pdf = doc.restrictedTraverse(body.split("?")[0])
                self._count += 1
                html = pdf(
                    macro=self.macro,
                    maxdepth=self.maxdepth,
                    maxbreadth=self.maxbreadth,
                    maxitems=self.maxitems,
                    depth=self.depth,
                    count=self.count
                )
            except Exception:
                continue
            else:
                self._count = getattr(pdf, 'count', self._count)
                yield html

        self.request.form['ajax_load'] = ajax_load

    def update(self, **kwargs):
        """ Update counters
        """
        self._macro = kwargs.get('macro', self._macro)
        self._maxdepth = kwargs.get('maxdepth', None)
        self._maxbreadth = kwargs.get('maxbreadth', None)
        self._maxitems = kwargs.get('maxitems', None)
        self._depth = kwargs.get('depth', self._depth)
        self._count = kwargs.get('count', self._count)

    def __call__(self, **kwargs):
        kwargs.update(self.request.form)
        self.update(**kwargs)

        return self.template(**kwargs)
Пример #15
0
class TempleView(BrowserView):
    """Default view of a Temple
    """
    implements(ITempleView)

    __call__ = ViewPageTemplateFile('temple.pt')

    def deity_term(self, value):
        factory = getUtility(IVocabularyFactory, 'deity_name')
        vocabulary = factory(self.context)
        try:
            existing = vocabulary.getTerm(value)
            return existing.title.split(',')[0]
        except LookupError:
            return value

    def t_title(self, vocab, value):
        factory = getUtility(IVocabularyFactory, vocab)
        vocabulary = factory(self.context)
        try:
            term = vocabulary.getTerm(value)
            return term.title
        except LookupError:
            return None

    def getTemplePilgrimage(self, temple):
        portal_catalog = getToolByName(self.context, 'portal_catalog')
        reference_catalog = getToolByName(self.context, REFERENCE_CATALOG)
        results = []
        # pil used here, but they are schedules actually.
        pil_uids = [
            r.sourceUID for r in reference_catalog.searchResults(
                targetUID=temple.UID(), relationship='temples_in_pilgrimage')
        ]
        if pil_uids:
            pil_brains = portal_catalog.searchResults(portal_type='Schedule',
                                                      UID=pil_uids,
                                                      sort_on='sortable_title')
            for brain in pil_brains:
                url = brain.getURL()
                obj = brain.getObject()
                parent = obj.aq_inner.aq_parent
                full_title = parent.Title() + obj.Title()
                results.append(dict(
                    url=url,
                    full_title=full_title,
                ))
        return results

    def getTempleFestival(self, temple):
        portal_catalog = getToolByName(self.context, 'portal_catalog')
        reference_catalog = getToolByName(temple, REFERENCE_CATALOG)
        results = []
        fsv_uids = [
            r.sourceUID
            for r in reference_catalog.searchResults(targetUID=temple.UID(),
                                                     relationship='relatesTo')
        ]
        if fsv_uids:
            fsv_brains = portal_catalog.searchResults(portal_type='Event',
                                                      UID=fsv_uids,
                                                      sort_on='start',
                                                      sort_order='ascending')
            for brain in fsv_brains:
                results.append(
                    dict(
                        url=brain.getURL(),
                        full_title=str(brain.start)[:4] + '年' + brain.Title,
                    ))
        return results

    def getTempleBiXieWu(self, temple):
        portal_catalog = getToolByName(self.context, 'portal_catalog')
        reference_catalog = getToolByName(temple, REFERENCE_CATALOG)
        results = []
        bxw_uids = [
            r.sourceUID for r in reference_catalog.searchResults(
                targetUID=temple.UID(), relationship='temple_bixiewu')
        ]
        if bxw_uids:
            bxw_brains = portal_catalog.searchResults(portal_type='BiXieWu',
                                                      UID=bxw_uids)
            for brain in bxw_brains:
                results.append(dict(
                    url=brain.getURL(),
                    title=brain.Title,
                ))
        return results
    def fetchcomments(self,uid,itemindex,lasttimestamp,commentcount,lastcommentid,viewtype):
        query = {'UID':uid}
        pdt = getToolByName(self.context, 'portal_discussion', None)
        cat = getToolByName(self.context, 'uid_catalog')
        resbrains = cat.searchResults(query)
        if len(resbrains) == 1:
            zopecommands = self.getCommandSet('zope')
            ksscore = self.getCommandSet('core')
            jq = self.getCommandSet('jquery')
            
            listcommentcontainer = ksscore.getHtmlIdSelector('comcynapselistcommentscontainer' + itemindex)
	    listcountspan = ksscore.getHtmlIdSelector('commentcountspan' + itemindex)
	    nocommentsyet = ksscore.getCssSelector('.nocommentsyet')
            listtimeoutuid = ksscore.getHtmlIdSelector('comcynapsecyninfetchUID')
            listtimeoutindex = ksscore.getHtmlIdSelector('comcynapsecyninfetchindex')
            listtimeouttimestamp = ksscore.getHtmlIdSelector('comcynapselasttimestamp')
            listtimeoutlastcommentid = ksscore.getHtmlIdSelector('comcynapselastcommentid')
            listtimeoutcommentcount = ksscore.getHtmlIdSelector('comcynapsecommentcount')
	    
            
            listcommentscount = ksscore.getHtmlIdSelector('listdiscussioncount' + itemindex)            
            
            contobj = resbrains[0].getObject()
            isDiscussable = contobj.isDiscussable()
            canReply = self.canreply(contobj)
            if isDiscussable and canReply:                
                passedcommentcount = 0
                passedcommentcount = int(commentcount)
                flasttimestamp = float(lasttimestamp)
                datefromlasttimestamp = DateTime(flasttimestamp)
                newlastdate = datefromlasttimestamp.timeTime()
                
                disc_container = pdt.getDiscussionFor(contobj)
                newreplycount = disc_container.replyCount(contobj)
                allreplies = self.get_replies(pdt,contobj)
                
                if passedcommentcount <> newreplycount:
                    alldiscussions = disc_container.objectValues()
                    newlastcommentid = lastcommentid
                    
                    newlyaddedcomments = [k for k in alldiscussions if k.modified().greaterThan(datefromlasttimestamp) and k.id not in (lastcommentid)]
                    newlyaddedcomments.sort(lambda x,y:cmp(x.modified(),y.modified()))
                    
                    lenofnewcomments = len(newlyaddedcomments)
                    display_count = self.get_displaycountforlist()
                    
                    lastxdiscussions = []
                    if lenofnewcomments >= display_count:
                        newlyaddedcomments.sort(lambda x,y:cmp(x.modified(),y.modified()),reverse=True)
                        lastxdiscussions = newlyaddedcomments[:display_count]
                        lastxdiscussions.sort(lambda x,y:cmp(x.modified(),y.modified()))
                        ksscore.clearChildNodes(listcommentcontainer)
                    else:
                        lastxdiscussions = newlyaddedcomments
                        if lenofnewcomments > 0 and len(alldiscussions) > display_count:
                            alldiscussions.sort(lambda x,y:cmp(x.modified(),y.modified()),reverse=True)
                            marker_discussion = alldiscussions[display_count-1: display_count]
                            if len(marker_discussion) > 0:
                                #delete nodes before this item
                                marker_node = ksscore.getHtmlIdSelector('commenttable' + marker_discussion[0].id)
                                ksscore.deleteNodeBefore(marker_node)
                    
                    complete_output = ''
                    list_reply_ids = []
                    for eachcomment in lastxdiscussions:                    
                        reply = disc_container.getReply(eachcomment.id)
                        if reply <> None:     
                            parentsInThread = reply.parentsInThread()
                            depthvalue = 0
                            if viewtype.lower() == 'threadedview':
                                lenofparents = len(parentsInThread)
                                depthvalue = lenofparents - 1
                            
                            prev_reply_id = self.findpreviouscommentid(allreplies,reply)
                            
                            newlastdate = reply.modified().timeTime()
                            newlastcommentid = reply.id
                            commenttemplate = ViewPageTemplateFile('ksstemplates/commentrow.pt')
                            commenttemplate = commenttemplate.__of__(self.context)
                            
                            replydict = [{'depth': depthvalue, 'object': reply,'prev_id':prev_reply_id,'view_type':viewtype, 'showoutput':False},]
                            output = commenttemplate.render(reply_dict=replydict,allowdiscussion = isDiscussable,usercanreply = canReply)
                            list_reply_ids.append(reply.id)
                            complete_output += output
                            
                    if complete_output <> '' and len(lastxdiscussions) > 0:
                        ksscore.insertHTMLAsLastChild(listcommentcontainer,complete_output)
                        for erid in list_reply_ids:
                            newcomment = ksscore.getHtmlIdSelector('commenttable' + erid)
                            jq.serverEffect(newcomment,"fadeIn", "slow")			    
                        
                    ksscore.setAttribute(listtimeoutuid,'value',uid)
                    ksscore.setAttribute(listtimeoutindex,'value',itemindex)
                    ksscore.setAttribute(listtimeouttimestamp,'value',str(newlastdate))
                    ksscore.setAttribute(listtimeoutlastcommentid,'value',newlastcommentid)
                    ksscore.setAttribute(listtimeoutcommentcount,'value',str(newreplycount))
		    ksscore.setAttribute(listtimeoutuid,'value',uid)
		    
		    if newreplycount > display_count:
			xmorecomments = newreplycount - display_count
			ksscore.replaceInnerHTML(listcommentscount,str(xmorecomments))
			jq.serverEffect(nocommentsyet,"fadeOut", "fast")
			jq.serverEffect(listcountspan,"fadeIn", "slow")
		    elif newreplycount > 0 and newreplycount <= display_count:
			jq.serverEffect(nocommentsyet,"fadeOut", "fast")
		    
		    jq.serverCall(listcommentcontainer,'truncatetextonitemexpand')
Пример #17
0
class EditView(BrowserView):

    template = ViewPageTemplateFile('templates/batch_edit.pt')

    def __call__(self):
        request = self.request
        context = self.context
        self.form = request.form

        if 'submitted' in request:
            try:
                self.validate_form_input()
            except ValidationError as e:
                self.form_error(e.message)
                return

            context.setConstrainTypesMode(constraintypes.DISABLED)
            portal_factory = getToolByName(context, 'portal_factory')

            folder = context.aq_parent
            batch = None
            if not folder.hasObject(context.getId()):
                batch = portal_factory.doCreate(context, context.id)
            else:
                batch = context

            old_qty = int(batch.Quantity or 0)
            new_qty = int(self.form.get('Quantity', 0))

            membership = getToolByName(self.context, 'portal_membership')
            if membership.isAnonymousUser():
                member = 'anonymous'
            else:
                member = membership.getAuthenticatedMember().getUserName()

            batch.getField('ChangeUserName').set(batch, member)
            batch.getField('ChangeDateTime').set(batch, DateTime())

            if not batch.getField('DateCreated').get(batch):
                batch.getField('DateCreated').set(batch, DateTime())

            batch.processForm()
            self.create_samples(batch, self.form, new_qty - old_qty, member)
            batch.getField('BatchId').set(batch, batch.Title())
            batch.reindexObject()

            obj_url = batch.absolute_url_path()
            request.response.redirect(obj_url)

            return

        return self.template()

    def validate_form_input(self):
        subject_id = self.form.get('SubjectID')
        if not subject_id:
            raise ValidationError(['Subject ID cannot be empty!'])

        date_created = self.form.get('DateCreated')
        if not date_created:
            raise ValidationError(['Date Created cannot be empty!'])

        new_qty = int(self.form.get('Quantity', 0))
        old_qty = int(self.context.Quantity or 0)

        if new_qty <= 0:
            raise ValidationError(
                'Quantity of samples cannot be zero or less than zero!')
        if new_qty < old_qty:
            raise ValidationError(
                'New number of samples cannot be less than the number of samples already created!'
            )

    def get_biospecimen_storages(self):
        """Take a list of UIDs from the form, and resolve to a list of Storages.
        Accepts ManagedStorage, UnmanagedStorage, or StoragePosition UIDs.
        """
        uc = getToolByName(self.context, 'uid_catalog')
        bio_storages = []
        # form_uids = self.form['StorageLocation_uid'].split(',')
        form_uids = self.form['StorageLocation_uid'].split(
            ',') if self.form['StorageLocation_uid'] else []

        for uid in form_uids:
            brain = uc(UID=uid)[0]
            instance = brain.getObject()
            if IManagedStorage.providedBy(instance) \
                    or len(instance.get_free_positions()) > 0:
                bio_storages.append(instance)

        return bio_storages

    def create_samples(self, context, form, num_samples, member=None):
        """Create samples from form
        """

        sample_type = get_first_sampletype(context)
        uc = getToolByName(context, 'uid_catalog')

        project_uid = form.get('Project_uid', '')
        project = uc(UID=project_uid)[0].getObject()

        samples_gen = SampleGeneration(form, project)
        subject_id = form['SubjectID']
        try:
            parent_sample_uid = form.get('ParentBiospecimen_uid')
            parent_sample = uc(UID=parent_sample_uid)[0].getObject()
            parent_sampling_date = parent_sample.getField('SamplingDate').get(
                parent_sample)
        except:
            parent_sampling_date = None

        samples = []
        for i in range(num_samples):
            sample = samples_gen.create_sample(None, sample_type, context)
            sample.getField('SubjectID').set(sample, subject_id)
            sample.getField('SamplingDate').set(sample, parent_sampling_date)
            if member:
                sample.getField('ChangeUserName').set(sample, member)
            sample.getField('ChangeDateTime').set(sample, DateTime())
            samples.append(sample)

        storages = self.get_biospecimen_storages()

        if storages:
            samples_gen.store_samples(samples, storages)

        for storage in storages:
            storage.reindexObject()

        return samples

    def get_fields_with_visibility(self, visibility, mode=None):
        mode = mode if mode else 'edit'
        schema = self.context.Schema()
        fields = []
        for field in schema.fields():
            isVisible = field.widget.isVisible
            v = isVisible(self.context, mode, default='invisible', field=field)
            if v == visibility:
                fields.append(field)
        return fields

    def form_error(self, msg):
        self.context.plone_utils.addPortalMessage(msg)
        self.request.response.redirect(self.context.absolute_url())
    def replyToComment(self,viewtype,lasttimestamp,commentcount,lastcommentid):
        query = {'UID':self.request['cont_uid']}
        pdt = getToolByName(self.context, 'portal_discussion', None)
        cat = getToolByName(self.context, 'uid_catalog')
        resbrains = cat.searchResults(query)
	ksscore = self.getCommandSet('core')
        zopecore = self.getCommandSet('zope')
        jq = self.getCommandSet('jquery')
        if len(resbrains) == 1:
            contobj = resbrains[0].getObject()
            if contobj.isDiscussable() and self.canreply(contobj):
                mtool = getToolByName(self.context, 'portal_membership')
                username = mtool.getAuthenticatedMember().getId()
                dobj = pdt.getDiscussionFor(contobj)
                if len(self.request['commentbody'].strip(' ')) == 0 or self.request['commentbody'].lower() == self.request['comcynapsenewcommenttitle'].lower():
                    comcynapsecommenterrorlabel = ksscore.getHtmlIdSelector('comcynapsecommenterror'+ self.request['inreplyto'])
		    ksscore.setStyle(comcynapsecommenterrorlabel,'display','block')		    
                else:
                    id = dobj.createReply(title="", text=self.request['commentbody'], Creator=username)
                    reply = dobj.getReply(id)
                    reply.cooked_text = convertWebIntelligentPlainTextToHtml(reply.text)
                    replyto = dobj.getReply(self.request['inreplyto'])
                    reply.setReplyTo(replyto)
                    if reply <> None:
                        from ubify.cyninv2theme import triggerAddOnDiscussionItem
                        triggerAddOnDiscussionItem(reply)

                        #################Determine full reply to discussion to get placement peer of current comment
                        view_type = self.request['cviewtype']
                        replies = []
                        def getRs(obj, replies, counter):
                            rs = pdt.getDiscussionFor(obj).getReplies()
                            if len(rs) > 0:
                                rs.sort(lambda x, y: cmp(x.modified(), y.modified()))
                                for r in rs:
                                    replies.append({'depth':counter, 'object':r})
                                    getRs(r, replies, counter=counter + 1)

                        getRs(replyto, replies, 0)

                        if len(replies) > 1: ##There are more than 1 comments already children of the comment we just replied to, so the current comment can't have been the first reply
                            prevrep = replies[0]['object']
                        else:
                            prevrep = replyto

                        for rep in replies:
                            if rep['object'].id == reply.id:
                                belowreply = prevrep
                            else:
                                prevrep = rep['object']

                        mi = mtool.getMemberInfo();
                        commenttemplate = ViewPageTemplateFile('ksstemplates/commentrow.pt')
                        commenttemplate = commenttemplate.__of__(self.context)
                        depthvalue = 0
                        if view_type == 'threadedview':
                            depthvalue = int(self.request['depth']) + 1
                            
                        replydict = [{'depth': depthvalue, 'object': reply,'view_type':view_type},]
                        output = commenttemplate.render(indent=int(self.request['depth'])+2,fullname = mi['fullname'], avatarurl=self.context.portal_membership.getPersonalPortrait(username).absolute_url(),creator=username,showreply=self.canreply(self.context),showdelete=getSecurityManager().checkPermission('Manage portal',aq_inner(self.context)),commenttime=self.context.toLocalizedTime(reply.created,True),replyid=reply.id,replytitle=reply.Title(),replybody=reply.CookedBody(),replyurl=reply.absolute_url(),reply_dict=replydict)
                        
                        if view_type == 'threadedview':
                            commentscontainer = ksscore.getHtmlIdSelector('commenttable' + prevrep.id)
                            ksscore.insertHTMLAfter(commentscontainer,output)
                        else:
                            commentsoutercontainer = ksscore.getHtmlIdSelector('comcynapsecyninitemcommentscontainer')
                            ksscore.insertHTMLAsLastChild(commentsoutercontainer,output)
                        
                        taAddNewComment = ksscore.getCssSelector('textarea.commentbodyta')
                        ksscore.setAttribute(taAddNewComment,"value","")
                        itemcountcommentcount = ksscore.getHtmlIdSelector('itemcountcommentcount')
                        countofcomments = dobj.replyCount(self.context)
                        discussionlabel = ksscore.getHtmlIdSelector('discussionlabel')
                        ksscore.replaceInnerHTML(discussionlabel,str(countofcomments))
                        ksscore.replaceInnerHTML(itemcountcommentcount,str(countofcomments))
                        newcomment = ksscore.getHtmlIdSelector('commenttable' + reply.id)
                        frmreply = ksscore.getHtmlIdSelector('replyform' + self.request['inreplyto'])			
			ksscore.setStyle(frmreply,'display','none')
			comcynapsecommenterrorlabel = ksscore.getHtmlIdSelector('comcynapsecommenterror'+ self.request['inreplyto'])
			ksscore.setStyle(comcynapsecommenterrorlabel,'display','none')
                        self.fetchnewcomments(lasttimestamp,commentcount,lastcommentid,viewtype)
 def toggleCommentsView(self,viewtype):
     zopecommands = self.getCommandSet('zope')
     ksscore = self.getCommandSet('core')
     jq = self.getCommandSet('jquery')
     commentshiddencontainer = ksscore.getHtmlIdSelector('comcynapsehiddencomments')
     commentscontainer = ksscore.getHtmlIdSelector('comcynapsecyninitemcommentscontainer')
     addnewlasttimestamp = ksscore.getHtmlIdSelector('comcynapselasttimestamp')
     addnewlastcommentid = ksscore.getHtmlIdSelector('comcynapselastcommentid')
     addnewcommentcount = ksscore.getHtmlIdSelector('comcynapsecommentcount')
         
     objcommentslist = []
     pdt = getToolByName(self.context, 'portal_discussion', None)
     if pdt <> None:
         disc_container = pdt.getDiscussionFor(self.context)
         alldiscussions = disc_container.objectValues()
         allreplies = self.get_replies(pdt,self.context)
         newreplycount = disc_container.replyCount(self.context)
         newlastdate = DateTime().timeTime()
         
         if viewtype == 'flatview':
             alldiscussions.sort(lambda x,y:cmp(x.modified(),y.modified()))
             objcommentslist.extend(alldiscussions)
         else:
             objcommentslist.extend(allreplies)
         
         ksscore.replaceInnerHTML(commentscontainer,'')
         complete_output = ''
         for eachcomment in objcommentslist:
             if hasattr(eachcomment,'id'):
                 id = eachcomment.id
             elif eachcomment.has_key('id'):
                 id = eachcomment['id']
                 
             reply = disc_container.getReply(id)
             if reply <> None:                        
                 parentsInThread = reply.parentsInThread()
                 depthvalue = 0
                 if viewtype.lower() == 'threadedview':
                     lenofparents = len(parentsInThread)
                     depthvalue = lenofparents - 1
                 
                 prev_reply_id = self.findpreviouscommentid(allreplies,reply)
                 
                 newlastdate = reply.modified().timeTime()
                 commenttemplate = ViewPageTemplateFile('ksstemplates/commentrow.pt')
                 commenttemplate = commenttemplate.__of__(self.context)
                 replydict = [{'depth': depthvalue, 'object': reply,'prev_id':prev_reply_id,'view_type':viewtype,'showoutput':True},]
                 output = commenttemplate.render(reply_dict=replydict)
                 
                 #if there is no prev id found for new comment then insert it as last item to commentscontainer
                 #else insert it after prev id comments table.
                 if viewtype == 'flatview':                        
                     complete_output += output
                 else:
                     complete_output += output                        
         
         if complete_output <> '' and len(objcommentslist) > 0:
             ksscore.replaceInnerHTML(commentscontainer,complete_output)
             jq.serverCall(commentscontainer,'truncatetextonitemexpand')
         if len(alldiscussions) > 0:
             strlastcommentid = str(alldiscussions[-1].id)
             ksscore.setKssAttribute(commentshiddencontainer,'lastcommentid',strlastcommentid)
             ksscore.setAttribute(addnewlastcommentid,'value',strlastcommentid)
     
     
         newlasttimestamp = str(newlastdate)
         strcommentcount = str(newreplycount)
         ksscore.setKssAttribute(commentshiddencontainer,'lasttimestamp',newlasttimestamp)            
         ksscore.setKssAttribute(commentshiddencontainer,'commentcount',strcommentcount)            
         
         ksscore.setAttribute(addnewlasttimestamp,'value',newlasttimestamp)
         ksscore.setAttribute(addnewcommentcount,'value',strcommentcount)
         
         itemcountcommentcount = ksscore.getHtmlIdSelector('itemcountcommentcount')            
         discussionlabel = ksscore.getHtmlIdSelector('discussionlabel')
         ksscore.replaceInnerHTML(discussionlabel,strcommentcount)
         ksscore.replaceInnerHTML(itemcountcommentcount,strcommentcount)            
         
     ksscore.setKssAttribute(commentshiddencontainer,'viewtype',viewtype)
     addnewcommentviewtype = ksscore.getHtmlIdSelector('comcynapseviewtype')
     ksscore.setAttribute(addnewcommentviewtype,'value',viewtype)
     ksscore.setStyle(commentscontainer,'display','block')
Пример #20
0
class TinyLogoViewlet(ViewletBase):
    index = ViewPageTemplateFile('tiny_logo.pt')
Пример #21
0
class FooterViewlet(ViewletBase):
    index = ViewPageTemplateFile('footer.pt')

    def update(self):
        super(FooterViewlet, self).update()
        self.year = date.today().year
Пример #22
0
class SampleEdit(BrowserView):
    """
    Edit view
    """

    implements(IViewView)
    template = ViewPageTemplateFile("templates/sample.pt")
    header_table = ViewPageTemplateFile("../templates/header_table.pt")

    def __init__(self, context, request):
        BrowserView.__init__(self, context, request)
        self.icon = self.portal_url + "/++resource++bika.lims.images/sample_big.png"
        self.allow_edit = True
        self.context_actions = {}

    def now(self):
        return DateTime()

    def getDefaultSpec(self):
        """ Returns 'lab' or 'client' to set the initial value of the
            specification radios
        """
        mt = getToolByName(self.context, 'portal_membership')
        pg = getToolByName(self.context, 'portal_groups')
        member = mt.getAuthenticatedMember()
        member_groups = [pg.getGroupById(group.id).getGroupName() \
                         for group in pg.getGroupsByUserId(member.id)]
        default_spec = ('Clients' in member_groups) and 'client' or 'lab'
        return default_spec

    def __call__(self):
        if 'transition' in self.request.form:
            doActionFor(self.context, self.request.form['transition'])
        # Add an Analysis request creation button
        mtool = get_tool('portal_membership', context=self.context)
        if mtool.checkPermission(AddAnalysisRequest, self.context):
            self.context_actions[_('Add Analysis Request')] = \
                {'url': "ar_add?ar_count=1",
                 'icon': '++resource++bika.lims.images/add.png'}
        ## render header table
        self.header_table = HeaderTableView(self.context, self.request)

        ## Create Sample Partitions table
        parts_table = None
        if not self.allow_edit:
            p = SamplePartitionsView(self.context, self.request)
            p.allow_edit = self.allow_edit
            p.show_select_column = self.allow_edit
            p.show_workflow_action_buttons = self.allow_edit
            p.show_column_toggles = False
            p.show_select_all_checkbox = False
            p.review_states[0]['transitions'] = [
                {
                    'id': 'empty'
                },
            ]  # none
            parts_table = p.contents_table()
        self.parts = parts_table

        ## Create Field and Lab Analyses tables
        self.tables = {}
        if not self.allow_edit:
            for poc in POINTS_OF_CAPTURE:
                t = SampleAnalysesView(self.context,
                                       self.request,
                                       getPointOfCapture=poc,
                                       sort_on='getId')
                t.form_id = "sample_%s_analyses" % poc
                if poc == 'field':
                    t.review_states[0]['columns'].remove('DueDate')
                t.show_column_toggles = False
                t.review_states[0]['transitions'] = [{
                    'id': 'submit'
                }, {
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }]
                self.tables[POINTS_OF_CAPTURE.getValue(
                    poc)] = t.contents_table()

        return self.template()

    def tabindex(self):
        i = 0
        while True:
            i += 1
            yield i
Пример #23
0
class ContentViewsViewlet(ViewletBase):
    index = ViewPageTemplateFile('contentviews.pt')

    @memoize
    def prepareObjectTabs(self,
                          default_tab='view',
                          sort_first=['folderContents']):
        """Prepare the object tabs by determining their order and working
        out which tab is selected. Used in global_contentviews.pt
        """
        context = aq_inner(self.context)
        context_url = context.absolute_url()
        context_fti = context.getTypeInfo()

        context_state = getMultiAdapter((context, self.request),
                                        name=u'plone_context_state')
        actions = context_state.actions

        action_list = []
        if context_state.is_structural_folder():
            action_list = actions('folder')
        action_list.extend(actions('object'))

        tabs = []
        found_selected = False
        fallback_action = None

        try:
            request_url = self.request['ACTUAL_URL']
        except KeyError:
            # not a real request, could be a test. Let's not fail.
            request_url = context_url
        request_url_path = request_url[len(context_url):]

        if request_url_path.startswith('/'):
            request_url_path = request_url_path[1:]

        for item in action_list:
            item.update({'selected': False})

            action_url = item['url'].strip()
            starts = action_url.startswith
            if starts('http') or starts('javascript'):
                item['url'] = action_url
            else:
                item['url'] = '%s/%s' % (context_url, action_url)
            item['url'] = addTokenToUrl(item['url'], self.request)

            action_method = item['url'].split('/')[-1].split('?')[0]

            # Action method may be a method alias:
            # Attempt to resolve to a template.
            action_method = context_fti.queryMethodID(action_method,
                                                      default=action_method)
            if action_method:
                request_action = unquote(request_url_path).split('?')[0]
                request_action = context_fti.queryMethodID(
                    request_action, default=request_action)
                if action_method == request_action:
                    item['selected'] = True
                    found_selected = True

            current_id = item['id']
            if current_id == default_tab:
                fallback_action = item

            modal = item.get('modal', None)
            item['cssClass'] = ''
            if modal:
                item['cssClass'] += ' pat-modal'
                item['url'] += '?ajax_load=1'

            tabs.append(item)

        if not found_selected and fallback_action is not None:
            fallback_action['selected'] = True

        def sortOrder(tab):
            try:
                return sort_first.index(tab['id'])
            except ValueError:
                return 255

        tabs.sort(key=sortOrder)
        return tabs
Пример #24
0
class FolderView(BikaListingView):

    implements(IFolderContentsView, IViewView)

    template = ViewPageTemplateFile("../templates/worksheets.pt")

    def __init__(self, context, request):
        super(FolderView, self).__init__(context, request)
        self.catalog = 'bika_catalog'
        self.contentFilter = {
            'portal_type': 'Worksheet',
            'review_state': ['open', 'to_be_verified', 'verified', 'rejected'],
            'sort_on': 'id',
            'sort_order': 'reverse'
        }
        self.context_actions = {
            _('Add'): {
                'url': 'worksheet_add',
                'icon': '++resource++bika.lims.images/add.png',
                'class': 'worksheet_add'
            }
        }
        self.show_table_only = False
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_all_checkbox = True
        self.show_select_column = True
        self.pagesize = 25
        self.restrict_results = False

        request.set('disable_border', 1)

        self.icon = self.portal_url + "/++resource++bika.lims.images/worksheet_big.png"
        self.title = self.context.translate(_("Worksheets"))
        self.description = ""

        pm = getToolByName(context, "portal_membership")
        # this is a property of self, because self.getAnalysts returns it
        self.analysts = getUsers(self, ['Manager', 'LabManager', 'Analyst'])
        self.analysts = self.analysts.sortedByKey()

        bsc = getToolByName(context, 'bika_setup_catalog')
        templates = [
            t for t in bsc(portal_type='WorksheetTemplate',
                           inactive_state='active')
        ]

        self.templates = [(t.UID, t.Title) for t in templates]
        self.templates.sort(lambda x, y: cmp(x[1], y[1]))

        self.instruments = [
            (i.UID, i.Title)
            for i in bsc(portal_type='Instrument', inactive_state='active')
        ]
        self.instruments.sort(lambda x, y: cmp(x[1], y[1]))

        self.templateinstruments = {}
        for t in templates:
            i = t.getObject().getInstrument()
            if i:
                self.templateinstruments[t.UID] = i.UID()
            else:
                self.templateinstruments[t.UID] = ''

        self.columns = {
            'Title': {
                'title': _('Worksheet'),
                'index': 'sortable_title'
            },
            'Priority': {
                'title': _('Priority'),
                'index': 'Priority',
                'toggle': True
            },
            'Analyst': {
                'title': _('Analyst'),
                'index': 'getAnalyst',
                'toggle': True
            },
            'Template': {
                'title': _('Template'),
                'toggle': True
            },
            'Services': {
                'title': _('Services'),
                'sortable': False,
                'toggle': False
            },
            'SampleTypes': {
                'title': _('Sample Types'),
                'sortable': False,
                'toggle': False
            },
            'Instrument': {
                'title': _('Instrument'),
                'sortable': False,
                'toggle': False
            },
            'QC': {
                'title': _('QC'),
                'sortable': False,
                'toggle': False
            },
            'QCTotals': {
                'title': _('QC Samples(Analyses)'),
                'sortable': False,
                'toggle': False
            },
            'RoutineTotals': {
                'title': _('Routine Samples(Analyses)'),
                'sortable': False,
                'toggle': False
            },
            'CreationDate': {
                'title': PMF('Date Created'),
                'toggle': True,
                'index': 'created'
            },
            'state_title': {
                'title': _('State'),
                'index': 'review_state'
            },
        }
        self.review_states = [
            {
                'id':
                'default',
                'title':
                _('All'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': [
                        'open',
                        'to_be_verified',
                    ],
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            # getAuthenticatedMember does not work in __init__
            # so 'mine' is configured further in 'folderitems' below.
            {
                'id':
                'mine',
                'title':
                _('Mine'),
                'contentFilter': {
                    'portal_type':
                    'Worksheet',
                    'review_state':
                    ['open', 'to_be_verified', 'verified', 'rejected'],
                    'sort_on':
                    'id',
                    'sort_order':
                    'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'open',
                'title':
                _('Open'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'open',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'to_be_verified',
                'title':
                _('To be verified'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'to_be_verified',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [{
                    'id': 'retract'
                }, {
                    'id': 'verify'
                }, {
                    'id': 'reject'
                }],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
            {
                'id':
                'verified',
                'title':
                _('Verified'),
                'contentFilter': {
                    'portal_type': 'Worksheet',
                    'review_state': 'verified',
                    'sort_on': 'id',
                    'sort_order': 'reverse'
                },
                'transitions': [],
                'columns': [
                    'Title', 'Priority', 'Analyst', 'Template', 'Services',
                    'SampleTypes', 'Instrument', 'QC', 'QCTotals',
                    'RoutineTotals', 'CreationDate', 'state_title'
                ]
            },
        ]

    def __call__(self):
        if not self.isManagementAllowed():
            # The current has no prvileges to manage WS.
            # Remove the add button
            self.context_actions = {}

        return super(FolderView, self).__call__()

    def isManagementAllowed(self):
        mtool = getToolByName(self.context, 'portal_membership')
        return mtool.checkPermission(ManageWorksheets, self.context)

    def isEditionAllowed(self):
        pm = getToolByName(self.context, "portal_membership")
        checkPermission = self.context.portal_membership.checkPermission
        return checkPermission(EditWorksheet, self.context)

    def isItemAllowed(self, obj):
        # Only show "my" worksheets
        # this cannot be setup in contentFilter,
        # because AuthenticatedMember is not available in __init__
        if self.selected_state == 'mine' or self.restrict_results == True:
            analyst = obj.getAnalyst().strip()
            if analyst != _c(self.member.getId()):
                return False

        return BikaListingView.isItemAllowed(self, obj)

    def folderitems(self):
        wf = getToolByName(self, 'portal_workflow')
        rc = getToolByName(self, REFERENCE_CATALOG)
        pm = getToolByName(self.context, "portal_membership")

        self.member = pm.getAuthenticatedMember()
        roles = self.member.getRoles()
        self.restrict_results = 'Manager' not in roles \
                and 'LabManager' not in roles \
                and 'LabClerk' not in roles \
                and 'RegulatoryInspector' not in roles \
                and self.context.bika_setup.getRestrictWorksheetUsersAccess()

        if self.restrict_results == True:
            # Remove 'Mine' button and hide 'Analyst' column
            del self.review_states[1]  # Mine
            self.columns['Analyst']['toggle'] = False

        can_manage = pm.checkPermission(ManageWorksheets, self.context)

        self.selected_state = self.request.get(
            "%s_review_state" % self.form_id, 'default')

        items = BikaListingView.folderitems(self)
        new_items = []
        analyst_choices = []
        for a in self.analysts:
            analyst_choices.append({
                'ResultValue': a,
                'ResultText': self.analysts.getValue(a)
            })
        can_reassign = False
        self.allow_edit = self.isEditionAllowed()

        for x in range(len(items)):
            if not items[x].has_key('obj'):
                new_items.append(items[x])
                continue

            obj = items[x]['obj']

            analyst = obj.getAnalyst().strip()
            creator = obj.Creator().strip()
            items[x]['Analyst'] = analyst

            priority = obj.getPriority()
            items[x]['Priority'] = ''

            instrument = obj.getInstrument()
            items[x]['Instrument'] = instrument and instrument.Title() or ''

            items[x]['Title'] = obj.Title()
            wst = obj.getWorksheetTemplate()
            items[x]['Template'] = wst and wst.Title() or ''
            if wst:
                items[x]['replace']['Template'] = "<a href='%s'>%s</a>" % \
                    (wst.absolute_url(), wst.Title())

            items[x]['getPriority'] = ''
            items[x]['CreationDate'] = self.ulocalized_time(obj.creation_date)

            nr_analyses = len(obj.getAnalyses())
            if nr_analyses == '0':
                # give empties pretty classes.
                items[x]['table_row_class'] = 'state-empty-worksheet'

            layout = obj.getLayout()

            if len(layout) > 0:
                items[x]['replace']['Title'] = "<a href='%s/manage_results'>%s</a>" % \
                    (items[x]['url'], items[x]['Title'])
            else:
                items[x]['replace']['Title'] = "<a href='%s/add_analyses'>%s</a>" % \
                    (items[x]['url'], items[x]['Title'])

            # set Services
            ws_services = {}
            for slot in [s for s in layout if s['type'] == 'a']:
                analysis = rc.lookupObject(slot['analysis_uid'])
                service = analysis.getService()
                title = service.Title()
                if title not in ws_services:
                    ws_services[title] = "<a href='%s'>%s,</a>" % \
                        (service.absolute_url(), title)
            keys = list(ws_services.keys())
            keys.sort()
            services = []
            for key in keys:
                services.append(ws_services[key])
            if services:
                services[-1] = services[-1].replace(",", "")
            items[x]['Services'] = ""
            items[x]['replace']['Services'] = " ".join(services)

            # set Sample Types
            pos_parent = {}
            for slot in layout:
                # compensate for bad data caused by a stupid bug.
                if type(slot['position']) in (list, tuple):
                    slot['position'] = slot['position'][0]
                if slot['position'] == 'new':
                    continue
                if slot['position'] in pos_parent:
                    continue
                pos_parent[slot['position']] = rc.lookupObject(
                    slot['container_uid'])

            sampletypes = {}
            blanks = {}
            controls = {}
            for container in pos_parent.values():
                if container.portal_type == 'AnalysisRequest':
                    sampletypes["<a href='%s'>%s,</a>" % \
                               (container.getSample().getSampleType().absolute_url(),
                                container.getSample().getSampleType().Title())] = 1
                if container.portal_type == 'ReferenceSample' and container.getBlank(
                ):
                    blanks["<a href='%s'>%s,</a>" % \
                           (container.absolute_url(),
                            container.Title())] = 1
                if container.portal_type == 'ReferenceSample' and not container.getBlank(
                ):
                    controls["<a href='%s'>%s,</a>" % \
                           (container.absolute_url(),
                            container.Title())] = 1
            sampletypes = list(sampletypes.keys())
            sampletypes.sort()
            blanks = list(blanks.keys())
            blanks.sort()
            controls = list(controls.keys())
            controls.sort()

            # remove trailing commas
            if sampletypes:
                sampletypes[-1] = sampletypes[-1].replace(",", "")
            if controls:
                controls[-1] = controls[-1].replace(",", "")
            else:
                if blanks:
                    blanks[-1] = blanks[-1].replace(",", "")

            items[x]['SampleTypes'] = ""
            items[x]['replace']['SampleTypes'] = " ".join(sampletypes)
            items[x]['QC'] = ""
            items[x]['replace']['QC'] = " ".join(blanks + controls)
            items[x]['QCTotals'] = ''

            # Get all Worksheet QC Analyses
            totalQCAnalyses = [
                a for a in obj.getAnalyses()
                if a.portal_type == 'ReferenceAnalysis'
                or a.portal_type == 'DuplicateAnalysis'
            ]
            totalQCSamples = []
            # Get all Worksheet QC samples
            for analysis in totalQCAnalyses:
                if analysis.getSample().UID() not in totalQCSamples:
                    totalQCSamples.append(analysis.getSample().UID())
            # Total QC Samples (Total Routine Analyses)
            items[x]['QCTotals'] = str(len(totalQCSamples)) + '(' + str(
                len(totalQCAnalyses)) + ')'

            totalRoutineAnalyses = [
                a for a in obj.getAnalyses() if a not in totalQCAnalyses
            ]
            totalRoutineSamples = []
            for analysis in totalRoutineAnalyses:
                if analysis.getSample().UID() not in totalRoutineSamples:
                    totalRoutineSamples.append(analysis.getSample().UID())

            # Total Routine Samples (Total Routine Analyses)
            items[x]['RoutineTotals'] = str(
                len(totalRoutineSamples)) + '(' + str(
                    len(totalRoutineAnalyses)) + ')'

            if items[x]['review_state'] == 'open' \
                and self.allow_edit \
                and self.restrict_results == False \
                and can_manage == True:
                items[x]['allow_edit'] = [
                    'Analyst',
                ]
                items[x]['required'] = [
                    'Analyst',
                ]
                can_reassign = True
                items[x]['choices'] = {'Analyst': analyst_choices}

            new_items.append(items[x])

        if can_reassign:
            for x in range(len(self.review_states)):
                if self.review_states[x]['id'] in ['default', 'mine', 'open']:
                    self.review_states[x]['custom_actions'] = [
                        {
                            'id': 'reassign',
                            'title': _('Reassign')
                        },
                    ]

        self.show_select_column = can_reassign
        self.show_workflow_action_buttons = can_reassign

        return new_items

    def getAnalysts(self):
        """ Present the LabManagers and Analysts as options for analyst
            Used in bika_listing.pt
        """
        return self.analysts

    def getWorksheetTemplates(self):
        """ List of templates
            Used in bika_listing.pt
        """
        return DisplayList(self.templates)

    def getInstruments(self):
        """ List of instruments
            Used in bika_listing.pt
        """
        return DisplayList(self.instruments)

    def getTemplateInstruments(self):
        """ Distionary of instruments per template
            Used in bika_listing.pt
        """
        return json.dumps(self.templateinstruments)
Пример #25
0
class ExportOrdersForm(YAMLForm):
    browser_template = ViewPageTemplateFile('export.pt')
    form_template = 'bda.plone.orders.browser:forms/orders_export.yaml'
    message_factory = _
    action_resource = 'exportorders'

    def __call__(self):
        # check if authenticated user is vendor
        if not get_vendors_for():
            raise Unauthorized
        self.prepare()
        controller = Controller(self.form, self.request)
        if not controller.next:
            self.rendered_form = controller.rendered
            return self.browser_template(self)
        return controller.next

    def vendor_vocabulary(self):
        return vendors_form_vocab()

    def vendor_mode(self):
        return len(vendors_form_vocab()) > 2 and 'edit' or 'skip'

    def customer_vocabulary(self):
        return customers_form_vocab()

    def customer_mode(self):
        return len(customers_form_vocab()) > 2 and 'edit' or 'skip'

    def from_before_to(self, widget, data):
        from_date = data.fetch('exportorders.from').extracted
        to_date = data.fetch('exportorders.to').extracted
        if to_date <= from_date:
            raise ExtractionError(
                _('from_date_before_to_date',
                  default=u'From-date after to-date'))
        return data.extracted

    def export(self, widget, data):
        self.vendor = self.request.form.get('exportorders.vendor')
        self.customer = self.request.form.get('exportorders.customer')
        self.from_date = data.fetch('exportorders.from').extracted
        self.to_date = data.fetch('exportorders.to').extracted

    def export_val(self, record, attr_name):
        """Get attribute from record and cleanup.
        Since the record object is available, you can return aggregated values.
        """
        val = record.attrs.get(attr_name)
        return cleanup_for_csv(val)

    def csv(self, request):
        # get orders soup
        orders_soup = get_orders_soup(self.context)
        # get bookings soup
        bookings_soup = get_bookings_soup(self.context)
        # fetch user vendor uids
        vendor_uids = get_vendor_uids_for()
        # base query for time range
        query = Ge('created', self.from_date) & Le('created', self.to_date)
        # filter by given vendor uid or user vendor uids
        vendor_uid = self.vendor
        if vendor_uid:
            vendor_uid = uuid.UUID(vendor_uid)
            # raise if given vendor uid not in user vendor uids
            if vendor_uid not in vendor_uids:
                raise Unauthorized
            query = query & Any('vendor_uids', [vendor_uid])
        else:
            query = query & Any('vendor_uids', vendor_uids)
        # filter by customer if given
        customer = self.customer
        if customer:
            query = query & Eq('creator', customer)
        # prepare csv writer
        sio = StringIO()
        ex = csv.writer(sio, dialect='excel-colon', quoting=csv.QUOTE_MINIMAL)
        # exported column keys as first line
        ex.writerow(ORDER_EXPORT_ATTRS + COMPUTED_ORDER_EXPORT_ATTRS.keys() +
                    BOOKING_EXPORT_ATTRS +
                    COMPUTED_BOOKING_EXPORT_ATTRS.keys())
        # query orders
        for order in orders_soup.query(query):
            # restrict order bookings for current vendor_uids
            order_data = OrderData(self.context,
                                   order=order,
                                   vendor_uids=vendor_uids)
            order_attrs = list()
            # order export attrs
            for attr_name in ORDER_EXPORT_ATTRS:
                val = self.export_val(order, attr_name)
                order_attrs.append(val)
            # computed order export attrs
            for attr_name in COMPUTED_ORDER_EXPORT_ATTRS:
                cb = COMPUTED_ORDER_EXPORT_ATTRS[attr_name]
                val = cb(self.context, order_data)
                val = cleanup_for_csv(val)
                order_attrs.append(val)
            for booking in order_data.bookings:
                booking_attrs = list()
                # booking export attrs
                for attr_name in BOOKING_EXPORT_ATTRS:
                    val = self.export_val(booking, attr_name)
                    booking_attrs.append(val)
                # computed booking export attrs
                for attr_name in COMPUTED_BOOKING_EXPORT_ATTRS:
                    cb = COMPUTED_BOOKING_EXPORT_ATTRS[attr_name]
                    val = cb(self.context, booking)
                    val = cleanup_for_csv(val)
                    booking_attrs.append(val)
                ex.writerow(order_attrs + booking_attrs)
                booking.attrs['exported'] = True
                bookings_soup.reindex(booking)
        # create and return response
        s_start = self.from_date.strftime('%G-%m-%d_%H-%M-%S')
        s_end = self.to_date.strftime('%G-%m-%d_%H-%M-%S')
        filename = 'orders-export-%s-%s.csv' % (s_start, s_end)
        self.request.response.setHeader('Content-Type', 'text/csv')
        self.request.response.setHeader('Content-Disposition',
                                        'attachment; filename=%s' % filename)
        ret = sio.getvalue()
        sio.close()
        return ret
Пример #26
0
class RegistryExporterView(BrowserView):
    """this view make sane exports of the registry.

    Main goal is to export in a way, that the output can be reused as
    best practive settings
    """

    template = ViewPageTemplateFile(
        os.path.join(_current_dir, 'templates', 'exportxml.pt'))

    def __call__(self):
        interface = self.request.form.get('interface', None)
        name = self.request.form.get('name', None)
        if not interface and not name:
            return self.template()
        return self.export(sinterface=interface, sname=name)

    def interfaces(self):
        prefixes = []
        registry = getUtility(IRegistry)
        baseurl = '{0}/@@configuration_registry_export_xml?interface='.format(
            self.context.absolute_url())
        for record in registry.records.values():
            if record.interfaceName is None:
                continue
            name = record.interfaceName
            url = '{0}{1}'.format(baseurl, record.interfaceName)
            pair = (name, url)
            if pair not in prefixes:
                prefixes.append(pair)

        return sorted(prefixes, key=_sort_first_lower)

    def prefixes(self):
        prefixes = []
        registry = getUtility(IRegistry)
        baseurl = '{0}/@@configuration_registry_export_xml?'.format(
            self.context.absolute_url())
        for record in registry.records.values():
            if record.interfaceName == record.__name__:
                continue

            def add_split(part):
                url = '{0}name={1}'.format(baseurl, part)
                pair = (part, url)
                if pair not in prefixes:
                    prefixes.append(pair)
                if part.rfind('/') > part.rfind('.'):
                    new_parts = part.rsplit('/', 1)
                else:
                    new_parts = part.rsplit('.', 1)
                if len(new_parts) > 1:
                    add_split(new_parts[0])

            add_split(record.__name__)
        return sorted(prefixes, key=_sort_first_lower)

    def export(self, sinterface=None, sname=None):
        registry = getUtility(IRegistry)
        root = etree.Element('registry')
        values = {}  # full prefix to valuerecord
        interface2values = {}
        interface2prefix = {}
        for record in registry.records.values():
            if sinterface and sinterface != record.interfaceName:
                continue
            if sname and not record.__name__.startswith(sname):
                continue
            prefix, value_key = record.__name__.rsplit('.', 1)
            xmlvalue = etree.Element('value')
            if record.value is None:
                continue
            if isinstance(record.value, (list, tuple)):
                for element in record.value:
                    xmlel = etree.SubElement(xmlvalue, 'element')
                    xmlel.text = element
            elif isinstance(record.value, bool):
                xmlvalue.text = 'True' if record.value else 'False'
            elif isinstance(record.value, six.string_types):
                xmlvalue.text = record.value
            else:
                xmlvalue.text = str(record.value)

            if record.interfaceName:
                xmlvalue.attrib['key'] = value_key
                if record.interfaceName not in interface2values:
                    interface2values[record.interfaceName] = []
                interface2values[record.interfaceName].append(record.__name__)
                interface2prefix[record.interfaceName] = prefix
            values[record.__name__] = xmlvalue

        for ifname in sorted(interface2values):
            xmlrecord = etree.SubElement(root, 'records')
            xmlrecord.attrib['interface'] = ifname
            xmlrecord.attrib['prefix'] = interface2prefix[ifname]
            for value in sorted(interface2values[ifname]):
                xmlrecord.append(values.pop(value))
        for name, xmlvalue in values.items():
            xmlrecord = etree.SubElement(root, 'records')
            xmlrecord.attrib['prefix'] = name
            xmlrecord.append(xmlvalue)

        self.request.response.setHeader('Content-Type', 'text/xml')
        filename = ''
        if sinterface:
            filename += sinterface
        if sinterface and sname:
            filename += '_-_'
        if sname:
            filename += sname
        self.request.response.setHeader(
            'Content-Disposition',
            'attachment; filename={0}.xml'.format(filename))
        return etree.tostring(root,
                              pretty_print=True,
                              xml_declaration=True,
                              encoding='UTF-8')
Пример #27
0
class NavigationView(BrowserView):

    template = ViewPageTemplateFile('templates/navigation.pt')

    def __call__(self):
        return self.template()

    def check_displayed_types(self, item):
        """
        Check settings if content type should be displayed in navigation.
        """
        types = api.portal.get_registry_record(name='plone.displayed_types')
        if item.portal_type not in types:
            return True

    def check_filter_on_workflow(self, item):
        """
        Check workflow settings if item should be displayed in navigation.
        """
        filter = api.portal.get_registry_record(
            name='plone.filter_on_workflow',
        )
        states = api.portal.get_registry_record(
            name='plone.workflow_states_to_show',
        )
        if filter:
            state = api.content.get_state(obj=item.getObject())
            if state not in states:
                return True

    def check_item(self, item):
        """
        Check if we want to have the given item in the navigation.
        """
        if self.check_displayed_types(item):
            return False
        if self.check_filter_on_workflow(item):
            return False
        if item.exclude_from_nav:
            return False
        try:
            if self.context.default_page == item.id:
                return False
        except AttributeError:
            pass
        return True

    def get_icon(self, icon):
        return get_icon(icon)

    def get_back(self):
        """
        Get link to parent.
        """
        context = self.context
        portal = api.portal.get()
        parent = context.aq_parent
        root_nav = api.portal.get_registry_record(
            name='collective.sidebar.root_nav',
            default=False,
        )
        if context == portal or context.portal_type == 'LRF' or root_nav:
            return None
        try:
            if parent.default_page == context.id:
                if parent == api.portal.get_navigation_root(context):
                    return None
                return parent.aq_parent.absolute_url()
        except AttributeError:
            pass
        return parent.absolute_url()

    def get_show(self):
        """
        Get link to current folder.
        """
        if self.get_back() and IFolderish.providedBy(self.context):
            data = {
                'title': self.context.Title(),
                'title_cropped': crop(self.context.Title(), 100),
                'url': self.context.absolute_url(),
                'type': 'link-folder',
            }
            return data

    def contains_items(self, item):
        """
        Check if navigation will return items for folder
        """
        items = item.getObject().getFolderContents()
        for item in items:
            if self.check_item(item):
                return True
        return False

    def get_items(self):
        """
        Get folder contents and return.
        """
        context = self.context
        root_nav = api.portal.get_registry_record(
            name='collective.sidebar.root_nav',
            default=False,
        )
        view_types = api.portal.get_registry_record(
            name='plone.types_use_view_action_in_listings',
        )

        # root level navigation is enabled in settings
        if root_nav:
            context = api.portal.get_navigation_root(context)

        # context is folderish, list content
        if IFolderish.providedBy(context):
            # context is an endpoint, list parents content
            if INavigationEndpoint.providedBy(context):
                context = context.aq_parent
        else:
            # context is an item, list parents content
            context = context.aq_parent

        contents = list()

        # Can not remember what edgecase we catch here.
        try:
            contents = context.getFolderContents()
        except Exception:  # noqa: 902
            pass

        items = list()
        for item in contents:
            if self.check_item(item):
                item_type = 'link-item'
                url = item.getURL()
                if item.portal_type in view_types:
                    url = url + '/view'
                if item.is_folderish and self.contains_items(item):
                    item_type = 'link-folder'
                data = {
                    'title': item.Title,
                    'title_cropped': crop(item.Title, 100),
                    'url': url,
                    'type': item_type,
                }
                items.append(data)
        return items
Пример #28
0
class CommentsViewlet(ViewletBase):

    form = CommentForm
    index = ViewPageTemplateFile('comments.pt')

    def update(self):
        super(CommentsViewlet, self).update()
        discussion_allowed = self.is_discussion_allowed()
        anonymous_allowed_or_can_reply = (
            self.is_anonymous() and self.anonymous_discussion_allowed()
            or self.can_reply())
        if discussion_allowed and anonymous_allowed_or_can_reply:
            z2.switch_on(self, request_layer=IFormLayer)
            self.form = self.form(aq_inner(self.context), self.request)
            alsoProvides(self.form, IWrappedForm)
            self.form.update()

    # view methods

    def can_reply(self):
        """Returns true if current user has the 'Reply to item' permission.
        """
        return getSecurityManager().checkPermission('Reply to item',
                                                    aq_inner(self.context))

    def can_manage(self):
        """We keep this method for <= 1.0b9 backward compatibility. Since we do
           not want any API changes in beta releases.
        """
        return self.can_review()

    def can_review(self):
        """Returns true if current user has the 'Review comments' permission.
        """
        return getSecurityManager().checkPermission('Review comments',
                                                    aq_inner(self.context))

    def can_delete_own(self, comment):
        """Returns true if the current user can delete the comment. Only
        comments without replies can be deleted.
        """
        try:
            return comment.restrictedTraverse(
                '@@delete-own-comment').can_delete()
        except Unauthorized:
            return False

    def could_delete_own(self, comment):
        """Returns true if the current user could delete the comment if it had
        no replies. This is used to prepare hidden form buttons for JS.
        """
        try:
            return comment.restrictedTraverse(
                '@@delete-own-comment').could_delete()
        except Unauthorized:
            return False

    def can_edit(self, reply):
        """Returns true if current user has the 'Edit comments'
        permission.
        """
        return getSecurityManager().checkPermission('Edit comments',
                                                    aq_inner(reply))

    def can_delete(self, reply):
        """Returns true if current user has the 'Delete comments'
        permission.
        """
        return getSecurityManager().checkPermission('Delete comments',
                                                    aq_inner(reply))

    def is_discussion_allowed(self):
        context = aq_inner(self.context)
        return context.restrictedTraverse('@@conversation_view').enabled()

    def comment_transform_message(self):
        """Returns the description that shows up above the comment text,
           dependent on the text_transform setting and the comment moderation
           workflow in the discussion control panel.
        """
        context = aq_inner(self.context)
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)

        # text transform setting
        if settings.text_transform == "text/x-web-intelligent":
            message = translate(Message(COMMENT_DESCRIPTION_INTELLIGENT_TEXT),
                                context=self.request)
        elif settings.text_transform == "text/x-web-markdown":
            message = translate(Message(COMMENT_DESCRIPTION_MARKDOWN),
                                context=self.request)
        else:
            message = translate(Message(COMMENT_DESCRIPTION_PLAIN_TEXT),
                                context=self.request)

        # comment workflow
        wftool = getToolByName(context, "portal_workflow", None)
        workflow_chain = wftool.getChainForPortalType('Discussion Item')
        if workflow_chain:
            comment_workflow = workflow_chain[0]
            comment_workflow = wftool[comment_workflow]
            # check if the current workflow implements a pending state. If this
            # is true comments are moderated
            if 'pending' in comment_workflow.states:
                message = message + " " + \
                    translate(Message(COMMENT_DESCRIPTION_MODERATION_ENABLED),
                              context=self.request)

        return message

    def has_replies(self, workflow_actions=False):
        """Returns true if there are replies.
        """
        if self.get_replies(workflow_actions) is not None:
            try:
                self.get_replies(workflow_actions).next()
                return True
            except StopIteration:  # pragma: no cover
                pass
        return False

    def get_replies(self, workflow_actions=False):
        """Returns all replies to a content object.

        If workflow_actions is false, only published
        comments are returned.

        If workflow actions is true, comments are
        returned with workflow actions.
        """
        context = aq_inner(self.context)
        conversation = IConversation(context, None)

        if conversation is None:
            return iter([])

        wf = getToolByName(context, 'portal_workflow')

        # workflow_actions is only true when user
        # has 'Manage portal' permission

        def replies_with_workflow_actions():
            # Generator that returns replies dict with workflow actions
            for r in conversation.getThreads():
                comment_obj = r['comment']
                # list all possible workflow actions
                actions = [
                    a for a in wf.listActionInfos(object=comment_obj)
                    if a['category'] == 'workflow' and a['allowed']
                ]
                r = r.copy()
                r['actions'] = actions
                yield r

        def published_replies():
            # Generator that returns replies dict with workflow status.
            for r in conversation.getThreads():
                comment_obj = r['comment']
                workflow_status = wf.getInfoFor(comment_obj, 'review_state')
                if workflow_status == 'published':
                    r = r.copy()
                    r['workflow_status'] = workflow_status
                    yield r

        # Return all direct replies
        if len(conversation.objectIds()):
            if workflow_actions:
                return replies_with_workflow_actions()
            else:
                return published_replies()

    def get_commenter_home_url(self, username=None):
        if username is None:
            return None
        else:
            return "%s/author/%s" % (self.context.portal_url(), username)

    def get_commenter_portrait(self, username=None):

        if username is None:
            # return the default user image if no username is given
            return 'defaultUser.png'
        else:
            portal_membership = getToolByName(self.context,
                                              'portal_membership', None)
            return portal_membership\
                .getPersonalPortrait(username)\
                .absolute_url()

    def anonymous_discussion_allowed(self):
        # Check if anonymous comments are allowed in the registry
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)
        return settings.anonymous_comments

    def edit_comment_allowed(self):
        # Check if editing comments is allowed in the registry
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)
        return settings.edit_comment_enabled

    def delete_own_comment_allowed(self):
        # Check if delete own comments is allowed in the registry
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)
        return settings.delete_own_comment_enabled

    def show_commenter_image(self):
        # Check if showing commenter image is enabled in the registry
        registry = queryUtility(IRegistry)
        settings = registry.forInterface(IDiscussionSettings, check=False)
        return settings.show_commenter_image

    def is_anonymous(self):
        portal_membership = getToolByName(self.context, 'portal_membership',
                                          None)
        return portal_membership.isAnonymousUser()

    def login_action(self):
        return '%s/login_form?came_from=%s' % \
            (self.navigation_root_url,
             url_quote(self.request.get('URL', '')),)

    def format_time(self, time):
        # We have to transform Python datetime into Zope DateTime
        # before we can call toLocalizedTime.
        util = getToolByName(self.context, 'translation_service')
        zope_time = DateTime(time.isoformat())
        return util.toLocalizedTime(zope_time, long_format=True)
Пример #29
0
class ClientARImportAddView(BrowserView):
    implements(IViewView)
    template = ViewPageTemplateFile('templates/arimport_add_form.pt')

    def __call__(self):
        request = self.request
        response = request.response
        form = request.form
        plone.protect.CheckAuthenticator(form)
        if form.get('submitted'):
            csvfile = form.get('csvfile')
            option = form.get('ImportOption')
            client_id = form.get('ClientID')
            valid = False
            if option in ('c', 'p'):
                arimport, msg = self._import_file(option, csvfile, client_id)
            else:
                msg = "Import Option not yet available"
                IStatusMessage(request).addStatusMessage(_(msg), "warn")
                request.response.redirect('%s/arimports' %
                                          (self.context.absolute_url()))
                return

            if arimport:
                msg = "AR Import complete"
                IStatusMessage(request).addStatusMessage(_(msg), "info")
                request.response.write(
                    '<script>document.location.href="%s"</script>' %
                    (arimport.absolute_url()))
                return
            else:
                IStatusMessage(request).addStatusMessage(_(msg), "error")
                request.response.write(
                    '<script>document.location.href="%s/arimport_add"</script>'
                    % (self.context.absolute_url()))
                return
        return self.template()

    def _import_file(self, importoption, csvfile, client_id):
        fullfilename = csvfile.filename
        fullfilename = fullfilename.split('/')[-1]
        filename = fullfilename.split('.')[0]
        log = []
        r = self.portal_catalog(portal_type='Client', id=client_id)
        if len(r) == 0:
            #This is not a user input issue - client_id is added to template
            log.append('   Could not find Client %s' % client_id)
            return None, '\n'.join(log)

        client = r[0].getObject()
        updateable_states = ['sample_received', 'assigned']
        reader = csv.reader(csvfile.readlines())
        samples = []
        sample_headers = None
        batch_headers = None
        batch_remarks = []
        row_count = 0
        for row in reader:
            row_count = row_count + 1
            if not row:
                continue
            # a new batch starts
            if row_count == 1:
                if row[0] == 'Header':
                    continue
                else:
                    msg = '%s invalid batch header' % row
                    transaction_note(msg)
                    return None, msg
            elif row_count == 2:
                msg = None
                if row[1] != 'Import':
                    msg = 'Invalid batch header - Import required in cell B2'
                    transaction_note(msg)
                    return None, msg
                entered_name = fullfilename.split('.')[0]
                if not row[2] or entered_name.lower() != row[2].lower():
                    msg = 'Filename, %s, does not match entered filename, %s' \
                            % (filename, row[2])
                    transaction_note(msg)
                    return None, msg

                batch_headers = row[0:]
                arimport_id = tmpID()
                title = filename
                idx = 1
                while title in [i.Title() for i in client.objectValues()]:
                    title = '%s-%s' % (filename, idx)
                    idx += 1
                arimport = _createObjectByType("ARImport",
                                               client,
                                               arimport_id,
                                               title=title)
                arimport.unmarkCreationFlag()
                continue
            elif row_count == 3:
                sample_headers = row[10:]
                continue
            elif row_count in [4, 5, 6]:
                continue

            #otherwise add to list of sample
            samples.append(row)
        if not row_count:
            msg = 'Invalid batch header'
            transaction_note(msg)
            return None, msg

        pad = 8192 * ' '
        request = self.request

        title = 'Importing file'
        bar = ProgressBar(self.context, self.request, title, description='')
        notify(InitialiseProgressBar(bar))

        sample_count = len(samples)
        row_count = 0
        for sample in samples:
            next_num = tmpID()
            row_count = row_count + 1
            item_remarks = []
            progress_index = float(row_count) / float(sample_count) * 100.0
            progress = ProgressState(self.request, progress_index)
            notify(UpdateProgressEvent(progress))
            #TODO REmove for production - just to look pretty
            #time.sleep(1)
            analyses = []
            for i in range(10, len(sample)):
                if sample[i] != '1':
                    continue
                analyses.append(sample_headers[(i - 10)])
            if len(analyses) > 0:
                aritem_id = '%s_%s' % ('aritem', (str(next_num)))
                aritem = _createObjectByType("ARImportItem", arimport,
                                             aritem_id)
                aritem.edit(
                    SampleName=sample[0],
                    ClientRef=batch_headers[10],
                    ClientSid=sample[1],
                    SampleDate=sample[2],
                    SampleType=sample[3],
                    PickingSlip=sample[4],
                    ContainerType=sample[5],
                    ReportDryMatter=sample[6],
                    Priority=sample[7],
                )

                aritem.setRemarks(item_remarks)
                if importoption == 'c':
                    aritem.setAnalyses(analyses)
                elif importoption == 'p':
                    aritem.setAnalysisProfile(analyses)

        cc_names_report = ','.join(
                [i.strip() for i in batch_headers[6].split(';')]) \
                if (batch_headers and len(batch_headers) > 7) else ""
        cc_emails_report = ','.join(
                [i.strip() for i in batch_headers[7].split(';')]) \
                if batch_headers and len(batch_headers) > 8 else ""
        cc_emails_invoice = ','.join(
                [i.strip() for i in batch_headers[8].split(';')]) \
                if batch_headers and len(batch_headers) > 9 else ""

        try:
            numOfSamples = int(batch_headers[12])
        except:
            numOfSamples = 0
        arimport.edit(
            ImportOption=importoption,
            FileName=batch_headers[2],
            OriginalFile=csvfile,
            ClientTitle=batch_headers[3],
            ClientID=batch_headers[4],
            ContactID=batch_headers[5],
            CCNamesReport=cc_names_report,
            CCEmailsReport=cc_emails_report,
            CCEmailsInvoice=cc_emails_invoice,
            OrderID=batch_headers[9],
            QuoteID=batch_headers[10],
            SamplePoint=batch_headers[11],
            NumberSamples=numOfSamples,
            Remarks=batch_remarks,
            Analyses=sample_headers,
            DateImported=DateTime(),
        )
        arimport._renameAfterCreation()

        valid = arimport.validateIt()
        return arimport, msg
Пример #30
0
class FolderView(BikaListingView):
    """Listing view for Worksheets
    """
    template = ViewPageTemplateFile("../templates/worksheets.pt")

    def __init__(self, context, request):
        super(FolderView, self).__init__(context, request)

        self.catalog = CATALOG_WORKSHEET_LISTING
        self.contentFilter = {
            "review_state": ["open", "to_be_verified", "verified", "rejected"],
            "sort_on": "created",
            "sort_order": "reverse"
        }

        self.title = self.context.translate(_("Worksheets"))
        self.description = ""

        self.icon = "{}/{}".format(
            self.portal_url, "++resource++bika.lims.images/worksheet_big.png")

        self.context_actions = {
            _("Add"): {
                "url": "createObject?type_name=InstrumentMaintenanceTask",
                "icon": "++resource++bika.lims.images/add.png"
            }
        }

        self.context_actions = {
            _("Add"): {
                "url": "worksheet_add",
                "icon": "++resource++bika.lims.images/add.png",
                "class": "worksheet_add"
            }
        }

        self.show_select_column = True
        self.show_select_all_checkbox = True
        self.filter_by_user = False
        self.selected_state = ""
        self.analyst_choices = []
        self.can_reassign = False
        self.can_manage = False

        self.rc = getToolByName(self, REFERENCE_CATALOG)

        # this is a property of self, because self.getAnalysts returns it
        self.analysts = getUsers(self, ["Manager", "LabManager", "Analyst"])
        self.analysts = self.analysts.sortedByValue()
        self.analyst_choices = []
        for a in self.analysts:
            self.analyst_choices.append({
                "ResultValue":
                a,
                "ResultText":
                self.analysts.getValue(a),
            })

        self.columns = collections.OrderedDict((
            ("getProgressPercentage", {
                "title": _("Progress")
            }),
            ("Title", {
                "title": _("Worksheet"),
                "index": "getId"
            }),
            ("Analyst", {
                "title": _("Analyst"),
                "index": "getAnalyst"
            }),
            ("getWorksheetTemplateTitle", {
                "title": _("Template"),
                "replace_url": "getWorksheetTemplateURL"
            }),
            ("getNumberOfRegularSamples", {
                "title": _("Samples")
            }),
            ("getNumberOfQCAnalyses", {
                "title": _("QC Analyses")
            }),
            ("getNumberOfRegularAnalyses", {
                "title": _("Routine Analyses")
            }),
            ("CreationDate", {
                "title": _("Created"),
                "index": "created"
            }),
            ("state_title", {
                "title": _("State"),
                "index": "review_state",
                "attr": "state_title"
            }),
        ))
        self.review_states = [
            {
                "id": "default",
                "title": _("Active"),
                "contentFilter": {
                    "review_state": [
                        "open",
                        "to_be_verified",
                    ],
                    "sort_on": "CreationDate",
                    "sort_order": "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                "id": "open",
                "title": _("Open"),
                "contentFilter": {
                    "review_state": "open",
                    "sort_on": "CreationDate",
                    "sort_order": "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                "id": "to_be_verified",
                "title": _("To be verified"),
                "contentFilter": {
                    "review_state": "to_be_verified",
                    "sort_on": "CreationDate",
                    "sort_order": "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys()
            },
            {
                "id": "verified",
                "title": _("Verified"),
                "contentFilter": {
                    "review_state": "verified",
                    "sort_on": "CreationDate",
                    "sort_order": "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                "id": "all",
                "title": _("All"),
                "contentFilter": {
                    "review_state": [
                        "open",
                        "to_be_verified",
                        "verified",
                        "rejected",
                    ],
                    "sort_on":
                    "CreationDate",
                    "sort_order":
                    "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                # getAuthenticatedMember does not work in __init__ so "mine" is
                # configured further in "folderitems" below.
                "id": "mine",
                "title": _("Mine"),
                "contentFilter": {
                    "review_state":
                    ["open", "to_be_verified", "verified", "rejected"],
                    "sort_on":
                    "CreationDate",
                    "sort_order":
                    "reverse"
                },
                "transitions": [],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            }
        ]

    def before_render(self):
        """Before render hook of the listing base view
        """
        super(FolderView, self).before_render()

        # disable the editable border of the Add-, Display- and Workflow menu
        self.request.set("disable_border", 1)

        # the current selected WF state
        self.selected_state = self.get_selected_state()

        self.allow_edit = self.is_edit_allowed()
        self.can_manage = self.is_manage_allowed()

        # Check if analysts can be assigned
        if self.is_analyst_assignment_allowed():
            self.can_reassign = True
            self.allow_analyst_reassignment()

        if not self.can_manage:
            # The current has no prvileges to manage WS.
            # Remove the add button
            self.context_actions = {}

        if self.context.bika_setup.getRestrictWorksheetUsersAccess():
            # Display only the worksheets assigned to the current user unless
            # the user belongs to a privileged role
            allowed = ["Manager", "LabManager", "RegulatoryInspector"]
            diff = filter(lambda role: role in allowed, self.member.getRoles())
            self.filter_by_user = len(diff) == 0

        if self.filter_by_user:
            # Remove 'Mine' button and hide 'Analyst' column
            del self.review_states[1]  # Mine
            self.columns["Analyst"]["toggle"] = False
            self.contentFilter["getAnalyst"] = self.member.id
            for rvw in self.review_states:
                rvw["contentFilter"]["getAnalyst"] = self.member.id

    def is_analyst_assignment_allowed(self):
        """Check if the analyst can be assigned
        """
        if not self.allow_edit:
            return False
        if not self.can_manage:
            return False
        if self.filter_by_user:
            return False
        return True

    def allow_analyst_reassignment(self):
        """Allow the Analyst reassignment
        """
        reassing_analyst_transition = {
            "id": "reassign",
            "title": _("Reassign")
        }
        for rs in self.review_states:
            if rs["id"] not in ["default", "mine", "open", "all"]:
                continue
            rs["custom_transitions"].append(reassing_analyst_transition)
        self.show_select_column = True
        self.show_workflow_action_buttons = True

    def is_manage_allowed(self):
        """Check if the User is allowed to manage
        """
        checkPermission = self.context.portal_membership.checkPermission
        return checkPermission(ManageWorksheets, self.context)

    def is_edit_allowed(self):
        """Check if edit is allowed
        """
        checkPermission = self.context.portal_membership.checkPermission
        return checkPermission(EditWorksheet, self.context)

    def get_selected_state(self):
        """Returns the current selected state
        """
        form_key = "{}_review_state".format(self.form_id)
        return self.request.get(form_key, "default")

    def folderitem(self, obj, item, index):
        """Service triggered each time an item is iterated in folderitems.

        The use of this service prevents the extra-loops in child objects.

        :obj: the instance of the class to be foldered
        :item: dict containing the properties of the object to be used by
            the template
        :index: current index of the item
        """

        title = api.get_title(obj)
        url = api.get_url(obj)

        item["CreationDate"] = self.ulocalized_time(obj.created)

        title_link = "{}/{}".format(url, "add_analyses")
        if len(obj.getAnalysesUIDs) > 0:
            title_link = "{}/{}".format(url, "manage_results")

        item["Title"] = title
        item["replace"]["Title"] = get_link(title_link, value=title)

        # Total QC Analyses
        item["getNumberOfQCAnalyses"] = str(obj.getNumberOfQCAnalyses)
        # Total Routine Analyses
        item["getNumberOfRegularAnalyses"] = str(
            obj.getNumberOfRegularAnalyses)
        # Total Number of Samples
        item["getNumberOfRegularSamples"] = str(obj.getNumberOfRegularSamples)

        # Progress
        progress = obj.getProgressPercentage
        progress_bar_html = get_progress_bar_html(progress)
        item["replace"]["getProgressPercentage"] = progress_bar_html

        review_state = item["review_state"]
        if self.can_reassign and review_state == "open":
            item["Analyst"] = obj.getAnalyst
            item["allow_edit"] = ["Analyst"]
            item["required"] = ["Analyst"]
            item["choices"] = {"Analyst": self.analyst_choices}
        else:
            fullname = user_fullname(self.context, obj.getAnalyst)
            item["Analyst"] = fullname

        return item

    def getAnalysts(self):
        """Returns all analysts
        """
        return self.analysts

    def getWorksheetTemplates(self):
        """Returns a DisplayList with all active worksheet templates

        :return: DisplayList of worksheet templates (uid, title)
        :rtype: DisplayList
        """
        brains = self._get_worksheet_templates_brains()
        return get_display_list(brains)

    def getInstruments(self):
        """Returns a DisplayList with all active Instruments

        :return: DisplayList of worksheet templates (uid, title)
        :rtype: DisplayList
        """
        brains = self._get_instruments_brains()
        return get_display_list(brains)

    def getTemplateInstruments(self):
        """Returns worksheet templates as JSON
        """
        items = dict()
        templates = self._get_worksheet_templates_brains()
        for template in templates:
            template_obj = api.get_object(template)
            uid_template = api.get_uid(template_obj)
            instrument = template_obj.getInstrument()
            uid_instrument = ""
            if instrument:
                uid_instrument = api.get_uid(instrument)
            items[uid_template] = uid_instrument

        return json.dumps(items)

    def _get_worksheet_templates_brains(self):
        """Returns all active worksheet templates

        :returns: list of worksheet template brains
        """
        query = {
            "portal_type": "WorksheetTemplate",
            "is_active": True,
        }
        return api.search(query, "bika_setup_catalog")

    def _get_instruments_brains(self):
        """Returns all active Instruments

        :returns: list of brains
        """
        query = {"portal_type": "Instrument", "is_active": True}
        return api.search(query, "bika_setup_catalog")
    def fetchnewcomments(self,lasttimestamp,commentcount,lastcommentid,viewtype):        
        passedcommentcount = 0
        passedcommentcount = int(commentcount)
        
        flasttimestamp = float(lasttimestamp)
        datefromlasttimestamp = DateTime(flasttimestamp)
        
        newlastdate = datefromlasttimestamp.timeTime()
        
        zopecommands = self.getCommandSet('zope')
        ksscore = self.getCommandSet('core')
        jq = self.getCommandSet('jquery')
        
        pdt = getToolByName(self.context, 'portal_discussion', None)        
        
        if pdt <> None:
            allreplies = self.get_replies(pdt,self.context)
            
            disc_container = pdt.getDiscussionFor(self.context)
            replies = disc_container.getReplies()
            newreplycount = disc_container.replyCount(self.context)
            commentshiddencontainer = ksscore.getHtmlIdSelector('comcynapsehiddencomments')
            commentscontainer = ksscore.getHtmlIdSelector('comcynapsecyninitemcommentscontainer')
            addnewlasttimestamp = ksscore.getHtmlIdSelector('comcynapselasttimestamp')
            addnewlastcommentid = ksscore.getHtmlIdSelector('comcynapselastcommentid')
            addnewcommentcount = ksscore.getHtmlIdSelector('comcynapsecommentcount')
            
            if passedcommentcount <> newreplycount:
                #if comment count mismatch then only modify the stuff
                alldiscussions = disc_container.objectValues()                
                newlyaddedcomments = [k for k in alldiscussions if k.modified().greaterThan(datefromlasttimestamp) and k.id not in (lastcommentid)]
                newlyaddedcomments.sort(lambda x,y:cmp(x.modified(),y.modified()))
                for eachcomment in newlyaddedcomments:                    
                    reply = disc_container.getReply(eachcomment.id)
                    if reply <> None:                        
                        parentsInThread = reply.parentsInThread()
                        depthvalue = 0
                        if viewtype.lower() == 'threadedview':
                            lenofparents = len(parentsInThread)
                            depthvalue = lenofparents - 1
                        
                        prev_reply_id = self.findpreviouscommentid(allreplies,reply)
                        
                        newlastdate = reply.modified().timeTime()
                        commenttemplate = ViewPageTemplateFile('ksstemplates/commentrow.pt')
                        commenttemplate = commenttemplate.__of__(self.context)
                        replydict = [{'depth': depthvalue, 'object': reply,'prev_id':prev_reply_id,'view_type':viewtype},]
                        output = commenttemplate.render(reply_dict=replydict)
                        
                        #delete the node if already exists
                        old_comment = ksscore.getHtmlIdSelector('commenttable' + reply.id)
                        ksscore.deleteNode(old_comment)
                        
                        
                        #if there is no prev id found for new comment then insert it as last item to commentscontainer
                        #else insert it after prev id comments table.
                        if viewtype == 'flatview':
                            ksscore.insertHTMLAsLastChild(commentscontainer,output)
                        else:
                            if prev_reply_id == '':
                                ksscore.insertHTMLAsLastChild(commentscontainer,output)
                            else:
                                prevcommentcontainer = ksscore.getHtmlIdSelector('commenttable' + prev_reply_id)
                                ksscore.insertHTMLAfter(prevcommentcontainer,output)
                        
                        newcomment = ksscore.getHtmlIdSelector('commenttable' + reply.id)
                
                if len(newlyaddedcomments) > 0:
                    strlastcommentid = str(newlyaddedcomments[-1].id)
                    ksscore.setKssAttribute(commentshiddencontainer,'lastcommentid',strlastcommentid)
                    ksscore.setAttribute(addnewlastcommentid,'value',strlastcommentid)
		    jq.serverCall(commentscontainer,'truncatetextonitemexpand')
		    
            newlasttimestamp = str(newlastdate)
            strcommentcount = str(newreplycount)
            ksscore.setKssAttribute(commentshiddencontainer,'lasttimestamp',newlasttimestamp)
            ksscore.setKssAttribute(commentshiddencontainer,'commentcount',strcommentcount)
            ksscore.setAttribute(addnewlasttimestamp,'value',newlasttimestamp)
            ksscore.setAttribute(addnewcommentcount,'value',strcommentcount)
            
            
            itemcountcommentcount = ksscore.getHtmlIdSelector('itemcountcommentcount')            
            discussionlabel = ksscore.getHtmlIdSelector('discussionlabel')
            ksscore.replaceInnerHTML(discussionlabel,strcommentcount)
            ksscore.replaceInnerHTML(itemcountcommentcount,strcommentcount)
Пример #32
0
class A18CategoryDisplay(ItemDisplayForm):
    title = "Measure Progress display"

    extra_data_template = ViewPageTemplateFile('pt/extra-data-pivot.pt')
    mapper_class = sql2018.ART18Category1bNotWFD
    css_class = 'left-side-form'

    reported_date_info = {
        'mapper_class': sql2018.ReportedInformation,
        'col_import_id': 'Id',
        'col_import_time': 'ReportingDate'
    }

    def get_reported_date(self):
        return self.get_reported_date_2018()

    def get_import_id(self):
        import_id = self.item.IdReportedInformation

        return import_id

    @db.use_db_session('2018')
    def get_current_country(self):
        report_id = self.item.IdReportedInformation

        _, res = db.get_related_record(sql2018.ReportedInformation, 'Id',
                                       report_id)

        country = self.print_value(res.CountryCode)

        return country

    @db.use_db_session('2018')
    def download_results(self):
        mc_countries = sql2018.ReportedInformation
        mc_measure = sql2018.ART18Category1bNotWFDMeasure

        countries = self.get_form_data_by_key(self, 'member_states')
        ges_comps = self.get_form_data_by_key(self, 'ges_component')
        conditions = []

        if countries:
            conditions.append(mc_countries.CountryCode.in_(countries))

        count, report_ids = db.get_all_records(mc_countries, *conditions)
        report_ids = [x.Id for x in report_ids]

        conditions = [self.mapper_class.IdReportedInformation.in_(report_ids)]

        if ges_comps:
            conditions.append(self.mapper_class.Descriptor.in_(ges_comps))

        count, category = db.get_all_records(self.mapper_class, *conditions)
        id_category = [x.Id for x in category]

        count, category_measure = db.get_all_records(
            mc_measure, mc_measure.IdCategory1bNotWFD.in_(id_category))

        xlsdata = [
            ('ART18Category1bNotWFD', category),  # worksheet title, row data
            ('ART18Category1bNotWFDMeasure', category_measure),
        ]

        return data_to_xls(xlsdata)

    @db.use_db_session('2018')
    def get_db_results(self):
        page = self.get_page()

        mc_countries = sql2018.ReportedInformation

        countries = self.get_form_data_by_key(self, 'member_states')
        ges_comps = self.get_form_data_by_key(self, 'ges_component')

        conditions = []

        if countries:
            conditions.append(mc_countries.CountryCode.in_(countries))

        count, report_ids = db.get_all_records(mc_countries, *conditions)
        report_ids = [x.Id for x in report_ids]

        conditions = [self.mapper_class.IdReportedInformation.in_(report_ids)]

        if ges_comps:
            conditions.append(self.mapper_class.Descriptor.in_(ges_comps))

        item = db.get_item_by_conditions(self.mapper_class,
                                         'Id',
                                         *conditions,
                                         page=page)

        return item

    @db.use_db_session('2018')
    def get_extra_data(self):
        if not self.item:
            return {}

        mc = sql2018.ART18Category1bNotWFDMeasure
        excluded_columns = ('Id', 'IdCategory1bNotWFD')
        res = []
        id_category = self.item.Id

        count, data = db.get_all_records(mc,
                                         mc.IdCategory1bNotWFD == id_category)

        data = db_objects_to_dict(data, excluded_columns)
        res.append(('Category1bNotWFDMeasure', {'': data}))

        return res
    def getDiscussionView(self,uid,itemindex,state,openeditemindex):
        ksscore = self.getCommandSet('core')
        zopecore = self.getCommandSet('zope')
        jq = self.getCommandSet('jquery')
        
        clickednode = ksscore.getHtmlIdSelector('listitemdiscusslinktop' + itemindex)
        listcommentcontainer = ksscore.getHtmlIdSelector('listitemdiscussrow' + itemindex)
        listtimeoutuid = ksscore.getHtmlIdSelector('comcynapsecyninfetchUID')
        listtimeoutindex = ksscore.getHtmlIdSelector('comcynapsecyninfetchindex')
        listtimeouttimestamp = ksscore.getHtmlIdSelector('comcynapselasttimestamp')
        listtimeoutlastcommentid = ksscore.getHtmlIdSelector('comcynapselastcommentid')
        listtimeoutcommentcount = ksscore.getHtmlIdSelector('comcynapsecommentcount')
        listitemdetailright = ksscore.getHtmlIdSelector('listitemdetail' + itemindex)
        
        if openeditemindex != itemindex:            
            openednode = ksscore.getHtmlIdSelector('listitemdiscusslinktop' + openeditemindex)
            listopenedcommentcontainer = ksscore.getHtmlIdSelector('listitemdiscussrow' + openeditemindex)
            ksscore.setKssAttribute(openednode,'state','closed')
            ksscore.replaceInnerHTML(listopenedcommentcontainer,'')
            
        if state.lower() != 'closed':
            ksscore.setKssAttribute(clickednode,'state','closed')
            ksscore.replaceInnerHTML(listcommentcontainer,'')
            return
        
        query = {'UID':uid}
        pdt = getToolByName(self.context,'portal_discussion')
        cat = getToolByName(self.context, 'uid_catalog')
        resbrains = cat.searchResults(query)
        if len(resbrains) == 1:
            contobj = resbrains[0].getObject()
            isDiscussable = contobj.isDiscussable()
            canReply = self.canreply(contobj)
            if isDiscussable and canReply:
                dobj = pdt.getDiscussionFor(contobj)                
                alldiscussions = dobj.objectValues()
                alldiscussions.sort(lambda x,y:cmp(x.modified(),y.modified()),reverse=True)
		maxdispcomments = self.get_displaycountforlist()
                lastxdiscussions = alldiscussions[:maxdispcomments]
                
                commentscount = dobj.replyCount(contobj)
		if commentscount > maxdispcomments:
		    showxmorelink = True
		    xmorecomments = commentscount - maxdispcomments
		elif commentscount > 0 and commentscount <= maxdispcomments:
		    showxmorelink = False
		    xmorecomments = 0
		else:
		    showxmorelink = True
		    commentscount = 0
		    xmorecomments = 0
                lasttimestamp = DateTime().timeTime()
                lastcommentid = '0'
                if len(alldiscussions) > 0:
                    lasttimestamp = alldiscussions[0].modified().timeTime()
                    lastcommentid = alldiscussions[0].id
                    
                commenttemplate = ViewPageTemplateFile('ksstemplates/listcomment.pt')
                commenttemplate = commenttemplate.__of__(self.context)
                
                
                replydict = []
                lastxdiscussions.sort(lambda x,y:cmp(x.modified(),y.modified()))
                for eachdisc in lastxdiscussions:
                    reply = dobj.getReply(eachdisc.id)
                    if reply <> None:
                        replydict.append({'depth': 0,'object':reply,'view_type':'listview','showoutput':True})
                
                output = commenttemplate.render(contobj=contobj, showxmorelink = showxmorelink, xmorecomments = xmorecomments, itemindex=itemindex,uid=uid,reply_dict=replydict,title=contobj.Title(),commentcount=commentscount,lasttimestamp = lasttimestamp,lastcommentid = lastcommentid,allowdiscussion = isDiscussable,usercanreply = canReply)
                
                detailtemplate = ViewPageTemplateFile('ksstemplates/listitemdetails.pt')
                detailtemplate = detailtemplate.__of__(self.context)
                
                
                item = resbrains[0]
                fullpath = item.getPath()
                splitpath = fullpath.split('/')[:-1]
                prettypath = '/' + '/'.join(splitpath)
                URLsuffix = getListingTemplateForContextParent(item)
                pathlink = self.context.portal_url() + prettypath + '/' + URLsuffix
                pathtitle = prettypath
                
                detail = detailtemplate.render(item_type=contobj.portal_type,portal_url=self.context.portal_url(),item_type_title=contobj.Type(),item=item,pathlink=pathlink,pathtitle=pathtitle,contobj=contobj)
                ksscore.replaceInnerHTML(listitemdetailright,force_unicode(detail,'utf'))
                ksscore.replaceInnerHTML(listcommentcontainer,output)
                
                ksscore.setKssAttribute(clickednode,'state','opened')
                
                ksscore.setAttribute(listtimeoutuid,'value',uid)
                ksscore.setAttribute(listtimeoutindex,'value',itemindex)
                ksscore.setAttribute(listtimeouttimestamp,'value',str(lasttimestamp))
                ksscore.setAttribute(listtimeoutlastcommentid,'value',lastcommentid)
                ksscore.setAttribute(listtimeoutcommentcount,'value',str(commentscount))
		jq.serverCall(clickednode,'truncatetextonitemexpand')
		jq.serverCall(clickednode,'marklistedtags')
		jq.serverCall(listcommentcontainer,'activateinputlabel')
Пример #34
0
class GenerateExcerpt(AutoExtensibleForm, EditForm):

    has_model_breadcrumbs = True
    ignoreContext = True
    allow_prefill_from_GET_request = True  # XXX
    schema = IGenerateExcerpt

    template = ViewPageTemplateFile('templates/excerpt.pt')

    def __init__(self, context, request):
        super(GenerateExcerpt, self).__init__(context, request)
        self.model = self.context.model
        self._excerpt_data = None

    def update(self):
        self.inject_initial_data()
        super(GenerateExcerpt, self).update()

    def inject_initial_data(self):
        if self.request.method != 'GET':
            return

        initial_filename = self.model.get_excerpt_title()
        self.request['form.widgets.title'] = initial_filename

        dossier = self.model.get_dossier()
        self.request['form.widgets.dossier'] = [
            '/'.join(dossier.getPhysicalPath())
        ]

    def get_agenda_items(self):
        for agenda_item in self.model.agenda_items:
            if not agenda_item.is_paragraph:
                yield agenda_item

    @button.buttonAndHandler(_('Save', default=u'Save'), name='save')
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            return

        agenda_items_to_include = []
        for agenda_item in self.get_agenda_items():
            if agenda_item.name in self.request:
                agenda_items_to_include.append(agenda_item)

        if not agenda_items_to_include:
            raise (ActionExecutionError(
                Invalid(_(u"Please select at least one agenda item."))))

        operations = ManualExcerptOperations(
            agenda_items_to_include,
            data['title'],
            include_initial_position=data['include_initial_position'],
            include_legal_basis=data['include_legal_basis'],
            include_considerations=data['include_considerations'],
            include_proposed_action=data['include_proposed_action'],
            include_discussion=data['include_discussion'],
            include_decision=data['include_decision'],
            include_publish_in=data['include_publish_in'],
            include_disclose_to=data['include_disclose_to'],
            include_copy_for_attention=data['include_copy_for_attention'])
        command = CreateGeneratedDocumentCommand(data['dossier'], self.model,
                                                 operations)
        command.execute()
        command.show_message()
        return self.redirect_to_meeting()

    @button.buttonAndHandler(_('label_cancel', default=u'Cancel'),
                             name='cancel')
    def handleCancel(self, action):
        return self.redirect_to_meeting()

    def redirect_to_meeting(self):
        return self.request.RESPONSE.redirect(self.model.get_url())
Пример #35
0
class BannerViewlet(ViewletBase):
    """ A viewlet which renders the banner """

    banner_template = ViewPageTemplateFile('banner.pt')
    slider_template = ViewPageTemplateFile('slider.pt')

    def render(self):
        if '@@edit' in self.request.steps:
            return ''
        return self.index()

    def index(self):
        context = aq_inner(self.context)
        if ISlider.providedBy(context):
            if context.slider_relation and len(context.slider_relation) > 1:
                return self.slider_template()
        return self.banner_template()

    def find_banner(self):
        types = api.portal.get_registry_record(
            'collective.behavior.banner.browser.controlpanel.IBannerSettingsSchema.types'
        )  # noqa: E501
        context = aq_inner(self.context)
        # first handle the obj itself
        if IBanner.providedBy(context):
            if context.banner_hide:
                return False
            banner = self.banner(context)
            if banner:
                return banner
            if context.banner_stop_inheriting:
                return False
            # if all the fields are empty and inheriting is not stopped
        if context.portal_type not in types:
            return False
        context = context.__parent__

        # we walk up the path
        for item in context.aq_chain:
            if IBanner.providedBy(item):
                # we have a banner. check.
                if item.banner_stop_inheriting:
                    return False
                banner = self.banner(item)
                if banner:
                    return banner
            if INavigationRoot.providedBy(item):
                return False
            if item.portal_type not in types:
                return False

        return False

    def banner(self, obj):
        """ return banner of this object """
        banner = {}
        if getattr(obj, 'banner_image', False):
            banner['banner_image'] = '{0}/@@images/banner_image'.format(
                obj.absolute_url())
        if obj.banner_title:
            banner['banner_title'] = obj.banner_title
        if obj.banner_description:
            crop = Plone(self.context, self.request).cropText
            banner['banner_description'] = crop(obj.banner_description, 400)
        if obj.banner_text:
            banner['banner_text'] = obj.banner_text.output
        if obj.banner_link:
            to_obj = obj.banner_link.to_object
            if to_obj:
                banner['banner_link'] = to_obj.absolute_url()
                banner['banner_linktext'] = to_obj.Title()
        if obj.banner_linktext:
            banner['banner_linktext'] = obj.banner_linktext
        if obj.banner_fontcolor:
            banner['banner_fontcolor'] = obj.banner_fontcolor
        if obj.banner_url:
            banner['banner_url'] = obj.banner_url
        banner['banner_obj'] = obj
        return banner

    def random_banner(self):
        context = aq_inner(self.context)
        banners = []
        raw_banners = context.slider_relation
        for banner in raw_banners:
            banner = banner.to_object
            banners.append(self.banner(banner))

        self.scroll = len(banners) > 1

        return banners

    def getVideoEmbedMarkup(self, url):
        """ Build an iframe from a YouTube or Vimeo share url """
        # https://www.youtube.com/watch?v=Q6qYdJuWB6w
        YOUTUBE_TEMPLATE = '''
            <iframe
                width="660"
                height="495"
                src="//www.youtube-nocookie.com/embed/{1}?showinfo=0"
                frameborder="0"
                allowfullscreen>
            </iframe>
        '''
        # https://vimeo.com/75721023
        VIMEO_TEMPLATE = '''
            <iframe
                src="//player.vimeo.com/video/{0}?title=0&amp;byline=0&amp;portrait=0"
                width="660"
                height="371"
                frameborder="0"
                webkitallowfullscreen
                mozallowfullscreen
                allowfullscreen>
            </iframe>
        '''
        try:
            parsed = urlparse(url)
        except AttributeError:
            return ''
        path = parsed.path.replace('/', '')
        videoId = parsed.query.replace('v=', '')
        if 'youtube' in parsed.netloc:
            template = YOUTUBE_TEMPLATE
        elif 'vimeo' in parsed.netloc:
            template = VIMEO_TEMPLATE
        else:
            return ''
        # It so happens that path is needed by the Vimeo format,
        # while videoId is needed by the Youtube format, so only one
        # of the variables will have a useful value, depending on the player.
        # Each template will use the argument it cares about and ignore the
        # other.
        return template.format(path, videoId)
Пример #36
0
class PasswordAccountPanel(prefs.PasswordAccountPanel):
    template = ViewPageTemplateFile('pt/password-account-panel.pt')
Пример #37
0
class DashboardView(BrowserView):
    template = ViewPageTemplateFile("templates/dashboard.pt")

    def __call__(self):
        tofrontpage = True
        mtool = getToolByName(self.context, 'portal_membership')
        if not mtool.isAnonymousUser(
        ) and self.context.bika_setup.getDashboardByDefault():
            # If authenticated user with labman role,
            # display the Main Dashboard view
            pm = getToolByName(self.context, "portal_membership")
            member = pm.getAuthenticatedMember()
            roles = member.getRoles()
            tofrontpage = 'Manager' not in roles and 'LabManager' not in roles

        if tofrontpage == True:
            self.request.response.redirect(self.portal_url + "/bika-frontpage")
        else:
            self._init_date_range()
            return self.template()

    def _init_date_range(self):
        """ Sets the date range from which the data must be retrieved.
            Sets the values to the class parameters 'date_from',
            'date_to', 'date_range', 'base_date_range' and self.periodicity
            Calculates the date range according to the value of the
            request's 'p' parameter:
            - 'd' (daily)
            - 'w' (weekly)
            - 'm' (monthly)
            - 'q' (quarterly)
            - 'b' (biannual)
            - 'y' (yearly)
        """
        # By default, weekly
        self.periodicity = self.request.get('p', 'w')
        if (self.periodicity == 'd'):
            # Daily
            self.date_from = DateTime()
            self.date_to = DateTime() + 1
            # For time-evolution data, load last 30 days
            self.min_date = self.date_from - 30
        elif (self.periodicity == 'm'):
            # Monthly
            today = datetime.date.today()
            self.date_from = DateTime(today.year, today.month, 1)
            self.date_to = DateTime(today.year, today.month,
                                    monthrange(today.year, today.month)[1], 23,
                                    59, 59)
            # For time-evolution data, load last two years
            min_year = today.year - 1 if today.month == 12 else today.year - 2
            min_month = 1 if today.month == 12 else today.month
            self.min_date = DateTime(min_year, min_month, 1)
        elif (self.periodicity == 'q'):
            # Quarterly
            today = datetime.date.today()
            m = (((today.month - 1) / 3) * 3) + 1
            self.date_from = DateTime(today.year, m, 1)
            self.date_to = DateTime(today.year, m + 2,
                                    monthrange(today.year, m + 2)[1], 23, 59,
                                    59)
            # For time-evolution data, load last four years
            min_year = today.year - 4 if today.month == 12 else today.year - 5
            self.min_date = DateTime(min_year, m, 1)
        elif (self.periodicity == 'b'):
            # Biannual
            today = datetime.date.today()
            m = (((today.month - 1) / 6) * 6) + 1
            self.date_from = DateTime(today.year, m, 1)
            self.date_to = DateTime(today.year, m + 5,
                                    monthrange(today.year, m + 5)[1], 23, 59,
                                    59)
            # For time-evolution data, load last ten years
            min_year = today.year - 10 if today.month == 12 else today.year - 11
            self.min_date = DateTime(min_year, m, 1)
        elif (self.periodicity == 'y'):
            # Yearly
            today = datetime.date.today()
            self.date_from = DateTime(today.year, 1, 1)
            self.date_to = DateTime(today.year, 12, 31, 23, 59, 59)
            # For time-evolution data, load last 15 years
            min_year = today.year - 15 if today.month == 12 else today.year - 16
            self.min_date = DateTime(min_year, 1, 1)
        else:
            # weekly
            today = datetime.date.today()
            year, weeknum, dow = today.isocalendar()
            self.date_from = DateTime() - dow
            self.date_to = self.date_from + 7
            # For time-evolution data, load last six months
            min_year = today.year if today.month > 6 else today.year - 1
            min_month = today.month - 6 if today.month > 6 else (today.month -
                                                                 6) + 12
            self.min_date = DateTime(min_year, min_month, 1)

        self.date_range = {
            'query': (self.date_from, self.date_to),
            'range': 'min:max'
        }
        self.base_date_range = {
            'query': (DateTime('1990-01-01 00:00:00'), self.date_from - 1),
            'range': 'min:max'
        }
        self.min_date_range = {
            'query': (self.min_date, self.date_to),
            'range': 'min:max'
        }

    def get_sections(self):
        """ Returns an array with the sections to be displayed.
            Every section is a dictionary with the following structure:
                {'id': <section_identifier>,
                 'title': <section_title>,
                'panels': <array of panels>}
        """
        sections = [
            self.get_analyses_section(),
            self.get_analysisrequests_section(),
            self.get_worksheets_section()
        ]
        return sections

    def get_analysisrequests_section(self):
        """ Returns the section dictionary related with Analysis
            Requests, that contains some informative panels (like
            ARs to be verified, ARs to be published, etc.)
        """
        out = []
        sampenabled = self.context.bika_setup.getSamplingWorkflowEnabled()

        # Analysis Requests
        active_rs = [
            'to_be_sampled', 'to_be_preserved', 'scheduled_sampling',
            'sample_due', 'sample_received', 'assigned', 'to_be_verified',
            'attachment_due', 'verified'
        ]
        bc = getToolByName(self.context, "bika_catalog")
        numars = len(
            bc(portal_type="AnalysisRequest",
               created=self.date_range,
               cancellation_state=[
                   'active',
               ]))
        numars += len(
            bc(portal_type="AnalysisRequest",
               review_state=active_rs,
               cancellation_state=[
                   'active',
               ],
               created=self.base_date_range))

        if (sampenabled):
            # Analysis Requests awaiting to be sampled or scheduled
            review_state = [
                'to_be_sampled',
            ]
            ars = len(
                bc(portal_type="AnalysisRequest",
                   review_state=review_state,
                   cancellation_state=[
                       'active',
                   ]))
            ratio = (float(ars) /
                     float(numars)) * 100 if ars > 0 and numars > 0 else 0
            ratio = str("%%.%sf" % 1) % ratio
            msg = _("To be sampled")
            out.append({
                'type':
                'simple-panel',
                'name':
                _('Analysis Requests to be sampled'),
                'class':
                'informative',
                'description':
                msg,
                'number':
                ars,
                'total':
                numars,
                'legend':
                _('of') + " " + str(numars) + ' (' + ratio + '%)',
                'link':
                self.portal_url + '/samples?samples_review_state=to_be_sampled'
            })

            # Analysis Requests awaiting to be preserved
            review_state = [
                'to_be_preserved',
            ]
            ars = len(
                bc(portal_type="AnalysisRequest",
                   review_state=review_state,
                   cancellation_state=[
                       'active',
                   ]))
            ratio = (float(ars) /
                     float(numars)) * 100 if ars > 0 and numars > 0 else 0
            ratio = str("%%.%sf" % 1) % ratio
            msg = _("To be preserved")
            out.append({
                'type':
                'simple-panel',
                'name':
                _('Analysis Requests to be preserved'),
                'class':
                'informative',
                'description':
                msg,
                'number':
                ars,
                'total':
                numars,
                'legend':
                _('of') + " " + str(numars) + ' (' + ratio + '%)',
                'link':
                self.portal_url +
                '/analysisrequests?analysisrequests_review_state=to_be_preserved'
            })

            # Analysis Requests awaiting to be sampled
            review_state = [
                'scheduled_sampling',
            ]
            ars = len(
                bc(portal_type="AnalysisRequest",
                   review_state=review_state,
                   cancellation_state=[
                       'active',
                   ]))
            ratio = (float(ars) /
                     float(numars)) * 100 if ars > 0 and numars > 0 else 0
            ratio = str("%%.%sf" % 1) % ratio
            msg = _("Scheduled sampling")
            out.append({
                'type':
                'simple-panel',
                'name':
                _('Analysis Requests with scheduled sampling'),
                'class':
                'informative',
                'description':
                msg,
                'number':
                ars,
                'total':
                numars,
                'legend':
                _('of') + " " + str(numars) + ' (' + ratio + '%)',
                'link':
                self.portal_url + '/samples?samples_review_state=to_be_sampled'
            })

        # Analysis Requests awaiting for reception
        review_state = [
            'sample_due',
        ]
        ars = len(
            bc(portal_type="AnalysisRequest",
               review_state=review_state,
               cancellation_state=[
                   'active',
               ]))
        ratio = (float(ars) /
                 float(numars)) * 100 if ars > 0 and numars > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("Reception pending")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('Analysis Requests to be received'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ars,
            'total':
            numars,
            'legend':
            _('of') + " " + str(numars) + ' (' + ratio + '%)',
            'link':
            self.portal_url +
            '/analysisrequests?analysisrequests_review_state=sample_due'
        })

        # Analysis Requests under way
        review_state = ['attachment_due', 'sample_received', 'assigned']
        ars = len(
            bc(portal_type="AnalysisRequest",
               review_state=review_state,
               cancellation_state=[
                   'active',
               ]))
        ratio = (float(ars) /
                 float(numars)) * 100 if ars > 0 and numars > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("Results pending")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('Analysis Requests with results pending'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ars,
            'total':
            numars,
            'legend':
            _('of') + " " + str(numars) + ' (' + ratio + '%)',
            'link':
            self.portal_url +
            '/analysisrequests?analysisrequests_review_state=sample_received'
        })

        # Analysis Requests to be verified
        review_state = [
            'to_be_verified',
        ]
        ars = len(
            bc(portal_type="AnalysisRequest",
               review_state=review_state,
               cancellation_state=[
                   'active',
               ]))
        ratio = (float(ars) /
                 float(numars)) * 100 if ars > 0 and numars > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("To be verified")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('Analysis Requests to be verified'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ars,
            'total':
            numars,
            'legend':
            _('of') + " " + str(numars) + ' (' + ratio + '%)',
            'link':
            self.portal_url +
            '/analysisrequests?analysisrequests_review_state=to_be_verified'
        })

        # Analysis Requests to be published
        review_state = [
            'verified',
        ]
        ars = len(
            bc(portal_type="AnalysisRequest",
               review_state=review_state,
               cancellation_state=[
                   'active',
               ]))
        ratio = (float(ars) /
                 float(numars)) * 100 if ars > 0 and numars > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("To be published")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('Analysis Requests to be published'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ars,
            'total':
            numars,
            'legend':
            _('of') + " " + str(numars) + ' (' + ratio + '%)',
            'link':
            self.portal_url +
            '/analysisrequests?analysisrequests_review_state=verified'
        })

        # Chart with the evolution of ARs over a period, grouped by
        # periodicity
        workflow = getToolByName(self.context, 'portal_workflow')
        allars = bc(portal_type="AnalysisRequest",
                    sort_on="created",
                    created=self.min_date_range)
        outevo = []
        for ar in allars:
            ar = ar.getObject()
            state = 'other_status'
            try:
                state = workflow.getInfoFor(ar, 'cancellation_state')
                if (state == 'active'):
                    state = workflow.getInfoFor(ar, 'review_state')
                else:
                    state = 'inactive'
            except:
                pass

            created = self._getDateStr(self.periodicity, ar.created())
            state = 'sample_due' if state in [
                'to_be_sampled', 'to_be_preserved'
            ] else state
            state = 'sample_received' if state in [
                'assigned', 'attachment_due'
            ] else state
            if (len(outevo) > 0 and outevo[-1]['date'] == created):
                key = state if _(state) in outevo[-1] else 'other_status'
                outevo[-1][_(key)] += 1
            else:
                currow = {
                    'date': created,
                    _('sample_due'): 0,
                    _('sample_received'): 0,
                    _('to_be_verified'): 0,
                    _('verified'): 0,
                    _('published'): 0,
                    _('inactive'): 0,
                    _('other_status'): 0,
                }
                key = state if _(state) in currow else 'other_status'
                currow[_(key)] += 1
                outevo.append(currow)

        out.append({
            'type': 'bar-chart-panel',
            'name': _('Evolution of Analysis Requests'),
            'class': 'informative',
            'description': _('Evolution of Analysis Requests'),
            'data': json.dumps(outevo)
        })

        return {
            'id': 'analysisrequests',
            'title': _('Analysis Requests'),
            'panels': out
        }

    def get_worksheets_section(self):
        """ Returns the section dictionary related with Worksheets,
            that contains some informative panels (like
            WS to be verified, WS with results pending, etc.)
        """
        out = []
        bc = getToolByName(self.context, "bika_catalog")
        active_ws = ['open', 'to_be_verified', 'attachment_due']
        numws = len(bc(portal_type="Worksheet", created=self.date_range))

        numws += len(
            bc(portal_type="Worksheet",
               review_state=active_ws,
               created=self.base_date_range))

        # Open worksheets
        review_state = ['open', 'attachment_due']
        ws = len(bc(portal_type="Worksheet", review_state=review_state))
        ratio = (float(ws) / float(numws)) * 100 if ws > 0 and numws > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("Results pending")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('Results pending'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ws,
            'total':
            numws,
            'legend':
            _('of') + " " + str(numws) + ' (' + ratio + '%)',
            'link':
            self.portal_url + '/worksheets?list_review_state=open'
        })

        # Worksheets to be verified
        review_state = [
            'to_be_verified',
        ]
        ws = len(bc(portal_type="Worksheet", review_state=review_state))
        ratio = (float(ws) / float(numws)) * 100 if ws > 0 and numws > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("To be verified")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('To be verified'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ws,
            'total':
            numws,
            'legend':
            _('of') + " " + str(numws) + ' (' + ratio + '%)',
            'link':
            self.portal_url + '/worksheets?list_review_state=to_be_verified'
        })

        # Chart with the evolution of WSs over a period, grouped by
        # periodicity
        workflow = getToolByName(self.context, 'portal_workflow')
        allws = bc(portal_type="Worksheet",
                   sort_on="created",
                   created=self.min_date_range)
        outevo = []
        for ws in allws:
            ws = ws.getObject()
            state = 'other_status'
            try:
                state = workflow.getInfoFor(ws, 'cancellation_state')
                if (state == 'active'):
                    state = workflow.getInfoFor(ws, 'review_state')
                else:
                    state = 'inactive'
            except:
                pass

            created = self._getDateStr(self.periodicity, ws.created())

            if (len(outevo) > 0 and outevo[-1]['date'] == created):
                key = state if _(state) in outevo[-1] else 'other_status'
                outevo[-1][_(key)] += 1
            else:
                currow = {
                    'date': created,
                    _('open'): 0,
                    _('to_be_verified'): 0,
                    _('attachment_due'): 0,
                    _('verified'): 0,
                    _('inactive'): 0,
                    _('other_status'): 0,
                }
                key = state if _(state) in currow else 'other_status'
                currow[_(key)] += 1
                outevo.append(currow)

        out.append({
            'type': 'bar-chart-panel',
            'name': _('Evolution of Worksheets'),
            'class': 'informative',
            'description': _('Evolution of Worksheets'),
            'data': json.dumps(outevo)
        })

        return {'id': 'worksheets', 'title': _('Worksheets'), 'panels': out}

    def get_analyses_section(self):
        """ Returns the section dictionary related with Analyses,
            that contains some informative panels (analyses pending
            analyses assigned, etc.)

            sample_registered, not_requested, published, retracted,
            sample_due, sample_received, sample_prep, sampled, to_be_preserved,
            to_be_sampled, , to_be_verified, rejected, verified, to_be_verified,
            assigned
        """
        out = []
        active_rs = [
            'sample_received', 'assigned', 'attachment_due', 'to_be_verified',
            'verified'
        ]
        bac = getToolByName(self.context, "bika_analysis_catalog")
        numans = len(
            bac(portal_type="Analysis",
                created=self.date_range,
                cancellation_state=['active']))
        numans += len(
            bac(portal_type="Analysis",
                review_state=active_rs,
                cancellation_state=['active'],
                created=self.base_date_range))

        # Analyses pending
        review_state = [
            'sample_received', 'assigned', 'attachment_due', 'to_be_verified'
        ]
        ans = len(bac(portal_type="Analysis", review_state=review_state))
        ratio = (float(ans) /
                 float(numans)) * 100 if ans > 0 and numans > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("Analyses pending")
        out.append({
            'type': 'simple-panel',
            'name': _('Analyses pending'),
            'class': 'informative',
            'description': msg,
            'number': ans,
            'total': numans,
            'legend': _('of') + " " + str(numans) + ' (' + ratio + '%)',
            'link': self.portal_url + '/aggregatedanalyses'
        })

        # Analyses to be verified
        review_state = [
            'to_be_verified',
        ]
        ans = len(bac(portal_type="Analysis", review_state=review_state))
        ratio = (float(ans) /
                 float(numans)) * 100 if ans > 0 and numans > 0 else 0
        ratio = str("%%.%sf" % 1) % ratio
        msg = _("To be verified")
        out.append({
            'type':
            'simple-panel',
            'name':
            _('To be verified'),
            'class':
            'informative',
            'description':
            msg,
            'number':
            ans,
            'total':
            numans,
            'legend':
            _('of') + " " + str(numans) + ' (' + ratio + '%)',
            'link':
            self.portal_url + '/worksheets?list_review_state=to_be_verified'
        })

        # Chart with the evolution of WSs over a period, grouped by
        # periodicity
        workflow = getToolByName(self.context, 'portal_workflow')
        allans = bac(portal_type="Analysis",
                     sort_on="created",
                     created=self.min_date_range)
        outevo = []
        for an in allans:
            an = an.getObject()
            state = 'other_status'
            try:
                state = workflow.getInfoFor(an, 'cancellation_state')
                if (state == 'active'):
                    state = workflow.getInfoFor(an, 'review_state')
                else:
                    state = 'inactive'
            except:
                pass

            created = self._getDateStr(self.periodicity, an.created())

            if (len(outevo) > 0 and outevo[-1]['date'] == created):
                key = state if _(state) in outevo[-1] else 'other_status'
                outevo[-1][_(key)] += 1
            else:
                currow = {
                    'date': created,
                    _('assigned'): 0,
                    _('to_be_verified'): 0,
                    _('attachment_due'): 0,
                    _('verified'): 0,
                    _('inactive'): 0,
                    _('other_status'): 0,
                }
                key = state if _(state) in currow else 'other_status'
                currow[_(key)] += 1
                outevo.append(currow)

        out.append({
            'type': 'bar-chart-panel',
            'name': _('Evolution of Analyses'),
            'class': 'informative',
            'description': _('Evolution of Analyses'),
            'data': json.dumps(outevo)
        })
        return {'id': 'analyses', 'title': _('Analyses'), 'panels': out}

    def _getDateStr(self, period, created):
        if period == 'y':
            created = created.year()
        elif period == 'b':
            m = (((created.month() - 1) / 6) * 6) + 1
            created = '%s-%s' % (str(created.year())[2:], str(m).zfill(2))
        elif period == 'q':
            m = (((created.month() - 1) / 3) * 3) + 1
            created = '%s-%s' % (str(created.year())[2:], str(m).zfill(2))
        elif period == 'm':
            created = '%s-%s' % (str(created.year())[2:], str(
                created.month()).zfill(2))
        elif period == 'w':
            d = (((created.day() - 1) / 7) * 7) + 1
            year, weeknum, dow = created.asdatetime().isocalendar()
            created = created - dow
            created = '%s-%s-%s' % (str(
                created.year())[2:], str(
                    created.month()).zfill(2), str(created.day()).zfill(2))
        else:
            created = '%s-%s-%s' % (str(
                created.year())[2:], str(
                    created.month()).zfill(2), str(created.day()).zfill(2))
        return created
Пример #38
0
 def inspectViewletManager(self, managerName):
     """ Display information about a particular viewlet manager """
     logger.debug("in inspectViewletManager")
     # Get the viewletmanager object
     managerName = managerName.replace('-', '.')
     viewletManager = queryMultiAdapter((self.context, self.request, self), IViewletManager, managerName)
     
     # Gather information for the viewlet hashes
     managerInterface = list(providedBy(viewletManager).flattened())[0]
     
     # Look up the viewlets attached to this viewlet manager.
     # We do it this way because calling viewletManager.viewlets won't see the hidden viewlets...
     viewlets = getAdapters((self.context, self.request, viewletManager.__parent__, viewletManager),IViewlet)
     
     # Get the names of the hidden viewlets
     storage = getUtility(IViewletSettingsStorage)
     hidden = frozenset(storage.getHidden(managerName, self.context.getCurrentSkinName()))
     
     # Generate the output
     sortedViewlets = viewletManager.sort(viewlets)
     
     containedViewlets = []
     for viewletTuple in sortedViewlets:
         containedViewlet = {}
         viewletname = viewletTuple[0]
         
         # generate viewlet hashes...
         # TODO factor this up.
         
         # Get the "provided" interfaces for this viewlet manager.
         # TODO: Do this lookup properly.
         regs = [regs for regs in getGlobalSiteManager().registeredAdapters() if regs.name == viewletname and regs.required[-1].isOrExtends(managerInterface)]
         if regs:
             reg = regs[0]
             provided = ','.join([a.__identifier__ for a in reg.required])
             # logger.debug("%s - provided: %s" % (viewletName, provided))
             hashedInfo = binascii.b2a_hex("%s\n%s\n%s" % (viewletname, managerName, provided))
         else:
             hashedInfo = ""
             logger.debug("Unable to create hash for %s" % viewletname)
         
         # Give the viewlet a class name depending on the visibility
         classname = viewletname in hidden and 'hiddenViewlet' or 'visibleViewlet'
         logger.debug(classname)
         containedViewlet['className'] = classname
         containedViewlet['hashedInfo'] = hashedInfo
         containedViewlet['name'] = viewletname
         containedViewlets.append(containedViewlet)
     
     # Determine whether the contained viewlets can be sorted.
     skinname = self.context.getCurrentSkinName()
     canOrder = bool(storage.getOrder(managerName, skinname))
     
     template = ViewPageTemplateFile('panel_inspect_viewlet_manager.pt')
     # Wrap it so that Zope knows in what context it's being called
     # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
     template = template.__of__(self)
     out = template(managerName = managerName,
                    containedViewlets = containedViewlets,
                    canOrder = canOrder
                    )
     
     # Dump the output to the output panel
     self.updatePanelBodyContent(out)
     
     # Highlight the element
     ksscore = self.getCommandSet('core')
     self.highlightElement(ksscore.getCssSelector('.kssattr-viewletmanagername-%s' % managerName.replace('.', '-')))
     
     # And in the nav tree (Should this be here or in the nav tree viewlet code?)
     self.highlightInNavTree(ksscore.getCssSelector('#glowormPanelNavTree .kssattr-forviewletmanager-%s' % managerName.replace('.', '-')))
     
     return self.render()
# -*- coding: utf-8 -*-
from plone.z3cform.layout import wrap_form
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from rer.newsletterplugin.flask import _
from rer.newsletter.browser.message.sendmessageview import SendMessageView


class SendMessageViewCustom(SendMessageView):
    @property
    def success_message(self):
        return _(
            u'message_send',
            default=u'Message correctly enqueued to be sent to ${subscribers} '
            u'subscribers. Please check Channel history to know when '
            u'the task ends or wait the confirm email.',
            mapping=dict(subscribers=self.active_subscriptions),
        )


message_sending_view = wrap_form(
    SendMessageViewCustom,
    index=ViewPageTemplateFile('templates/sendmessageview.pt'),
)
Пример #40
0
class Download(Pdf):
    """ Download PDF
    """
    template = ViewPageTemplateFile('../zpt/download.pt')
    _message = ''
    _email = ''

    def make_pdf(self, dry_run=False, **kwargs):
        """ Compute pdf
        """
        data = super(Download, self).make_pdf(dry_run=dry_run, **kwargs)

        # Async
        if dry_run:
            return data

        # Sync events
        if not data:
            event.notify(PDFExportFail(self.context))
        event.notify(PDFExportSuccess(self.context))

        return data

    @property
    def message(self):
        """ Message
        """
        return self._message

    @property
    def email(self):
        """ User email
        """
        return self._email

    def _redirect(self, msg=''):
        """ Redirect
        """
        self.request.set('disable_border', 1)
        self.request.set('disable_plone.leftcolumn', 1)
        self.request.set('disable_plone.rightcolumn', 1)
        self._message = msg
        return self.template()

    def link(self):
        """ Download link
        """
        storage = IStorage(self.context).of('pdf')
        return storage.absolute_url()

    def period(self):
        """ Wait period
        """
        ptype = getattr(self.context, 'portal_type', '')
        if ptype.lower() in ('collection', 'topic', 'folder', 'atfolder'):
            return _(u"minutes")
        return _(u"seconds")

    def finish(self, email=''):
        """ Finish download
        """
        self._email = email
        return self._redirect(
            _(
                u"The PDF is being generated. "
                u"An email will be sent to you when the PDF is ready. "
                u"If you don't have access to your email address "
                u"check <a href='${link}'>this link</a> in a few ${period}.",
                mapping={
                    "link": self.link(),
                    "period": self.period()
                }))

    def download(self, email='', **kwargs):
        """ Download
        """
        # PDF already generated
        storage = IStorage(self.context).of('pdf')
        filepath = storage.filepath()
        fileurl = storage.absolute_url()
        url = self.context.absolute_url()
        title = self.context.title_or_id()

        portal = getSite()
        from_name = portal.getProperty('email_from_name')
        from_email = portal.getProperty('email_from_address')

        if async .file_exists(filepath):
            wrapper = async .ContextWrapper(self.context)(
                fileurl=fileurl,
                filepath=filepath,
                email=email,
                url=url,
                from_name=from_name,
                from_email=from_email,
                title=title)

            event.notify(AsyncPDFExportSuccess(wrapper))
            return self.finish(email=email)

        # Cheat condition @@plone_context_state/is_view_template
        self.request['ACTUAL_URL'] = self.context.absolute_url()

        # Async generate PDF
        converter = self.make_pdf(dry_run=True)
        worker = queryUtility(IAsyncService)
        worker.queueJob(async .make_async_pdf,
                        self.context,
                        converter,
                        email=email,
                        filepath=filepath,
                        fileurl=fileurl,
                        url=url,
                        from_name=from_name,
                        from_email=from_email,
                        title=title)

        return self.finish(email=email)
Пример #41
0
 def inspectElement(self,
                   insideInspectableArea=False,
                   talcontent=None,
                   talattributes=None,
                   talcondition=None,
                   metaldefmacro=None,
                   metalusemacro=None,
                   fieldname=None,
                   portlethash=None,
                   viewlethash=None,
                   sourceAnnotation=None):
     """ Get details about a particular html element. """
     # Make sure we're not clicking inside the inspector div since KSS doesn't seem to provide a
     # way to block processing of other rules.
     if insideInspectableArea:
         logger.debug("in inspectElement")
         
         parsedTalAttributes = []
         if talattributes:
             # logger.debug("talattributes: %s" % talattributes)
             # If there's only one item in the list being returned by the KSS method,
             # it's passing it as a string instead of a list/array. Not sure why.
             # Sniff the type and make it a list if needed.
             if isinstance(talattributes, str):
                 talattributes = [talattributes]
             for attr in talattributes:
                 # logger.debug("attr: %s" % attr)
                 attribute = {}
                 attribute['name'], attribute['expression'], attribute['result'] = attr.split(',')
                 parsedTalAttributes.append(attribute)
         
         unhashedPortletInfo = {}
         if portlethash:
             unhashedPortletInfo = unhashPortletInfo(portlethash)
         
         unhashedViewletInfo = {}
         if viewlethash:
             unhashedViewletInfo = unhashViewletInfo(viewlethash)
         
         if sourceAnnotation:
             sourceAnnotation = sourceAnnotation.strip(' =\n')
         
         template = ViewPageTemplateFile('panel_inspect_element.pt')
         # Wrap it so that Zope knows in what context it's being called
         # Otherwise, we get an "AttributeError: 'str' object has no attribute 'other'" error
         template = template.__of__(self)
         out = template(metalUseMacro = metalusemacro,
                        metalDefMacro = metaldefmacro,
                        fieldName = fieldname,
                        talContent = talcontent,
                        talAttributes = parsedTalAttributes,
                        talCondition = talcondition,
                        portletInfo = unhashedPortletInfo,
                        viewletInfo = unhashedViewletInfo,
                        sourceAnnotation = sourceAnnotation
                        )
         
         # Dump the output to the inspector panel
         self.updatePanelBodyContent(out)
         
         # Highlight this element
         ksscore = self.getCommandSet('core')
         self.highlightElement(ksscore.getSameNodeSelector())
         
         # And in the nav tree (Should this be here or in the nav tree viewlet code?)
         if viewlethash:
             self.highlightInNavTree(ksscore.getCssSelector('#glowormPanelNavTree .kssattr-forviewlet-%s' % viewlethash))
     
     return self.render()
Пример #42
0
class A18MeasureProgressDisplay(ItemDisplayForm):
    title = "Measure Progress display"

    extra_data_template = ViewPageTemplateFile('pt/extra-data-pivot.pt')
    mapper_class = sql2018.ART18MeasureProgres
    css_class = 'left-side-form'

    blacklist_labels = ('MeasureCode', )

    reported_date_info = {
        'mapper_class': sql2018.ReportedInformation,
        'col_import_id': 'Id',
        'col_import_time': 'ReportingDate'
    }

    def get_reported_date(self):
        return self.get_reported_date_2018()

    def get_import_id(self):
        import_id = self.item.IdReportedInformation

        return import_id

    @db.use_db_session('2018')
    def get_current_country(self):
        report_id = self.item.IdReportedInformation

        _, res = db.get_related_record(sql2018.ReportedInformation, 'Id',
                                       report_id)

        country = self.print_value(res.CountryCode)

        return country

    @db.use_db_session('2018')
    def download_results(self):
        mc_descr = sql2018.ART18MeasureProgressDescriptor
        mc_countries = sql2018.ReportedInformation

        countries = self.get_form_data_by_key(self, 'member_states')
        ges_comps = self.get_form_data_by_key(self, 'ges_component')

        conditions = []

        if countries:
            conditions.append(mc_countries.CountryCode.in_(countries))

        count, report_ids = db.get_all_records(mc_countries, *conditions)
        report_ids = [x.Id for x in report_ids]

        conditions = []
        if ges_comps:
            conditions.append(mc_descr.DescriptorCode.in_(ges_comps))

        count, measure_progress_ids = db.get_all_records(mc_descr, *conditions)
        measure_progress_ids = [
            x.IdMeasureProgress for x in measure_progress_ids
        ]

        count, measure_prog = db.get_all_records(
            self.mapper_class,
            self.mapper_class.IdReportedInformation.in_(report_ids),
            self.mapper_class.Id.in_(measure_progress_ids),
        )
        id_measure = [x.Id for x in measure_prog]

        count, measure_prog_descr = db.get_all_records(
            mc_descr, mc_descr.IdMeasureProgress.in_(id_measure))

        xlsdata = [
            ('ART18MeasureProgres', measure_prog),  # worksheet title, row data
            ('ART18MeasureProgressDescriptor', measure_prog_descr),
        ]

        return data_to_xls(xlsdata)

    @db.use_db_session('2018')
    def get_db_results(self):
        page = self.get_page()
        mc_descr = sql2018.ART18MeasureProgressDescriptor
        mc_countries = sql2018.ReportedInformation

        countries = self.get_form_data_by_key(self, 'member_states')
        ges_comps = self.get_form_data_by_key(self, 'ges_component')

        conditions = []

        if countries:
            conditions.append(mc_countries.CountryCode.in_(countries))

        count, report_ids = db.get_all_records(mc_countries, *conditions)
        report_ids = [x.Id for x in report_ids]

        conditions = []
        if ges_comps:
            conditions.append(mc_descr.DescriptorCode.in_(ges_comps))

        count, measure_progress_ids = db.get_all_records(mc_descr, *conditions)
        measure_progress_ids = [
            x.IdMeasureProgress for x in measure_progress_ids
        ]

        item = db.get_item_by_conditions(
            self.mapper_class,
            'Id',
            self.mapper_class.IdReportedInformation.in_(report_ids),
            self.mapper_class.Id.in_(measure_progress_ids),
            page=page)

        return item

    @db.use_db_session('2018')
    def get_extra_data(self):
        if not self.item:
            return {}

        mc = sql2018.ART18MeasureProgressDescriptor
        excluded_columns = ('IdMeasureProgress', )
        res = []
        id_measure = self.item.Id

        count, data = db.get_all_records(mc,
                                         mc.IdMeasureProgress == id_measure)

        data = db_objects_to_dict(data, excluded_columns)
        res.append(('Descriptor', {'': data}))

        return res
Пример #43
0
class DashboardPortletManagerRenderer(ColumnPortletManagerRenderer):
    """Render a column of the dashboard
    """

    adapts(Interface, IDefaultBrowserLayer, IBrowserView, IDashboard)
    template = ViewPageTemplateFile('browser/templates/dashboard-column.pt')
Пример #44
0
class SliderNavigation(navigation.SliderNavigation):
    template = ViewPageTemplateFile('slider.pt')
Пример #45
0
class LogoViewlet(LogoBaseViewlet):

    index = ViewPageTemplateFile('logo_viewlet.pt')
Пример #46
0
class Listing(BrowserView):
    index = ViewPageTemplateFile(
        pkg_resources.resource_filename('collective.eeafaceted.z3ctable',
                                        'browser/faceted-table-items.pt'))
Пример #47
0
class AddRequestFormView(FormWrapper):
    form = AddRequestForm
    index = ViewPageTemplateFile("templates/add_request_form_view.pt")
Пример #48
0
class AnalysisRequestsView(BikaListingView):
    """Listing View for all Analysis Requests in the System
    """

    template = ViewPageTemplateFile("templates/analysisrequests.pt")

    def __init__(self, context, request):
        super(AnalysisRequestsView, self).__init__(context, request)

        # hide the right column
        request.set("disable_plone.rightcolumn", 1)

        # hide the editable border
        if self.context.portal_type == "AnalysisRequestsFolder":
            self.request.set("disable_border", 1)

        # catalog used for the query
        self.catalog = CATALOG_ANALYSIS_REQUEST_LISTING

        # https://docs.plone.org/develop/plone/searching_and_indexing/query.html#searching-for-content-within-a-folder
        self.contentFilter = {
            "sort_on": "created",
            "sort_order": "descending",
            "cancellation_state": "active",
        }

        # Filter by Department
        if self.context.bika_setup.getAllowDepartmentFiltering():
            deps = self.request.get('filter_by_department_info', '')
            dep_uids = deps.split(",")
            dep_query = {"query": dep_uids, "operator": "or"}
            self.contentFilter['getDepartmentUIDs'] = dep_query

        self.context_actions = {}

        if self.view_url.find("analysisrequests") == -1:
            self.view_url = self.view_url + "/analysisrequests"

        self.allow_edit = True
        self.show_sort_column = False
        self.show_select_row = False
        self.show_select_column = True
        self.form_id = "analysisrequests"

        ar_image_path = "/++resource++bika.lims.images/analysisrequest_big.png"
        self.icon = "{}{}".format(self.portal_url, ar_image_path)
        self.title = self.context.translate(_("Analysis Requests"))
        self.description = ""

        SamplingWorkflowEnabled = \
            self.context.bika_setup.getSamplingWorkflowEnabled()

        # Check if the filter bar functionality is activated or not
        self.filter_bar_enabled =\
            self.context.bika_setup.\
            getDisplayAdvancedFilterBarForAnalysisRequests()

        self.columns = collections.OrderedDict((
            ("Priority", {
                "title": "",
                "index": "getPrioritySortkey",
                "sortable": True,
            }),
            ("Progress", {
                "title": "Progress",
                "sortable": False,
                "toggle": True
            }),
            ("getId", {
                "title": _("Request ID"),
                "attr": "getId",
                "replace_url": "getURL",
                "index": "getId"
            }),
            ("getClientOrderNumber", {
                "title": _("Client Order"),
                "sortable": True,
                "toggle": False
            }),
            ("Creator", {
                "title": _("Creator"),
                "index": "getCreatorFullName",
                "sortable": True,
                "toggle": True
            }),
            ("Created", {
                "title": _("Date Registered"),
                "index": "created",
                "toggle": False
            }),
            ("SamplingDate", {
                "title": _("Expected Sampling Date"),
                "index": "getSamplingDate",
                "toggle": SamplingWorkflowEnabled
            }),
            ("getDateSampled", {
                "title": _("Date Sampled"),
                "toggle": True,
                "input_class": "datetimepicker_nofuture",
                "input_width": "10"
            }),
            ("getDatePreserved", {
                "title": _("Date Preserved"),
                "toggle": False,
                "input_class": "datetimepicker_nofuture",
                "input_width": "10",
                "sortable": False
            }),  # no datesort without index
            ("getDateReceived", {
                "title": _("Date Received"),
                "toggle": False
            }),
            ("getDueDate", {
                "title": _("Due Date"),
                "toggle": False
            }),
            ("getDateVerified", {
                "title": _("Date Verified"),
                "input_width": "10",
                "toggle": False
            }),
            ("getDatePublished", {
                "title": _("Date Published"),
                "toggle": False
            }),
            ("getSample", {
                "title": _("Sample"),
                "attr": "getSampleID",
                "index": "getSampleID",
                "replace_url": "getSampleURL",
                "toggle": False
            }),
            ("BatchID", {
                "title": _("Batch ID"),
                "index": "getBatchID",
                "sortable": True,
                "toggle": False
            }),
            ("Client", {
                "title": _("Client"),
                "index": "getClientTitle",
                "attr": "getClientTitle",
                "replace_url": "getClientURL",
                "toggle": True
            }),
            ("Province", {
                "title": _("Province"),
                "sortable": True,
                "index": "getProvince",
                "attr": "getProvince",
                "toggle": False
            }),
            ("District", {
                "title": _("District"),
                "sortable": True,
                "index": "getDistrict",
                "attr": "getDistrict",
                "toggle": False
            }),
            ("getClientReference", {
                "title": _("Client Ref"),
                "sortable": True,
                "index": "getClientReference",
                "toggle": False
            }),
            ("getClientSampleID", {
                "title": _("Client SID"),
                "toggle": False
            }),
            ("ClientContact", {
                "title": _("Contact"),
                "sortable": True,
                "index": "getContactFullName",
                "toggle": False
            }),
            ("getSampleTypeTitle", {
                "title": _("Sample Type"),
                "sortable": True,
                "toggle": True
            }),
            ("getSamplePointTitle", {
                "title": _("Sample Point"),
                "sortable": True,
                "index": "getSamplePointTitle",
                "toggle": False
            }),
            ("getStorageLocation", {
                "title": _("Storage Location"),
                "sortable": True,
                "index": "getStorageLocationTitle",
                "toggle": False
            }),
            ("SamplingDeviation", {
                "title": _("Sampling Deviation"),
                "sortable": True,
                "index": "getSamplingDeviationTitle",
                "toggle": False
            }),
            ("getSampler", {
                "title": _("Sampler"),
                "toggle": SamplingWorkflowEnabled
            }),
            ("getPreserver", {
                "title": _("Preserver"),
                "sortable": False,
                "toggle": False
            }),
            ("getProfilesTitle", {
                "title": _("Profile"),
                "sortable": True,
                "index": "getProfilesTitle",
                "toggle": False
            }),
            ("getAnalysesNum", {
                "title": _("Number of Analyses"),
                "sortable": True,
                "index": "getAnalysesNum",
                "toggle": False
            }),
            ("getTemplateTitle", {
                "title": _("Template"),
                "sortable": True,
                "index": "getTemplateTitle",
                "toggle": False
            }),
            ("Printed", {
                "title": _("Printed"),
                "sortable": False,
                "index": "getPrinted",
                "toggle": False
            }),
            ("state_title", {
                "title": _("State"),
                "sortable": True,
                "index": "review_state"
            }),
        ))

        # custom print transition
        print_stickers = {
            "id": "print_stickers",
            "title": _("Print stickers"),
            "url": "workflow_action?action=print_stickers"
        }

        self.review_states = [
            {
                "id":
                "default",
                "title":
                _("Active"),
                "contentFilter": {
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "sample"
                    },
                    {
                        "id": "preserve"
                    },
                    {
                        "id": "receive"
                    },
                    {
                        "id": "retract"
                    },
                    {
                        "id": "verify"
                    },
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "publish"
                    },
                    {
                        "id": "republish"
                    },
                    {
                        "id": "cancel"
                    },
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id":
                "to_be_sampled",
                "title":
                _("To Be Sampled"),
                "contentFilter": {
                    "review_state": ("to_be_sampled", ),
                    "sort_on": "created",
                    "sort_order": "descending"
                },
                "transitions": [
                    {
                        "id": "sample"
                    },
                    {
                        "id": "submit"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys()
            },
            {
                "id": "to_be_preserved",
                "title": _("To Be Preserved"),
                "contentFilter": {
                    "review_state": ("to_be_preserved", ),
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "preserve"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns": self.columns.keys(),
            },
            {
                "id": "scheduled_sampling",
                "title": _("Scheduled sampling"),
                "contentFilter": {
                    "review_state": ("scheduled_sampling", ),
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "sample"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns": self.columns.keys(),
            },
            {
                "id":
                "sample_due",
                "title":
                _("Due"),
                "contentFilter": {
                    "review_state":
                    ("to_be_sampled", "to_be_preserved", "sample_due"),
                    "sort_on":
                    "created",
                    "sort_order":
                    "descending"
                },
                "transitions": [
                    {
                        "id": "sample"
                    },
                    {
                        "id": "preserve"
                    },
                    {
                        "id": "receive"
                    },
                    {
                        "id": "cancel"
                    },
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id":
                "sample_received",
                "title":
                _("Received"),
                "contentFilter": {
                    "review_state": "sample_received",
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "cancel"
                    },
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id":
                "to_be_verified",
                "title":
                _("To be verified"),
                "contentFilter": {
                    "review_state": "to_be_verified",
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "retract"
                    },
                    {
                        "id": "verify"
                    },
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "cancel"
                    },
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id": "verified",
                "title": _("Verified"),
                "contentFilter": {
                    "review_state": "verified",
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "publish"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns": self.columns.keys(),
            },
            {
                "id": "published",
                "title": _("Published"),
                "contentFilter": {
                    "review_state": ("published"),
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "republish"
                    },
                ],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                "id":
                "unpublished",
                "title":
                _("Unpublished"),
                "contentFilter": {
                    "cancellation_state":
                    "active",
                    "review_state": (
                        "sample_registered",
                        "to_be_sampled",
                        "to_be_preserved",
                        "sample_due",
                        "sample_received",
                        "to_be_verified",
                        "attachment_due",
                        "verified",
                    ),
                    "sort_on":
                    "created",
                    "sort_order":
                    "descending",
                },
                "transitions": [
                    {
                        "id": "sample"
                    },
                    {
                        "id": "preserve"
                    },
                    {
                        "id": "receive"
                    },
                    {
                        "id": "retract"
                    },
                    {
                        "id": "verify"
                    },
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "publish"
                    },
                    {
                        "id": "republish"
                    },
                    {
                        "id": "cancel"
                    },
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id": "cancelled",
                "title": _("Cancelled"),
                "contentFilter": {
                    "cancellation_state":
                    "cancelled",
                    "review_state": (
                        "sample_registered",
                        "to_be_sampled",
                        "to_be_preserved",
                        "sample_due",
                        "sample_received",
                        "to_be_verified",
                        "attachment_due",
                        "verified",
                        "published",
                    ),
                    "sort_on":
                    "created",
                    "sort_order":
                    "descending",
                },
                "transitions": [
                    {
                        "id": "reinstate"
                    },
                ],
                "custom_transitions": [],
                "columns": self.columns.keys(),
            },
            {
                "id": "invalid",
                "title": _("Invalid"),
                "contentFilter": {
                    "review_state": "invalid",
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [],
                "custom_transitions": [print_stickers],
                "columns": self.columns.keys(),
            },
            {
                "id":
                "rejected",
                "title":
                _("Rejected"),
                "contentFilter": {
                    "review_state": "rejected",
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [],
                "custom_transitions": [
                    {
                        "id": "print_stickers",
                        "title": _("Print stickers"),
                        "url": "workflow_action?action=print_stickers"
                    },
                ],
                "columns":
                self.columns.keys(),
            },
            {
                "id":
                "assigned",
                "title":
                get_image("assigned.png", title=t(_("Assigned"))),
                "contentFilter": {
                    "assigned_state": "assigned",
                    "cancellation_state": "active",
                    "review_state": (
                        "sample_received",
                        "attachment_due",
                    ),
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "receive"
                    },
                    {
                        "id": "retract"
                    },
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id":
                "unassigned",
                "title":
                get_image("unassigned.png", title=t(_("Unsassigned"))),
                "contentFilter": {
                    "assigned_state": "unassigned",
                    "cancellation_state": "active",
                    "review_state": (
                        "sample_received",
                        "attachment_due",
                    ),
                    "sort_on": "created",
                    "sort_order": "descending",
                },
                "transitions": [
                    {
                        "id": "receive"
                    },
                    {
                        "id": "retract"
                    },
                    {
                        "id": "prepublish"
                    },
                    {
                        "id": "cancel"
                    },
                ],
                "custom_transitions": [print_stickers],
                "columns":
                self.columns.keys(),
            },
            {
                "id": "late",
                "title": get_image("late.png", title=t(_("Late"))),
                "contentFilter": {
                    "cancellation_state":
                    "active",
                    # Query only for unpublished ARs that are late
                    "review_state": (
                        "sample_received",
                        "attachment_due",
                        "to_be_verified",
                        "verified",
                    ),
                    "getDueDate": {
                        "query": DateTime(),
                        "range": "max",
                    },
                    "sort_on":
                    "created",
                    "sort_order":
                    "descending",
                },
                "custom_transitions": [print_stickers],
                "columns": self.columns.keys(),
            }
        ]

    def update(self):
        """Called before the listing renders
        """
        super(AnalysisRequestsView, self).update()

        self.workflow = api.get_tool("portal_workflow")
        self.member = self.mtool.getAuthenticatedMember()
        self.roles = self.member.getRoles()

        setup = api.get_bika_setup()

        # remove `to_be_sampled` filter
        if not setup.getSamplingWorkflowEnabled():
            self.review_states = filter(
                lambda x: x.get("id") != "to_be_sampled", self.review_states)

        # remove `scheduled_sampling` filter
        if not setup.getScheduleSamplingEnabled():
            self.review_states = filter(
                lambda x: x.get("id") != "scheduled_sampling",
                self.review_states)

        # remove `to_be_preserved` filter
        if not setup.getSamplePreservationEnabled():
            self.review_states = filter(
                lambda x: x.get("id") != "to_be_preserved", self.review_states)

        # remove `rejected` filter
        if not setup.getRejectionReasons():
            self.review_states = filter(lambda x: x.get("id") != "rejected",
                                        self.review_states)

        self.hideclientlink = "RegulatoryInspector" in self.roles \
            and "Manager" not in self.roles \
            and "LabManager" not in self.roles \
            and "LabClerk" not in self.roles

        if self.context.portal_type == "AnalysisRequestsFolder" and \
                (self.mtool.checkPermission(AddAnalysisRequest, self.context)):
            self.context_actions[_("Add")] = \
                {"url": "ar_add?ar_count=1",
                 'permission': 'Add portal content',
                 "icon": "++resource++bika.lims.images/add.png"}

        self.editresults = -1
        self.clients = {}
        # self.user_is_preserver = "Preserver" in self.roles
        # Printing workflow enabled?
        # If not, remove the Column
        self.printwfenabled = \
            self.context.bika_setup.getPrintingWorkflowEnabled()
        printed_colname = "Printed"
        if not self.printwfenabled and printed_colname in self.columns:
            # Remove "Printed" columns
            del self.columns[printed_colname]
            tmprvs = []
            for rs in self.review_states:
                tmprs = rs
                tmprs["columns"] = [
                    c for c in rs.get("columns", []) if c != printed_colname
                ]
                tmprvs.append(tmprs)
            self.review_states = tmprvs
        elif self.printwfenabled:
            # Print button to choose multiple ARs and print them.
            review_states = []
            for review_state in self.review_states:
                review_state.get("custom_transitions", []).extend([
                    {
                        "id": "print",
                        "title": _("Print"),
                        "url": "workflow_action?action=print"
                    },
                ])
                review_states.append(review_state)
            self.review_states = review_states

        # Only "BIKA: ManageAnalysisRequests" may see the copy to new button.
        # elsewhere it is hacked in where required.
        if self.copy_to_new_allowed:
            review_states = []
            for review_state in self.review_states:
                review_state.get("custom_transitions", []).extend([
                    {
                        "id": "copy_to_new",
                        "title": _("Copy to new"),
                        "url": "workflow_action?action=copy_to_new"
                    },
                ])
                review_states.append(review_state)
            self.review_states = review_states

        # Hide Preservation/Sampling workflow actions if the edit columns
        # are not displayed.
        toggle_cols = self.get_toggle_cols()
        new_states = []
        for i, state in enumerate(self.review_states):
            if state["id"] == self.review_state:
                if "getSampler" not in toggle_cols \
                   or "getDateSampled" not in toggle_cols:
                    if "hide_transitions" in state:
                        state["hide_transitions"].append("sample")
                    else:
                        state["hide_transitions"] = [
                            "sample",
                        ]
                if "getPreserver" not in toggle_cols \
                   or "getDatePreserved" not in toggle_cols:
                    if "hide_transitions" in state:
                        state["hide_transitions"].append("preserve")
                    else:
                        state["hide_transitions"] = [
                            "preserve",
                        ]
            new_states.append(state)
        self.review_states = new_states

    def before_render(self):
        """Before template render hook
        """
        # If the current user is a client contact, display those analysis
        # requests that belong to same client only
        super(AnalysisRequestsView, self).before_render()
        client = api.get_current_client()
        if client:
            self.contentFilter['path'] = {
                "query": "/".join(client.getPhysicalPath()),
                "level": 0
            }
            # No need to display the Client column
            self.remove_column('Client')

    def isItemAllowed(self, obj):
        """ If Adnvanced Filter bar is enabled, this method checks if the item
        matches advanced filter bar criteria
        """
        return not self.filter_bar_enabled or self.filter_bar_check_item(obj)

    def folderitems(self, full_objects=False, classic=False):
        # We need to get the portal catalog here in roder to save process
        # while iterating over folderitems
        self.portal_catalog = api.get_tool("portal_catalog")
        return BikaListingView.folderitems(self, full_objects, classic)

    def folderitem(self, obj, item, index):
        # Additional info from AnalysisRequest to be added in the item
        # generated by default by bikalisting.
        # Call the folderitem method from the base class
        item = BikaListingView.folderitem(self, obj, item, index)
        if not item:
            return None
        # This variable will contain the full analysis request if there is
        # need to work with the full object instead of the brain
        full_object = None
        item["Creator"] = self.user_fullname(obj.Creator)
        # If we redirect from the folderitems view we should check if the
        # user has permissions to medify the element or not.
        priority_sort_key = obj.getPrioritySortkey
        if not priority_sort_key:
            # Default priority is Medium = 3.
            # The format of PrioritySortKey is <priority>.<created>
            priority_sort_key = "3.%s" % obj.created.ISO8601()
        priority = priority_sort_key.split(".")[0]
        priority_text = PRIORITIES.getValue(priority)
        priority_div = """<div class="priority-ico priority-%s">
                          <span class="notext">%s</span><div>
                       """
        item["replace"]["Priority"] = priority_div % (priority, priority_text)
        item["replace"]["getProfilesTitle"] = obj.getProfilesTitleStr

        analysesnum = obj.getAnalysesNum
        if analysesnum:
            num_verified = str(analysesnum[0])
            num_total = str(analysesnum[1])
            item["getAnalysesNum"] = "{0}/{1}".format(num_verified, num_total)
        else:
            item["getAnalysesNum"] = ""

        # Progress
        num_verified = 0
        num_submitted = 0
        num_total = 0
        if analysesnum and len(analysesnum) > 1:
            num_verified = analysesnum[0]
            num_total = analysesnum[1]
            num_submitted = num_total - num_verified
            if len(analysesnum) > 2:
                num_wo_results = analysesnum[2]
                num_submitted = num_total - num_verified - num_wo_results
        num_steps_total = num_total * 2
        num_steps = (num_verified * 2) + (num_submitted)
        progress_perc = 0
        if num_steps > 0 and num_steps_total > 0:
            progress_perc = (num_steps * 100) / num_steps_total
        progress = '<div class="progress-bar-container">' + \
                   '<div class="progress-bar" style="width:{0}%"></div>' + \
                   '<div class="progress-perc">{0}%</div></div>'
        item["replace"]["Progress"] = progress.format(progress_perc)

        item["BatchID"] = obj.getBatchID
        if obj.getBatchID:
            item['replace']['BatchID'] = "<a href='%s'>%s</a>" % \
                (obj.getBatchURL, obj.getBatchID)
        # TODO: SubGroup ???
        # val = obj.Schema().getField('SubGroup').get(obj)
        # item['SubGroup'] = val.Title() if val else ''

        date = obj.getSamplingDate
        item["SamplingDate"] = \
            self.ulocalized_time(date, long_format=1) if date else ""
        date = obj.getDateReceived
        item["getDateReceived"] = \
            self.ulocalized_time(date, long_format=1) if date else ""
        date = obj.getDueDate
        item["getDueDate"] = \
            self.ulocalized_time(date, long_format=1) if date else ""
        date = obj.getDatePublished
        item["getDatePublished"] = \
            self.ulocalized_time(date, long_format=1) if date else ""
        date = obj.getDateVerified
        item["getDateVerified"] = \
            self.ulocalized_time(date, long_format=1) if date else ""

        if self.printwfenabled:
            item["Printed"] = ""
            printed = obj.getPrinted if hasattr(obj, "getPrinted") else "0"
            print_icon = ""
            if printed == "0":
                print_icon = get_image("delete.png",
                                       title=t(_("Not printed yet")))
            elif printed == "1":
                print_icon = get_image("ok.png", title=t(_("Printed")))
            elif printed == "2":
                print_icon = get_image("exclamation.png",
                                       title=t(
                                           _("Republished after last print")))
            item["after"]["Printed"] = print_icon
        item["SamplingDeviation"] = obj.getSamplingDeviationTitle

        item["getStorageLocation"] = obj.getStorageLocationTitle

        after_icons = ""
        # Getting a dictionary with each workflow id and current state in it
        states_dict = obj.getObjectWorkflowStates
        if obj.assigned_state == 'assigned':
            after_icons += get_image("worksheet.png",
                                     title=t(_("All analyses assigned")))
        if states_dict.get('review_state', '') == 'invalid':
            after_icons += get_image("delete.png",
                                     title=t(_("Results have been withdrawn")))

        due_date = obj.getDueDate
        if due_date and due_date < (obj.getDatePublished or DateTime()):
            due_date_str = self.ulocalized_time(due_date)
            img_title = "{}: {}".format(t(_("Late Analyses")), due_date_str)
            after_icons += get_image("late.png", title=img_title)

        if obj.getSamplingDate and obj.getSamplingDate > DateTime():
            after_icons += get_image("calendar.png",
                                     title=t(_("Future dated sample")))
        if obj.getInvoiceExclude:
            after_icons += get_image("invoice_exclude.png",
                                     title=t(_("Exclude from invoice")))
        if obj.getHazardous:
            after_icons += get_image("hazardous.png", title=t(_("Hazardous")))
        if after_icons:
            item['after']['getId'] = after_icons

        item['Created'] = self.ulocalized_time(obj.created, long_format=1)
        if obj.getContactUID:
            item['ClientContact'] = obj.getContactFullName
            item['replace']['ClientContact'] = "<a href='%s'>%s</a>" % \
                (obj.getContactURL, obj.getContactFullName)
        else:
            item["ClientContact"] = ""
        # TODO-performance: If SamplingWorkflowEnabled, we have to get the
        # full object to check the user permissions, so far this is
        # a performance hit.
        if obj.getSamplingWorkflowEnabled:
            # We don't do anything with Sampling Date.
            # User can modify Sampling date
            # inside AR view. In this listing view,
            # we only let the user to edit Date Sampled
            # and Sampler if he wants to make 'sample' transaction.
            if not obj.getDateSampled:
                datesampled = self.ulocalized_time(DateTime(),
                                                   long_format=True)
                item["class"]["getDateSampled"] = "provisional"
            else:
                datesampled = self.ulocalized_time(obj.getDateSampled,
                                                   long_format=True)

            sampler = obj.getSampler
            if sampler:
                item["replace"]["getSampler"] = obj.getSamplerFullName
            if "Sampler" in self.roles and not sampler:
                sampler = self.member.id
                item["class"]["getSampler"] = "provisional"
            # sampling workflow - inline edits for Sampler and Date Sampled
            if states_dict.get('review_state', '') == 'to_be_sampled':
                # We need to get the full object in order to check
                # the permissions
                full_object = obj.getObject()
                checkPermission =\
                    self.context.portal_membership.checkPermission
                if checkPermission(SampleSample, full_object):
                    item["required"] = ["getSampler", "getDateSampled"]
                    item["allow_edit"] = ["getSampler", "getDateSampled"]
                    # TODO-performance: hit performance while getting the
                    # sample object...
                    # TODO Can LabManagers be a Sampler?!
                    samplers = getUsers(full_object.getSample(), [
                        "Sampler",
                    ])
                    username = self.member.getUserName()
                    users = [({
                        "ResultValue": u,
                        "ResultText": samplers.getValue(u)
                    }) for u in samplers]
                    item['choices'] = {'getSampler': users}
                    Sampler = sampler and sampler or \
                        (username in samplers.keys() and username) or ''
                    sampler = Sampler
                else:
                    datesampled = self.ulocalized_time(obj.getDateSampled,
                                                       long_format=True)
                    sampler = obj.getSamplerFullName if obj.getSampler else ''
        else:
            datesampled = self.ulocalized_time(obj.getDateSampled,
                                               long_format=True)
            sampler = ""
        item["getDateSampled"] = datesampled
        item["getSampler"] = sampler

        # These don't exist on ARs
        # XXX This should be a list of preservers...
        item["getPreserver"] = ""
        item["getDatePreserved"] = ""
        # TODO-performance: If inline preservation wants to be used, we
        # have to get the full object to check the user permissions, so
        # far this is a performance hit.
        # inline edits for Preserver and Date Preserved
        # if checkPermission(PreserveSample, obj):
        #     item['required'] = ['getPreserver', 'getDatePreserved']
        #     item['allow_edit'] = ['getPreserver', 'getDatePreserved']
        #     preservers = getUsers(obj, ['Preserver',
        #                           'LabManager', 'Manager'])
        #     username = self.member.getUserName()
        #     users = [({'ResultValue': u,
        #                'ResultText': preservers.getValue(u)})
        #              for u in preservers]
        #     item['choices'] = {'getPreserver': users}
        #     preserver = username in preservers.keys() and username or ''
        #     item['getPreserver'] = preserver
        #     item['getDatePreserved'] = self.ulocalized_time(
        #         DateTime(),
        #         long_format=1)
        #     item['class']['getPreserver'] = 'provisional'
        #     item['class']['getDatePreserved'] = 'provisional'

        # Submitting user may not verify results
        # Thee conditions to improve performance, some functions to check
        # the condition need to get the full analysis request.
        if states_dict.get("review_state", "") == "to_be_verified":
            allowed = user.has_permission(VerifyPermission,
                                          username=self.member.getUserName())
            # TODO-performance: isUserAllowedToVerify getts all analysis
            # objects inside the analysis request.
            if allowed:
                # Gettin the full object if not get before
                full_object = full_object if full_object else obj.getObject()
                if not full_object.isUserAllowedToVerify(self.member):
                    item["after"]["state_title"] = get_image(
                        "submitted-by-current-user.png",
                        title=t(_("Cannot verify: Submitted by current user")))
        return item

    @property
    def copy_to_new_allowed(self):
        mtool = api.get_tool("portal_membership")
        if mtool.checkPermission(ManageAnalysisRequests, self.context) \
                or mtool.checkPermission(ModifyPortalContent, self.context):
            return True
        return False

    def getFilterBar(self):
        """
        This function creates an instance of BikaListingFilterBar if the
        class has not created one yet.
        :returns: a BikaListingFilterBar instance
        """
        self._advfilterbar = self._advfilterbar if self._advfilterbar else \
            AnalysisRequestsBikaListingFilterBar(
                context=self.context, request=self.request)
        return self._advfilterbar

    def getDefaultAddCount(self):
        return self.context.bika_setup.getDefaultNumberOfARsToAdd()
Пример #49
0
 def _write_body(self):
     response = self.request.response
     body = ViewPageTemplateFile('templates/event_vcal.pt')(self)
     response.setHeader('Content-Type', 'text/vCal')
     response.setHeader('Content-Disposition', 'filename=cmf.vcs')
     response.write(body.encode("UTF-8"))
Пример #50
0
class TilesPageView(BrowserView):
    index = ViewPageTemplateFile("templates/tiles_page_view.pt")

    def __call__(self, **kwargs):
        return self.index()