Exemplo n.º 1
0
 def navtree(self):
     root = self.navtreeitem(None, None, None, '', None)
     model = self.navroot
     # XXX: default child
     path = node_path(self.model)[len(node_path(model)):]
     self.fillchildren(model, path, root)
     return root
Exemplo n.º 2
0
 def navtree(self):
     root = self.navtreeitem(None, None, None, '', None)
     model = self.navroot
     # XXX: default child
     path = node_path(self.model)[len(node_path(model)):]
     self.fillchildren(model, path, root)
     return root
Exemplo n.º 3
0
 def fillchildren(self, model, path, tree):
     """XXX: consider cone.app.interfaces.INavigationLeaf
     """
     curpath = None
     if path:
         curpath = path[0]
     default_child = None
     if model.properties.default_child:
         if not curpath or curpath == model.properties.default_child:
             default_child = model[model.properties.default_child]
     if default_child and default_child.properties.hide_if_default:
         model = default_child
         default_child = None
         if path:
             path = path[1:]
             if path:
                 curpath = path[0]
     if default_child:
         if not curpath:
             curpath = model.properties.default_child
     for key in model:
         node = model[key]
         if not self.request.has_permission('view', node):
             continue
         if not node.properties.get('in_navtree'):
             continue
         title = node.metadata.title
         if title:
             title = safe_decode(title)
         url = make_url(self.request, node=node)
         query = make_query(
             contenttile=node.properties.default_content_tile)
         target = make_url(self.request, node=node, query=query)
         curnode = curpath == safe_decode(key)
         icon = node_icon(node)
         css = ''
         if IWorkflowState.providedBy(node):
             css = 'state-%s' % node.state
         child = self.navtreeitem(title, url, target, node_path(node), icon,
                                  css)
         child['showchildren'] = curnode
         if curnode:
             child['selected'] = True
             if default_child:
                 self.fillchildren(default_child, path[1:], child)
             else:
                 self.fillchildren(node, path[1:], child)
         else:
             selected_path = node_path(self.model)
             if default_child:
                 selected_path.append(default_child.name)
             selected = False
             # XXX: probably superfluous. keep as of cone.app 1.1
             # if selected_path == node_path(node):
             #     selected = True
             child['selected'] = selected
         tree['children'].append(child)
Exemplo n.º 4
0
 def fillchildren(self, model, path, tree):
     """XXX: consider cone.app.interfaces.INavigationLeaf
     """
     curpath = None
     if path:
         curpath = path[0]
     default_child = None
     if model.properties.default_child:
         if not curpath or curpath == model.properties.default_child:
             default_child = model[model.properties.default_child]
     if default_child and default_child.properties.hide_if_default:
         model = default_child
         default_child = None
         if path:
             path = path[1:]
             if path:
                 curpath = path[0]
     if default_child:
         if not curpath:
             curpath = model.properties.default_child
     for key in model:
         node = model[key]
         if not self.request.has_permission('view', node):
             continue
         if not node.properties.get('in_navtree'):
             continue
         title = node.metadata.title
         if title:
             title = safe_decode(title)
         url = make_url(self.request, node=node)
         query = make_query(contenttile=node.properties.default_content_tile)
         target = make_url(self.request, node=node, query=query)
         curnode = curpath == safe_decode(key)
         icon = node_icon(node)
         css = ''
         if IWorkflowState.providedBy(node):
             css = 'state-%s' % node.state
         child = self.navtreeitem(
             title, url, target, node_path(node), icon, css)
         child['showchildren'] = curnode
         if curnode:
             child['selected'] = True
             if default_child:
                 self.fillchildren(default_child, path[1:], child)
             else:
                 self.fillchildren(node, path[1:], child)
         else:
             selected_path = node_path(self.model)
             if default_child:
                 selected_path.append(default_child.name)
             selected = False
             # XXX: probably superfluous. keep as of cone.app 1.1
             # if selected_path == node_path(node):
             #     selected = True
             child['selected'] = selected
         tree['children'].append(child)
Exemplo n.º 5
0
 def menuitems(self):
     ret = list()
     path = node_path(self.model)
     if path:
         curpath = path[0]
     else:
         curpath = ''
     # work with ``self.model.root.keys()``, ``values()`` propably not works
     # due to the use of factory node.
     root = self.model.root
     root_props = root.properties
     # check for default child id if no curpath
     if not curpath and root_props.default_child:
         curpath = root_props.default_child
     # check wether to render mainmenu item title
     empty_title = root_props.mainmenu_empty_title
     # XXX: icons
     for key in root.keys():
         child = root[key]
         props = child.properties
         if self.ignore_node(child, props):
             continue
         selected = curpath == key
         item = self.create_item(child, props, empty_title, selected)
         if props.mainmenu_display_children:
             item['children'] = self.create_children(child, selected)
         else:
             item['children'] = None
         ret.append(item)
     return ret
Exemplo n.º 6
0
 def menuitems(self):
     ret = list()
     path = node_path(self.model)
     if path:
         curpath = path[0]
     else:
         curpath = ''
     # work with ``self.model.root.keys()``, ``values()`` propably not works
     # due to the use of factory node.
     root = self.model.root
     root_props = root.properties
     # check for default child id if no curpath
     if not curpath and root_props.default_child:
         curpath = root_props.default_child
     # check wether to render mainmenu item title
     empty_title = root_props.mainmenu_empty_title
     # XXX: icons
     for key in root.keys():
         child = root[key]
         props = child.properties
         if self.ignore_node(child, props):
             continue
         selected = curpath == key
         item = self.create_item(child, props, empty_title, selected)
         if props.mainmenu_display_children:
             item['children'] = self.create_children(child, selected)
         else:
             item['children'] = None
         ret.append(item)
     return ret
