From dc7707ff3033bcb2ec321d164b51716a9513a269 Mon Sep 17 00:00:00 2001
From: Eric Barbour <emb4gu@virginia.edu>
Date: Jul 26 2016 15:13:59 +0000
Subject: [PATCH 1/3] Naive implementation of User Members widget


---

diff --git a/hubs/widgets/__init__.py b/hubs/widgets/__init__.py
index 323aa70..6423e3e 100755
--- a/hubs/widgets/__init__.py
+++ b/hubs/widgets/__init__.py
@@ -16,6 +16,7 @@ from hubs.widgets import pagureissues
 from hubs.widgets import githubissues
 from hubs.widgets import bugzilla
 from hubs.widgets import fhosted
+from hubs.widgets import memberships
 
 from hubs.widgets.workflow import pendingacls
 from hubs.widgets.workflow import updates2stable
@@ -41,6 +42,7 @@ registry = {
     'githubissues': githubissues,
     'bugzilla': bugzilla,
     'fedorahosted': fhosted,
+    'memberships': memberships,
 
     'workflow.pendingacls': pendingacls,
     'workflow.updates2stable': updates2stable,
diff --git a/hubs/widgets/memberships.py b/hubs/widgets/memberships.py
new file mode 100644
index 0000000..8389657
--- /dev/null
+++ b/hubs/widgets/memberships.py
@@ -0,0 +1,29 @@
+import hubs.models
+from hubs.hinting import hint, prefixed as _
+import hubs.validators as validators
+from hubs.widgets.base import argument
+from hubs.widgets.chrome import panel
+from hubs.widgets import templating
+
+chrome = panel('Hubs')
+template = templating.environment.get_template('templates/memberships.html')
+position = 'both'
+
+
+@argument(name="username",
+          default=None,
+          validator=validators.username,
+          help="A FAS username.")
+def data(session, widget, username, **kwargs):
+    user = hubs.models.User.by_username(session, username)
+    memberships = [m.__json__(session) for m in user.memberships
+                   if m.name != user.username and not m.user_hub]
+    return dict(memberships=memberships)
+
+
+@hint(topics=[_('hubs.hub.update')])
+def should_invalidate(message, session, widget):
+    if message['topic'].endswith('hubs.hub.update'):
+        if message['msg']['hub']['name'] == widget.hub.name:
+            return True
+    return False
diff --git a/hubs/widgets/templates/memberships.html b/hubs/widgets/templates/memberships.html
new file mode 100644
index 0000000..482d616
--- /dev/null
+++ b/hubs/widgets/templates/memberships.html
@@ -0,0 +1,18 @@
+{% for member in memberships %}
+<div class="card-block">
+  <img class="col-md-3 img-responsive membership-avatar" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
+  <a href="/{{member.name}}">{{ member.name }}</a>
+  {% if g.auth.username in member.owners %}
+    <p class="text-muted">Owner</p>
+  {% else %}
+    <p>Member</p>
+  {% endif %}
+</div>
+{% endfor %}
+
+<style>
+ .membership-avatar {
+   height: 4em;
+   width: 6em;
+ }
+</style>

From 4737208e61400c0b0eb48a23ab19fc2d1c74f6c6 Mon Sep 17 00:00:00 2001
From: Eric Barbour <ebarbour@redhat.com>
Date: Jul 26 2016 15:13:59 +0000
Subject: [PATCH 2/3] Configure user membership for user and groups


* Add ellipsize of member/membership list

---

diff --git a/hubs/widgets/memberships.py b/hubs/widgets/memberships.py
index 8389657..48d8fea 100644
--- a/hubs/widgets/memberships.py
+++ b/hubs/widgets/memberships.py
@@ -5,20 +5,30 @@ from hubs.widgets.base import argument
 from hubs.widgets.chrome import panel
 from hubs.widgets import templating
 
+ELLIPSIS_LIMIT = 3
 chrome = panel('Hubs')
 template = templating.environment.get_template('templates/memberships.html')
 position = 'both'
 
 
-@argument(name="username",
-          default=None,
-          validator=validators.username,
-          help="A FAS username.")
-def data(session, widget, username, **kwargs):
-    user = hubs.models.User.by_username(session, username)
-    memberships = [m.__json__(session) for m in user.memberships
-                   if m.name != user.username and not m.user_hub]
-    return dict(memberships=memberships)
+def data(session, widget, **kwargs):
+    hub = widget.hub
+    members = []
+    if hub.user_hub:
+        user = hubs.models.User.by_username(session, hub.name)
+        members = [m.__json__(session) for m in user.memberships
+                   if m.name != user.username]
+    else:
+        members_name = []
+        for member in widget.hub.members:
+            if member.username in members_name:
+                continue
+            members_name.append(member.username)
+            members.append(member.__json__(session))
+
+    oldest_members = sorted(members,
+                            key=lambda m: m.get('created_on'))[:ELLIPSIS_LIMIT]
+    return dict(memberships=list(members), oldest_members=list(oldest_members))
 
 
 @hint(topics=[_('hubs.hub.update')])
diff --git a/hubs/widgets/templates/memberships.html b/hubs/widgets/templates/memberships.html
index 482d616..b489188 100644
--- a/hubs/widgets/templates/memberships.html
+++ b/hubs/widgets/templates/memberships.html
@@ -1,18 +1,69 @@
-{% for member in memberships %}
 <div class="card-block">
-  <img class="col-md-3 img-responsive membership-avatar" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
-  <a href="/{{member.name}}">{{ member.name }}</a>
-  {% if g.auth.username in member.owners %}
-    <p class="text-muted">Owner</p>
+  {% if memberships|length > oldest_members|length %}
+  {% for member in oldest_members %}
+  <div class="card-block">
+    <img class="img-responsive membership-avatar col-md-3" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
+    <a href="/{{member.name}}">{{ member.name }}</a>
+    {% if g.auth.username in member.owners %}
+      <p class="text-muted">Owner</p>
+    {% else %}
+      <p>Member</p>
+    {% endif %}
+  </div>
+  {% endfor %}
+  <a href="#" class="btn btn-default" data-toggle="modal" data-target="#membersModal">View All</a>
   {% else %}
-    <p>Member</p>
-  {% endif %}
+  {% for member in memberships %}
+  <div class="card-block">
+    <img class="img-responsive membership-avatar col-md-3" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
+    <a href="/{{member.name}}">{{ member.name }}</a>
+    {% if g.auth.username in member.owners %}
+      <p class="text-muted">Owner</p>
+    {% else %}
+      <p>Member</p>
+    {% endif %}
+  </div>
+  {% endfor %}
+  {%endif%}
+</div>
+
+<!-- View all modal -->
+<div class="modal fade" id="membersModal" tabindex="-1" role="dialog" aria-labelledby="membersModal" aria-hidden="true">
+  <div class="modal-dialog">
+    <div class="modal-content">
+      <div class="modal-header">
+        <h4 class="modal-title" id="myModalLabel">All Memberships</h4>
+      </div>
+      <div id="owners" class="modal-body">
+        {% for member in memberships %}
+        <div class="card-block">
+          <img class="img-responsive membership-avatar col-md-3" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
+          <a href="/{{member.name}}">{{ member.name }}</a>
+          {% if g.auth.username in member.owners %}
+          <p class="text-muted">Owner</p>
+          {% else %}
+          <p>Member</p>
+          {% endif %}
+        </div>
+        {% endfor %}
+      </div>
+      <div class="modal-footer clearfix">
+        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
+      </div>
+    </div>
+  </div>
 </div>
-{% endfor %}
 
 <style>
  .membership-avatar {
    height: 4em;
    width: 6em;
  }
+ .modal-header {
+   border-bottom: 0;
+ }
+
+ #owners {
+   padding: 10px;
+ }
 </style>

