products/CPSRSS

changeset 247:56b98a8dd994

now able to set the list of activated channels on current doc
author Georges Racinet on purity.racinet.fr <georges@racinet.fr>
date Mon, 06 Dec 2010 09:22:16 +0100
parents 6b024ed7b935
children 6514f2a16d9b
files browser/channels.py browser/configure.zcml browser/manage_channels.pt tests/test_views.py
diffstat 4 files changed, 75 insertions(+), 24 deletions(-) [+]
line diff
     1.1 --- a/browser/channels.py
     1.2 +++ b/browser/channels.py
     1.3 @@ -42,6 +42,17 @@
     1.4  DEFAULT_RSS_ITEM_DISPLAY = 'cpsportlet_rssitem_display'
     1.5  
     1.6  class ManageChannels(AqSafeBrowserView):
     1.7 +    """This view class serves as a view mostly for local channels.
     1.8 +
     1.9 +    It does the container lookup, and provides interface to the container.
    1.10 +    It also maintains the list of channels to be rendered on context proxy,
    1.11 +    and provides the rendering logic.
    1.12 +
    1.13 +    Some options make it possible for the regular portlet to call it as well,
    1.14 +    by forcing the container.
    1.15 +    This is still experimental, and will likely evolve in something
    1.16 +    more uniform, in which the portlet can also render local channels.
    1.17 +    """
    1.18  
    1.19      security = ClassSecurityInfo()
    1.20  
    1.21 @@ -68,11 +79,19 @@
    1.22      def hasContainer(self):
    1.23          return self.aqSafeGet('container') is not None
    1.24  
    1.25 -    def channels(self):
    1.26 +    def channels(self, with_activation=True):
    1.27          cont = self.aqSafeGet('container')
    1.28          if cont is None:
    1.29              return ()
    1.30 -        return cont.objectValues([RSSChannel.meta_type])
    1.31 +        proxy = self.context
    1.32 +        channels = cont.objectValues([RSSChannel.meta_type])
    1.33 +        if not with_activation:
    1.34 +            return channels
    1.35 +
    1.36 +        dm = proxy.getContent().getDataModel(proxy=proxy)
    1.37 +        activated = dm.get('channels', ())
    1.38 +        return tuple(dict(channel=chan, activated=chan.getId() in activated)
    1.39 +                     for chan in channels)
    1.40  
    1.41      # traditional security declaration is necessary for browser:view,
    1.42      # and further in current Five 1.3.2 takes precedence over zcml
    1.43 @@ -163,6 +182,23 @@
    1.44  
    1.45          return data_items
    1.46  
    1.47 +    def setActivated(self):
    1.48 +        """Set the list of activated channels."""
    1.49 +        activated = self.request.form['activated']
    1.50 +        proxy = self.context
    1.51 +        doc = proxy.getEditableContent()
    1.52 +        dm = doc.getDataModel(proxy=proxy)
    1.53 +        if not 'channels' in dm:
    1.54 +            raise RuntimeError(
    1.55 +                "Document type %r lacks fields for channels management",
    1.56 +                doc.portal_type)
    1.57 +
    1.58 +        available = set(chan.getId()
    1.59 +                        for chan in self.channels(with_activation=False))
    1.60 +        dm['channels'] = [cid for cid in activated if cid in available]
    1.61 +        dm._commit()
    1.62 +        self.redirectManageChannels()
    1.63 +
    1.64      def redirectManageChannels(self):
    1.65          self.request.RESPONSE.redirect('/'.join((
    1.66                  self.context.absolute_url_path(), 'manage_channels.html')))
     2.1 --- a/browser/configure.zcml
     2.2 +++ b/browser/configure.zcml
     2.3 @@ -20,6 +20,14 @@
     2.4  
     2.5    <browser:page
     2.6      for="Products.CPSCore.interfaces.ICPSProxy"
     2.7 +    name="set_activated"
     2.8 +    permission="cps.rss.ManageChannels"
     2.9 +    class=".browser.channels.ManageChannels"
    2.10 +    attribute="setActivated"
    2.11 +    />
    2.12 +
    2.13 +  <browser:page
    2.14 +    for="Products.CPSCore.interfaces.ICPSProxy"
    2.15      name="refresh_channels"
    2.16      permission="cps.rss.ManageChannels"
    2.17      class=".browser.channels.ManageChannels"
     3.1 --- a/browser/manage_channels.pt
     3.2 +++ b/browser/manage_channels.pt
     3.3 @@ -14,41 +14,48 @@
     3.4        i18n:translate="manage_rss_channels_no_channel">
     3.5      Il n'y a pas encore de flux RSS &agrave; cet emplacement.
     3.6     </p>
     3.7 +
     3.8     <tal:block condition="channels">
     3.9      <h2 i18n:translate="manage_rss_channels_available">Flux disponibles</h2>
    3.10 -    <ul>
    3.11 -     <li tal:repeat="channel channels">
    3.12 -       <a tal:content="channel/title"
    3.13 -          tal:attributes="href string:${channel/absolute_url_path}/edit.html">
    3.14 -       </a>
    3.15 -       <p tal:content="channel/description"/>
    3.16 -     </li>
    3.17 -    </ul>
    3.18 +    <form action="set_activated" encoding="multipart-form-data"
    3.19 +          method="post">
    3.20 +     <ul>
    3.21 +      <li tal:repeat="channel_info channels">
    3.22 +       <tal:block define="channel nocall:channel_info/channel">
    3.23 +        <input name="activated:list" type="checkbox"
    3.24 +               tal:attributes="value channel/getId;
    3.25 +                               checked channel_info/activated;"/>
    3.26 +        <a tal:content="channel/title"
    3.27 +           tal:attributes="href string:${channel/absolute_url_path}/edit.html"
    3.28 +           />
    3.29 +        <p tal:content="channel/description"/>
    3.30 +       </tal:block>
    3.31 +      </li>
    3.32 +     </ul>
    3.33 +     <input type="submit" class="standalone" value="activer/desactiver"
    3.34 +            name="submit"/>
    3.35 +    </form>
    3.36     </tal:block>
    3.37  
    3.38     <h2 i18n:translate="manage_rss_channels_add_channel">Ajouter un flux</h2>
    3.39 -   <p>
    3.40 -    <form action="add_channel" enctype="multipart/form-data" method="post">
    3.41 -     <label for="new_channel_url"
    3.42 -            i18n:translate="manage_rss_channels_new_url">
    3.43 +   <form action="add_channel" enctype="multipart/form-data" method="post">
    3.44 +    <label for="new_channel_url"
    3.45 +           i18n:translate="manage_rss_channels_new_url">
    3.46        Adresse du flux (URL)
    3.47        <input id="new_channel_url" name="url" type="text" width="60" />
    3.48        <br/>
    3.49        <input type="submit" value="button_ok" name="add" class="standalone"
    3.50               i18n:attributes="value" />
    3.51 -      </label>
    3.52 +    </label>
    3.53       </form>
    3.54 -   </p>
    3.55  
    3.56     <h2 i18n:translate="manage_rss_channels_refresh">
    3.57      Mettre &agrave; jour tous les flux
    3.58     </h2>
    3.59 -   <p>
    3.60 -    <form action="refresh_channels" method="post">
    3.61 -      <input type="submit" value="button_ok" name="add" class="standalone"
    3.62 -             i18n:attributes="value" />
    3.63 -     </form>
    3.64 -   </p>
    3.65 +   <form action="refresh_channels" method="post">
    3.66 +    <input type="submit" value="button_ok" name="add" class="standalone"
    3.67 +           i18n:attributes="value" />
    3.68 +   </form>
    3.69    </metal:main>
    3.70  
    3.71   </body>
     4.1 --- a/tests/test_views.py
     4.2 +++ b/tests/test_views.py
     4.3 @@ -59,7 +59,7 @@
     4.4          # call the view API and present channels as dicts for easy assert
     4.5          # why staticmethod ? for fun
     4.6          return tuple(dict(id=chan.getId(), title=chan.title)
     4.7 -                     for chan in view.channels())
     4.8 +                     for chan in view.channels(with_activation=False))
     4.9  
    4.10      def test_channels(self):
    4.11          view = self.makeView()
    4.12 @@ -89,7 +89,7 @@
    4.13          view.addChannel(url=get_feed_url('zope.rss'))
    4.14  
    4.15          # low level url change
    4.16 -        channel = view.channels()[0]
    4.17 +        channel = view.channels(with_activation=False)[0]
    4.18          channel.channel_url = get_feed_url('trac_cps.rss')
    4.19          # before refresh
    4.20          self.assertEquals(channel.title, 'Zope.org')