Exemplo n.º 7
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     count = self.table_tile.item_count
     slicesize = self.table_tile.slicesize
     pages = count / slicesize
     if count % slicesize != 0:
         pages += 1
     current = self.request.params.get('b_page', '0')
     params = {
         'sort': self.table_tile.sort_column,
         'order': self.table_tile.sort_order,
         'size': slicesize,
         'term': self.table_tile.filter_term,
     }
     for term in self.table_tile.query_whitelist:
         params[term] = self.request.params.get(term, '')
     for i in range(pages):
         params['b_page'] = str(i)
         query = make_query(**params)
         url = make_url(
             self.request,
             path=path,
             #resource=self.related_view,
             query=query)
         ret.append({
             'page': '%i' % (i + 1),
             'current': current == str(i),
             'visible': True,
             'url': url,
         })
     return ret
Exemplo n.º 8
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     count = self.table_tile.item_count
     slicesize = self.table_tile.slicesize
     pages = count // slicesize
     if count % slicesize != 0:
         pages += 1
     current = self.request.params.get('b_page', '0')
     params = {
         'sort': self.table_tile.sort_column,
         'order': self.table_tile.sort_order,
         'size': slicesize,
         'term': self.table_tile.filter_term,
     }
     for term in self.table_tile.query_whitelist:
         params[term] = self.request.params.get(term, '')
     for i in range(pages):
         params['b_page'] = str(i)
         query = make_query(**params)
         url = make_url(
             self.request,
             path=path,
             # resource=self.related_view,
             query=query
         )
         ret.append({
             'page': '%i' % (i + 1),
             'current': current == str(i),
             'visible': True,
             'url': url,
         })
     return ret
Exemplo n.º 9
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     current = self.request.params.get('b_page', '0')
     for i in range(10):
         query = make_query(b_page=str(i))
         url = make_url(self.request, path=path, query=query)
         ret.append({
             'page': '%i' % i,
             'current': current == str(i),
             'visible': True,
             'url': url
         })
     return ret
Exemplo n.º 10
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     current = self.request.params.get('b_page', '0')
     for i in range(10):
         query = make_query(b_page=str(i))
         url = make_url(self.request, path=path, query=query)
         ret.append({
             'page': '%i' % i,
             'current': current == str(i),
             'visible': True,
             'url': url
         })
     return ret
Exemplo n.º 11
0
 def create_children(self, node, selected):
     children = list()
     path = node_path(self.model)
     if path and len(path) > 1 and path[0] == node.name:
         curpath = path[1]
     else:
         curpath = ''
     for key in node.keys():
         child = node[key]
         props = child.properties
         if self.ignore_node(child, props):
             continue
         selected = curpath == key
         item = self.create_item(child, props, False, selected)
         children.append(item)
     return children
Exemplo n.º 12
0
 def create_children(self, node, selected):
     children = list()
     path = node_path(self.model)
     if path and len(path) > 1 and path[0] == node.name:
         curpath = path[1]
     else:
         curpath = ''
     for key in node.keys():
         child = node[key]
         props = child.properties
         if self.ignore_node(child, props):
             continue
         selected = curpath == key
         item = self.create_item(child, props, False, selected)
         children.append(item)
     return children
Exemplo n.º 13
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     current = self.request.params.get('b_page', '0')
     for i in range(10):
         query = make_query(b_page=str(i))
         href = make_url(self.request,
                         path=path,
                         resource='someview',
                         query=query)
         target = make_url(self.request, path=path, query=query)
         ret.append({
             'page': '%i' % i,
             'current': current == str(i),
             'visible': True,
             'href': href,
             'target': target,
         })
     return ret
Exemplo n.º 14
0
 def vocab(self):
     ret = list()
     path = node_path(self.model)
     current = self.request.params.get('b_page', '0')
     for i in range(10):
         query = make_query(b_page=str(i))
         href = make_url(
             self.request,
             path=path,
             resource='someview',
             query=query
         )
         target = make_url(self.request, path=path, query=query)
         ret.append({
             'page': '%i' % i,
             'current': current == str(i),
             'visible': True,
             'href': href,
             'target': target,
         })
     return ret
Exemplo n.º 15
0
 def vocab(self):
     """Batch vocabulary.
     """
     ret = list()
     path = node_path(self.model)
     count = self.parent.item_count
     slice_size = self.parent.slice_size
     pages = count / slice_size
     if count % slice_size != 0:
         pages += 1
     current = self.parent.current_page
     for i in range(pages):
         href = self.parent.make_page_url(path, str(i), include_view=True)
         target = self.parent.make_page_url(path, str(i))
         ret.append({
             'page': '%i' % (i + 1),
             'current': current == i,
             'visible': True,
             'href': href,
             'target': target
         })
     return ret
