#493 get basic allgroups page working
Merged 6 years ago by abompard. Opened 6 years ago by ryanlerch.
ryanlerch/fedora-hubs all-groups  into  develop

@@ -0,0 +1,81 @@ 

+ import React from 'react';

+ import PropTypes from 'prop-types';

+ import { connect } from 'react-redux';

+ import {

+   defineMessages,

+   FormattedMessage,

+   } from 'react-intl';

+ import PageStructure from './PageStructure';

+ import { monogramColour } from '../core/utils';

+ 

+ 

+ class AllGroupsPage extends React.Component {

+ 

+   render() {

+     return (

+       <PageStructure

+         cssClass="AllGroupsPage"

+         header={

+             <div className="row">

+               <div className="col-md-12">

+                 <h1>Groups</h1>

+                 <p>Summary of available team hubs</p>

+               </div>

+             </div>

+           }

+           content={

+             <div className="row">

+               <div className="col-md-12">

+                 <div className="list-group">

+                 {this.props.hubslist.hubs.map(function(hub, i) {

+                     return (

+                     <a className="list-group-item list-group-item-action d-flex justify-content-between align-items-center"

+                        key={i}

+                        href={hub.hub_url}

+                        >

+                         <div className="d-flex">

+                         { !hub.config.avatar ?

+                             <div className={`monogram-avatar avatar bg-fedora-${monogramColour(hub.name)} text-fedora-${monogramColour(hub.name)}-dark`}>

+                                 {hub.name.charAt(0).toUpperCase()}

+                             </div>

+                             :

+                             <img

+                                 className="avatar"

+                                 src={hub.config.avatar}

+                                 width='60px'

+                                 />

+                         }

+                             <div className="text-dark align-self-center ml-3">

+                                 <h3>{hub.name}</h3>

+                                 <div>{hub.config.summary}</div>

+                             </div>

+                         </div>

+                         <div className="d-flex">

+                             <div className="mx-2 align-self-center">

+                                 <div className="text-uppercase text-secondary"><small>Members</small></div>

+                                 <div className="text-primary text-center">{hub.member_count}</div>

+                             </div>

+                             <div className="mx-2 align-self-center">

+                                 <div className="text-uppercase text-secondary"><small>Subscribers</small></div>

+                                 <div className="text-primary text-center">{hub.subscriber_count}</div>

+                             </div>

+                         </div>

+                     </a>

+                     );

+                 })}

+                 </div>

+               </div>

+             </div>

+           }

+         />

+     );

+   }

+ }

+ 

+ const mapStateToProps = (state) => {

+     return {

+       hubslist: state.hubslist,

+     }

+   };

+ 

+   export default connect(mapStateToProps)(AllGroupsPage);

@@ -14,6 +14,10 @@ 

    "Loading...",

    "Sorry, there was a problem loading the page."

  );

+ const Groups = makeLoadable(

+   () => import(/* webpackChunkName: "page-allgroups" */ '../components/AllGroupsPage'),

+   "Loading...",

+   "Sorry, there was a problem loading the page."

+ );

  

- 

- export {Hub, Streams};

+ export {Hub, Streams, Groups};

@@ -40,6 +40,7 @@ 

    globalConfig: noop,

    urls: noop,

    currentUser: userReducer,

+   hubslist: noop,

    ui,

    entities,

  });

file modified
+10 -10
@@ -401,16 +401,16 @@ 

  }

  

  /*Move these color defs into fedora-bootstrap*/

