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()
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
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()