Exemplo n.º 16
0
 def vocab(self):
     """Batch vocabulary.
     """
     ret = list()
     path = node_path(self.model)
     count = self.parent.item_count
     slice_size = self.parent.slice_size
     pages = count // slice_size
     if count % slice_size != 0:
         pages += 1
     current = self.parent.current_page
     for i in range(pages):
         href = self.parent.make_page_url(path, str(i), include_view=True)
         target = self.parent.make_page_url(path, str(i))
         ret.append({
             'page': '%i' % (i + 1),
             'current': current == i,
             'visible': True,
             'href': href,
             'target': target
         })
     return ret
Exemplo n.º 17
0
    def next(self, request):
        """Read ``came_from`` parameter from request and compute next URL.

        If ``came_from`` not found on request, ``default_came_from`` property
        is used.

        If ``came_from`` is special value ``parent``, URL of model parent is
        computed.

        If ``came_from`` is set, it is considered as URL to use. The given URL
        must match the basic application URL, otherwise an error gets logged
        and URL of current model is computed.

        If ``came_from`` is set to empty value, URL of current model is
        computed.
        """
        # read came_from from request
        came_from = request.get('came_from')
        # fall back to default_came_from if came_from not passed on request
        if came_from is None:
            came_from = self.default_came_from
        # use model URL and path if no came_from
        if not came_from:
            url = make_url(request.request, node=self.model)
            path = '/'.join(node_path(self.model))
        # use model parent URL and path if came_from is 'parent'
        elif came_from == 'parent':
            url = make_url(request.request, node=self.model.parent)
            path = '/'.join(node_path(self.model.parent))
        # consider came_from a URL
        else:
            url = compat.unquote(came_from)
            parsed = compat.urlparse.urlparse(url)
            app_loc = compat.urlparse.urlparse(
                self.request.application_url).netloc
            # behave as if no came_from given if application location not
            # matches came_from location
            if app_loc != parsed.netloc:
                logger.error(
                    ('CameFromNext.next(): Application location "{}" does not '
                     'match came_from location "{}". Use model for URL '
                     'computing instead').format(app_loc, parsed.netloc))
                url = make_url(request.request, node=self.model)
                path = '/'.join(node_path(self.model))
            # include query to path
            elif parsed.query:
                path = '{}?{}'.format(parsed.path, parsed.query)
            # query without path
            else:
                path = '{}'.format(parsed.path)
        # ajax continuation definitions if ajax request
        if self.ajax_request:
            event = AjaxEvent(url, 'contextchanged', '#layout')
            # return continuation path and event if browser history should be
            # written
            if self.write_history_on_next:
                cpath = AjaxPath(path,
                                 target=url,
                                 event='contextchanged:#layout')
                return [cpath, event]
            # return event only if writing browser history should be skipped
            return [event]
        # regular redirection if no ajax request
        return HTTPFound(location=url)