- .bg-fedora-blue{background-color:#3c6eb4;}

- .bg-fedora-magenta{background-color: #db3279;}

- .bg-fedora-orange{background-color: #e59728;}

- .bg-fedora-green{background-color: #79db32;}

- .bg-fedora-purple{background-color: #a07cbc;}

- .text-fedora-blue-dark{color: #294a7a;}

- .text-fedora-magenta-dark{color: #9a1b51;}

- .text-fedora-orange-dark{color: #9a6213;}

- .text-fedora-green-dark{color: #488b18;}

- .text-fedora-purple-dark{color: #70488f;}

+ .bg-fedora-blue{background-color:#3c6eb4!important;}

+ .bg-fedora-magenta{background-color: #db3279!important;}

+ .bg-fedora-orange{background-color: #e59728!important;}

+ .bg-fedora-green{background-color: #79db32!important;}

+ .bg-fedora-purple{background-color: #a07cbc!important;}

+ .text-fedora-blue-dark{color: #294a7a!important;}

+ .text-fedora-magenta-dark{color: #9a1b51!important;}

+ .text-fedora-orange-dark{color: #9a6213!important;}

+ .text-fedora-green-dark{color: #488b18!important;}

+ .text-fedora-purple-dark{color: #70488f!important;}

  

  .typeahead, .twitter-typeahead {

    width: 100%!important;

@@ -1,60 +0,0 @@ 

- {% extends "master.html" %}

- 

- {% block title %}Groups{% endblock %}

- 

- 

- {% block header %}

-   <h1 class="team">Groups</h2>

-   <p>Summary of available team hubs</p>

- {% endblock header %}

- 

- 

- {% block content %}

- 

-   <div class="row">

-     <div class="col-md-12">

-       {% for group in promoted %}

-         <a href="{{ url_for('hub', name=group.name)}}">{{group.name}}</a>

-         is a promoted group, and it has {{

-             group.subscribers | length }} subscribers and {{

-             group.members | length }} members, and {{

-             group.owners | length }} owners

-       {% endfor %}

-     </div>

-   </div>

- 

-   <hr/>

- 

-   <div class="row">

-     <div class="col-md-12">

-       ZOMG - {{ hub_of_the_month.name }} is the Hub Of The Month! <br/>

-       It has {{ hub_of_the_month.subscribers | length }} subscribers and {{

-         hub_of_the_month.members | length }} members, and {{

-         hub_of_the_month.owners | length }} owners

-       <h6>group owners</h6>

-       {% for owner in hub_of_the_month.owners %}

-           <div class="col-sm-6">

-               <img class="img-circle" src="{{owner.username | avatar}}"/>

-               <a href="{{ url_for('hub', name=owner.username)}}">{{owner.username}}</a>

-           </div>

-       {% endfor %}

-     </div>

-   </div>

- 

-   <hr/>

- 

-   <div class="row">

-     <div class="col-md-12">

-       {% for group in secondary %}

-         <a href="{{ url_for('hub', name=group.name)}}">{{group.name}}</a>

-         is not a promoted group

-         but it has {{ group.subscribers | length }} subscribers and {{

-             group.members | length }} members, and {{

-             group.owners | length }} owners

-         <br/>

-       {% endfor %}

-     </div>

-   </div>

- </div>

- 

- {% endblock content %}

file modified
+67 -4
@@ -1,7 +1,10 @@ 

  from __future__ import unicode_literals

  

  from six.moves.urllib.parse import urlparse

+ import mock

+ import json

  

+ import hubs

  from hubs.app import app

  from hubs.tests import APPTest, FakeAuthorization, auth_set

  
@@ -41,11 +44,71 @@ 

          # this will redirect to fedora.login

          self.assertEqual(urlparse(result.location).path, "/")

  

-     def test_groups_logged_in(self):

+ 

+ class RootGroupsTestCase(APPTest):

+     def _parse_setuppage_json(self, result):

+         result = result.get_data(as_text=True)

+         result = result.partition('function() {\n  Hubs.setupPage("page", ')[2]

+         result = result.partition(');\n})();\n</script>')[0]

+         return json.loads(result)

+ 

+     def _add_assoc(self, hubname, username, role):

+         hub = hubs.models.Hub.query.get(hubname)

+         user = hubs.models.User.query.get(username)

+         self.session.add(hubs.models.Association(

+             hub=hub, user=user, role=role))

+ 

+     @mock.patch('hubs.views.root.log.warning')

+     def test_groups_HOTM_not_found(self, warning):

+         """

+         Test we log a warning if the HUB_OF_THE_MONTH value

+         set in the config does not name a hub that exists.

+         The config in the base tests sets commops, as the

+         HOTM, but this hub doesnt exist in the base testcase

+         """

          user = FakeAuthorization('ralph')

          with auth_set(app, user):

              result = self.app.get('/groups/', follow_redirects=True)

-             # assert the status code of the response

+             data = self._parse_setuppage_json(result)

+ 

+             self.assertEqual(result.status_code, 200)

+             warning.assert_called_once_with("The hub (commops) set as the "

+                                             "HUB_OF_THE_MONTH in the config "

+                                             "does not exist")

+             self.assertEquals(data["hubslist"]["hub_of_the_month"], None)

+ 

+     @mock.patch('hubs.views.root.log.warning')

+     @mock.patch('hubs.app.app.config.get', return_value="infra")

+     def test_groups_HOTM_found(self, config, warning):

+         """

+         Test that we return the HOTM in the JSON we give to

+         the react component

+         """

+         user = FakeAuthorization('ralph')

+         with auth_set(app, user):

+             result = self.app.get('/groups/', follow_redirects=True)

+             data = self._parse_setuppage_json(result)

+ 

+             self.assertEqual(result.status_code, 200)

+             warning.assert_not_called()

+             self.assertEquals(data["hubslist"]

+                                   ["hub_of_the_month"]

+                                   ["name"], "infra")

+ 

+     def test_groups(self):

+         """

+         Test that we return the correct groups list

+         in the JSON we give to the react component

+         """

+         user = FakeAuthorization('ralph')

+         self._add_assoc("infra", "ralph", "stargazer")

+         self._add_assoc("infra", "ralph", "member")

+         self._add_assoc("infra", "ralph", "subscriber")

+         with auth_set(app, user):

+             result = self.app.get('/groups/', follow_redirects=True)

+             data = self._parse_setuppage_json(result)

              self.assertEqual(result.status_code, 200)

-             self.assertIn("ZOMG -  is the Hub Of The Month!",

-                           result.get_data(as_text=True))

+             self.assertEqual(len(data["hubslist"]["hubs"]), 3)

+             self.assertEqual(data["hubslist"]["hubs"][0]["name"], "i18n")

+             self.assertEqual(data["hubslist"]["hubs"][1]["name"], "infra")

+             self.assertEqual(data["hubslist"]["hubs"][2]["name"], "old")

file modified
+48 -10
@@ -1,10 +1,16 @@ 

  from __future__ import unicode_literals, absolute_import

  

+ import logging

  import flask

  import hubs.models

  

  from hubs.app import app, OIDC

- from hubs.utils.views import authenticated, is_safe_url, login_required

+ from hubs.utils import hubname2monogramcolour

+ from hubs.utils.views import (authenticated, is_safe_url,

+                               login_required, get_user_details)

+ 

+ 

+ log = logging.getLogger("hubs")

  

  

  @app.route('/')
@@ -21,21 +27,53 @@ 

  @app.route('/groups/')

  @login_required

  def groups():

-     # Get the list of promoted and non-promoted group hubs from the DB

-     promoted_names = app.config.get('PROMOTED_GROUPS')

+     current_user = get_user_details()

+     urls = {

+         "allGroups": flask.url_for("groups"),

+     }

+     flash_messages = [

+         {"msg": msg[1], "type": msg[0]} for msg in

+         flask.get_flashed_messages(with_categories=True)

+         ]

+ 

      groups = hubs.models.Hub.all_group_hubs()

-     promoted = [g for g in groups if g.name in promoted_names]

-     secondary = [g for g in groups if g.name not in promoted_names]

+     hubslist = []

+     for group in groups:

+         hub = group.get_props()

+         hub["monogram_colour"] = hubname2monogramcolour(hub["name"])

+         hub["hub_url"] = flask.url_for('hub', name=hub["name"])

+ 

+         member_count = len(hub["users"]["member"])

+         owner_count = len(hub["users"]["owner"])

+         hub["member_count"] = member_count + owner_count

+ 

+         subscriber_count = len(hub["users"]["subscriber"])

+         hub["subscriber_count"] = subscriber_count

+ 

+         hubslist.append(hub)

  

      name_of_the_month = app.config.get('HUB_OF_THE_MONTH')

      hub_of_the_month = hubs.models.Hub.by_name(name_of_the_month)

+     if hub_of_the_month:

+         hub_of_the_month = hub_of_the_month.get_props()

+     else:

+         log.warning("The hub (%s) set as the HUB_OF_THE_MONTH "

+                     "in the config does not exist" % name_of_the_month)

  

      return flask.render_template(

-         'groups.html',

-         promoted=promoted,

-         secondary=secondary,

-         hub_of_the_month=hub_of_the_month,

-     )

+         'react.html',

+         page_title="All Groups",

+         initial_state=dict(

+             ui=dict(

+                 page="Groups",

+                 flashMessages=flash_messages,

+             ),

+             urls=urls,

+             currentUser=current_user,

+             hubslist={"hubs": hubslist,

+                       "hub_of_the_month": hub_of_the_month}

+             ),

+         )

  

  

  @app.route('/login/', methods=('GET', 'POST'))

Updates the allgroups page.

This updates the page to kinda partially use react. We will probably want to update this in the future to a full react-style component, with a proper backend APO point so we can enable filtering on the list ajax-style, but for MVP, i think a simple static list of available teams hubs is a go!

I recommend removing this commented code.

Looks fine to me, though I recommend tests for the new Python code. Also, I don't really know React so my review isn't worth much on that code :)

whoops! yeah i need to uncomment that block, and remove the line below. The line below does the same thing, just isused to provide better debugging info (without bundling stuff).

Thanks for the review @bowlofeggs !

I have updated the commit to test the new python code i have added.

as well as fixing up the commented block in the javascrip that you pointed out.

rebased onto 07ec473

6 years ago

Pull-Request has been merged by abompard

6 years ago