FEATURE: Group logs.

This commit is contained in:
Guo Xiang Tan
2016-12-11 23:36:15 +08:00
parent 790f1ef9f3
commit 05f55dbc10
37 changed files with 857 additions and 45 deletions

View File

@@ -0,0 +1,21 @@
import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Component.extend({
tagName: '',
@computed('type')
label(type) {
return I18n.t(`groups.logs.${type}`);
},
@computed('value', 'type')
filterText(value, type) {
return type === 'action' ? I18n.t(`group_histories.actions.${value}`) : value;
},
actions: {
clearFilter(param) {
this.sendAction("clearFilter", param);
}
}
});

View File

@@ -0,0 +1,14 @@
export default Ember.Component.extend({
tagName: '',
expandDetails: false,
actions: {
toggleDetails() {
this.toggleProperty('expandDetails');
},
filter(params) {
this.set(`filters.${params.key}`, params.value);
}
}
});

View File

@@ -0,0 +1,57 @@
import { default as computed, observes } from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({
group: Ember.inject.controller(),
loading: false,
offset: 0,
init() {
this._super();
this.set('filters', Ember.Object.create());
},
@computed('filters.action', 'filters.acting_user', 'filters.target_user', 'filters.subject')
filterParams(action, acting_user, target_user, subject) {
return { action, acting_user, target_user, subject };
},
@observes('filters.action', 'filters.acting_user', 'filters.target_user', 'filters.subject')
_refreshModel() {
this.get('group.model').findLogs(0, this.get('filterParams')).then(results => {
this.set('offset', 0);
this.get('model').setProperties({
logs: results.logs,
all_loaded: results.all_loaded
});
});
},
reset() {
this.setProperties({
offset: 0,
filters: Ember.Object.create()
});
},
actions: {
loadMore() {
if (this.get('model.all_loaded')) return;
this.set('loading', true);
this.get('group.model').findLogs(this.get('offset') + 1, this.get('filterParams'))
.then(results => {
results.logs.forEach(result => this.get('model.logs').addObject(result));
this.incrementProperty('offset');
this.set('model.all_loaded', results.all_loaded);
}).finally(() => {
this.set('loading', false);
});
},
clearFilter(key) {
this.set(`filters.${key}`, '');
}
}
});

View File

