FEATURE: show members on group landing page

This commit is contained in:
Arpit Jalan 2016-05-23 15:34:30 +05:30
parent 8817b00a4c
commit 90a27f118f
14 changed files with 157 additions and 158 deletions

View File

@ -1,27 +1,50 @@
import { fmt } from 'discourse/lib/computed';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import computed from 'ember-addons/ember-computed-decorators';
import Group from 'discourse/models/group';
export default Ember.ArrayController.extend({
needs: ['group'],
export default Ember.Controller.extend({
loading: false,
emptyText: fmt('type', 'groups.empty.%@'),
limit: null,
offset: null,
@computed('model.owners.[]')
isOwner(owners) {
if (this.get('currentUser.admin')) {
return true;
}
const currentUserId = this.get('currentUser.id');
if (currentUserId) {
return !!owners.findBy('id', currentUserId);
}
},
actions: {
removeMember(user) {
this.get('model').removeMember(user);
},
addMembers() {
const usernames = this.get('usernames');
if (usernames && usernames.length > 0) {
this.get('model').addMembers(usernames).then(() => this.set('usernames', [])).catch(popupAjaxError);
}
},
loadMore() {
if (this.get("loading")) { return; }
if (this.get("model.members.length") >= this.get("model.user_count")) { return; }
if (this.get('loading')) { return; }
this.set('loading', true);
const posts = this.get('model');
if (posts && posts.length) {
const beforePostId = posts[posts.length-1].get('id');
const group = this.get('controllers.group.model');
this.set("loading", true);
const opts = { beforePostId, type: this.get('type') };
group.findPosts(opts).then(newPosts => {
posts.addObjects(newPosts);
this.set('loading', false);
Group.loadMembers(this.get("model.name"), this.get("model.members.length"), this.get("limit")).then(result => {
this.get("model.members").addObjects(result.members.map(member => Discourse.User.create(member)));
this.setProperties({
loading: false,
user_count: result.meta.total,
limit: result.meta.limit,
offset: Math.min(result.meta.offset + result.meta.limit, result.meta.total)
});
});
}
}
}
});

View File

@ -0,0 +1,26 @@
import { fmt } from 'discourse/lib/computed';
export default Ember.ArrayController.extend({
needs: ['group'],
loading: false,
emptyText: fmt('type', 'groups.empty.%@'),
actions: {
loadMore() {
if (this.get('loading')) { return; }
this.set('loading', true);
const posts = this.get('model');
if (posts && posts.length) {
const beforePostId = posts[posts.length-1].get('id');
const group = this.get('controllers.group.model');
const opts = { beforePostId, type: this.get('type') };
group.findPosts(opts).then(newPosts => {
posts.addObjects(newPosts);
this.set('loading', false);
});
}
}
}
});

View File

@ -15,7 +15,7 @@ var Tab = Em.Object.extend({
export default Ember.Controller.extend({
counts: null,
showing: 'posts',
showing: 'members',
@observes('counts')
countsChanged() {
@ -35,10 +35,10 @@ export default Ember.Controller.extend({
},
tabs: [
Tab.create({ name: 'posts', active: true, 'location': 'group.index' }),
Tab.create({ name: 'members', active: true, 'location': 'group.index' }),
Tab.create({ name: 'posts' }),
Tab.create({ name: 'topics' }),
Tab.create({ name: 'mentions' }),
Tab.create({ name: 'members' }),
Tab.create({ name: 'messages' }),
]
});

View File

@ -1,50 +0,0 @@
import { popupAjaxError } from 'discourse/lib/ajax-error';
import computed from 'ember-addons/ember-computed-decorators';
import Group from 'discourse/models/group';
export default Ember.Controller.extend({
loading: false,
limit: null,
offset: null,
@computed('model.owners.[]')
isOwner(owners) {
if (this.get('currentUser.admin')) {
return true;
}
const currentUserId = this.get('currentUser.id');
if (currentUserId) {
return !!owners.findBy('id', currentUserId);
}
},
actions: {
removeMember(user) {
this.get('model').removeMember(user);
},
addMembers() {
const usernames = this.get('usernames');
if (usernames && usernames.length > 0) {
this.get('model').addMembers(usernames).then(() => this.set('usernames', [])).catch(popupAjaxError);
}
},
loadMore() {
if (this.get("loading")) { return; }
if (this.get("model.members.length") >= this.get("model.user_count")) { return; }
this.set("loading", true);
Group.loadMembers(this.get("model.name"), this.get("model.members.length"), this.get("limit")).then(result => {
this.get("model.members").addObjects(result.members.map(member => Discourse.User.create(member)));
this.setProperties({
loading: false,
user_count: result.meta.total,
limit: result.meta.limit,
offset: Math.min(result.meta.offset + result.meta.limit, result.meta.total)
});
});
}
}
});

View File

@ -49,9 +49,9 @@ export default function() {
});
this.resource('group', { path: '/groups/:name' }, function() {
this.route('posts');
this.route('topics');
this.route('mentions');
this.route('members');
this.route('messages');
});

View File

@ -1,24 +1,11 @@
export function buildIndex(type) {
return Discourse.Route.extend({
type,
export default Discourse.Route.extend({
model() {
return this.modelFor("group").findPosts({ type });
return this.modelFor("group");
},
setupController(controller, model) {
this.controllerFor('group-index').setProperties({ model, type });
this.controllerFor("group").set("showing", type);
},
renderTemplate() {
this.render('group-index');
},
actions: {
didTransition() { return true; }
this.controllerFor("group").set("showing", "members");
controller.set("model", model);
model.findMembers();
}
});
}
export default buildIndex('posts');

View File

@ -1,11 +0,0 @@
export default Discourse.Route.extend({
model() {
return this.modelFor("group");
},
setupController(controller, model) {
this.controllerFor("group").set("showing", "members");
controller.set("model", model);
model.findMembers();
}
});

View File

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

View File

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

View File

@ -0,0 +1,24 @@
export function buildGroupPage(type) {
return Discourse.Route.extend({
type,
model() {
return this.modelFor("group").findPosts({ type });
},
setupController(controller, model) {
this.controllerFor('group-posts').setProperties({ model, type });
this.controllerFor("group").set("showing", type);
},
renderTemplate() {
this.render('group-posts');
},
actions: {
didTransition() { return true; }
}
});
}
export default buildGroupPage('posts');

View File

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

View File

@ -1 +1,45 @@
{{group-post-stream posts=model emptyText=emptyText loadMore="loadMore"}}
{{#if model}}
{{#if isOwner}}
<div class='clearfix'>
<form id='add-user-to-group' autocomplete="off">
{{user-selector usernames=usernames placeholderKey="groups.selector_placeholder" id="user-search-selector" name="usernames"}}
{{d-button action="addMembers" class="add" icon="plus" label="groups.add"}}
</form>
</div>
{{/if}}
{{#load-more selector=".group-members tr" action="loadMore"}}
<table class='group-members'>
<tr>
<th colspan="2">{{i18n 'last_post'}}</th>
<th>{{i18n 'last_seen'}}</th>
{{#if isOwner}}
<th></th>
{{/if}}
</tr>
{{#each model.members as |m|}}
<tr>
<td class='avatar'>
{{user-info user=m}}
{{#if m.owner}}<span class='is-owner'>{{i18n "groups.owner"}}</span>{{/if}}
</td>
<td>
<span class="text">{{bound-date m.last_posted_at}}</span>
</td>
<td>
<span class="text">{{bound-date m.last_seen_at}}</span>
</td>
{{#if isOwner}}
<td class='remove-user'>
{{#unless m.owner}}
<a class="remove-link" {{action "removeMember" m}}><i class="fa fa-times"></i></a>
{{/unless}}
</td>
{{/if}}
</tr>
{{/each}}
</table>
{{/load-more}}
{{else}}
<div>{{i18n "groups.empty.users"}}</div>
{{/if}}

View File

@ -1,45 +0,0 @@
{{#if model}}
{{#if isOwner}}
<div class='clearfix'>
<form id='add-user-to-group' autocomplete="off">
{{user-selector usernames=usernames placeholderKey="groups.selector_placeholder" id="user-search-selector" name="usernames"}}
{{d-button action="addMembers" class="add" icon="plus" label="groups.add"}}
</form>
</div>
{{/if}}
{{#load-more selector=".group-members tr" action="loadMore"}}
<table class='group-members'>
<tr>
<th colspan="2">{{i18n 'last_post'}}</th>
<th>{{i18n 'last_seen'}}</th>
{{#if isOwner}}
<th></th>
{{/if}}
</tr>
{{#each model.members as |m|}}
<tr>
<td class='avatar'>
{{user-info user=m}}
{{#if m.owner}}<span class='is-owner'>{{i18n "groups.owner"}}</span>{{/if}}
</td>
<td>
<span class="text">{{bound-date m.last_posted_at}}</span>
</td>
<td>
<span class="text">{{bound-date m.last_seen_at}}</span>
</td>
{{#if isOwner}}
<td class='remove-user'>
{{#unless m.owner}}
<a class="remove-link" {{action "removeMember" m}}><i class="fa fa-times"></i></a>
{{/unless}}
</td>
{{/if}}
</tr>
{{/each}}
</table>
{{/load-more}}
{{else}}
<div>{{i18n "groups.empty.users"}}</div>
{{/if}}

View File

@ -0,0 +1 @@
{{group-post-stream posts=model emptyText=emptyText loadMore="loadMore"}}