Exemplo n.º 18
0
    def test_BatchedItems(self):
        # Concrete ``BatchedItems`` implementation.
        class MyBatchedItems(BatchedItems):
            slice_template = 'cone.app.testing:dummy_batched_items.pt'

            @property
            def item_count(self):
                return len(self.filtered_items)

            @property
            def slice_items(self):
                start, end = self.current_slice
                return self.filtered_items[start:end]

            @property
            def filtered_items(self):
                items = list()
                term = self.filter_term
                term = term.lower() if term else term
                for node in self.model.values():
                    if term and node.name.find(term) == -1:
                        continue
                    items.append(node)
                return items

        # Create model
        model = BaseNode(name='container')
        for i in range(35):
            model['child_{}'.format(i)] = BaseNode()

        # Create batched items with model
        batched_items = MyBatchedItems()
        batched_items.model = model
        batched_items.request = self.layer.new_request()

        # The helper function ``make_query`` considers ``query_whitelist`` and
        # is used for query creation within batched items implementation.
        self.assertEqual(batched_items.query_whitelist, [])

        batched_items.query_whitelist = ['a', 'b']
        batched_items.request.params['a'] = 'a'

        self.assertEqual(batched_items.make_query({'c': 'c'}), '?a=a&b=&c=c')

        # A query parameter which already exists on request gets overwritten
        self.assertEqual(batched_items.make_query({'a': 'b'}), '?a=b&b=')

        # The helper function ``make_url`` uses ``make_query``, thus considers
        # ``query_whitelist`` as well and is used for URL creation within
        # batched items implementation.
        self.assertEqual(
            batched_items.make_url(dict(c='c')),
            u'http://example.com/container?a=a&b=&c=c'
        )

        # It's also possible to pass a model path to ``make_url`` to avoid
        # multiple computing of model path
        path = node_path(model)
        self.assertEqual(
            batched_items.make_url(dict(c='c'), path=path),
            u'http://example.com/container?a=a&b=&c=c'
        )

        # ``BatchedItems`` plumbs ``RelatedViewConsumer`` and considers
        # ``related_view`` if ``include_view`` passed to ``make_url``
        request = batched_items.request = self.layer.new_request()
        set_related_view(request, 'someview')

        self.assertEqual(
            batched_items.make_url(dict(c='c')),
            u'http://example.com/container?a=&b=&c=c'
        )
        self.assertEqual(
            batched_items.make_url(dict(c='c'), include_view=True),
            u'http://example.com/container/someview?a=&b=&c=c'
        )
        self.assertEqual(
            batched_items.make_url(dict(c='c'), path=path),
            u'http://example.com/container?a=&b=&c=c'
        )
        self.assertEqual(
            batched_items.make_url(dict(c='c'), path=path, include_view=True),
            u'http://example.com/container/someview?a=&b=&c=c'
        )

        # Default slice size
        self.assertEqual(batched_items.default_slice_size, 15)
        # Current slice size
        self.assertEqual(batched_items.slice_size, 15)
        # Number of available slice slizes
        self.assertEqual(batched_items.num_slice_sizes, 4)
        # Available slice sizes for slice size selection
        self.assertEqual(batched_items.slice_sizes, [15, 30, 45, 60])

        batched_items.default_slice_size = 10
        batched_items.num_slice_sizes = 5
        self.assertEqual(batched_items.slice_sizes, [10, 20, 30, 40, 50])

        batched_items.default_slice_size = 15
        batched_items.num_slice_sizes = 4

        # Test ``slice_target``
        self.assertEqual(batched_items.query_whitelist, ['a', 'b'])

        request = batched_items.request = self.layer.new_request()
        request.params['a'] = 'a'
        request.params['b'] = 'b'
        request.params['term'] = 'Hello'

        self.assertEqual(batched_items.filter_term, u'Hello')
        self.assertEqual(
            batched_items.slice_target,
            u'http://example.com/container?a=a&b=b&term=Hello'
        )

        # Test ``filter_target``
        self.assertEqual(
            batched_items.filter_target,
            u'http://example.com/container?a=a&b=b&size=15'
        )

        request.params['size'] = '30'
        self.assertEqual(
            batched_items.filter_target,
            u'http://example.com/container?a=a&b=b&size=30'
        )

        # Header template path
        self.assertEqual(
            batched_items.header_template,
            'cone.app.browser:templates/batched_items_header.pt'
        )

        # Rendered header
        self.checkOutput("""
        ...<div class="panel-heading batched_items_header">...
        """, batched_items.rendered_header)

        # Header title. Taken from ``model.metadata`` by default
        self.assertEqual(batched_items.title, 'container')

        # Title can be skipped by setting ``show_title`` to False
        expected = '<span class="label label-primary">container</span>'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_title = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_title = True

        # Slice size can be skipped by setting ``show_slice_size`` to False
        expected = '<select name="size"'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_slice_size = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_slice_size = True

        # CSS class set on slice size selection wrapper
        expected = 'col-xs-4 col-sm3'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.slice_size_css = 'col-xs-3 col-sm2'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.slice_size_css = 'col-xs-4 col-sm3'

        # Flag whether to show search filter
        expected = '<input name="term"'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_filter = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_filter = True

        # CSS class set on slice search filter
        expected = 'col-xs-3'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.filter_css = 'col-xs-4'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.filter_css = 'col-xs-3'

        # Additional markup displayed in header
        expected = '<div class="additional">Additional</div>'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.head_additional = expected
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.head_additional = None

        # Batched items pagination. Pagination object is provided by
        # ``pagination`` property on ``BatchedItems``
        request = self.layer.new_request()
        set_related_view(request, 'someview')

        batched_items = MyBatchedItems()
        batched_items.model = BaseNode(name='container')
        batched_items.request = request

        pagination = batched_items.pagination
        self.assertTrue(isinstance(pagination, BatchedItemsBatch))

        pagination.model = batched_items.model
        pagination.request = batched_items.request

        # Pagination batch uses ``page_target`` on ``BatchedItems`` for target
        # URL computing.
        path = node_path(batched_items.model)
        page = '1'
        self.assertEqual(
            batched_items.page_target(path, page),
            u'http://example.com/container?b_page=1&size=15'
        )

        # Pagination batch name is created from batched items ``items_id``
        self.assertEqual(batched_items.items_id, 'batched_items')
        self.assertEqual(pagination.name, 'batched_itemsbatch')

        # Pagination batch only gets displayed if there are batched items.
        self.assertEqual(batched_items.item_count, 0)
        self.assertFalse(pagination.display)
        self.assertEqual(pagination.vocab, [])

        batched_items.model = pagination.model = model
        self.assertEqual(batched_items.item_count, 35)
        self.assertTrue(pagination.display)
        self.assertEqual(batched_items.current_page, 0)

        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_page, 1)

        vocab = pagination.vocab
        self.assertEqual(len(vocab), 3)

        self.assertEqual(sorted(vocab[0].items()), [
            ('current', False),
            ('href', u'http://example.com/container/someview?b_page=0&size=15'),
            ('page', '1'),
            ('target', u'http://example.com/container?b_page=0&size=15'),
            ('visible', True)
        ])
        self.assertEqual(sorted(vocab[1].items()), [
            ('current', True),
            ('href', u'http://example.com/container/someview?b_page=1&size=15'),
            ('page', '2'),
            ('target', u'http://example.com/container?b_page=1&size=15'),
            ('visible', True)
        ])
        self.assertEqual(sorted(vocab[2].items()), [
            ('current', False),
            ('href', u'http://example.com/container/someview?b_page=2&size=15'),
            ('page', '3'),
            ('target', u'http://example.com/container?b_page=2&size=15'),
            ('visible', True)
        ])

        # Rendered pagination
        self.checkOutput("""
        ...<ul class="pagination pagination-sm">...
        """, batched_items.rendered_pagination)

        # Batched items footer
        batched_items = MyBatchedItems()
        batched_items.model = model
        batched_items.request = self.layer.new_request()

        # Default template path
        self.assertEqual(
            batched_items.footer_template,
            'cone.app.browser:templates/batched_items_footer.pt'
        )
        self.checkOutput("""
        ...<div class="panel-footer batched_items_footer">...
        """, batched_items.rendered_footer)

        # Slice ID
        self.assertEqual(batched_items.slice_id, 'batched_items_slice')

        # Current slice to display as tuple
        self.assertEqual(batched_items.current_slice, (0, 15))

        # Overall item count
        self.assertEqual(batched_items.item_count, 35)

        # Current slice items
        self.checkOutput("""
        [<BaseNode object 'child_0' at ...>,
        ...
        <BaseNode object 'child_14' at ...>]
        """, str(batched_items.slice_items))

        # Chage current page and check again
        request = batched_items.request = self.layer.new_request()
        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_slice, (15, 30))
        self.checkOutput("""
        [<BaseNode object 'child_15' at ...>,
        ...
        <BaseNode object 'child_29' at ...>]
        """, str(batched_items.slice_items))

        # Change the slice size
        request = batched_items.request = self.layer.new_request()
        request.params['size'] = '10'
        self.assertEqual(batched_items.slice_size, 10)
        self.assertEqual(batched_items.current_slice, (0, 10))
        self.checkOutput("""
        [<BaseNode object 'child_0' at ...>,
        ...
        <BaseNode object 'child_9' at ...>]
        """, str(batched_items.slice_items))

        # Change the filter term
        request = batched_items.request = self.layer.new_request()
        request.params['term'] = '1'
        request.params['size'] = '5'
        self.assertEqual(batched_items.filter_term, u'1')

        self.checkOutput("""
        [<BaseNode object 'child_1' at ...>,
        <BaseNode object 'child_10' at ...>,
        <BaseNode object 'child_11' at ...>,
        <BaseNode object 'child_12' at ...>,
        <BaseNode object 'child_13' at ...>,
        <BaseNode object 'child_14' at ...>,
        <BaseNode object 'child_15' at ...>,
        <BaseNode object 'child_16' at ...>,
        <BaseNode object 'child_17' at ...>,
        <BaseNode object 'child_18' at ...>,
        <BaseNode object 'child_19' at ...>,
        <BaseNode object 'child_21' at ...>,
        <BaseNode object 'child_31' at ...>]
        """, str(batched_items.filtered_items))

        self.assertEqual(batched_items.current_slice, (0, 5))

        self.checkOutput("""
        [<BaseNode object 'child_1' at ...>,
        <BaseNode object 'child_10' at ...>,
        <BaseNode object 'child_11' at ...>,
        <BaseNode object 'child_12' at ...>,
        <BaseNode object 'child_13' at ...>]
        """, str(batched_items.slice_items))

        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_slice, (5, 10))

        self.checkOutput("""
        [<BaseNode object 'child_14' at ...>,
        <BaseNode object 'child_15' at ...>,
        <BaseNode object 'child_16' at ...>,
        <BaseNode object 'child_17' at ...>,
        <BaseNode object 'child_18' at ...>]
        """, str(batched_items.slice_items))

        # Test ``rendered_slice``
        request = batched_items.request = self.layer.new_request()
        self.checkOutput("""
        <div id="batched_items_slice">
          <div>child_0</div>
          ...
          <div>child_14</div>
        </div>
        """, batched_items.rendered_slice)

        # ``BatchItems`` rendering default template
        self.assertEqual(
            batched_items.path,
            'cone.app.browser:templates/batched_items.pt'
        )

        # Batched items DOM element ID. Used for bdajax binding.
        self.assertEqual(batched_items.items_id, 'batched_items')

        self.checkOutput("""
        ...<div id="batched_items"...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_id = 'my_batched_items'

        self.checkOutput("""
        ...<div id="my_batched_items"...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_id = 'batched_items'

        # Test ``items_css``
        self.assertEqual(
            batched_items.items_css,
            'batched_items panel panel-default'
        )

        self.checkOutput("""
        ...class="...batched_items ...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_css = (
            'my_batched_items batched_items panel panel-default'
        )

        self.checkOutput("""
        ...class="...my_batched_items batched_items ...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_css = 'batched_items panel panel-default'

        # Test ``bind_events``
        self.assertEqual(batched_items.bind_events, 'batchclicked')

        self.checkOutput("""
        ...ajax:bind="batchclicked"...
        """, batched_items(model=model, request=self.layer.new_request()))

        # Test ``bind_selectors``
        self.assertEqual(
            batched_items.bind_selectors,
            'batched_itemsbatchsensitiv'
        )

        self.checkOutput("""
        ...class="batched_itemsbatchsensitiv...
        """, batched_items(model=model, request=self.layer.new_request()))

        # Test ``display_header``
        self.assertTrue(batched_items.display_header)

        expected = '<div class="panel-heading batched_items_header">'
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertTrue(rendered.find(expected) > -1)

        batched_items.display_header = False
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertFalse(rendered.find(expected) > -1)

        batched_items.display_header = True

        # Test ``display_footer``
        self.assertTrue(batched_items.display_header)

        expected = '<div class="panel-footer batched_items_footer">'
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertTrue(rendered.find(expected) > -1)

        batched_items.display_footer = False
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertFalse(rendered.find(expected) > -1)
Exemplo n.º 19
0
    def next(self, request):
        """Read ``came_from`` parameter from request and compute next URL.

        If ``came_from`` not found on request, ``default_came_from`` property
        is used.

        If ``came_from`` is special value ``parent``, URL of model parent is
        computed.

        If ``came_from`` is set, it is considered as URL to use. The given URL
        must match the basic application URL, otherwise an error gets logged
        and URL of current model is computed.

        If ``came_from`` is set to empty value, URL of current model is
        computed.
        """
        # read came_from from request
        came_from = request.get('came_from')
        # fall back to default_came_from if came_from not passed on request
        if came_from is None:
            came_from = self.default_came_from
        # use model URL and path if no came_from
        if not came_from:
            url = make_url(request.request, node=self.model)
            path = '/'.join(node_path(self.model))
        # use model parent URL and path if came_from is 'parent'
        elif came_from == 'parent':
            url = make_url(request.request, node=self.model.parent)
            path = '/'.join(node_path(self.model.parent))
        # consider came_from a URL
        else:
            url = compat.unquote(came_from)
            parsed = compat.urlparse.urlparse(url)
            app_loc = compat.urlparse.urlparse(
                self.request.application_url
            ).netloc
            # behave as if no came_from given if application location not
            # matches came_from location
            if app_loc != parsed.netloc:
                logger.error((
                    'CameFromNext.next(): Application location "{}" does not '
                    'match came_from location "{}". Use model for URL '
                    'computing instead'
                ).format(app_loc, parsed.netloc))
                url = make_url(request.request, node=self.model)
                path = '/'.join(node_path(self.model))
            # include query to path
            elif parsed.query:
                path = '{}?{}'.format(parsed.path, parsed.query)
            # query without path
            else:
                path = '{}'.format(parsed.path)
        # ajax continuation definitions if ajax request
        if self.ajax_request:
            event = AjaxEvent(url, 'contextchanged', '#layout')
            # return continuation path and event if browser history should be
            # written
            if self.write_history_on_next:
                cpath = AjaxPath(
                    path,
                    target=url,
                    event='contextchanged:#layout'
                )
                return [cpath, event]
            # return event only if writing browser history should be skipped
            return [event]
        # regular redirection if no ajax request
        return HTTPFound(location=url)
Exemplo n.º 20
0
    def test_BatchedItems(self):
        # Concrete ``BatchedItems`` implementation.
        class MyBatchedItems(BatchedItems):
            slice_template = 'cone.app.testing:dummy_batched_items.pt'

            @property
            def item_count(self):
                return len(self.filtered_items)

            @property
            def slice_items(self):
                start, end = self.current_slice
                return self.filtered_items[start:end]

            @property
            def filtered_items(self):
                items = list()
                term = self.filter_term
                term = term.lower() if term else term
                for node in self.model.values():
                    if term and node.name.find(term) == -1:
                        continue
                    items.append(node)
                return items

        # Create model
        model = BaseNode(name='container')
        for i in range(35):
            model['child_{}'.format(i)] = BaseNode()

        # Create batched items with model
        batched_items = MyBatchedItems()
        batched_items.model = model
        batched_items.request = self.layer.new_request()

        # The helper function ``make_query`` considers ``query_whitelist`` and
        # is used for query creation within batched items implementation.
        self.assertEqual(batched_items.query_whitelist, [])

        batched_items.query_whitelist = ['a', 'b']
        batched_items.request.params['a'] = 'a'

        self.assertEqual(batched_items.make_query({'c': 'c'}), '?a=a&b=&c=c')

        # A query parameter which already exists on request gets overwritten
        self.assertEqual(batched_items.make_query({'a': 'b'}), '?a=b&b=')

        # The helper function ``make_url`` uses ``make_query``, thus considers
        # ``query_whitelist`` as well and is used for URL creation within
        # batched items implementation.
        self.assertEqual(batched_items.make_url(dict(c='c')),
                         u'http://example.com/container?a=a&b=&c=c')

        # It's also possible to pass a model path to ``make_url`` to avoid
        # multiple computing of model path
        path = node_path(model)
        self.assertEqual(batched_items.make_url(dict(c='c'), path=path),
                         u'http://example.com/container?a=a&b=&c=c')

        # ``BatchedItems`` plumbs ``RelatedViewConsumer`` and considers
        # ``related_view`` if ``include_view`` passed to ``make_url``
        request = batched_items.request = self.layer.new_request()
        set_related_view(request, 'someview')

        self.assertEqual(batched_items.make_url(dict(c='c')),
                         u'http://example.com/container?a=&b=&c=c')
        self.assertEqual(
            batched_items.make_url(dict(c='c'), include_view=True),
            u'http://example.com/container/someview?a=&b=&c=c')
        self.assertEqual(batched_items.make_url(dict(c='c'), path=path),
                         u'http://example.com/container?a=&b=&c=c')
        self.assertEqual(
            batched_items.make_url(dict(c='c'), path=path, include_view=True),
            u'http://example.com/container/someview?a=&b=&c=c')

        # Default slice size
        self.assertEqual(batched_items.default_slice_size, 15)
        # Current slice size
        self.assertEqual(batched_items.slice_size, 15)
        # Number of available slice slizes
        self.assertEqual(batched_items.num_slice_sizes, 4)
        # Available slice sizes for slice size selection
        self.assertEqual(batched_items.slice_sizes, [15, 30, 45, 60])

        batched_items.default_slice_size = 10
        batched_items.num_slice_sizes = 5
        self.assertEqual(batched_items.slice_sizes, [10, 20, 30, 40, 50])

        batched_items.default_slice_size = 15
        batched_items.num_slice_sizes = 4

        # Test ``slice_target``
        self.assertEqual(batched_items.query_whitelist, ['a', 'b'])

        request = batched_items.request = self.layer.new_request()
        request.params['a'] = 'a'
        request.params['b'] = 'b'
        request.params['term'] = 'Hello'

        self.assertEqual(batched_items.filter_term, u'Hello')
        self.assertEqual(batched_items.slice_target,
                         u'http://example.com/container?a=a&b=b&term=Hello')

        # Test ``filter_target``
        self.assertEqual(batched_items.filter_target,
                         u'http://example.com/container?a=a&b=b&size=15')

        request.params['size'] = '30'
        self.assertEqual(batched_items.filter_target,
                         u'http://example.com/container?a=a&b=b&size=30')

        # Header template path
        self.assertEqual(batched_items.header_template,
                         'cone.app.browser:templates/batched_items_header.pt')

        # Rendered header
        self.checkOutput(
            """
        ...<div class="panel-heading batched_items_header">...
        """, batched_items.rendered_header)

        # Header title. Taken from ``model.metadata`` by default
        self.assertEqual(batched_items.title, 'container')

        # Title can be skipped by setting ``show_title`` to False
        expected = '<span class="label label-primary">container</span>'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_title = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_title = True

        # Slice size can be skipped by setting ``show_slice_size`` to False
        expected = '<select name="size"'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_slice_size = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_slice_size = True

        # CSS class set on slice size selection wrapper
        expected = 'col-xs-4 col-sm3'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.slice_size_css = 'col-xs-3 col-sm2'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.slice_size_css = 'col-xs-4 col-sm3'

        # Flag whether to show search filter
        expected = '<input name="term"'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_filter = False
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.show_filter = True

        # CSS class set on slice search filter
        expected = 'col-xs-3'
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.filter_css = 'col-xs-4'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.filter_css = 'col-xs-3'

        # Additional markup displayed in header
        expected = '<div class="additional">Additional</div>'
        self.assertFalse(batched_items.rendered_header.find(expected) > -1)

        batched_items.head_additional = expected
        self.assertTrue(batched_items.rendered_header.find(expected) > -1)

        batched_items.head_additional = None

        # Batched items pagination. Pagination object is provided by
        # ``pagination`` property on ``BatchedItems``
        request = self.layer.new_request()
        set_related_view(request, 'someview')

        batched_items = MyBatchedItems()
        batched_items.model = BaseNode(name='container')
        batched_items.request = request

        pagination = batched_items.pagination
        self.assertTrue(isinstance(pagination, BatchedItemsBatch))

        pagination.model = batched_items.model
        pagination.request = batched_items.request

        # Pagination batch uses ``page_target`` on ``BatchedItems`` for target
        # URL computing.
        path = node_path(batched_items.model)
        page = '1'
        self.assertEqual(batched_items.page_target(path, page),
                         u'http://example.com/container?b_page=1&size=15')

        # Pagination batch name is created from batched items ``items_id``
        self.assertEqual(batched_items.items_id, 'batched_items')
        self.assertEqual(pagination.name, 'batched_itemsbatch')

        # Pagination batch only gets displayed if there are batched items.
        self.assertEqual(batched_items.item_count, 0)
        self.assertFalse(pagination.display)
        self.assertEqual(pagination.vocab, [])

        batched_items.model = pagination.model = model
        self.assertEqual(batched_items.item_count, 35)
        self.assertTrue(pagination.display)
        self.assertEqual(batched_items.current_page, 0)

        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_page, 1)

        vocab = pagination.vocab
        self.assertEqual(len(vocab), 3)

        self.assertEqual(
            sorted(vocab[0].items()),
            [('current', False),
             ('href',
              u'http://example.com/container/someview?b_page=0&size=15'),
             ('page', '1'),
             ('target', u'http://example.com/container?b_page=0&size=15'),
             ('visible', True)])
        self.assertEqual(
            sorted(vocab[1].items()),
            [('current', True),
             ('href',
              u'http://example.com/container/someview?b_page=1&size=15'),
             ('page', '2'),
             ('target', u'http://example.com/container?b_page=1&size=15'),
             ('visible', True)])
        self.assertEqual(
            sorted(vocab[2].items()),
            [('current', False),
             ('href',
              u'http://example.com/container/someview?b_page=2&size=15'),
             ('page', '3'),
             ('target', u'http://example.com/container?b_page=2&size=15'),
             ('visible', True)])

        # Rendered pagination
        self.checkOutput(
            """
        ...<ul class="pagination pagination-sm">...
        """, batched_items.rendered_pagination)

        # Batched items footer
        batched_items = MyBatchedItems()
        batched_items.model = model
        batched_items.request = self.layer.new_request()

        # Default template path
        self.assertEqual(batched_items.footer_template,
                         'cone.app.browser:templates/batched_items_footer.pt')
        self.checkOutput(
            """
        ...<div class="panel-footer batched_items_footer">...
        """, batched_items.rendered_footer)

        # Slice ID
        self.assertEqual(batched_items.slice_id, 'batched_items_slice')

        # Current slice to display as tuple
        self.assertEqual(batched_items.current_slice, (0, 15))

        # Overall item count
        self.assertEqual(batched_items.item_count, 35)

        # Current slice items
        self.checkOutput(
            """
        [<BaseNode object 'child_0' at ...>,
        ...
        <BaseNode object 'child_14' at ...>]
        """, str(batched_items.slice_items))

        # Chage current page and check again
        request = batched_items.request = self.layer.new_request()
        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_slice, (15, 30))
        self.checkOutput(
            """
        [<BaseNode object 'child_15' at ...>,
        ...
        <BaseNode object 'child_29' at ...>]
        """, str(batched_items.slice_items))

        # Change the slice size
        request = batched_items.request = self.layer.new_request()
        request.params['size'] = '10'
        self.assertEqual(batched_items.slice_size, 10)
        self.assertEqual(batched_items.current_slice, (0, 10))
        self.checkOutput(
            """
        [<BaseNode object 'child_0' at ...>,
        ...
        <BaseNode object 'child_9' at ...>]
        """, str(batched_items.slice_items))

        # Change the filter term
        request = batched_items.request = self.layer.new_request()
        request.params['term'] = '1'
        request.params['size'] = '5'
        self.assertEqual(batched_items.filter_term, u'1')

        self.checkOutput(
            """
        [<BaseNode object 'child_1' at ...>,
        <BaseNode object 'child_10' at ...>,
        <BaseNode object 'child_11' at ...>,
        <BaseNode object 'child_12' at ...>,
        <BaseNode object 'child_13' at ...>,
        <BaseNode object 'child_14' at ...>,
        <BaseNode object 'child_15' at ...>,
        <BaseNode object 'child_16' at ...>,
        <BaseNode object 'child_17' at ...>,
        <BaseNode object 'child_18' at ...>,
        <BaseNode object 'child_19' at ...>,
        <BaseNode object 'child_21' at ...>,
        <BaseNode object 'child_31' at ...>]
        """, str(batched_items.filtered_items))

        self.assertEqual(batched_items.current_slice, (0, 5))

        self.checkOutput(
            """
        [<BaseNode object 'child_1' at ...>,
        <BaseNode object 'child_10' at ...>,
        <BaseNode object 'child_11' at ...>,
        <BaseNode object 'child_12' at ...>,
        <BaseNode object 'child_13' at ...>]
        """, str(batched_items.slice_items))

        request.params['b_page'] = '1'
        self.assertEqual(batched_items.current_slice, (5, 10))

        self.checkOutput(
            """
        [<BaseNode object 'child_14' at ...>,
        <BaseNode object 'child_15' at ...>,
        <BaseNode object 'child_16' at ...>,
        <BaseNode object 'child_17' at ...>,
        <BaseNode object 'child_18' at ...>]
        """, str(batched_items.slice_items))

        # Test ``rendered_slice``
        request = batched_items.request = self.layer.new_request()
        self.checkOutput(
            """
        <div id="batched_items_slice">
          <div>child_0</div>
          ...
          <div>child_14</div>
        </div>
        """, batched_items.rendered_slice)

        # ``BatchItems`` rendering default template
        self.assertEqual(batched_items.path,
                         'cone.app.browser:templates/batched_items.pt')

        # Batched items DOM element ID. Used for bdajax binding.
        self.assertEqual(batched_items.items_id, 'batched_items')

        self.checkOutput(
            """
        ...<div id="batched_items"...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_id = 'my_batched_items'

        self.checkOutput(
            """
        ...<div id="my_batched_items"...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_id = 'batched_items'

        # Test ``items_css``
        self.assertEqual(batched_items.items_css,
                         'batched_items panel panel-default')

        self.checkOutput(
            """
        ...class="...batched_items ...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_css = (
            'my_batched_items batched_items panel panel-default')

        self.checkOutput(
            """
        ...class="...my_batched_items batched_items ...
        """, batched_items(model=model, request=self.layer.new_request()))

        batched_items.items_css = 'batched_items panel panel-default'

        # Test ``bind_events``
        self.assertEqual(batched_items.bind_events, 'batchclicked')

        self.checkOutput(
            """
        ...ajax:bind="batchclicked"...
        """, batched_items(model=model, request=self.layer.new_request()))

        # Test ``bind_selectors``
        self.assertEqual(batched_items.bind_selectors,
                         'batched_itemsbatchsensitiv')

        self.checkOutput(
            """
        ...class="batched_itemsbatchsensitiv...
        """, batched_items(model=model, request=self.layer.new_request()))

        # Test ``display_header``
        self.assertTrue(batched_items.display_header)

        expected = '<div class="panel-heading batched_items_header">'
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertTrue(rendered.find(expected) > -1)

        batched_items.display_header = False
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertFalse(rendered.find(expected) > -1)

        batched_items.display_header = True

        # Test ``display_footer``
        self.assertTrue(batched_items.display_header)

        expected = '<div class="panel-footer batched_items_footer">'
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertTrue(rendered.find(expected) > -1)

        batched_items.display_footer = False
        rendered = batched_items(model=model, request=self.layer.new_request())
        self.assertFalse(rendered.find(expected) > -1)
Exemplo n.º 21
0
 def test_node_path(self):
     root = BaseNode()
     root['child'] = BaseNode()
     self.assertEqual(node_path(root['child']), [u'child'])
Exemplo n.º 22
0
 def test_node_path(self):
     root = BaseNode()
     root['child'] = BaseNode()
     self.assertEqual(node_path(root['child']), [u'child'])