You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by tv...@apache.org on 2014/02/21 23:21:54 UTC

[06/10] git commit: [#7097] Refactored User Profile to use Profile Sections

[#7097] Refactored User Profile to use Profile Sections

Signed-off-by: Cory Johns <cj...@slashdotmedia.com>


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

Branch: refs/heads/master
Commit: bd978f7951248d537de2d9d680c3665624e7acbf
Parents: 7ad2a9a
Author: Cory Johns <cj...@slashdotmedia.com>
Authored: Wed Feb 12 02:00:38 2014 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Fri Feb 21 21:14:08 2014 +0000

----------------------------------------------------------------------
 Allura/allura/config/app_cfg.py                 |   3 +
 .../templates/profile_section_base.html         |  28 +++
 .../templates/sections/personal-data.html       |  63 +++++
 .../templates/sections/projects.html            |  49 ++++
 .../user_profile/templates/sections/skills.html |  39 +++
 .../user_profile/templates/sections/tools.html  |  39 +++
 .../ext/user_profile/templates/user_index.html  | 245 +------------------
 Allura/allura/ext/user_profile/user_main.py     |  34 ++-
 Allura/allura/lib/helpers.py                    |  26 ++
 Allura/allura/lib/plugin.py                     |   6 +-
 .../allura/templates/jinja_master/nav_menu.html |  14 +-
 Allura/setup.py                                 |   6 +
 ForgeActivity/forgeactivity/main.py             |   1 -
 .../templates/widgets/profile_section.html      |  24 +-
 14 files changed, 321 insertions(+), 256 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/config/app_cfg.py
----------------------------------------------------------------------
diff --git a/Allura/allura/config/app_cfg.py b/Allura/allura/config/app_cfg.py
index 1661356..bcca0c2 100644
--- a/Allura/allura/config/app_cfg.py
+++ b/Allura/allura/config/app_cfg.py
@@ -31,6 +31,7 @@ convert them into boolean, for example, you should use the
 
 """
 import logging
+from functools import partial
 
 import tg
 import jinja2
@@ -102,6 +103,8 @@ class ForgeConfig(AppConfig):
         jinja2_env.install_gettext_translations(pylons.i18n)
         jinja2_env.filters['filesizeformat'] = helpers.do_filesizeformat
         jinja2_env.filters['datetimeformat'] = helpers.datetimeformat
+        jinja2_env.filters['filter'] = lambda s,t=None: filter(t and jinja2_env.tests[t], s)
+        jinja2_env.filters['map'] = helpers.map_jinja_filter
         jinja2_env.globals.update({'hasattr': hasattr})
         config['pylons.app_globals'].jinja2_env = jinja2_env
         # Jinja's unable to request c's attributes without strict_c

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/templates/profile_section_base.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/profile_section_base.html b/Allura/allura/ext/user_profile/templates/profile_section_base.html
new file mode 100644
index 0000000..7e15dad
--- /dev/null
+++ b/Allura/allura/ext/user_profile/templates/profile_section_base.html
@@ -0,0 +1,28 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+<div class="profile-section {% block section_class %}{% endblock %}">
+    <h3>
+        {% block title %}{% endblock %}
+        <span class="actions">{% block actions %}{% endblock %}</span>
+    </h3>
+
+    <div class="section-body">
+        {% block content %}{% endblock %}
+    </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/templates/sections/personal-data.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/sections/personal-data.html b/Allura/allura/ext/user_profile/templates/sections/personal-data.html
new file mode 100644
index 0000000..94b0421
--- /dev/null
+++ b/Allura/allura/ext/user_profile/templates/sections/personal-data.html
@@ -0,0 +1,63 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
+
+{% block title %}
+    Personal Data
+{% endblock %}
+
+{% block actions %}
+    {% if user == c.user %}
+        <a href="{{auth.account_urls['account_user_info']}}">Edit Personal Data</a>
+    {% endif %}
+{% endblock %}
+
+{% block section_class %}personal-data{% endblock %}
+
+{% block content %}
+    <dl class="personal-data">
+        <dt>Joined:</dt><dd>{{auth.user_registration_date(user)}}</dd>
+        <dt>Location:</dt><dd>
+            {% set loc = user.get_pref('localization') %}
+            {{ [loc.city, loc.country, timezone]|filter|join(' / ') }}
+        </dd>
+        <dt>Username:</dt><dd>
+            {{user.username}}
+        </dd>
+        <dt>Gender:</dt><dd>
+            {{user.get_pref('sex')}}
+        </dd>
+        <dt>Phone Number:</dt><dd>
+            {{user.get_pref('telnumbers')|join(', ')}}
+        </dd>
+        <dt>Skype:</dt><dd>
+            {{user.get_pref('skypeaccount')}}
+        </dd>
+        <dt>Web Site{% if user.get_pref('webpages')|length > 1 %}s{% endif %}:</dt><dd>
+            {{user.get_pref('webpages')|filter|map('urlize', 20, true)|join(', ')}}
+        </dd>
+        <dt>Availability:</dt><dd>
+            <ol>
+            {% for slot in user.get_localized_availability('utc') %}
+                <li>{{ slot.week_day }}: {{ slot.start_time.strftime('%H:%M') }} to {{ slot.end_time.strftime('%H:%M') }}</li>
+            {% endfor %}
+            </ol>
+        </dd>
+    </dl>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/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
new file mode 100644
index 0000000..4fc5eda
--- /dev/null
+++ b/Allura/allura/ext/user_profile/templates/sections/projects.html
@@ -0,0 +1,49 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
+
+{% block title %}
+    Projects
+{% endblock %}
+
+{% block actions %}
+    {% if user == c.user %}
+        <a href="/{{config.get('default_neighborhood', 'p')}}/add_project">Add Project</a>
+    {% endif %}
+{% endblock %}
+
+{% block section_class %}projects{% endblock %}
+
+{% block content %}
+    <ul>
+        {% for project in user.my_projects() %}
+        <li>
+            {% if project.icon -%}
+                <img src="{{project.url()}}/icon?{{project.icon._id.generation_time}}" alt="Project Logo"/>
+            {%- else -%}
+                <img src="{{g.forge_static('images/project_default.png')}}" alt="Project Logo"/>
+            {%- endif -%}
+            <span class="project-info">
+                <a href="{{project.url()}}">{{project.name}}</a>
+                {{project.summary}}
+            </span>
+        </li>
+        {% endfor %}
+    </ul>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/templates/sections/skills.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/sections/skills.html b/Allura/allura/ext/user_profile/templates/sections/skills.html
new file mode 100644
index 0000000..104cc7a
--- /dev/null
+++ b/Allura/allura/ext/user_profile/templates/sections/skills.html
@@ -0,0 +1,39 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
+
+{% block title %}
+    Skills
+{% endblock %}
+
+{% block actions %}
+    {% if user == c.user %}
+        <a href="{{auth.account_urls['account_user_info']}}/skills">Edit Skills</a>
+    {% endif %}
+{% endblock %}
+
+{% block section_class %}skills{% endblock %}
+
+{% block content %}
+    <ul>
+        {% for skill in user.get_skills() %}
+        <li>{{ skill.skill.fullname }}</li>
+        {% endfor %}
+    </ul>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/templates/sections/tools.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/sections/tools.html b/Allura/allura/ext/user_profile/templates/sections/tools.html
new file mode 100644
index 0000000..4427c8b
--- /dev/null
+++ b/Allura/allura/ext/user_profile/templates/sections/tools.html
@@ -0,0 +1,39 @@
+{#-
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+{% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
+
+{% block title %}
+    Tools
+{% endblock %}
+
+{% block actions %}
+    {% if user == c.user %}
+        <a href="{{c.project.url()}}/admin/tools">Add Tools</a>
+    {% endif %}
+{% endblock %}
+
+{% block section_class %}tools{% endblock %}
+
+{% block content %}
+    <ul>
+        {% for tool in c.project.ordered_mounts() %}
+        <li><a href="{{tool['ac'].url()}}">{{ tool['ac'].options.mount_label }}</a></li>
+        {% endfor %}
+    </ul>
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/templates/user_index.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/templates/user_index.html b/Allura/allura/ext/user_profile/templates/user_index.html
index 047c21e..30e4ea3 100644
--- a/Allura/allura/ext/user_profile/templates/user_index.html
+++ b/Allura/allura/ext/user_profile/templates/user_index.html
@@ -32,250 +32,11 @@
   <a href="{{c.app.url}}feed.rss" title="Follow"><b data-icon="{{g.icons['feed'].char}}" class="ico {{g.icons['feed'].css}}"></b></a>
 {% endblock %}
 
-{% block content %}
-  {% if user.preferences.email_address %}
-    <p>{{lib.gravatar(user)}}</p>
-  {% endif %}
-  <div class="project-list grid-18">
-    <b>Projects</b>
-    <ul>
-      {% for p in user.my_projects() %}
-        {% if (c.user == user) or h.has_access(p, 'read') %}
-          <li>
-              <a class="project-name" href="{{p.url()}}">{{p.name}}</a>
-          </li>
-        {% endif %}
-      {% endfor %}
-    </ul>
-  </div>
-
-  <div class="grid-24">
-    <div class="grid-24" style="margin:0;"><b>Personal data</b></div>
-    <div class="grid-24" style="margin:0;">
-      <div class="grid-4">Registration Date:</div>
-      <div class="grid-8">{{reg_date}}</div>
-    </div>
-    {% if user.get_pref('sex') == 'Male' or user.get_pref('sex') == 'Female' %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Gender:</div>
-        <div class="grid-8">{{user.get_pref('sex')}}</div>
-      </div>
-    {% endif %}
-    {% if user.get_pref('birthdate') %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Birthdate:</div>
-        <div class="grid-8">
-          {{ user.get_pref('birthdate').strftime('%d %B %Y')}}
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('localization').country or user.get_pref('localization').city %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Localization:</div>
-        <div class="grid-8">
-          {% if user.get_pref('localization').city %}
-            {{user.get_pref('localization').city}}{{ ',' if user.get_pref('localization').country else '' }}
-          {% endif %}
-          {% if user.get_pref('localization').country %}
-            {{user.get_pref('localization').country}}
-         {% endif %}
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('timezone') %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Timezone:</div>
-        <div class="grid-8">
-          {{user.get_pref('timezone')}}
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('socialnetworks')|length > 0 %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Social networks:</div>
-        <div class="grid-18">
-           {{user.get_pref('display_name')}}'s account(s):
-           <ul>
-             {% for i in user.get_pref('socialnetworks') %}
-                <li>{{i.socialnetwork}}: <a href="{{i.accounturl}}">{{i.accounturl}}</a></li>
-             {% endfor %}
-           </ul>
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('webpages')|length > 0 %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Websites:</div>
-        <div class="grid-18">
-           {{user.get_pref('display_name')}}'s website(s):
-           <ul>
-             {% for i in user.get_pref('webpages') %}
-                <li><a href="{{i}}">{{i}}</a></li>
-             {% endfor %}
-           </ul>
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('telnumbers')|length > 0 %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Telephone number(s):</div>
-        <div class="grid-18">
-           {{user.get_pref('display_name')}}'s telephone number(s):
-           <ul>
-             {% for i in user.get_pref('telnumbers') %}
-                <li>{{i}}</li>
-             {% endfor %}
-           </ul>
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('skypeaccount') %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Skype account:</div>
-        <div class="grid-8">{{user.get_pref('skypeaccount')}}</div>
-      </div>
-    {% endif %}
+{% block nav_menu %}{{super()}}{% endblock %}
 
-    {% if user.get_pref('timezone') and user.get_availability_timeslots() |length > 0 %}
-      <div class="grid-24" style="margin:0;">
-        <div class="grid-4">Availability:</div>
-
-          {% if c.user.get_pref('timezone') %}
-          <div class="grid-18" id="timeslotsconverted" style="visibility: visible; display:none;">
-             {{user.get_pref('display_name')}}'s availability time-slots.
-             <div style="float:right;">
-               See timeslots in:
-               <a href="JavaScript:void(0);" onclick="changeTimezone('utc')">UTC</a> |
-               <a href="JavaScript:void(0);" onclick="changeTimezone('local')">
-                  {{user.get_pref('display_name')}}'s local time
-               </a> |
-               <b>Your local time</b>
-             </div>
-             <ul>
-               {% for i in user.get_localized_availability(c.user.get_pref('timezone')) %}
-                  <li>{{i.week_day}}: from {{i.start_time.strftime("%H:%M")}} to {{i.end_time.strftime("%H:%M")}} </li>
-               {% endfor %}
-             </ul>
-          </div>
-          {% endif %}
-
-          <div class="grid-18" id="timeslotsutc" style="visibility: visible; display:block;">
-             {{user.get_pref('display_name')}}'s availability time-slots.
-             <div style="float:right;">
-               See timeslots in:
-               <b>UTC</b> |
-               <a href="JavaScript:void(0);" onclick="changeTimezone('local')">
-                  {{user.get_pref('display_name')}}'s local time
-               </a>
-               {% if c.user.get_pref('timezone') %} |
-                  <a href="JavaScript:void(0);" onclick="changeTimezone('converted')">
-                    Your local time
-                  </a>
-               {% endif %}
-             </div>
-             <ul>
-               {% for i in user.get_localized_availability('utc') %}
-                  <li>{{i.week_day}}: from {{i.start_time.strftime("%H:%M")}} to {{i.end_time.strftime("%H:%M")}} </li>
-               {% endfor %}
-             </ul>
-          </div>
-
-          <div class="grid-18" id="timeslotslocal" style="visibility: visible; display:none;">
-             {{user.get_pref('display_name')}}'s availability time-slots.
-             <div style="float:right;">
-               See timeslots in:
-               <a href="JavaScript:void(0);" onclick="changeTimezone('utc')">UTC</a> |
-               <b>
-                  {{user.get_pref('display_name')}}'s local time
-               </b>
-               {% if c.user.get_pref('timezone') %} |
-                  <a href="JavaScript:void(0);" onclick="changeTimezone('converted')">
-                    Your local time
-                  </a>
-               {% endif %}
-             </div>
-             <ul>
-               {% for i in user.get_availability_timeslots() %}
-                  <li>{{i.week_day}}: from {{i.start_time.strftime("%H:%M")}} to {{i.end_time.strftime("%H:%M")}} </li>
-               {% endfor %}
-             </ul>
-          </div>
-
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_inactive_periods(include_past_periods=False)|length > 0 %}
-      <div class="grid-24">
-        <div class="grid-4">Inactive periods:</div>
-        <div class="grid-18">
-          This user won't be able to work on the forge in the following period(s):
-          <ul>
-            {% for p in user.get_inactive_periods(include_past_periods=False) %}
-              <li>From {{p.start_date.strftime('%d %B %Y')}} to {{p.end_date.strftime('%d %B %Y')}}.</li>
-            {% endfor %}
-        </div>
-      </div>
-    {% endif %}
-
-    {% if user.get_pref('email_address') and c.user.get_pref('email_address') and not user.get_pref('disable_user_messages') %}
-    <div class="grid-24">
-      <b><a href="send_message">Send me a message</a></b>
-    </div>
-    {% endif %}
-  </div><!-- end of Personal data section -->
-  <div class="grid-24">
-    <b>Current {{user.get_pref('display_name')}}'s skills list</b>
-    <div class="grid-24">
-      {% if user.get_skills()|length > 0 %}
-        <table>
-          <thead>
-            <tr>
-              <th>Skill</th>
-              <th>Level</th>
-              <th>Comments</th>
-            </tr>
-          </thead>
-          <tbody>
-            {% for s in user.get_skills() %}
-              <tr>
-                <td>{{s.skill.fullpath}}</td>
-                <td>{{s.level}}</td>
-                <td>{{s.comment}}</td>
-              </tr>
-            {% endfor %}
-          </tbody>
-        </table>
-      {% else %}
-        <div class="grid-24">At the moment, {{user.get_pref('display_name')}}'s skills list is empty!</div>
-      {% endif %}
-    </div>
-  </div>
-
-  {% if c.user.username == user.username %}
-      <div class="address-list grid-18">
-        <b>Email Addresses</b>
-        <ul>
-          {% for email in user.email_addresses %}
-          <li>
-              {{lib.email_gravatar(email, size=24)}}
-              {% if email == user.preferences.email_address %}
-                <span class="prime email-address">{{email}}</span>
-              {% else %}
-                <span class="email-address">{{email}}</span>
-              {% endif %}
-          </li>
-          {% endfor %}
-        </ul>
-      </div>
-  {% endif %}
+{% block top_nav %}{# disabled #}{% endblock %}
 
+{% block content %}
   {% for section in sections %}
     {{ section.display() }}
   {% endfor %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/ext/user_profile/user_main.py
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/user_profile/user_main.py b/Allura/allura/ext/user_profile/user_main.py
index 1112aa8..01bb6b8 100644
--- a/Allura/allura/ext/user_profile/user_main.py
+++ b/Allura/allura/ext/user_profile/user_main.py
@@ -27,6 +27,8 @@ from tg import expose, redirect, validate, flash
 import tg
 from webob import exc
 from jinja2 import Markup
+from pytz import timezone
+from datetime import datetime
 
 from allura import version
 from allura.app import Application, SitemapEntry
@@ -257,5 +259,35 @@ class ProfileSectionBase(object):
         if not self.check_display():
             return ''
         tmpl = g.jinja2_env.get_template(self.template)
-        context = self.prepare_context({'h': h, 'c': c, 'g': g})
+        context = self.prepare_context({
+            'h': h,
+            'c': c,
+            'g': g,
+            'user': self.user,
+            'config': tg.config,
+            'auth': AuthenticationProvider.get(request),
+        })
         return Markup(tmpl.render(context))
+
+
+class PersonalDataSection(ProfileSectionBase):
+    template = 'allura.ext.user_profile:templates/sections/personal-data.html'
+
+    def prepare_context(self, context):
+        context['timezone'] = self.user.get_pref('timezone')
+        if context['timezone']:
+            tz = timezone(context['timezone'])
+            context['timezone'] = tz.tzname(datetime.utcnow())
+        return context
+
+
+class ProjectsSection(ProfileSectionBase):
+    template = 'allura.ext.user_profile:templates/sections/projects.html'
+
+
+class SkillsSection(ProfileSectionBase):
+    template = 'allura.ext.user_profile:templates/sections/skills.html'
+
+
+class ToolsSection(ProfileSectionBase):
+    template = 'allura.ext.user_profile:templates/sections/tools.html'

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index ac54d13..83992aa 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -32,6 +32,7 @@ from datetime import datetime, timedelta
 from collections import defaultdict
 import shlex
 import socket
+from functools import partial
 
 import tg
 import genshi.template
@@ -49,6 +50,7 @@ from tg.decorators import before_validate
 from formencode.variabledecode import variable_decode
 import formencode
 from jinja2 import Markup
+from jinja2.filters import contextfilter
 from paste.deploy.converters import asbool, aslist
 
 from webhelpers import date, feedgenerator, html, number, misc, text
@@ -1154,3 +1156,27 @@ def login_overlay(exceptions=None):
                 if request.path.rstrip('/').endswith('/%s' % exception):
                     raise
         c.show_login_overlay = True
+
+
+def get_filter(ctx, filter_name):
+    """
+    Gets a named Jinja2 filter, passing through
+    any context requested by the filter.
+    """
+    filter_ = ctx.environment.filters[filter_name]
+    if getattr(filter_, 'contextfilter', False):
+        return partial(filter_, ctx)
+    elif getattr(filter_, 'evalcontextfilter', False):
+        return partial(filter_, ctx.eval_ctx)
+    elif getattr(filter_, 'environmentfilter', False):
+        return partial(filter_, ctx.environment)
+
+
+@contextfilter
+def map_jinja_filter(ctx, seq, filter_name, *a, **kw):
+    """
+    A Jinja2 filter that applies the named filter with the
+    given args to the sequence this filter is applied to.
+    """
+    filter_ = get_filter(ctx, filter_name)
+    return [filter_(value, *a, **kw) for value in seq]

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index cd0ed23..084501f 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -173,7 +173,7 @@ class AuthenticationProvider(object):
                 'alt': 'Manage Personal Information',
             },
             {
-                'tabid': 'account_sfnet_beta_index',
+                'tabid': 'account_subscriptions',
                 'title': 'Subscriptions',
                 'target': "/auth/subscriptions",
                 'alt': 'Manage Subscription Preferences',
@@ -186,6 +186,10 @@ class AuthenticationProvider(object):
             },
         ]
 
+    @LazyProperty
+    def account_urls(self):
+        return {m['tabid']: m['target'] for m in self.account_navigation()}
+
     def user_project_shortname(self, user):
         '''
         :param user: a :class:`User <allura.model.auth.User>`

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/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 4280881..b29d566 100644
--- a/Allura/allura/templates/jinja_master/nav_menu.html
+++ b/Allura/allura/templates/jinja_master/nav_menu.html
@@ -24,13 +24,21 @@
 {% else %}
     {{ theme_macros.breadcrumbs(c.project, c.app) }}
     {{ theme_macros.project_header_right(c.project, c.app) }}
-    {% if c.project.user_project_of %}
+    {% 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">
     {% endif %}
     <h1 class="project_title">
-      <a href="{{c.project.url()}}" class="project_link">{{ c.project.neighborhood.name if c.project.is_nbhd_project else c.project.name }}</a>
+        <a href="{{c.project.url()}}" class="project_link">
+            {%- if c.project.is_user_project -%}
+                {{ c.project.user_project_of.display_name }}
+            {%- elif c.project.is_nbhd_project -%}
+                {{ c.project.neighborhood.name }}
+            {%- else -%}
+                {{ c.project.name }}
+            {%- endif -%}
+        </a>
     </h1>
     {% set status = c.project.troves_by_type('developmentstatus')|sort(attribute='fullname') %}
     {% set status = status[-1] %}
@@ -40,6 +48,7 @@
     <h2 class="project_summary{% if c.project.icon %} with-icon{% endif %}">
         {{c.project.summary}}
     </h2>
+    {% if not c.project.is_user_project %}
     <div class="brought-by{% if c.project.icon %} with-icon{% endif %}">
         Brought to you by:
         {% set admins = c.project.admins()|sort(attribute='username') %}
@@ -51,4 +60,5 @@
             {% endif %}
         {%- endfor -%}
     </div>
+    {% endif %}
 {% endif %}

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/Allura/setup.py
----------------------------------------------------------------------
diff --git a/Allura/setup.py b/Allura/setup.py
index 252328c..7d2d924 100644
--- a/Allura/setup.py
+++ b/Allura/setup.py
@@ -126,6 +126,12 @@ setup(
     [allura.site_admin]
     stats = allura.controllers.site_admin:StatsSiteAdminExtension
 
+    [allura.user_profile.sections]
+    personal-data = allura.ext.user_profile.user_main:PersonalDataSection
+    projects = allura.ext.user_profile.user_main:ProjectsSection
+    skills = allura.ext.user_profile.user_main:SkillsSection
+    tools = allura.ext.user_profile.user_main:ToolsSection
+
     [paste.paster_command]
     taskd = allura.command.taskd:TaskdCommand
     taskd_cleanup = allura.command.taskd_cleanup:TaskdCleanupCommand

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/ForgeActivity/forgeactivity/main.py
----------------------------------------------------------------------
diff --git a/ForgeActivity/forgeactivity/main.py b/ForgeActivity/forgeactivity/main.py
index 269dbfc..e82cca7 100644
--- a/ForgeActivity/forgeactivity/main.py
+++ b/ForgeActivity/forgeactivity/main.py
@@ -255,7 +255,6 @@ class ForgeActivityProfileSection(ProfileSectionBase):
         filtered_timeline = list(islice(ifilter(perm_check(c.user), full_timeline),
                                         0, 5))
         context.update({
-            'user': self.user,
             'follow_toggle': W.follow_toggle,
             'following': g.director.is_connected(c.user, self.user),
             'timeline': filtered_timeline,

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/bd978f79/ForgeActivity/forgeactivity/templates/widgets/profile_section.html
----------------------------------------------------------------------
diff --git a/ForgeActivity/forgeactivity/templates/widgets/profile_section.html b/ForgeActivity/forgeactivity/templates/widgets/profile_section.html
index 4e1bec2..5f2230e 100644
--- a/ForgeActivity/forgeactivity/templates/widgets/profile_section.html
+++ b/ForgeActivity/forgeactivity/templates/widgets/profile_section.html
@@ -16,18 +16,24 @@
        specific language governing permissions and limitations
        under the License.
 -#}
+{% extends "allura.ext.user_profile:templates/profile_section_base.html" %}
 {% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 {% import 'forgeactivity:templates/macros.html' as am with context %}
 
-<div class="user-activity grid-8">
-    <h3>
-        User Activity
+{% block title %}
+    User Activity
+{% endblock %}
 
-        {% if c.user and not c.user.is_anonymous() and c.user != user %}
-            {{follow_toggle.display(following=following, action=activity_app.url+'follow')}}
-        {% endif %}
-        <a href="feed.rss" title="RSS"><b data-icon="{{g.icons['feed'].char}}" class="ico {{g.icons['feed'].css}}" title="Feed"></b></a>
-    </h3>
+{% block actions %}
+    {% if c.user and not c.user.is_anonymous() and c.user != user %}
+        {{follow_toggle.display(following=following, action=activity_app.url+'follow')}}
+    {% endif %}
+    <a href="feed.rss" title="RSS"><b data-icon="{{g.icons['feed'].char}}" class="ico {{g.icons['feed'].css}}" title="Feed"></b></a>
+{% endblock %}
+
+{% block section_class %}user-activity{% endblock %}
+
+{% block content %}
     {% if not timeline %}
         <p class="empty">No activity to display.</p>
     {% else %}
@@ -49,4 +55,4 @@
     </ul>
     <a class="view-all" href="{{activity_app.url}}">View All</a>
     {% endif %}
-</div>
+{% endblock %}