Merge pull request #4619 from tgxworld/group_page_design

UX: Redesign group page to follow user page.
This commit is contained in:
Guo Xiang Tan 2016-12-22 13:42:28 +08:00 committed by GitHub
commit 96c70c74a1
24 changed files with 180 additions and 84 deletions

View File

@ -14,6 +14,7 @@ export default Ember.Component.extend({
}, },
tagName: 'ul', tagName: 'ul',
selectedHtml: null,
classNames: ['mobile-nav'], classNames: ['mobile-nav'],

View File

@ -0,0 +1,10 @@
import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({
application: Ember.inject.controller(),
@computed('model.is_group_user')
showGroupMessages(isGroupUser) {
return isGroupUser || (this.currentUser && this.currentUser.admin);
}
});

View File

@ -16,19 +16,15 @@ export default Ember.Controller.extend({
application: Ember.inject.controller(), application: Ember.inject.controller(),
counts: null, counts: null,
showing: 'members', showing: 'members',
tabs: [ tabs: [
Tab.create({ name: 'members', active: true, 'location': 'group.index' }), Tab.create({ name: 'members', 'location': 'group.index', icon: 'users' }),
Tab.create({ name: 'posts' }), Tab.create({ name: 'activity' }),
Tab.create({ name: 'topics' }),
Tab.create({ name: 'mentions' }),
Tab.create({ name: 'messages', requiresMembership: true }),
Tab.create({ Tab.create({
name: 'edit', i18nKey: 'edit.title', name: 'edit', i18nKey: 'edit.title', icon: 'pencil', requiresGroupAdmin: true
requiresMembership: true, requiresGroupAdmin: true
}), }),
Tab.create({ Tab.create({
name: 'logs', i18nKey: 'logs.title', name: 'logs', i18nKey: 'logs.title', icon: 'list-alt', requiresGroupAdmin: true
requiresMembership: true, requiresGroupAdmin: true
}) })
], ],
@ -57,31 +53,22 @@ export default Ember.Controller.extend({
this.get('tabs')[0].set('count', this.get('model.user_count')); this.get('tabs')[0].set('count', this.get('model.user_count'));
}, },
@observes('showing')
showingChanged() {
const showing = this.get('showing');
this.get('tabs').forEach(tab => {
tab.set('active', showing === tab.get('name'));
});
},
@computed('model.is_group_user', 'model.is_group_owner', 'model.automatic') @computed('model.is_group_user', 'model.is_group_owner', 'model.automatic')
getTabs(isGroupUser, isGroupOwner, automatic) { getTabs(isGroupUser, isGroupOwner, automatic) {
return this.get('tabs').filter(t => { return this.get('tabs').filter(t => {
let isMember = false; let display = true;
if (this.currentUser && !automatic) { if (this.currentUser) {
let admin = this.currentUser.admin; let admin = this.currentUser.admin;
if (t.get('requiresGroupAdmin')) { if (automatic && t.get('requiresGroupAdmin')) {
isMember = admin || isGroupOwner; display = false;
} else { } else {
isMember = admin || isGroupUser; display = admin || isGroupOwner;
} }
} }
return isMember || !t.get('requiresMembership'); return display;
}); });
} }
}); });

View File

