Metadata-Version: 1.1
Name: collective.listingviews
Version: 1.0beta3
Summary: Listing views
Home-page: http://github.com/collective/collective.listingviews
Author: Pretaweb
Author-email: support@pretaweb.com
License: GPL
Description: .. contents::
        
        Introduction
        ============
        
        .. image:: https://secure.travis-ci.org/collective/collective.listingviews.png
            :target: http://travis-ci.org/collective/collective.listingviews
        
        ``collective.listingviews`` allows a Plone site administrator to create
        new views through the web.  They can use this to:
        
        - create custom views of folders or collections that include metadata and
          content from contained or matching items;
        - create custom listing portlets with additional information such as
          lead images, publication dates or authors;
        - create listing views with subqueries or python via `TAL expressions`_;
        - create additional views of non-folderish content items, showing other aspects of the
          content;
        - create portlets to display information about the current item such as last
          updated date, or even the whole content replacing plugins like ItemViewPortlet;
        - create carousel portlets which pull content or images from collections or
          folders and apply javascript to them, replacing collective.carousel are related
          plugins;
        - create custom listings for ``eea.facetednavigation``;
        
        Listing Views are designed to be simple to create quickly on a Plone site
        and avoid the complexity of creating custom page templates or overridden
        views for many common cases.
        
        View definitions are created inside the Plone Site setup by TTW developers. 
        Content editors can apply the views to content items via the
        ``Display Menu`` for content or in a ``Listing View Portlet`` for portlets 
        (and in the future in a ``Content Listing Tile``).
        
        The HTML markup used by the view is simple and designed to be easily adapted
        to your needs using CSS or Diazo. Each view consists of:
        
        - a definition list of fields of the target or context content item;
        - a list of definition lists of fields for each the listed items if the
          target or context is a folder, or collection;
        - unique CSS classes for the lists and each field type.
        
        By default Fields that can make up a ListingView are :
        
        - Any Metadata fields stored in the catalog (e.g. Title, Effective Date)
        - Some Metadata fields with formatting applied (e.g. Title (Link), Effective Date (Date & Time))
        - Any custom TAL expressions
        
        Worked Examples
        ===============
        
        
        Creating a custom field
        -----------------------
        
        Let's say have a design that demands that has a folder displaying the publication date for each item.
        
        Most of this can be achieved using diazo and css however the publication date isn't in any of Plone's default listing
        views.
        Previously you would have to dig into Plone's code base, find it's folder template implementation and then
        use ``jbot`` or ``ZCML`` template overrides to customise the folder listing template.
        Not only will you need to learn about TAL, python, packaging and deployment but the end result will make your site
        harder to upgrade. Any future enhancements in Plone's folder template will have to be merged back into your patched
        overriden template.
        
        Instead here is how you do it using a ListingView.
        
        First we need to create a custom field using TAL since we want a custom date format rather than Plones default.
        A TAL Expression like the following will work.
        
        >>> tal = "python:item.effective.strftime('%d/%m/%Y') if item.EffectiveDate != 'None' else '' "
        
        - Go to ``Site Setup > Listing Custom Fields > Add``
        - The ``Id`` is unique and is also used as a CSS class in the final html
        - The ``Title`` is what the editor picks from the ``Display Menu`` or in the ``ListingView Portlet``
        - Finally the TAL Expression that is evaluated when showing the field. ``item`` is the catalog brain.
          ``object`` or ``here`` is the context object. Below is the TAL we are going to use.
        
        >>> browser = layer['manager']
        >>> browser.getLink('Site Setup').click()
        >>> browser.getLink('Listing Custom Fields').click()
        >>> browser.getControl('Add').click()
        >>> browser.getControl('Id').value = "pubdate"
        >>> browser.getControl('Title').value = "Local Publication Date"
        >>> browser.getControl('TAL expression').value = tal
        >>> browser.getControl('Save').click()
        
        
        Creating a listing view
        -----------------------
        
        Now that we've created our custom field we can add a new Listing View via
        ``Site Setup > Listing View > Add``.
        
        >>> browser.getLink('Site Setup').click()
        >>> browser.getLink('Listing View').click()
        >>> browser.getControl('Add').click()
        
        There are two kinds of information a listing view display. Information about the context object called
        ``Item Fields`` and information about the contents or matched items called ``Listing Fields``.
        These fields come from either standard metadata or the custom fields we add.
        
        >>> print '\n'.join( browser.getControl('Title', index=1).control.displayOptions )
        Creation Date (Date)
        Creation Date (Date & Time)
        Creator
        Description
        Effective Date (Date)
        Effective Date (Date & Time)
        End Date (Date)
        End Date (Date & Time)
        Expiration Date (Date)
        Expiration Date (Date & Time)
        Short Name
        Short Name (Link)
        Size
        Location
        Modification Date (Date)
        Modification Date (Date & Time)
        State
        Start Date (Date)
        Start Date (Date & Time)
        Tags
        Title
        Title (Link)
        Total number of comments
        Item Type
        Local Publication Date (Custom)
        
        By default the view will be enabled for standard content types. These are
        
        >>> options = browser.getControl('Page').control.displayOptions
        >>> options = [o for o in options if 'old-style' not in o]
        >>> print '\n'.join( options )
        Collection
        Comment
        Event
        File
        Folder
        Image
        Link
        News Item
        Page
        
        In this case we'll create a view called ``News with publication``.
        For the context object we'll show
        
         - ``Title``
        
        for each of the content items
        
         - ``Title``
         - ``Title (Link)``
         - ``Effective Date``
         - ``Local Publication Date``
        
        and finally we'll enable the view for all content types
        
        >>> browser.getControl('Id').value = "pubnews"
        >>> browser.getControl('Title', index=0).value = "News with publication"
        >>> layer.setInAndOut(browser, ['Title'], index=1)
        >>> layer.setInAndOut(browser, ['Title', 'Title (Link)', 'Effective Date (Date)', 'Local Publication Date (Custom)'], index=3)
        >>> layer.setInAndOut(browser, browser.getControl('Page').control.displayOptions, index=0 )
        >>> browser.getControl('Add').click()
        
        We can manage our existing listing views including a link to edit the view we just created.
        
        >>> browser.getLink('pubnews')
        <Link text='pubnews' url='http://nohost/plone/listingviews_controlpanel/pubnews'>
        
        Using a listing view on a folder
        --------------------------------
        
        We have a ``folder1`` with some pages in including a Page called ``item1``.
        Using the ``Display > News with publication`` menu we will change the folder view to
        ``News with publication`` view we created.
        
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('item1')
        <Link text='item1' url='http://nohost/plone/folder1/item1'>
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('News with publication').click()
        >>> browser.contents
        '...View changed...'
        
        
        You will now have a listing that contains all the information you need.
        We have
        
        - a definition for the fields of the folder (the context item)
        - an unordered list of definition lists for every item contained in the folder.
        
          - the title of ``item1``
          - a title made into a link to ``item1``
          - the ``EffectiveDate`` using Plone's default Date format
          - and finally our custom version of the effective date
        
        Note the html is in exactly the same order as we specifed in our view definition
        
        
        >>> print browser.contents
        <...
              <div class="listing-item-fields">
                <dl class="pubnews-item item-fields">
                      <dt class="listing-field field-Title">Title</dt>
                      <dd class="listing-field field-Title">folder1</dd>
                </dl>
              </div>
        ...
        >>> print browser.contents
        <...
              <ul class="pubnews-listing listing-items-view">
                  <li class="listing-item">
                      <dl class="listing-fields">
                      ...
                      </dl>
                  </li>
              </ul>
        ...
        >>> print browser.contents
        <...
        <dt class="listing-field field-Title">Title</dt>
        <dd class="listing-field field-Title">item1</dd>
        ...
        >>> print browser.contents
        <...
        <dt class="listing-field field-Title-tolink">Title</dt>
        <dd class="listing-field field-Title-tolink"><a href="http://nohost/plone/folder1/item1">item1</a></dd>
        ...
        >>> print browser.contents
        <...
        <dt class="listing-field field-EffectiveDate-localshort">Effective Date</dt>
        <dd class="listing-field field-EffectiveDate-localshort">..., ...</dd>
        ...
        >>> print browser.contents
        <...
        <dt class="listing-field pubdate">Local Publication Date</dt>
        <dd class="listing-field pubdate">.../.../...</dd>
        ...
        >>> print browser.contents
        <...
        <dt class="listing-field field-Title">Title</dt>
        ...
        <dt class="listing-field field-Title-tolink">Title</dt>
        ...
        <dt class="listing-field field-EffectiveDate-localshort">Effective Date</dt>
        ...
        <dt class="listing-field pubdate">Local Publication Date</dt>
        ...
        
        
        The styling of this view is very basic. With ``Diazo`` we can turn this into a much nicer looking view by
        matching against the CSS class ``pubnews-listing``::
        
            <replace css:content="ul.pubnews-listing">
                <xsl:for-each select="./li[contains(@class, 'listing-item')]">
                    <div class="span8">
                        <div class="headline">
                            <xsl:element name="a">
                                <xsl:attribute name="href"><xsl:value-of select="./dl/dd[contains(@class, 'field-location')]"/></xsl:attribute>
                                <xsl:value-of select="./dl/dd[contains(@class, 'field-Title')]"/>
                            </xsl:element>
                        </div>
                        <div id="publishedDets1" class="publishDate">Published <xsl:value-of select="./dl/dd[contains(@class, 'custom-date')]"/></div>
                        <div class="description"><xsl:value-of select="./dl/dd[contains(@class, 'field-Description')]"/></div>
                        <div class="newsLink">
                            <xsl:element name="a">
                                <xsl:attribute name="href"><xsl:value-of select="./dl/dd[contains(@class, 'field-location')]"/></xsl:attribute>
                                <xsl:text>Read Full Article</xsl:text>
                            </xsl:element>
                        </div>
                    </div>
                </xsl:for-each>
            </replace>
        
        
        Adding publication date to a Page using a portlet
        -------------------------------------------------
        
        We can use the same custom publication date field when viewing Page items.
        
        We'll create a new Listing View
        called ``Publication Info``, .
        add ``Local Publication Date`` to the 'item' fields, rather than the listing fields.
        
        Finally we only want this to be applied to a Page content type
        
        >>> browser.getLink('Site Setup').click()
        >>> browser.getLink('Listing View').click()
        >>> browser.getControl('Add').click()
        >>> browser.getControl('Id').value = "pubnewsitem"
        >>> browser.getControl('Title', index=0).value = "Publication Info"
        >>> layer.setInAndOut(browser, ['Local Publication Date (Custom)'], index=0)
        >>> layer.setInAndOut(browser, ['Page'])
        >>> browser.getControl('Add').click()
        
        
        Go to your  folder where all the pages are located
        and
        
        1. Add a ``ListingView Portlet`` portlet to the left side using ``Manage porlets``.
        2. Enter ``Publication Info`` as the Portlet header.
        3. Select ``Publication Info`` as the ``Listing views``.
        4. Leave ``Target`` target blank as you want portlet to show information of the current item. Click ``Save``.
        
        Alternatively you can also add the portlet as a Content Type portlet which also ensures it will only be shown only when
        viewing this content type. (e.g. ``Site Setup > Types > News Item > Manage Portlets assigned to this content type``).
        
        >>> browser.getLink('Home').click()
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('Manage portlets').click()
        >>> browser.getControl('ListingView Portlet', index=1).click()
        >>> layer.getFormFromControl(browser.getControl('ListingView Portlet', index=1)).submit()
        >>> browser.getControl('Portlet header').value = 'Publication Info'
        >>> browser.getControl('Publication Info').click()
        >>> browser.getControl('Save').click()
        
        
        Now whenever you view a news item you will get a portlet on the left hand side.
        We can see
        
        - a portlet with the heading ``Publication Info``.
        - Our portlet shows data about the context item (in this case item1)
        - and because item1 has no contents we have an empty list in the listing part of the portlet.
        
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('item1').click()
        >>> print browser.contents
        <...
            <dl class="portlet portletListing portlet-listing-publication-info">
            ...
            </dl>
        ...
        >>> print browser.contents
        <...
            <dt class="portletHeader">
                <span class="portletTopLeft"></span>
                <span>
                   Publication Info
                </span>
                <span class="portletTopRight"></span>
            </dt>
        ...
        >>> print browser.contents
        <...
          <div class="listing-item-fields-portlet">
              <dl class="pubnewsitem-item item-fields">
                          <dt class="listing-field pubdate">Local Publication Date</dt>
                          <dd class="listing-field pubdate">.../.../...</dd>
                    </dl>
          </div>
        ...
        >>> print browser.contents
        <...
            <ul class="pubnewsitem-listing listing-items-view">
            </ul>
        ...
        
        Using the diazo mockup and rules.xml to change the final design we can move the publication date below the title
        and remove the portlet completely::
        
            <drop content-children="//dl[contains(@class, 'portlet-listing-news-item')]" />
            <replace css:content="#parent-fieldname-title" if-content="//dl[contains(@class, 'portlet-listing-news-item')]" >
                <xsl:copy-of select="." />
                <div id="publishedDets" class="publishDate">Published <xsl:value-of select="//dl[contains(@class, 'portlet-listing-news-item')]//dd[contains(@class, 'custom-date')]"/></div>
            </replace>
        
        
        Because we restricted which types the view can be applied to we won't see the portlet on the folder.
        We also aren't able to select that view from the display menu because this is a folder not a Page.
        
        >>> browser.getLink('folder1').click()
        >>> 'portlet-listing-news-item-info' in browser.contents
        False
        >>> 'There was an error while rendering the portlet' in browser.contents
        False
        >>> browser.getLink('Publication Info')
        Traceback (most recent call last):
        ...
        LinkNotFoundError
        
        
        Item View on content
        --------------------
        
        We are also able to select our ``Publication Info`` view as a view for the ``item1`` main content as well
        via the ``Display > Publication Info`` menu.
        
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('item1').click()
        >>> browser.getLink('Publication Info')
        <Link text='Publication Info' url='.../folder1/item1/selectViewTemplate?templateId=collective.listingviews.pubnewsitem'>
        
        
        Item View portlet for fixed item
        --------------------------------
        It's also possible to fix a portlet to show information on particular item instead of the current content context.
        Edit the portlet and search for ``item1`` in the ``Target`` Field.
        
        >>> browser.getLink('Manage portlets').click()
        >>> browser.getLink('Publication Info').click()
        >>> browser.getControl('Save').mech_form.new_control('text','form.root', {'value':'/folder1/item1'})
        >>> browser.getControl('Save').click()
        
        #TODO show what happens if we pick an item of invalid type
        
        We will now see the portlet at the folder level
        
        >>> browser.getLink('folder1').click()
        >>> print browser.contents
        <...
          <div class="listing-item-fields-portlet">
              <dl class="pubnewsitem-item item-fields">
                  <dt class="listing-field pubdate">Local Publication Date</dt>
                  <dd class="listing-field pubdate">.../.../...</dd>
              </dl>
          </div>
        ...
        
        Listing Views for collections
        -----------------------------
        
        We have create a collection in our folder1 called collection1
        
        >>> browser.getLink('folder1').click()
        >>> browser.getLink('collection1').click()
        >>> browser.getLink('item1')
        <Link text='item1' url='http://nohost/plone/folder1/item1'>
        
        Switch to our publication view
        
        Select ``Display > 'News with publication'``.
        
        >>> browser.getLink('collection1').click()
        >>> browser.getLink('News with publication').click()
        >>> browser.contents
        '...View changed...'
        
        And we'll still see item1
        and our custom field
        
        >>> browser.getLink('item1')
        <Link text='item1' url='http://nohost/plone/folder1/item1'>
        >>> print browser.contents
        <...
        <dt class="listing-field pubdate">Local Publication Date</dt>
        <dd class="listing-field pubdate">.../.../...</dd>
        ...
        
        
        Collection Portlets
        -------------------
        
        We can also create a portlet on the home page listing the contents of this collection
        
        On the home page we have no link to item1
        
        >>> browser.getLink('Home').click()
        >>> browser.getLink('item1')
        Traceback (most recent call last):
        ...
        LinkNotFoundError
        
        We'll create a portlet to give us links.
        Give the portlet a header.
        We have a choice of Listing Views to pick from.
        Select ``News with publication`` as the ``Listing views``.
        We can select a specific collection to display by searching by
        name for ``collection1`` in the ``Target`` field.
        
        >>> browser.getLink('Manage portlets').click()
        >>> browser.getControl('ListingView Portlet', index=1).click()
        >>> layer.getFormFromControl(browser.getControl('ListingView Portlet', index=1)).submit()
        >>> browser.getControl('Portlet header').value = 'Collection Portlet'
        >>> browser.getControl('Listing views').displayOptions
        ['(nothing selected)', 'News with publication', 'Publication Info']
        >>> browser.getControl('News with publication').click()
        >>> browser.getControl('Save').mech_form.new_control('text','form.root', {'value':'/folder1/collection1'})
        >>> browser.getControl('Save').click()
        
        New when we view home we  see the items inside ``folder1` based on criteria in ``collection1``, so we'll see
        a link to the ``item1``
        
        >>> browser.getLink('Home').click()
        >>> browser.getLink('item1')
        <Link text='item1' url='http://nohost/plone/folder1/item1'>
        
        
        Example: News listing in table view
        -----------------------------------
        
        Let's say have a design that demands that has a news folder that displays the publication date for each news item in table form.
        
        We just copy our listing view and give it a new class. Add the following to your diazo rules.xml to turn the plain view into a table::
        
            <replace css:content="ul.listing-items-view">
                <table>
                    <tr>
                        <th><xsl:value-of select="./li[contains(@class, 'listing-item')][1]/dl/dt[contains(@class, 'field-Title')]"/></th>
                        <th><xsl:value-of select="./li[contains(@class, 'listing-item')][1]/dl/dt[contains(@class, 'custom-date')]"/></th>
                        <th><xsl:value-of select="./li[contains(@class, 'listing-item')][1]/dl/dt[contains(@class, 'field-Description')]"/></th>
                    </tr>
                    <xsl:for-each select="./li[contains(@class, 'listing-item')]">
                        <tr>
                            <td>
                                <xsl:element name="a">
                                    <xsl:attribute name="href"><xsl:value-of select="./dl/dd[contains(@class, 'field-location')]"/></xsl:attribute>
                                    <xsl:value-of select="./dl/dd[contains(@class, 'field-Title')]"/>
                                </xsl:element>
                            </td>
                            <td>
                                <p id="publishedDets1" class="publishDate">Published <xsl:value-of select="./dl/dd[contains(@class, 'custom-date')]"/></p>
                            </td>
                            <td>
                                <p class="description"><xsl:value-of select="./dl/dd[contains(@class, 'field-Description')]"/></p>
                            </td>
                        </tr>
                    </xsl:for-each>
                </table>
            </replace>
        
        
        
        
        
        
        Contributing
        ============
        
        ``collective.listingviews`` is an initial attempt to create a Plone plugin
        that is flexible yet simple to understand.  To make it even more useful we
        need feedback and pull requests to enable it to replace custom Page
        Templates in more cases, while keeping it easy to understand.
        
        Development is at http://github.com/collective/collective.listingviews
        
        Initial development was funded by `PretaWeb`_.
        
        We have some ideas on where this could go:
        
        - Safe HTML filtering for all fields. Currently not implemented.
        - Support `plone.app.contentlistingtile`_ for Deco or ``collective.cover``.
          ``contentlistingtile`` allows custom views to be selected so this should
          be simple.
        - Support `plone.app.collection`_. Currently only old-style collections
          are supported.
        - Preview view as ZPT. This provides a way to learn ZPT and a base to start
          from when more complex views are needed.
        - Debug custom fields. Allow selection of content to test fields quickly.
        - Migration of views. Provide a way to make bulk changes in content from one
          listingview to another listingview. This would allow a new "template" to
          be created and tested and then switched in production.
        - Support customisation of batching settings.
        - Allow GET requests so that the list can act as a custom search listing
          page.
        - Support grouping.
        - Support hierarchical listing. Allow navigation portlets, sitemaps with
          additional fields. Maybe different kind of views?  Maybe allow views to be
          used as fields within other views?
        - Support AJAX batching and infinite lists (auto-load next when scrolled
          down).
        - Reuse TAL on different fields. The TAL becomes a formatter function
          instead of a field; e.g. convert date or turn Title into link.  Functions
          let you select with fields they apply to, or apply to whole item (i.e.
          custom field).
        - Pre-calculate custom fields, i.e. add them to catalog metadata.
        
        .. _plone.app.contentlistingtile: https://github.com/plone/plone.app.contentlistingtile
        .. _plone.app.collection: https://github.com/plone/plone.app.collection
        .. _PretaWeb: http://www.pretaweb.com
        .. _TAL expressions: http://developer.plone.org/functionality/expressions.html
        
        Changelog
        =========
        
        1.0beta3 (2013-09-11)
        ---------------------
        
        - fix import of getSite to work with Plone 4.3
        
        1.0beta2 (2013-01-31)
        ---------------------
        - fixed bug where can set dynamic view for 'Discussion Item' [Dylan Jay]
        
        1.0beta1 (2013-01-30)
        ---------------------
        
        - Renamed TAL attributes. object->item (catalog metadata), context->object [Dylan Jay]
        - Functional tests [Dylan Jay]
        - Use CRUD z3cform framework and autoform so make easier to use and easier to replace widgets  [Dylan Jay]
        - Make "Restricted to types" work [Dylan Jay]
        - Add date and link filters  [Dylan Jay]
        - Views appear in display menu directly [Dylan Jay]
        
        1.0alpha1 (unreleased)
        ----------------------
        
        - Refactor to support eea.facetednavigation [Dylan Jay]
        - Precompile TAL expressions before loop [Dylan Jay]
        - Initial version [Ivan Teoh]
        - Package created using templer [Ivan Teoh]
        
        
Keywords: Plone Python TTW
Platform: UNKNOWN
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 4.2
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development :: Libraries :: Python Modules
