def put_bundle(new_bundle_name, original_bundle_name=None):
    """Puts a new ResourceBundle, optionally copying from another bundle."""
    new_bundle = ResourceBundle(key_name=new_bundle_name)
    entities = [new_bundle]
    if original_bundle_name:
        original_bundle = ResourceBundle.get_by_key_name(original_bundle_name)
        original_resources = Resource.all().ancestor(original_bundle)
        entities += [Resource(parent=new_bundle,
                              key_name=resource.key().name(),
                              cache_seconds=resource.cache_seconds,
                              content=resource.content)
                     for resource in original_resources]
    db.put(entities)
def put_bundle(new_bundle_name, original_bundle_name=None):
    """Puts a new ResourceBundle, optionally copying from another bundle."""
    new_bundle = ResourceBundle(key_name=new_bundle_name)
    entities = [new_bundle]
    if original_bundle_name:
        original_bundle = ResourceBundle.get_by_key_name(original_bundle_name)
        original_resources = Resource.all().ancestor(original_bundle)
        entities += [Resource(parent=new_bundle,
                              key_name=resource.key().name(),
                              cache_seconds=resource.cache_seconds,
                              content=resource.content)
                     for resource in original_resources]
    db.put(entities)
    def test_admin_resources(self):
        # Verify that the bundle listing loads.
        doc = self.go_as_admin('/global/admin/resources')

        # Add a new bundle (redirects to the new bundle's resource listing).
        doc = self.s.submit(doc.cssselect('form')[-1], resource_bundle='xyz')
        assert doc.cssselect_one('a.sel').text == 'Bundle: xyz'
        bundle = ResourceBundle.get_by_key_name('xyz')
        assert bundle

        # Add a resource (redirects to the resource's edit page).
        doc = self.s.submit(doc.cssselect('form')[0], resource_name='abc')
        assert doc.cssselect_one('a.sel').text == 'Resource: abc'

        # The new Resource shouldn't exist in the datastore until it is saved.
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Enter some content for the resource.
        doc = self.s.submit(doc.cssselect('form')[0], content='pqr')
        assert Resource.get_by_key_name('abc', parent=bundle).content == 'pqr'

        # Use the breadcrumb navigation bar to go back to the resource listing.
        doc = self.s.follow('Bundle: xyz')

        # Add a localized variant of the resource.
        row = doc.xpath_one('//tr[td[normalize-space(.)="abc"]]')
        doc = self.s.submit(row.cssselect('form')[0], resource_lang='pl')
        assert doc.cssselect_one('a.sel').text == 'pl: Polish'

        # Enter some content for the localized resource.
        doc = self.s.submit(doc.cssselect('form')[0], content='jk')
        assert Resource.get_by_key_name('abc:pl',
                                        parent=bundle).content == 'jk'

        # Confirm that both the generic and localized resource are listed.
        doc = self.s.follow('Bundle: xyz')
        resource_texts = [a.text for a in doc.cssselect('a.resource')]
        assert 'abc' in resource_texts
        assert 'pl' in resource_texts

        # Copy all the resources to a new bundle.
        doc = self.s.submit(doc.cssselect('form')[-1],
                            resource_bundle='zzz',
                            resource_bundle_original='xyz')
        parent = ResourceBundle.get_by_key_name('zzz')
        assert Resource.get_by_key_name('abc', parent=parent).content == 'pqr'
        assert Resource.get_by_key_name('abc:pl',
                                        parent=parent).content == 'jk'

        # Verify that we can't add a resource to the default bundle.
        bundle = ResourceBundle.get_by_key_name('1')
        assert (bundle)
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.follow('1 (default)')
        self.s.submit(doc.cssselect('form')[0], resource_name='abc')
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Verify that we can't edit a resource in the default bundle.
        self.s.back()
        doc = self.s.follow('base.html.template')
        self.s.submit(doc.cssselect('form')[0], content='xyz')
        assert not Resource.get_by_key_name('base.html.template',
                                            parent=bundle)

        # Verify that we can't copy resources into the default bundle.
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.follow('xyz')
        doc = self.s.submit(doc.cssselect('form')[-1],
                            resource_bundle='1',
                            resource_bundle_original='xyz')
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Switch the default bundle version.
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.submit(doc.cssselect('form')[0],
                            resource_bundle_default='xyz')
        assert 'xyz (default)' in doc.text
        # Undo.
        doc = self.s.submit(doc.cssselect('form')[0],
                            resource_bundle_default='1')
        assert '1 (default)' in doc.text
    def list_resources(self, bundle_name, editable):
        """Displays a list of the resources in a bundle."""
        bundle = ResourceBundle.get_by_key_name(bundle_name)
        editable_class = editable and 'editable' or 'readonly'

        langs_by_name = {}  # Group language variants of each resource together.
        for filename in Resource.list_files():
            name, lang = (filename.rsplit(':', 1) + [None])[:2]
            langs_by_name.setdefault(name, {})[lang] = 'file'
        for resource_name in bundle.list_resources():
            name, lang = (resource_name.rsplit(':', 1) + [None])[:2]
            langs_by_name.setdefault(name, {})[lang] = 'resource'

        rows = []  # Each row shows one Resource and its localized variants.
        for name in sorted(langs_by_name):
            sources_by_lang = langs_by_name[name]
            altered = 'resource' in sources_by_lang.values()
            generic = '<a class="%s" href="%s">%s</a>' % (
                sources_by_lang.pop(None, 'missing'),
                self.get_admin_url(bundle_name, name), html(name))
            variants = ['<a class="%s" href="%s">%s</a>' % (
                sources_by_lang[lang],
                self.get_admin_url(bundle_name, name, lang), html(lang))
                for lang in sorted(sources_by_lang)]
            rows.append('''
<tr class="%(altered)s">
  <td>%(generic)s</td>
  <td>%(variants)s
    <form method="post" class="%(class)s">
      <input type="hidden" name="operation" value="add_resource">
      <input type="hidden" name="resource_name" value="%(name)s">
      <input name="resource_lang" size=3 class="hide-when-readonly"
          placeholder="lang">
      <input type="submit" value="Add" class="hide-when-readonly">
    </form>
  </td>
</tr>''' % {'altered': altered and 'altered' or 'unaltered',
            'generic': generic,
            'variants': ', '.join(variants),
            'class': editable_class,
            'name': name})

        self.write('''
<table cellpadding=0 cellspacing=0>
<tr><th>
  Resource name
  <span id="show-unaltered">
    <input id="show-unaltered-checkbox" type="checkbox"
        onchange="show_unaltered(this.checked)">
    <label for="show-unaltered-checkbox">Show unaltered files</label>
  </span>
</th><th>Localized variants</th></tr>
<tr class="add"><td>
  <form method="post" class="%(class)s">
    <input type="hidden" name="operation" value="add_resource">
    <input name="resource_name" size="36" class="hide-when-readonly"
        placeholder="resource filename">
    <input type="submit" value="Add" class="hide-when-readonly">
    <div class="warning hide-when-editable">
      This bundle cannot be edited while it is set as default.
    </div>
  </form>
</td><td></td></tr>
%(rows)s
</table>
<script>
function show_unaltered(show) {
  var rows = document.getElementsByClassName('unaltered');
  for (var r = 0; r < rows.length; r++) {
    rows[r].style.display = show ? '' : 'none';
  }
}
show_unaltered(false);
</script>
<form method="post" action="%(action)s">
  <input type="hidden" name="operation" value="add_bundle">
  <input type="hidden" name="resource_bundle_original" value="%(bundle_name)s">
  <table cellpadding=0 cellspacing=0>
    <tr><td>
      Copy all these resources to another bundle:
      <input name="resource_bundle" size="18"
          placeholder="bundle name">
      <input type="submit" value="Copy">
    </td></tr>
  </table>
</form>''' % {'class': editable_class,
              'rows': ''.join(rows),
              'action': self.get_admin_url(),
              'bundle_name': bundle_name})
    def handle(self, operation):
        """Handles both GET and POST requests.  POST requests include an
        'operation' param describing what the user is trying to change."""
        bundle_name = self.params.resource_bundle or ''
        name = self.params.resource_name or ''
        lang = self.params.resource_lang or ''
        key_name = name + (lang and ':' + lang)
        editable = (bundle_name != self.env.default_resource_bundle)
        if not ResourceBundle.get_by_key_name(self.env.default_resource_bundle):
            ResourceBundle(key_name=self.env.default_resource_bundle).put()

        if operation == 'set_preview':
            # Set the resource_bundle cookie.  This causes all pages to render
            # using the selected bundle (see main.py).  We use a cookie so that
            # it's possible to preview PF as embedded on external sites.
            self.response.headers['Set-Cookie'] = \
                'resource_bundle=%s; path=/' % bundle_name
            return self.redirect(self.get_admin_url())

        if operation == 'set_default':
            # Set the default resource bundle.
            config.set(default_resource_bundle=
                       self.params.resource_bundle_default)
            return self.redirect(self.get_admin_url())

        if operation == 'add_bundle' and editable:
            # Add a new bundle, optionally copying from an existing bundle.
            put_bundle(bundle_name, self.params.resource_bundle_original)
            return self.redirect(self.get_admin_url(bundle_name))

        if operation == 'add_resource' and editable:
            # Go to the edit page for a new resource (don't create until save).
            return self.redirect(self.get_admin_url(bundle_name, name, lang))

        if operation == 'delete_resource' and editable:
            # Delete a resource.
            resource = Resource.get(key_name, bundle_name)
            if resource:
                resource.delete()
            return self.redirect(self.get_admin_url(bundle_name))

        if operation == 'put_resource' and editable:
            # Store the content of a resource.
            if isinstance(self.request.POST.get('file'), cgi.FieldStorage):
                content = self.request.get('file')  # uploaded file content
            elif 'content' in self.request.POST:  # edited text
                content = self.request.get('content').encode('utf-8')
            else:  # modify cache_seconds but leave content unchanged
                resource = Resource.get(key_name, bundle_name)
                content = resource and resource.content or ''
            put_resource(bundle_name, key_name, content=content,
                         cache_seconds=self.params.cache_seconds)
            return self.redirect(self.get_admin_url(bundle_name))

        if not operation:
            self.write(PREFACE + self.format_nav_html(bundle_name, name, lang))
            if bundle_name and name:
                self.show_resource(bundle_name, key_name, name, lang, editable)
            elif bundle_name:
                self.list_resources(bundle_name, editable)
            else:
                self.list_bundles()