@ -49,10 +49,14 @@ export default function() {
this.route('group', { path: '/groups/:name', resetNamespace: true }, function() { this.route('group', { path: '/groups/:name', resetNamespace: true }, function() {
this.route('members'); this.route('members');
this.route('activity', function() {
this.route('posts'); this.route('posts');
this.route('topics'); this.route('topics');
this.route('mentions'); this.route('mentions');
this.route('messages'); this.route('messages');
});
this.route('logs'); this.route('logs');
this.route('edit'); this.route('edit');
}); });

View File

@ -0,0 +1,3 @@
import { buildGroupPage } from 'discourse/routes/group-activity-posts';
export default buildGroupPage('mentions');

View File

@ -0,0 +1,3 @@
import { buildGroupPage } from 'discourse/routes/group-activity-posts';
export default buildGroupPage('messages');

View File

@ -11,12 +11,12 @@ export function buildGroupPage(type) {
}, },
setupController(controller, model) { setupController(controller, model) {
this.controllerFor('group-posts').setProperties({ model, type }); this.controllerFor('group-activity-posts').setProperties({ model, type });
this.controllerFor("group").set("showing", type); this.controllerFor("group").set("showing", type);
}, },
renderTemplate() { renderTemplate() {
this.render('group-posts'); this.render('group-activity-posts');
}, },
actions: { actions: {

View File

@ -0,0 +1,3 @@
import { buildGroupPage } from 'discourse/routes/group-activity-posts';
export default buildGroupPage('topics');

View File

@ -0,0 +1,5 @@
export default Ember.Route.extend({
beforeModel: function() {
this.transitionTo("group.activity.posts");
}
});

View File

@ -1,3 +0,0 @@
import { buildGroupPage } from 'discourse/routes/group-posts';
export default buildGroupPage('mentions');

View File

@ -1,3 +0,0 @@
import { buildGroupPage } from 'discourse/routes/group-posts';
export default buildGroupPage('messages');

View File

@ -1,3 +0,0 @@
import { buildGroupPage } from 'discourse/routes/group-posts';
export default buildGroupPage('topics');

View File

@ -1,6 +1,4 @@
<div class="container group"> <div class="container group">
{{#link-to "groups" class='group-breadcrumb'}}{{fa-icon 'arrow-left'}} {{i18n 'groups.index.title'}}{{/link-to}}
<div class='group-details-container'> <div class='group-details-container'>
<div class='group-info'> <div class='group-info'>
{{#if model.flair_url}} {{#if model.flair_url}}
@ -31,10 +29,11 @@
{{/if}} {{/if}}
</div> </div>
{{#mobile-nav class='group-nav' desktopClass="pull-left nav nav-stacked" currentPath=application.currentPath}} {{#mobile-nav class='group-nav' desktopClass="nav nav-pills" currentPath=application.currentPath}}
{{#each getTabs as |tab|}} {{#each getTabs as |tab|}}
<li class="{{if tab.active 'active'}}"> <li>
{{#link-to tab.location model title=tab.message}} {{#link-to tab.location model title=tab.message}}
{{#if tab.icon}}{{fa-icon tab.icon}}{{/if}}
{{tab.message}} {{tab.message}}
{{#if tab.count}}<span class='count'>({{tab.count}})</span>{{/if}} {{#if tab.count}}<span class='count'>({{tab.count}})</span>{{/if}}
{{/link-to}} {{/link-to}}
@ -42,9 +41,7 @@
{{/each}} {{/each}}
{{/mobile-nav}} {{/mobile-nav}}
<div class='pull-left group-outlet'> <div class='group-outlet'>
<div class='user-main'>
{{outlet}} {{outlet}}
</div> </div>
</div>
</div> </div>

View File

@ -0,0 +1,27 @@
<div class='group-activity container'>
{{#mobile-nav class='group-activity-nav' desktopClass="pull-left nav nav-stacked" currentPath=application.currentPath}}
<li>
{{#link-to 'group.activity.posts'}}{{i18n 'groups.posts'}}{{/link-to}}
</li>
<li>
{{#link-to 'group.activity.topics'}}{{i18n 'groups.topics'}}{{/link-to}}
</li>
<li>
{{#link-to 'group.activity.mentions'}}{{i18n 'groups.mentions'}}{{/link-to}}
</li>
{{#if showGroupMessages}}
<li>
{{#link-to 'group.activity.messages'}}{{i18n 'groups.messages'}}{{/link-to}}
</li>
{{/if}}
{{/mobile-nav}}
<div class="{{if site.mobileView "" "pull-left"}} group-activity-outlet">
<div class='user-main'>
{{outlet}}
</div>
</div>
</div>

View File

@ -1,4 +1,6 @@
<li><a {{action 'toggleExpanded'}}>{{{selectedHtml}}} <i class='fa fa-caret-down'></i></a></li> {{#if selectedHtml}}
<li><a {{action 'toggleExpanded'}}>{{{selectedHtml}}} <i class='fa fa-caret-down'></i></a></li>
{{/if}}
<ul class='drop {{if expanded 'expanded'}}'> <ul class='drop {{if expanded 'expanded'}}'>
{{yield}} {{yield}}
</ul> </ul>

View File

@ -1,12 +1,7 @@
.group-details-container { .group-details-container {
background: rgba(230, 230, 230, 0.3); background: rgba(230, 230, 230, 0.3);
padding: 20px; padding: 20px;
margin-bottom: 30px; margin-bottom: 15px;
}
.group-breadcrumb {
display: block;
margin-bottom: 10px;
} }
.group-info { .group-info {
@ -160,10 +155,12 @@ table.group-members {
} }
} }
.group-edit .form-horizontal { .group-edit {
.form-horizontal {
label { label {
font-weight: bold; font-weight: bold;
} }
}
} }
#add-user-to-group { #add-user-to-group {

View File

@ -1,8 +1,4 @@
.group-members-input { .group-members-input {
.ac-wrap {
width: 100% !important;
}
.group-members-input-selector { .group-members-input-selector {
margin-top: 10px; margin-top: 10px;

View File

@ -1,12 +1,59 @@
.group-outlet {
width: 75%;
}
.group-nav { .group-nav {
width: 20%; li {
margin-right: 30px; float: left;
a, i {
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 40%));
}
.active {
a, i {
color: $secondary;
}
}
}
margin-bottom: 30px;
} }
.group-info { .group-info {
margin-bottom: 20px; margin-bottom: 20px;
} }
.group-activity-nav {
width: 15%;
background-color: transparent;
li {
border: none;
a {
padding: 8px 13px;
}
a.active {
background-color: transparent;
font-weight: bold;
color: $primary;
}
a.active:after {
display: none;
}
}
}
.group-activity-outlet {
width: 85%;
}
.group-edit {
border: 1px solid dark-light-diff($primary, $secondary, 90%, -60%);
padding: 10px;
.form-horizontal {
button {
float: none;
}
}
}

View File

@ -10,7 +10,7 @@
margin: 5px 0px 0px 0px; margin: 5px 0px 0px 0px;
} }
.group-nav, .group-outlet { .group-nav {
width: 100%; width: 100%;
} }
@ -20,16 +20,20 @@
.group-nav.mobile-nav { .group-nav.mobile-nav {
margin-bottom: 15px; margin-bottom: 15px;
}
> li { .group-activity {
a { position: relative;
color: white; }
.fa { color: white; } .group-activity-nav.mobile-nav {
} position: absolute;
} right: 0px;
top: -50px;
}
background-color: $quaternary; .group-activity-outlet {
float: none;
} }
.form-horizontal { .form-horizontal {
@ -55,7 +59,7 @@ table.group-members {
tr { tr {
.user-info { .user-info {
width: 130px; width: auto;
} }
td { td {

View File

@ -432,6 +432,7 @@ en:
title: title:
one: "group" one: "group"
other: "groups" other: "groups"
activity: "Activity"
members: "Members" members: "Members"
topics: "Topics" topics: "Topics"
posts: "Posts" posts: "Posts"

View File

@ -401,6 +401,8 @@ Discourse::Application.routes.draw do
get "posts.rss" => "groups#posts_feed", format: :rss get "posts.rss" => "groups#posts_feed", format: :rss
get "mentions.rss" => "groups#mentions_feed", format: :rss get "mentions.rss" => "groups#mentions_feed", format: :rss
get 'activity' => "groups#show"
get 'activity/:filter' => "groups#show"
get 'members' get 'members'
get 'posts' get 'posts'
get 'topics' get 'topics'

View File

@ -24,24 +24,31 @@ test("Viewing Group", () => {
ok(count('.group-members tr') > 0, "it lists group members"); ok(count('.group-members tr') > 0, "it lists group members");
}); });
visit("/groups/discourse/posts"); click(".nav-pills li a[title='Activity']");
andThen(() => { andThen(() => {
ok(count('.user-stream .item') > 0, "it lists stream items"); ok(count('.user-stream .item') > 0, "it lists stream items");
}); });
visit("/groups/discourse/topics"); click(".group-activity-nav li a[href='/groups/discourse/activity/topics']");
andThen(() => { andThen(() => {
ok(count('.user-stream .item') > 0, "it lists stream items"); ok(count('.user-stream .item') > 0, "it lists stream items");
}); });
visit("/groups/discourse/mentions"); click(".group-activity-nav li a[href='/groups/discourse/activity/mentions']");
andThen(() => { andThen(() => {
ok(count('.user-stream .item') > 0, "it lists stream items"); ok(count('.user-stream .item') > 0, "it lists stream items");
}); });
visit("/groups/discourse/messages");
andThen(() => { andThen(() => {
ok(find(".nav-stacked li a[title='Messages']").length === 0, 'it should not show messages tab if user is not admin'); equal(
find(".group-activity li a[href='/groups/discourse/activity/messages']").length,
0,
'it should not show messages tab if user is not a group user or admin'
);
ok(find(".nav-stacked li a[title='Edit Group']").length === 0, 'it should not show messages tab if user is not admin'); ok(find(".nav-stacked li a[title='Edit Group']").length === 0, 'it should not show messages tab if user is not admin');
ok(find(".nav-stacked li a[title='Logs']").length === 0, 'it should not show Logs tab if user is not admin'); ok(find(".nav-stacked li a[title='Logs']").length === 0, 'it should not show Logs tab if user is not admin');
ok(count('.user-stream .item') > 0, "it lists stream items"); ok(count('.user-stream .item') > 0, "it lists stream items");
@ -55,10 +62,19 @@ test("Admin Viewing Group", () => {
visit("/groups/discourse"); visit("/groups/discourse");
andThen(() => { andThen(() => {
ok(find(".nav-stacked li a[title='Messages']").length === 1, 'it should show messages tab if user is admin'); ok(find(".nav-pills li a[title='Edit Group']").length === 1, 'it should show edit group tab if user is admin');
ok(find(".nav-stacked li a[title='Edit Group']").length === 1, 'it should show edit group tab if user is admin'); ok(find(".nav-pills li a[title='Logs']").length === 1, 'it should show Logs tab if user is admin');
ok(find(".nav-stacked li a[title='Logs']").length === 1, 'it should show Logs tab if user is admin');
equal(find('.group-info-name').text(), 'Awesome Team', 'it should display the group name'); equal(find('.group-info-name').text(), 'Awesome Team', 'it should display the group name');
}); });
click(".nav-pills li a[title='Activity']");
andThen(() => {
equal(
find(".group-activity li a[href='/groups/discourse/activity/messages']").length,
1,
'it should show messages tab if user is admin'
);
});
}); });