mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Group logs.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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}`, '');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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')
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
});
|
||||
@@ -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 || {};
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ export default function() {
|
||||
this.route('topics');
|
||||
this.route('mentions');
|
||||
this.route('messages');
|
||||
this.route('logs');
|
||||
});
|
||||
|
||||
// User routes
|
||||
|
||||
20
app/assets/javascripts/discourse/routes/group-logs.js.es6
Normal file
20
app/assets/javascripts/discourse/routes/group-logs.js.es6
Normal 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();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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}}
|
||||
@@ -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}}
|
||||
33
app/assets/javascripts/discourse/templates/group-logs.hbs
Normal file
33
app/assets/javascripts/discourse/templates/group-logs.hbs
Normal 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}}
|
||||
@@ -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}}
|
||||
|
||||
Reference in New Issue
Block a user