Example #6
0
    def test_admin_resources(self):
        # Verify that the bundle listing loads.
        doc = self.go_as_admin('/global/admin/resources')

        # Add a new bundle (redirects to the new bundle's resource listing).
        doc = self.s.submit(doc.last('form'), resource_bundle='xyz')
        assert doc.first('a', class_='sel', content='Bundle: xyz')
        bundle = ResourceBundle.get_by_key_name('xyz')
        assert(bundle)

        # Add a resource (redirects to the resource's edit page).
        doc = self.s.submit(doc.first('form'), resource_name='abc')
        assert doc.first('a', class_='sel', content='Resource: abc')

        # The new Resource shouldn't exist in the datastore until it is saved.
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Enter some content for the resource.
        doc = self.s.submit(doc.first('form'), content='pqr')
        assert Resource.get_by_key_name('abc', parent=bundle).content == 'pqr'

        # Use the breadcrumb navigation bar to go back to the resource listing.
        doc = self.s.follow('Bundle: xyz')

        # Add a localized variant of the resource.
        row = doc.first('td', content='abc').enclosing('tr')
        doc = self.s.submit(row.first('form'), resource_lang='pl')
        assert doc.first('a', class_='sel', content='pl: Polish')

        # Enter some content for the localized resource.
        doc = self.s.submit(doc.first('form'), content='jk')
        assert Resource.get_by_key_name('abc:pl', parent=bundle).content == 'jk'

        # Confirm that both the generic and localized resource are listed.
        doc = self.s.follow('Bundle: xyz')
        assert doc.first('a', class_='resource', content='abc')
        assert doc.first('a', class_='resource', content='pl')

        # Copy all the resources to a new bundle.
        doc = self.s.submit(doc.last('form'), resource_bundle='zzz',
                            resource_bundle_original='xyz')
        parent = ResourceBundle.get_by_key_name('zzz')
        assert Resource.get_by_key_name('abc', parent=parent).content == 'pqr'
        assert Resource.get_by_key_name('abc:pl', parent=parent).content == 'jk'

        # Verify that we can't add a resource to the default bundle.
        bundle = ResourceBundle.get_by_key_name('1')
        assert(bundle)
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.follow('1 (default)')
        self.s.submit(doc.first('form'), resource_name='abc')
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Verify that we can't edit a resource in the default bundle.
        self.s.back()
        doc = self.s.follow('base.html.template')
        self.s.submit(doc.first('form'), content='xyz')
        assert not Resource.get_by_key_name('base.html.template', parent=bundle)

        # Verify that we can't copy resources into the default bundle.
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.follow('xyz')
        doc = self.s.submit(doc.last('form'), resource_bundle='1',
                            resource_bundle_original='xyz')
        assert not Resource.get_by_key_name('abc', parent=bundle)

        # Switch the default bundle version.
        doc = self.go_as_admin('/global/admin/resources')
        doc = self.s.submit(doc.first('form'), resource_bundle_default='xyz')
        assert 'xyz (default)' in doc.text
        # Undo.
        doc = self.s.submit(doc.first('form'), resource_bundle_default='1')
        assert '1 (default)' in doc.text