From 260fd583d6ef6102e439b12a5b7dda4a026808b6 Mon Sep 17 00:00:00 2001
From: Eric Barbour <ebarbour@redhat.com>
Date: Jul 26 2016 15:13:59 +0000
Subject: [PATCH 3/3] Display memberships in modal as two columns


---

diff --git a/hubs/widgets/templates/memberships.html b/hubs/widgets/templates/memberships.html
index b489188..534aa95 100644
--- a/hubs/widgets/templates/memberships.html
+++ b/hubs/widgets/templates/memberships.html
@@ -35,24 +35,31 @@
         <h4 class="modal-title" id="myModalLabel">All Memberships</h4>
       </div>
       <div id="owners" class="modal-body">
-        {% for member in memberships %}
         <div class="card-block">
-          <img class="img-responsive membership-avatar col-md-3" src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
-          <a href="/{{member.name}}">{{ member.name }}</a>
-          {% if g.auth.username in member.owners %}
-          <p class="text-muted">Owner</p>
-          {% else %}
-          <p>Member</p>
-          {% endif %}
+          <div class="row">
+            {% for member in memberships %}
+            <div class="col-sm-6">
+              <img class="img-responsive membership-avatar col-sm-3"
+                src="{{ member.avatar }}" alt="Hub avatar for {{ member.name }}">
+              <a href="/{{member.name}}">{{ member.name }}</a>
+              {% if g.auth.username in member.owners %}
+              <p class="text-muted">Owner</p>
+              {% else %}
+              <p>Member</p>
+              {% endif %}
+            </div>
+            {% if (loop.index % 2) == 0 %}
+              </div>
+              <div class="row">
+            {% endif %}
+          {% endfor %}
+        </div>
+        <div class="modal-footer clearfix">
+          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
         </div>
-        {% endfor %}
-      </div>
-      <div class="modal-footer clearfix">
-        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
       </div>
     </div>
   </div>
-</div>
 
 <style>
  .membership-avatar {

