You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2017/01/31 20:27:03 UTC

[1/7] allura git commit: [#8143] better transparency check, so thumbnails preserve transparency

Repository: allura
Updated Branches:
  refs/heads/db/8143 [created] e3a19fb06


[#8143] better transparency check, so thumbnails preserve transparency


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/fe262530
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/fe262530
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/fe262530

Branch: refs/heads/db/8143
Commit: fe26253008a497541c45109032db0d96eb340fb4
Parents: d3cd129
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Jan 30 13:49:10 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 11:36:02 2017 -0500

----------------------------------------------------------------------
 Allura/allura/model/filesystem.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/fe262530/Allura/allura/model/filesystem.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/filesystem.py b/Allura/allura/model/filesystem.py
index 47c5eeb..00a306e 100644
--- a/Allura/allura/model/filesystem.py
+++ b/Allura/allura/model/filesystem.py
@@ -132,7 +132,7 @@ class File(MappedClass):
         width = image.size[1]
         if square and height != width:
             sz = max(width, height)
-            if 'transparency' in image.info:
+            if image.mode == 'RGBA':
                 new_image = PIL.Image.new('RGBA', (sz, sz))
             else:
                 new_image = PIL.Image.new('RGB', (sz, sz), 'white')


[7/7] allura git commit: [#8143] hi-res neighborhood icons; adjust to share Project logic

Posted by br...@apache.org.
[#8143] hi-res neighborhood icons; adjust to share Project logic


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e3a19fb0
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e3a19fb0
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e3a19fb0

Branch: refs/heads/db/8143
Commit: e3a19fb06df304c0575918da9217a73af9c73750
Parents: 2b894fc
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jan 31 14:47:43 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 15:21:53 2017 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/project.py               | 17 +++++++++++------
 Allura/allura/lib/widgets/forms.py                 |  2 +-
 Allura/allura/model/neighborhood.py                |  8 +++++++-
 .../templates/jinja_master/neigh_nav_menu.html     |  3 ++-
 .../widgets/neighborhood_overview_form.html        |  2 +-
 5 files changed, 22 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e3a19fb0/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 32167dc..6854c00 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -246,8 +246,15 @@ class NeighborhoodController(object):
         redirect(c.project.script_name + 'admin/?first-visit')
 
     @expose()
-    def icon(self, **kw):
-        icon = self.neighborhood.icon
+    def icon(self, w=None, **kw):
+        try:
+            icon = c.project.icon_sized(w=int(w or 48))
+        except ValueError as e:
+            log.info('Invalid project icon size: %s on %s', e, request.url)
+            icon = None
+        if icon is None and w is None:
+            # fallback to older icons stored with neighborhood_id rather than using the nbhd project_id
+            icon = self.neighborhood.icon
         if not icon:
             raise exc.HTTPNotFound
         return icon.serve()
@@ -674,11 +681,9 @@ class NeighborhoodAdminController(object):
         if icon is not None and icon != '':
             if self.neighborhood.icon:
                 self.neighborhood.icon.delete()
+                M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
             M.AuditLog.log('update neighborhood icon')
-            M.NeighborhoodFile.save_image(
-                icon.filename, icon.file, content_type=icon.type,
-                square=True, thumbnail_size=(48, 48),
-                thumbnail_meta=dict(neighborhood_id=self.neighborhood._id))
+            c.project.save_icon(icon.filename, icon.file, content_type=icon.type)
         redirect('overview')
 
     @expose('jinja:allura:templates/neighborhood_help.html')

http://git-wip-us.apache.org/repos/asf/allura/blob/e3a19fb0/Allura/allura/lib/widgets/forms.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 91e7dee..98d7efe 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -805,7 +805,7 @@ class NeighborhoodOverviewForm(ForgeForm):
         css = ffw.AutoResizeTextarea()
         project_template = ffw.AutoResizeTextarea(
             validator=V.JsonValidator(if_empty=''))
-        icon = ew.FileField()
+        icon = ew.FileField(attrs={'accept': 'image/*'})
         tracking_id = ew.TextField()
         project_list_url = ew.TextField()
         anchored_tools = ffw.AutoResizeTextarea()

http://git-wip-us.apache.org/repos/asf/allura/blob/e3a19fb0/Allura/allura/model/neighborhood.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/neighborhood.py b/Allura/allura/model/neighborhood.py
index b27be4d..1c7ff9e 100644
--- a/Allura/allura/model/neighborhood.py
+++ b/Allura/allura/model/neighborhood.py
@@ -165,7 +165,13 @@ class Neighborhood(MappedClass):
 
     @property
     def icon(self):
-        return NeighborhoodFile.query.get(neighborhood_id=self._id)
+        # New icon storage uses the neighborhood_project object, so Project.icon* methods can be shared
+        if self.neighborhood_project.get_tool_data('allura', 'icon_original_size'):
+            icon = self.neighborhood_project.icon
+        else:
+            # fallback to older storage location
+            icon = NeighborhoodFile.query.get(neighborhood_id=self._id)
+        return icon
 
     @property
     def allow_custom_css(self):

http://git-wip-us.apache.org/repos/asf/allura/blob/e3a19fb0/Allura/allura/templates/jinja_master/neigh_nav_menu.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/neigh_nav_menu.html b/Allura/allura/templates/jinja_master/neigh_nav_menu.html
index 907ad5f..d9abc13 100644
--- a/Allura/allura/templates/jinja_master/neigh_nav_menu.html
+++ b/Allura/allura/templates/jinja_master/neigh_nav_menu.html
@@ -16,11 +16,12 @@
        specific language governing permissions and limitations
        under the License.
 -#}
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 {% if not neighborhood or not neighborhood.show_title %}
   <div id="nav_menu_missing"></div>
 {% else %}
     {% if neighborhood.icon %}
-      <a href="{{neighborhood.url()}}"><img src="{{neighborhood.url()}}icon" class="project_icon" alt="{{neighborhood.name}} Logo"/></a>
+      <a href="{{neighborhood.url()}}"><img {{ lib.project_icon_srcs(neighborhood.neighborhood_project) }} class="project_icon" alt="{{neighborhood.name}} Logo"/></a>
     {% endif %}
 	<h1 class="project_title"><a href="{{neighborhood.url()}}">{{neighborhood.name}}</a></h1>
   {% if neighborhood.project_list_url %}

http://git-wip-us.apache.org/repos/asf/allura/blob/e3a19fb0/Allura/allura/templates/widgets/neighborhood_overview_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/neighborhood_overview_form.html b/Allura/allura/templates/widgets/neighborhood_overview_form.html
index 7ba2a88..936b5ab 100644
--- a/Allura/allura/templates/widgets/neighborhood_overview_form.html
+++ b/Allura/allura/templates/widgets/neighborhood_overview_form.html
@@ -50,7 +50,7 @@
     <label class="grid-4">Icon</label>
     <div class="grid-14">
       {% if neighborhood.icon %}
-        <img src="{{neighborhood.url()}}icon" style="vertical-align: middle" alt=""/>
+        <img {{ lib.project_icon_srcs(neighborhood.neighborhood_project) }} style="vertical-align: middle" alt=""/>
       {% endif %}
       {{widget.display_field(widget.fields.icon)}}
     </div>


[3/7] allura git commit: [#8143] Upload & serve hi-res logos

Posted by br...@apache.org.
[#8143] Upload & serve hi-res logos


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/bfca80fe
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/bfca80fe
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/bfca80fe

Branch: refs/heads/db/8143
Commit: bfca80feed431a8269396409507bbaabbbf411e1
Parents: 887ca59
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Jan 27 18:12:20 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 11:36:02 2017 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/project.py            |  8 +++--
 Allura/allura/ext/admin/admin_main.py           | 12 ++++---
 .../templates/admin_widgets/metadata_admin.html |  1 +
 Allura/allura/lib/plugin.py                     |  1 +
 Allura/allura/model/filesystem.py               |  2 +-
 Allura/allura/model/project.py                  | 36 ++++++++++++++++----
 Allura/development.ini                          |  6 ++++
 7 files changed, 52 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 8821f9e..eca8833 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -420,8 +420,12 @@ class ProjectController(FeedController):
             project.url())
 
     @expose()
-    def icon(self, **kw):
-        icon = c.project.icon
+    def icon(self, w=48, **kw):
+        try:
+            icon = c.project.icon_sized(w=int(w))
+        except ValueError as e:
+            log.info('Invalid project icon size: %s on %s', e, request.url)
+            icon = None
         if not icon:
             raise exc.HTTPNotFound
         return icon.serve()

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index 6e21e4a..fc7e9c5 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -16,6 +16,7 @@
 #       under the License.
 
 import logging
+import re
 from collections import OrderedDict
 from datetime import datetime
 from urlparse import urlparse
@@ -348,8 +349,7 @@ class ProjectAdminController(BaseController):
             c.project.removal = removal
             c.project.removal_changed_date = datetime.utcnow()
         if 'delete_icon' in kw:
-            M.ProjectFile.query.remove(
-                dict(project_id=c.project._id, category='icon'))
+            M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
             M.AuditLog.log('remove project icon')
             h.log_action(log, 'remove project icon').info('')
             g.post_event('project_updated')
@@ -448,13 +448,15 @@ class ProjectAdminController(BaseController):
 
         if icon is not None and icon != '':
             if c.project.icon:
-                M.ProjectFile.remove(
-                    dict(project_id=c.project._id, category='icon'))
+                M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
             M.AuditLog.log('update project icon')
             M.ProjectFile.save_image(
                 icon.filename, icon.file, content_type=icon.type,
                 square=True, thumbnail_size=(48, 48),
-                thumbnail_meta=dict(project_id=c.project._id, category='icon'))
+                thumbnail_meta=dict(project_id=c.project._id, category='icon'),
+                save_original=True,
+                original_meta=dict(project_id=c.project._id, category='icon_original'),
+            )
         g.post_event('project_updated')
         flash('Saved', 'success')
         redirect('overview')

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
index d7a1506..e26c98e 100644
--- a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
+++ b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
@@ -114,6 +114,7 @@
       <div id="project-icon-upload" class="hidden">
           {{widget.display_field(widget.fields.icon)}}
           <input type="submit" value="Save" name="save" style="float: none" />
+          <br><small>(best if square & hi-res)</small>
       </div>
     </div>
     {%if c.project.neighborhood.name != 'Users'%}

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 4b2bf0a..952dc72 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -947,6 +947,7 @@ class ProjectRegistrationProvider(object):
                 project_template['icon']['filename'], icon_file,
                 square=True, thumbnail_size=(48, 48),
                 thumbnail_meta=dict(project_id=p._id, category='icon'))
+            # FIXME
 
         if user_project:
             # Allow for special user-only tools

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/model/filesystem.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/filesystem.py b/Allura/allura/model/filesystem.py
index 5b747b2..47c5eeb 100644
--- a/Allura/allura/model/filesystem.py
+++ b/Allura/allura/model/filesystem.py
@@ -128,7 +128,6 @@ class File(MappedClass):
                        thumbnail_size=None,
                        thumbnail_meta=None,
                        square=False):
-        format = image.format
         height = image.size[0]
         width = image.size[1]
         if square and height != width:
@@ -151,6 +150,7 @@ class File(MappedClass):
         thumbnail_meta = thumbnail_meta or {}
         thumbnail = cls(
             filename=filename, content_type=content_type, **thumbnail_meta)
+        format = image.format or 'png'
         with thumbnail.wfile() as fp_w:
             if 'transparency' in image.info:
                 image.save(fp_w,

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 3b36ea2..c80a136 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -27,11 +27,12 @@ from xml.etree import ElementTree as ET
 from tg import config
 from pylons import tmpl_context as c, app_globals as g
 from pylons import request
-from paste.deploy.converters import asbool
+from paste.deploy.converters import asbool, aslist
 import formencode as fe
-import json
 from webob import exc
+import PIL
 
+from allura.lib.decorators import memoize
 from ming import schema as S
 from ming.utils import LazyProperty
 from ming.orm import ThreadLocalORMSession
@@ -63,6 +64,8 @@ log = logging.getLogger(__name__)
 # max sitemap entries per tool type
 SITEMAP_PER_TOOL_LIMIT = 10
 
+DEFAULT_ICON_WIDTH = 48
+
 
 class ProjectFile(File):
 
@@ -354,11 +357,32 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             project_id=self._id,
             category='screenshot')).sort('sort').all()
 
-    @LazyProperty
+    @property
     def icon(self):
-        return ProjectFile.query.get(
-            project_id=self._id,
-            category='icon')
+        return self.icon_sized(DEFAULT_ICON_WIDTH)
+
+    @memoize
+    def icon_sized(self, w):
+        allowed_sizes = map(int, aslist(config.get('project_icon_sizes', '48 72 96')))
+        if w not in allowed_sizes:
+            raise ValueError('Width must be one of {} (see project_icon_sizes in your .ini file)'.format(allowed_sizes))
+        if w == DEFAULT_ICON_WIDTH:
+            icon_cat_name = 'icon'
+        else:
+            icon_cat_name = 'icon-{}'.format(w)
+        sized = ProjectFile.query.get(project_id=self._id, category=icon_cat_name)
+        if not sized and w != DEFAULT_ICON_WIDTH:
+            orig = ProjectFile.query.get(project_id=self._id, category='icon_original')
+            if not orig:
+                return None
+            sized = orig.save_thumbnail(filename='',
+                                        image=PIL.Image.open(orig.rfile()),
+                                        content_type=orig.content_type,
+                                        thumbnail_size=(w, w),
+                                        thumbnail_meta=dict(project_id=c.project._id, category=icon_cat_name),
+                                        square=True,
+                                        )
+        return sized
 
     @property
     def description_html(self):

http://git-wip-us.apache.org/repos/asf/allura/blob/bfca80fe/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index a030020..5cc3219 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -131,6 +131,12 @@ global_nav = [{"title": "Site Home", "url": "/"}]
 registration.method = local
 theme = allura
 
+; These are the sizes of project icons that may be requested.  They will be saved to the database.
+; If your theme is going to support other sizes, update this list.
+; If you remove sizes, you can clean up space in mongodb with e.g: `db.fs.remove({category:/^icon-84/}, {multi:true})`
+; 48 is the historical default size
+project_icon_sizes = 48 72 96
+
 ; For LDAP see https://forge-allura.apache.org/docs/getting_started/installation.html#using-ldap
 ;auth.method = ldap
 auth.method = local


[6/7] allura git commit: [#8143] hi-res user icons, including gravatar

Posted by br...@apache.org.
[#8143] hi-res user icons, including gravatar


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/2b894fcd
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/2b894fcd
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/2b894fcd

Branch: refs/heads/db/8143
Commit: 2b894fcd2dace3c9e68fd41456fb77c827f5db80
Parents: a124e25
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jan 31 13:01:06 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 15:12:31 2017 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/project.py          |  2 +-
 Allura/allura/model/auth.py                   | 11 +++++++++--
 Allura/allura/templates/jinja_master/lib.html | 11 +++++++++--
 3 files changed, 19 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/2b894fcd/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index eca8833..32167dc 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -433,7 +433,7 @@ class ProjectController(FeedController):
     @expose()
     def user_icon(self, **kw):
         try:
-            return self.icon()
+            return self.icon(**kw)
         except exc.HTTPNotFound:
             redirect(g.forge_static('images/user.png'))
 

http://git-wip-us.apache.org/repos/asf/allura/blob/2b894fcd/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index 94bbcf0..69a3bd7 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -624,7 +624,7 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
         return '/%s/' % plugin.AuthenticationProvider.get(request).user_project_shortname(self)
 
     @memoize
-    def icon_url(self, gravatar_default_url=None):
+    def icon_url(self, gravatar_default_url=None, return_more=False):
         icon_url = None
         try:
             private_project = self.private_project()
@@ -632,14 +632,21 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
             log.warn('Error getting/creating user-project for %s',
                      self.username, exc_info=True)
             private_project = None
+        icon_source = None
         if private_project and private_project.icon:
             icon_url = self.url() + 'user_icon'
+            icon_source = 'local'
         elif self.preferences.email_address:
             gravatar_args = {}
             if gravatar_default_url:
                 gravatar_args['d'] = gravatar_default_url
             icon_url = g.gravatar(self.preferences.email_address, **gravatar_args)
-        return icon_url
+            icon_source = 'gravatar'
+
+        if return_more:
+            return icon_url, private_project, icon_source
+        else:
+            return icon_url
 
     @classmethod
     def upsert(cls, username):

http://git-wip-us.apache.org/repos/asf/allura/blob/2b894fcd/Allura/allura/templates/jinja_master/lib.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/lib.html b/Allura/allura/templates/jinja_master/lib.html
index 65a5f52..8feabf0 100644
--- a/Allura/allura/templates/jinja_master/lib.html
+++ b/Allura/allura/templates/jinja_master/lib.html
@@ -54,8 +54,15 @@
 
 {% macro gravatar(user, size, className, gravatar_default_url=None) -%}
   {% set display_name = h.really_unicode(user.display_name) %}
-  {% if user.icon_url() %}
-    <img src="{{user.icon_url(gravatar_default_url)}}"
+  {% set icon_url, user_proj, icon_source = user.icon_url(gravatar_default_url, return_more=True) %}
+  {% if icon_url %}
+    <img {% if icon_source == 'local' %}
+             {{ project_icon_srcs(user_proj, icon_url=icon_url) }}
+         {% elif icon_source == 'gravatar' %}
+             src="{{ icon_url }}"
+             srcset="{{icon_url}}&s={{ size*1.5 }} 1.5x,
+                     {{icon_url}}&s={{ size*2 }} 2x,"
+         {% endif %}
          alt="{{display_name}}"
          title="{{display_name}}"
          class="emboss{% if size %} x{{size}}{% endif %}{% if className %} {{className}}{% endif %}">


[4/7] allura git commit: [#8143] use the hi-res logos from HTML

Posted by br...@apache.org.
[#8143] use the hi-res logos from HTML


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/419df7e1
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/419df7e1
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/419df7e1

Branch: refs/heads/db/8143
Commit: 419df7e1e33669ac18bdadc366e28cad6efedae9
Parents: fe26253
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Jan 30 16:31:32 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 15:12:30 2017 -0500

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py           | 12 ++++++----
 .../templates/admin_widgets/metadata_admin.html |  2 +-
 .../templates/sections/projects.html            |  3 ++-
 Allura/allura/lib/utils.py                      |  3 +++
 Allura/allura/model/project.py                  | 25 +++++++++++++++++---
 Allura/allura/templates/jinja_master/lib.html   | 14 +++++++++++
 .../allura/templates/jinja_master/nav_menu.html |  2 +-
 .../templates/widgets/project_summary.html      |  5 ++--
 8 files changed, 54 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index fc7e9c5..ef0f666 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -23,6 +23,7 @@ from urlparse import urlparse
 import json
 from operator import itemgetter, attrgetter
 import pkg_resources
+
 from pylons import tmpl_context as c, app_globals as g, response
 from pylons import request
 from paste.deploy.converters import asbool, aslist
@@ -32,12 +33,12 @@ from webob import exc
 from bson import ObjectId
 from ming.orm.ormsession import ThreadLocalORMSession
 from ming.odm import session
-from ming.utils import LazyProperty
+import PIL
+
 from allura.app import Application, DefaultAdminController, SitemapEntry
 from allura.lib import helpers as h
 from allura import version
 from allura import model as M
-from allura.lib.repository import RepositoryApp
 from allura.lib.security import has_access, require_access
 from allura.lib.widgets import form_fields as ffw
 from allura.lib import exceptions as forge_exc
@@ -46,7 +47,6 @@ from allura.controllers import BaseController
 from allura.lib.decorators import require_post
 from allura.tasks import export_tasks
 from allura.lib.widgets.project_list import ProjectScreenshots
-from allura.lib.utils import is_ajax
 
 from . import widgets as aw
 
@@ -350,6 +350,7 @@ class ProjectAdminController(BaseController):
             c.project.removal_changed_date = datetime.utcnow()
         if 'delete_icon' in kw:
             M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
+            c.project.set_tool_data('allura', icon_original_size=None)
             M.AuditLog.log('remove project icon')
             h.log_action(log, 'remove project icon').info('')
             g.post_event('project_updated')
@@ -450,13 +451,16 @@ class ProjectAdminController(BaseController):
             if c.project.icon:
                 M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
             M.AuditLog.log('update project icon')
-            M.ProjectFile.save_image(
+            icon_orig, icon_thumb = M.ProjectFile.save_image(
                 icon.filename, icon.file, content_type=icon.type,
                 square=True, thumbnail_size=(48, 48),
                 thumbnail_meta=dict(project_id=c.project._id, category='icon'),
                 save_original=True,
                 original_meta=dict(project_id=c.project._id, category='icon_original'),
             )
+            # store the dimensions so we don't have to read the whole image each time we need to know
+            icon_orig_img = PIL.Image.open(icon_orig.rfile())
+            c.project.set_tool_data('allura', icon_original_size=icon_orig_img.size)
         g.post_event('project_updated')
         flash('Saved', 'success')
         redirect('overview')

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
index e26c98e..a26eb9e 100644
--- a/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
+++ b/Allura/allura/ext/admin/templates/admin_widgets/metadata_admin.html
@@ -99,7 +99,7 @@
     <div id="project-icon" class="viewing">
       {% if value.icon %}
         <div class="viewer" style="overflow: auto">
-          <img src="{{value.url()}}icon?{{value.icon._id.generation_time}}" style="float:left; margin-right: 1em;" alt="">
+          <img {{ lib.project_icon_srcs(value) }} style="float:left; margin-right: 1em;" alt="">
           {{ g.icons['edit'].render(id='edit-icon', style='display:inline-block;margin-top:15px') }}
           {{ g.icons['delete'].render(id='delete-icon', style='display:inline-block;margin-top:15px') }}
         </div>

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/ext/user_profile/templates/sections/projects.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/sections/projects.html b/Allura/allura/ext/user_profile/templates/sections/projects.html
index 7e1756b..7f9c2d8 100644
--- a/Allura/allura/ext/user_profile/templates/sections/projects.html
+++ b/Allura/allura/ext/user_profile/templates/sections/projects.html
@@ -17,6 +17,7 @@
        under the License.
 -#}
 {% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 
 {% block title %}
     Projects
@@ -35,7 +36,7 @@
     {% for project in projects %}
         <li{% if loop.index > 5 %} class="hidden"{% endif %}>
             {% if project.icon -%}
-                <img src="{{project.url()}}icon?{{project.icon._id.generation_time}}" alt="Project Logo" width="48" height="48"/>
+                <img {{ lib.project_icon_srcs(project) }} alt="Project Logo" width="48" height="48"/>
             {%- else -%}
                 <img src="{{g.forge_static('images/project_default.png')}}" alt="Project Logo" width="48" height="48"/>
             {%- endif -%}

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/lib/utils.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index b75a7f8..e68e287 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -559,6 +559,9 @@ class ForgeHTMLSanitizer(html5lib.sanitizer.HTMLSanitizer):
                        + html5lib.sanitizer.HTMLSanitizer.mathml_elements \
                        + html5lib.sanitizer.HTMLSanitizer.svg_elements
 
+    # srcset is used in our own project_list/project_summary widgets which are used as macros so go through markdown
+    allowed_attributes = html5lib.sanitizer.HTMLSanitizer.allowed_attributes + ['srcset']
+
     valid_iframe_srcs = ('https://www.youtube.com/embed/', 'https://www.gittip.com/')
 
     _prev_token_was_ok_iframe = False

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index c80a136..db85b84 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -17,6 +17,7 @@
 #       under the License.
 
 import logging
+from calendar import timegm
 from collections import Counter, OrderedDict
 from datetime import datetime
 from copy import deepcopy
@@ -372,7 +373,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             icon_cat_name = 'icon-{}'.format(w)
         sized = ProjectFile.query.get(project_id=self._id, category=icon_cat_name)
         if not sized and w != DEFAULT_ICON_WIDTH:
-            orig = ProjectFile.query.get(project_id=self._id, category='icon_original')
+            orig = self.icon_original
             if not orig:
                 return None
             sized = orig.save_thumbnail(filename='',
@@ -384,6 +385,25 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
                                         )
         return sized
 
+    @LazyProperty
+    def icon_original(self):
+        return ProjectFile.query.get(project_id=self._id, category='icon_original')
+
+    @LazyProperty
+    def icon_max_size(self):
+        stored_original_size = self.get_tool_data('allura', 'icon_original_size')
+        if stored_original_size:
+            # max not min, since non-square images get white padding added
+            return max(stored_original_size)
+        elif self.icon:
+            return DEFAULT_ICON_WIDTH
+        else:
+            return None
+
+    @LazyProperty
+    def icon_timestamp(self):
+        return timegm(self.icon._id.generation_time.timetuple())
+
     @property
     def description_html(self):
         return g.markdown.cached_convert(self, 'description')
@@ -503,8 +523,7 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         for icon in ProjectFile.query.find(dict(
                 project_id={'$in': result.keys()},
                 category='icon')):
-            result[icon.project_id] = project_index[
-                icon.project_id].url() + 'icon'
+            result[icon.project_id] = project_index[icon.project_id].url() + 'icon'
         return result
 
     @classmethod

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/templates/jinja_master/lib.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/lib.html b/Allura/allura/templates/jinja_master/lib.html
index ad4e227..65a5f52 100644
--- a/Allura/allura/templates/jinja_master/lib.html
+++ b/Allura/allura/templates/jinja_master/lib.html
@@ -200,6 +200,20 @@
     {{ g.icons['restore'].render(show_title=True, id='restore-content') }}
 {%- endmacro %}
 
+{#
+ icon_url param is entirely optional; only pass it if you already have one for effeciency
+#}
+{%- macro project_icon_srcs(project, icon_url=None) %}
+    {% set icon_url = icon_url or project.url() + 'icon' %}
+    src="{{icon_url}}?{{project.icon_timestamp}}"
+    {% if project.icon_max_size >= 72 -%}
+        srcset="{{icon_url}}?w=72&amp;{{project.icon_timestamp}} 1.5x,
+        {% if project.icon_max_size >= 96 -%}
+            {{icon_url}}?w=96&amp;{{project.icon_timestamp}} 2x,
+        {%- endif -%}
+        "
+   {%- endif -%}
+{%- endmacro %}
 
 
 {% macro markdown_syntax(id='') %}

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/templates/jinja_master/nav_menu.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/jinja_master/nav_menu.html b/Allura/allura/templates/jinja_master/nav_menu.html
index e100912..0f956ce 100644
--- a/Allura/allura/templates/jinja_master/nav_menu.html
+++ b/Allura/allura/templates/jinja_master/nav_menu.html
@@ -29,7 +29,7 @@
     {% if c.project.is_user_project %}
       {{lib.gravatar(c.project.user_project_of, size=48, className='project_icon')}}
     {% elif c.project.icon %}
-      <img src="{{c.project.url()}}icon?{{c.project.icon._id.generation_time}}" class="project_icon" alt="Project Logo">
+      <img class="project_icon" alt="Project Logo" {{ lib.project_icon_srcs(c.project) }}>
     {% endif %}
         <h1 class="project_title">
             <a href="{{c.project.url()}}" class="project_link">

http://git-wip-us.apache.org/repos/asf/allura/blob/419df7e1/Allura/allura/templates/widgets/project_summary.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/project_summary.html b/Allura/allura/templates/widgets/project_summary.html
index 10d8693..ee1b61f 100644
--- a/Allura/allura/templates/widgets/project_summary.html
+++ b/Allura/allura/templates/widgets/project_summary.html
@@ -16,6 +16,7 @@
        specific language governing permissions and limitations
        under the License.
 -#}
+{% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 <div class="list card{% if show_proj_icon%} proj_icon{% endif %}"
 	{%- if columns == 2 %} style="width: 330px"{% elif columns == 3 %} style="width: 220px"{% endif %}>
   {% if accolades %}
@@ -23,11 +24,11 @@
       <div class="feature">
         <a href="{{accolades[0].award_url}}" title="{{accolades[0].comment}}">{{accolades[0].award.short}}</a>
       </div>
-      {% if icon_url %}<img src="{{icon_url}}" alt="{{value.name}} Logo"/>{% endif %}
+      {% if icon_url %}<img {{ lib.project_icon_srcs(project=value, icon_url=icon_url) }} alt="{{value.name}} Logo" width="48" height="48"/>{% endif %}
     </div>
   {% elif icon_url %}
     <div class="box">
-      <img src="{{icon_url}}" alt="{{value.name}} Logo"/>
+      <img {{ lib.project_icon_srcs(value, icon_url=icon_url) }} alt="{{value.name}} Logo" width="48" height="48"/>
     </div>
   {% endif %}
   <h2><a href="{{value.url()}}">{{value.name}}</a></h2>


[2/7] allura git commit: [#8143] better upload dialogs

Posted by br...@apache.org.
[#8143] better upload dialogs


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d3cd1292
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d3cd1292
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d3cd1292

Branch: refs/heads/db/8143
Commit: d3cd129259d61d8181ed0b94ff52b3248f9777f8
Parents: bfca80f
Author: Dave Brondsema <da...@brondsema.net>
Authored: Mon Jan 30 13:48:28 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 11:36:02 2017 -0500

----------------------------------------------------------------------
 Allura/allura/ext/admin/widgets.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/d3cd1292/Allura/allura/ext/admin/widgets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/widgets.py b/Allura/allura/ext/admin/widgets.py
index de8046f..633c374 100644
--- a/Allura/allura/ext/admin/widgets.py
+++ b/Allura/allura/ext/admin/widgets.py
@@ -149,7 +149,7 @@ class ScreenshotAdmin(ff.ForgeForm):
     def fields(self):
         fields = [
             ew.InputField(name='screenshot', field_type='file',
-                          label='New Screenshot'),
+                          label='New Screenshot', attrs={'accept': 'image/*'}),
             ew.InputField(name='caption',
                           field_type="text",
                           label='Caption',
@@ -213,7 +213,7 @@ class MetadataAdmin(ff.AdminForm):
             append_to='bottom',
             extra_field_on_focus_name='feature',
             field=FeaturesField())
-        icon = ew.FileField(label='Icon')
+        icon = ew.FileField(label='Icon', attrs={'accept': 'image/*'})
         external_homepage = ew.InputField(field_type="text", label='Homepage',
                                           validator=fev.URL(add_http=True))
         video_url = ew.InputField(field_type="text", label="Video (YouTube)",


[5/7] allura git commit: [#8143] refactor icon-saving logic into method; use it from nbhd-template code too

Posted by br...@apache.org.
[#8143] refactor icon-saving logic into method; use it from nbhd-template code too


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a124e25d
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a124e25d
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a124e25d

Branch: refs/heads/db/8143
Commit: a124e25d95678ad676da23130d28f84e42420a67
Parents: 419df7e
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Jan 31 11:51:45 2017 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Tue Jan 31 15:12:31 2017 -0500

----------------------------------------------------------------------
 Allura/allura/ext/admin/admin_main.py | 11 +----------
 Allura/allura/lib/plugin.py           |  9 ++-------
 Allura/allura/model/project.py        | 12 ++++++++++++
 3 files changed, 15 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a124e25d/Allura/allura/ext/admin/admin_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/admin_main.py b/Allura/allura/ext/admin/admin_main.py
index ef0f666..44c34df 100644
--- a/Allura/allura/ext/admin/admin_main.py
+++ b/Allura/allura/ext/admin/admin_main.py
@@ -451,16 +451,7 @@ class ProjectAdminController(BaseController):
             if c.project.icon:
                 M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon')))
             M.AuditLog.log('update project icon')
-            icon_orig, icon_thumb = M.ProjectFile.save_image(
-                icon.filename, icon.file, content_type=icon.type,
-                square=True, thumbnail_size=(48, 48),
-                thumbnail_meta=dict(project_id=c.project._id, category='icon'),
-                save_original=True,
-                original_meta=dict(project_id=c.project._id, category='icon_original'),
-            )
-            # store the dimensions so we don't have to read the whole image each time we need to know
-            icon_orig_img = PIL.Image.open(icon_orig.rfile())
-            c.project.set_tool_data('allura', icon_original_size=icon_orig_img.size)
+            c.project.save_icon(icon.filename, icon.file, content_type=icon.type)
         g.post_event('project_updated')
         flash('Saved', 'success')
         redirect('overview')

http://git-wip-us.apache.org/repos/asf/allura/blob/a124e25d/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 952dc72..a0c20bf 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -941,13 +941,8 @@ class ProjectRegistrationProvider(object):
                     troves.append(
                         M.TroveCategory.query.get(trove_cat_id=trove_id)._id)
         if 'icon' in project_template:
-            icon_file = StringIO(
-                urlopen(project_template['icon']['url']).read())
-            M.ProjectFile.save_image(
-                project_template['icon']['filename'], icon_file,
-                square=True, thumbnail_size=(48, 48),
-                thumbnail_meta=dict(project_id=p._id, category='icon'))
-            # FIXME
+            icon_file = StringIO(urlopen(project_template['icon']['url']).read())
+            p.save_icon(project_template['icon']['filename'], icon_file)
 
         if user_project:
             # Allow for special user-only tools

http://git-wip-us.apache.org/repos/asf/allura/blob/a124e25d/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index db85b84..f05c0f0 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -358,6 +358,18 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
             project_id=self._id,
             category='screenshot')).sort('sort').all()
 
+    def save_icon(self, filename, file_input, content_type=None):
+        icon_orig, icon_thumb = ProjectFile.save_image(
+            filename, file_input, content_type=content_type,
+            square=True, thumbnail_size=(48, 48),
+            thumbnail_meta=dict(project_id=self._id, category='icon'),
+            save_original=True,
+            original_meta=dict(project_id=self._id, category='icon_original'),
+        )
+        # store the dimensions so we don't have to read the whole image each time we need to know
+        icon_orig_img = PIL.Image.open(icon_orig.rfile())
+        self.set_tool_data('allura', icon_original_size=icon_orig_img.size)
+
     @property
     def icon(self):
         return self.icon_sized(DEFAULT_ICON_WIDTH)