Example #7
0
    def list_resources(self, bundle_name, editable):
        """Displays a list of the resources in a bundle."""
        bundle = ResourceBundle.get_by_key_name(bundle_name)
        editable_class = editable and 'editable' or 'readonly'

        langs_by_name = {
        }  # Group language variants of each resource together.
        for filename in Resource.list_files():
            name, lang = (filename.rsplit(':', 1) + [None])[:2]
            langs_by_name.setdefault(name, {})[lang] = 'file'
        for resource_name in bundle.list_resources():
            name, lang = (resource_name.rsplit(':', 1) + [None])[:2]
            langs_by_name.setdefault(name, {})[lang] = 'resource'

        rows = []  # Each row shows one Resource and its localized variants.
        for name in sorted(langs_by_name):
            sources_by_lang = langs_by_name[name]
            altered = 'resource' in sources_by_lang.values()
            generic = '<a class="%s" href="%s">%s</a>' % (sources_by_lang.pop(
                None, 'missing'), self.get_admin_url(bundle_name,
                                                     name), html(name))
            variants = [
                '<a class="%s" href="%s">%s</a>' %
                (sources_by_lang[lang],
                 self.get_admin_url(bundle_name, name, lang), html(lang))
                for lang in sorted(sources_by_lang)
            ]
            rows.append(
                '''
<tr class="%(altered)s">
  <td>%(generic)s</td>
  <td>%(variants)s
    <form method="post" class="%(class)s">
      <input type="hidden" name="operation" value="add_resource">
      <input type="hidden" name="resource_name" value="%(name)s">
      <input name="resource_lang" size=3 class="hide-when-readonly"
          placeholder="lang">
      <input type="submit" value="Add" class="hide-when-readonly">
    </form>
  </td>
</tr>''' % {
                    'altered': altered and 'altered' or 'unaltered',
                    'generic': generic,
                    'variants': ', '.join(variants),
                    'class': editable_class,
                    'name': name
                })

        self.write(
            '''
<table cellpadding=0 cellspacing=0>
<tr><th>
  Resource name
  <span id="show-unaltered">
    <input id="show-unaltered-checkbox" type="checkbox"
        onchange="show_unaltered(this.checked)">
    <label for="show-unaltered-checkbox">Show unaltered files</label>
  </span>
</th><th>Localized variants</th></tr>
<tr class="add"><td>
  <form method="post" class="%(class)s">
    <input type="hidden" name="operation" value="add_resource">
    <input name="resource_name" size="36" class="hide-when-readonly"
        placeholder="resource filename">
    <input type="submit" value="Add" class="hide-when-readonly">
    <div class="warning hide-when-editable">
      This bundle cannot be edited while it is set as default.
    </div>
  </form>
</td><td></td></tr>
%(rows)s
</table>
<script>
function show_unaltered(show) {
  var rows = document.getElementsByClassName('unaltered');
  for (var r = 0; r < rows.length; r++) {
    rows[r].style.display = show ? '' : 'none';
  }
}
show_unaltered(false);
</script>
<form method="post" action="%(action)s">
  <input type="hidden" name="operation" value="add_bundle">
  <input type="hidden" name="resource_bundle_original" value="%(bundle_name)s">
  <table cellpadding=0 cellspacing=0>
    <tr><td>
      Copy all these resources to another bundle:
      <input name="resource_bundle" size="18"
          placeholder="bundle name">
      <input type="submit" value="Copy">
    </td></tr>
  </table>
</form>''' % {
                'class': editable_class,
                'rows': ''.join(rows),
                'action': self.get_admin_url(),
                'bundle_name': bundle_name
            })