@@ -6,9 +6,9 @@ var Tab = Em.Object.extend({
return 'group.' + name;
},
@computed('name')
message(name) {
return I18n.t('groups.' + name);
@computed('name', 'i18nKey')
message(name, i18nKey) {
return I18n.t(`groups.${i18nKey || name}`);
}
});
@@ -20,7 +20,8 @@ export default Ember.Controller.extend({
Tab.create({ name: 'posts' }),
Tab.create({ name: 'topics' }),
Tab.create({ name: 'mentions' }),
Tab.create({ name: 'messages', requiresMembership: true })
Tab.create({ name: 'messages', requiresMembership: true }),
Tab.create({ name: 'logs', i18nKey: 'logs.title', icon: 'shield', requiresMembership: true })
],
@computed('model.is_group_owner', 'model.automatic')

View File

@@ -0,0 +1,9 @@
import computed from 'ember-addons/ember-computed-decorators';
import RestModel from 'discourse/models/rest';
export default RestModel.extend({
@computed('action')
actionTitle(action) {
return I18n.t(`group_histories.actions.${action}`);
}
});

View File

@@ -1,5 +1,6 @@
import { ajax } from 'discourse/lib/ajax';
import computed from "ember-addons/ember-computed-decorators";
import GroupHistory from 'discourse/models/group-history';
const Group = Discourse.Model.extend({
limit: 50,
@@ -141,6 +142,15 @@ const Group = Discourse.Model.extend({
return ajax("/admin/groups/" + this.get('id'), { type: "DELETE" });
},
findLogs(offset, filters) {
return ajax(`/groups/${this.get('name')}/logs.json`, { data: { offset, filters } }).then(results => {
return Ember.Object.create({
logs: results["logs"].map(log => GroupHistory.create(log)),
all_loaded: results["all_loaded"]
});
});
},
findPosts(opts) {
opts = opts || {};

View File

@@ -56,6 +56,7 @@ export default function() {
this.route('topics');
this.route('mentions');
this.route('messages');
this.route('logs');
});
// User routes

View File

@@ -0,0 +1,20 @@
export default Ember.Route.extend({
titleToken() {
return I18n.t('groups.logs');
},
model() {
return this.modelFor('group').findLogs();
},
setupController(controller, model) {
this.controllerFor('group-logs').setProperties({ model });
this.controllerFor("group").set("showing", 'logs');
},
actions: {
willTransition() {
this.controllerFor('group-logs').reset();
}
}
});

View File

@@ -0,0 +1,6 @@
{{#if value}}
{{#d-button class="btn-small group-logs-filter" action="clearFilter" actionParam=type}}
<span>{{label}}</span>: {{filterText}}
{{fa-icon "times-circle"}}
{{/d-button}}
{{/if}}

View File

@@ -0,0 +1,59 @@
<tr class="group-logs-row">
<td>
{{#d-button class="btn-small" action="filter" actionParam=(hash value=log.action key="action")}}
{{log.actionTitle}}
{{/d-button}}
</td>
<td>
<span>{{avatar log.acting_user imageSize='tiny'}}</span>
{{#d-button class="btn-small" action="filter" actionParam=(hash value=log.acting_user.username key="acting_user")}}
{{log.acting_user.username}}
{{/d-button}}
</td>
<td>
{{#if log.target_user}}
<span>{{avatar log.target_user imageSize='tiny'}}</span>
{{#d-button class="btn-small" action="filter" actionParam=(hash value=log.target_user.username key="target_user")}}
{{log.target_user.username}}
{{/d-button}}
{{/if}}
</td>
<td>
{{#if log.subject}}
{{#d-button class="btn-small" action="filter" actionParam=(hash value=log.subject key="subject")}}
{{log.subject}}
{{/d-button}}
{{/if}}
</td>
<td>{{bound-date log.created_at}}</td>
<td {{action "toggleDetails"}} class="group-logs-expand-details">
{{#if log.prev_value}}
{{#if expandDetails}}
{{fa-icon 'ellipsis-v'}}
{{else}}
{{fa-icon 'ellipsis-h'}}
{{/if}}
{{/if}}
</td>
</tr>
{{#if expandDetails}}
<tr>
<td colspan='6'>
<p>
<strong>{{i18n 'groups.logs.from'}}</strong>: <code>{{log.prev_value}}</code>
</p>
<p>
<strong>{{i18n 'groups.logs.to'}}</strong>: <code>{{log.new_value}}</code>
</p>
</td>
</tr>
{{/if}}

View File

@@ -0,0 +1,33 @@
{{#if model}}
<div class="group-logs-controls">
{{group-logs-filter clearFilter="clearFilter" value=filters.action type="action"}}
{{group-logs-filter clearFilter="clearFilter" value=filters.acting_user type="acting_user"}}
{{group-logs-filter clearFilter="clearFilter" value=filters.target_user type="target_user"}}
{{group-logs-filter clearFilter="clearFilter" value=filters.subject type="subject"}}
</div>
{{#load-more selector=".group-logs .group-logs-row" action="loadMore"}}
<table class="group-logs">
<thead>
<th>{{i18n 'groups.logs.action'}}</th>
<th>{{i18n 'groups.logs.acting_user'}}</th>
<th>{{i18n 'groups.logs.target_user'}}</th>
<th>{{i18n 'groups.logs.subject'}}</th>
<th>{{i18n 'groups.logs.when'}}</th>
<th></th>
</thead>
<tbody>
{{#each model.logs as |log|}}
{{group-logs-row
log=log
filters=filters}}
{{/each}}
</tbody>
</table>
{{/load-more}}
{{conditional-loading-spinner condition=loading}}
{{else}}
<div>{{i18n "groups.empty.logs"}}</div>
{{/if}}

View File

@@ -41,6 +41,7 @@
{{#each getTabs as |tab|}}
<li class="{{if tab.active 'active'}}">
{{#link-to tab.location model title=tab.message}}
{{#if tab.icon}}{{fa-icon tab.icon}}{{/if}}
{{tab.message}}
{{#if tab.count}}<span class='count'>({{tab.count}})</span>{{/if}}
{{/link-to}}