Example #8
0
    def handle(self, operation):
        """Handles both GET and POST requests.  POST requests include an
        'operation' param describing what the user is trying to change."""
        bundle_name = self.params.resource_bundle or ''
        name = self.params.resource_name or ''
        lang = self.params.resource_lang or ''
        key_name = name + (lang and ':' + lang)
        editable = (bundle_name != self.env.default_resource_bundle)
        if not ResourceBundle.get_by_key_name(
                self.env.default_resource_bundle):
            ResourceBundle(key_name=self.env.default_resource_bundle).put()

        if operation == 'set_preview':
            # Set the resource_bundle cookie.  This causes all pages to render
            # using the selected bundle (see main.py).  We use a cookie so that
            # it's possible to preview PF as embedded on external sites.
            self.response.headers['Set-Cookie'] = \
                'resource_bundle=%s; path=/' % bundle_name
            return self.redirect(self.get_admin_url())

        if operation == 'set_default':
            # Set the default resource bundle.
            config.set(
                default_resource_bundle=self.params.resource_bundle_default)
            return self.redirect(self.get_admin_url())

        if operation == 'add_bundle' and editable:
            # Add a new bundle, optionally copying from an existing bundle.
            put_bundle(bundle_name, self.params.resource_bundle_original)
            return self.redirect(self.get_admin_url(bundle_name))

        if operation == 'add_resource' and editable:
            # Go to the edit page for a new resource (don't create until save).
            return self.redirect(self.get_admin_url(bundle_name, name, lang))

        if operation == 'delete_resource' and editable:
            # Delete a resource.
            resource = Resource.get(key_name, bundle_name)
            if resource:
                resource.delete()
            return self.redirect(self.get_admin_url(bundle_name))

        if operation == 'put_resource' and editable:
            # Store the content of a resource.
            if isinstance(self.request.POST.get('file'), cgi.FieldStorage):
                content = self.request.get('file')  # uploaded file content
            elif 'content' in self.request.POST:  # edited text
                content = self.request.get('content').encode('utf-8')
            else:  # modify cache_seconds but leave content unchanged
                resource = Resource.get(key_name, bundle_name)
                content = resource and resource.content or ''
            put_resource(bundle_name,
                         key_name,
                         content=content,
                         cache_seconds=self.params.cache_seconds)
            return self.redirect(self.get_admin_url(bundle_name))

        if not operation:
            self.write(PREFACE + self.format_nav_html(bundle_name, name, lang))
            if bundle_name and name:
                self.show_resource(bundle_name, key_name, name, lang, editable)
            elif bundle_name:
                self.list_resources(bundle_name, editable)
            else:
                self.list_bundles()