mirror of
https://github.com/discourse/discourse.git
synced 2025-05-29 10:57:16 +08:00
UX: separate custom from automatic groups in user admin
REFACTOR: some moar ES6 refactoring
This commit is contained in:
@ -1,31 +1,36 @@
|
|||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
tagName: 'div',
|
tagName: 'div',
|
||||||
|
|
||||||
didInsertElement: function(){
|
_init: function(){
|
||||||
this.$("input").select2({
|
this.$("input").select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
query: function(opts){
|
query: function(opts) {
|
||||||
opts.callback({
|
opts.callback({ results: this.get("available").map(this._format) });
|
||||||
results: this.get("available").map(this._format)
|
|
||||||
});
|
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
}).on("change", function(evt) {
|
}).on("change", function(evt) {
|
||||||
if (evt.added){
|
if (evt.added){
|
||||||
this.triggerAction({action: "groupAdded",
|
this.triggerAction({
|
||||||
actionContext: this.get("available"
|
action: "groupAdded",
|
||||||
).findBy("id", evt.added.id)});
|
actionContext: this.get("available").findBy("id", evt.added.id)
|
||||||
|
});
|
||||||
} else if (evt.removed) {
|
} else if (evt.removed) {
|
||||||
this.triggerAction({action:"groupRemoved",
|
this.triggerAction({
|
||||||
actionContext: this.get("selected"
|
action:"groupRemoved",
|
||||||
).findBy("id", evt.removed.id)});
|
actionContext: evt.removed.id
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
this._refreshOnReset();
|
|
||||||
},
|
|
||||||
|
|
||||||
_format: function(item){
|
this._refreshOnReset();
|
||||||
return {"text": item.name, "id": item.id, "locked": item.automatic};
|
}.on("didInsertElement"),
|
||||||
|
|
||||||
|
_format(item) {
|
||||||
|
return {
|
||||||
|
"text": item.name,
|
||||||
|
"id": item.id,
|
||||||
|
"locked": item.automatic
|
||||||
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
_refreshOnReset: function() {
|
_refreshOnReset: function() {
|
||||||
|
@ -11,58 +11,61 @@ export default ObjectController.extend(CanCheckEmails, {
|
|||||||
|
|
||||||
primaryGroupDirty: Discourse.computed.propertyNotEqual('originalPrimaryGroupId', 'primary_group_id'),
|
primaryGroupDirty: Discourse.computed.propertyNotEqual('originalPrimaryGroupId', 'primary_group_id'),
|
||||||
|
|
||||||
custom_groups: Ember.computed.filter("model.groups", function(g){
|
automaticGroups: function() {
|
||||||
return (!g.automatic && g.visible);
|
return this.get("model.automaticGroups").map((g) => g.name).join(", ");
|
||||||
}),
|
}.property("model.automaticGroups"),
|
||||||
|
|
||||||
userFields: function() {
|
userFields: function() {
|
||||||
var siteUserFields = this.site.get('user_fields'),
|
const siteUserFields = this.site.get('user_fields'),
|
||||||
userFields = this.get('user_fields');
|
userFields = this.get('user_fields');
|
||||||
|
|
||||||
if (!Ember.isEmpty(siteUserFields)) {
|
if (!Ember.isEmpty(siteUserFields)) {
|
||||||
return siteUserFields.map(function(uf) {
|
return siteUserFields.map(function(uf) {
|
||||||
var value = userFields ? userFields[uf.get('id').toString()] : null;
|
let value = userFields ? userFields[uf.get('id').toString()] : null;
|
||||||
return {name: uf.get('name'), value: value};
|
return { name: uf.get('name'), value: value };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
}.property('user_fields.@each'),
|
}.property('user_fields.@each'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
toggleTitleEdit: function() {
|
toggleTitleEdit() {
|
||||||
this.toggleProperty('editingTitle');
|
this.toggleProperty('editingTitle');
|
||||||
},
|
},
|
||||||
|
|
||||||
saveTitle: function() {
|
saveTitle() {
|
||||||
Discourse.ajax("/users/" + this.get('username').toLowerCase(), {
|
const self = this;
|
||||||
|
|
||||||
|
return Discourse.ajax("/users/" + this.get('username').toLowerCase(), {
|
||||||
data: {title: this.get('title')},
|
data: {title: this.get('title')},
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
}).then(null, function(e){
|
}).catch(function(e) {
|
||||||
bootbox.alert(I18n.t("generic_error_with_reason", {error: "http: " + e.status + " - " + e.body}));
|
bootbox.alert(I18n.t("generic_error_with_reason", {error: "http: " + e.status + " - " + e.body}));
|
||||||
|
}).finally(function() {
|
||||||
|
self.send('toggleTitleEdit');
|
||||||
});
|
});
|
||||||
|
|
||||||
this.send('toggleTitleEdit');
|
|
||||||
},
|
},
|
||||||
|
|
||||||
generateApiKey: function() {
|
generateApiKey() {
|
||||||
this.get('model').generateApiKey();
|
this.get('model').generateApiKey();
|
||||||
},
|
},
|
||||||
|
|
||||||
groupAdded: function(added){
|
groupAdded(added) {
|
||||||
this.get('model').groupAdded(added).catch(function() {
|
this.get('model').groupAdded(added).catch(function() {
|
||||||
bootbox.alert(I18n.t('generic_error'));
|
bootbox.alert(I18n.t('generic_error'));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
groupRemoved: function(removed){
|
groupRemoved(groupId) {
|
||||||
this.get('model').groupRemoved(removed).catch(function() {
|
this.get('model').groupRemoved(groupId).catch(function() {
|
||||||
bootbox.alert(I18n.t('generic_error'));
|
bootbox.alert(I18n.t('generic_error'));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
savePrimaryGroup: function() {
|
savePrimaryGroup() {
|
||||||
var self = this;
|
const self = this;
|
||||||
Discourse.ajax("/admin/users/" + this.get('id') + "/primary_group", {
|
|
||||||
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/primary_group", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {primary_group_id: this.get('primary_group_id')}
|
data: {primary_group_id: this.get('primary_group_id')}
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
@ -72,33 +75,41 @@ export default ObjectController.extend(CanCheckEmails, {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
resetPrimaryGroup: function() {
|
resetPrimaryGroup() {
|
||||||
this.set('primary_group_id', this.get('originalPrimaryGroupId'));
|
this.set('primary_group_id', this.get('originalPrimaryGroupId'));
|
||||||
},
|
},
|
||||||
|
|
||||||
regenerateApiKey: function() {
|
regenerateApiKey() {
|
||||||
var self = this;
|
const self = this;
|
||||||
bootbox.confirm(I18n.t("admin.api.confirm_regen"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
|
||||||
if (result) {
|
bootbox.confirm(
|
||||||
self.get('model').generateApiKey();
|
I18n.t("admin.api.confirm_regen"),
|
||||||
|
I18n.t("no_value"),
|
||||||
|
I18n.t("yes_value"),
|
||||||
|
function(result) {
|
||||||
|
if (result) { self.get('model').generateApiKey(); }
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
revokeApiKey: function() {
|
revokeApiKey() {
|
||||||
var self = this;
|
const self = this;
|
||||||
bootbox.confirm(I18n.t("admin.api.confirm_revoke"), I18n.t("no_value"), I18n.t("yes_value"), function(result) {
|
|
||||||
if (result) {
|
bootbox.confirm(
|
||||||
self.get('model').revokeApiKey();
|
I18n.t("admin.api.confirm_revoke"),
|
||||||
|
I18n.t("no_value"),
|
||||||
|
I18n.t("yes_value"),
|
||||||
|
function(result) {
|
||||||
|
if (result) { self.get('model').revokeApiKey(); }
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
anonymize: function() {
|
anonymize() {
|
||||||
this.get('model').anonymize();
|
this.get('model').anonymize();
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function() {
|
destroy() {
|
||||||
this.get('model').destroy();
|
this.get('model').destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,58 +1,36 @@
|
|||||||
/**
|
const AdminUser = Discourse.User.extend({
|
||||||
Our data model for dealing with users from the admin section.
|
|
||||||
|
|
||||||
@class AdminUser
|
customGroups: Em.computed.filter("groups", (g) => !g.automatic && g.visible && Discourse.Group.create(g)),
|
||||||
@extends Discourse.Model
|
automaticGroups: Em.computed.filter("groups", (g) => g.automatic && Discourse.Group.create(g)),
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AdminUser = Discourse.User.extend({
|
|
||||||
|
|
||||||
/**
|
generateApiKey() {
|
||||||
Generates an API key for the user. Will regenerate if they already have one.
|
const self = this;
|
||||||
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/generate_api_key", {
|
||||||
@method generateApiKey
|
type: 'POST'
|
||||||
@returns {Promise} a promise that resolves to the newly generated API key
|
}).then(function (result) {
|
||||||
**/
|
const apiKey = Discourse.ApiKey.create(result.api_key);
|
||||||
generateApiKey: function() {
|
|
||||||
var self = this;
|
|
||||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/generate_api_key", {type: 'POST'}).then(function (result) {
|
|
||||||
var apiKey = Discourse.ApiKey.create(result.api_key);
|
|
||||||
self.set('api_key', apiKey);
|
self.set('api_key', apiKey);
|
||||||
return apiKey;
|
return apiKey;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
groupAdded: function(added){
|
groupAdded(added) {
|
||||||
var self = this;
|
|
||||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups", {
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups", {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: {group_id: added.id}
|
data: { group_id: added.id }
|
||||||
}).then(function () {
|
}).then(() => this.get('groups').pushObject(added));
|
||||||
self.get('groups').pushObject(added);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
groupRemoved: function(removed){
|
groupRemoved(groupId) {
|
||||||
var self = this;
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups/" + groupId, {
|
||||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/groups/" + removed.id, {
|
|
||||||
type: 'DELETE'
|
type: 'DELETE'
|
||||||
}).then(function () {
|
}).then(() => this.set('groups.[]', this.get('groups').rejectBy("id", groupId)));
|
||||||
self.set('groups.[]', self.get('groups').rejectBy("id", removed.id));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
revokeApiKey() {
|
||||||
Revokes a user's current API key
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_api_key", {
|
||||||
|
type: 'DELETE'
|
||||||
@method revokeApiKey
|
}).then(() => this.set('api_key', null));
|
||||||
@returns {Promise} a promise that resolves when the API key has been deleted
|
|
||||||
**/
|
|
||||||
revokeApiKey: function() {
|
|
||||||
var self = this;
|
|
||||||
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_api_key", {type: 'DELETE'}).then(function () {
|
|
||||||
self.set('api_key', null);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteAllPostsExplanation: function() {
|
deleteAllPostsExplanation: function() {
|
||||||
@ -70,10 +48,10 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
}
|
}
|
||||||
}.property('can_delete_all_posts', 'deleteForbidden'),
|
}.property('can_delete_all_posts', 'deleteForbidden'),
|
||||||
|
|
||||||
deleteAllPosts: function() {
|
deleteAllPosts() {
|
||||||
var user = this;
|
const user = this,
|
||||||
var message = I18n.t('admin.user.delete_all_posts_confirm', {posts: user.get('post_count'), topics: user.get('topic_count')});
|
message = I18n.t('admin.user.delete_all_posts_confirm', { posts: user.get('post_count'), topics: user.get('topic_count') }),
|
||||||
var buttons = [{
|
buttons = [{
|
||||||
"label": I18n.t("composer.cancel"),
|
"label": I18n.t("composer.cancel"),
|
||||||
"class": "cancel-inline",
|
"class": "cancel-inline",
|
||||||
"link": true
|
"link": true
|
||||||
@ -81,35 +59,39 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("admin.user.delete_all_posts"),
|
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("admin.user.delete_all_posts"),
|
||||||
"class": "btn btn-danger",
|
"class": "btn btn-danger",
|
||||||
"callback": function() {
|
"callback": function() {
|
||||||
Discourse.ajax("/admin/users/" + (user.get('id')) + "/delete_all_posts", {type: 'PUT'}).then(function(){
|
Discourse.ajax("/admin/users/" + user.get('id') + "/delete_all_posts", {
|
||||||
user.set('post_count', 0);
|
type: 'PUT'
|
||||||
});
|
}).then(() => user.set('post_count', 0));
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
bootbox.dialog(message, buttons, {"classes": "delete-all-posts"});
|
bootbox.dialog(message, buttons, { "classes": "delete-all-posts" });
|
||||||
},
|
},
|
||||||
|
|
||||||
// Revoke the user's admin access
|
revokeAdmin() {
|
||||||
revokeAdmin: function() {
|
const self = this;
|
||||||
this.set('admin', false);
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_admin", {
|
||||||
this.set('can_grant_admin', true);
|
type: 'PUT'
|
||||||
this.set('can_revoke_admin', false);
|
}).then(function() {
|
||||||
return Discourse.ajax("/admin/users/" + (this.get('id')) + "/revoke_admin", {type: 'PUT'});
|
self.setProperties({
|
||||||
|
admin: false,
|
||||||
|
can_grant_admin: true,
|
||||||
|
can_revoke_admin: false
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
grantAdmin: function() {
|
grantAdmin() {
|
||||||
this.set('admin', true);
|
const self = this;
|
||||||
this.set('can_grant_admin', false);
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/grant_admin", {
|
||||||
this.set('can_revoke_admin', true);
|
type: 'PUT'
|
||||||
var self = this;
|
}).then(function() {
|
||||||
|
self.setProperties({
|
||||||
Discourse.ajax("/admin/users/" + (this.get('id')) + "/grant_admin", {type: 'PUT'})
|
admin: true,
|
||||||
.then(null, function(e) {
|
can_grant_admin: false,
|
||||||
self.set('admin', false);
|
can_revoke_admin: true
|
||||||
self.set('can_grant_admin', true);
|
});
|
||||||
self.set('can_revoke_admin', false);
|
}).catch(function(e) {
|
||||||
|
let error;
|
||||||
var error;
|
|
||||||
if (e.responseJSON && e.responseJSON.error) {
|
if (e.responseJSON && e.responseJSON.error) {
|
||||||
error = e.responseJSON.error;
|
error = e.responseJSON.error;
|
||||||
}
|
}
|
||||||
@ -118,26 +100,31 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Revoke the user's moderation access
|
revokeModeration() {
|
||||||
revokeModeration: function() {
|
const self = this;
|
||||||
this.set('moderator', false);
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/revoke_moderation", {
|
||||||
this.set('can_grant_moderation', true);
|
type: 'PUT'
|
||||||
this.set('can_revoke_moderation', false);
|
}).then(function() {
|
||||||
return Discourse.ajax("/admin/users/" + (this.get('id')) + "/revoke_moderation", {type: 'PUT'});
|
self.setProperties({
|
||||||
|
moderator: false,
|
||||||
|
can_grant_moderation: true,
|
||||||
|
can_revoke_moderation: false
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
grantModeration: function() {
|
grantModeration() {
|
||||||
this.set('moderator', true);
|
const self = this;
|
||||||
this.set('can_grant_moderation', false);
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/grant_moderation", {
|
||||||
this.set('can_revoke_moderation', true);
|
type: 'PUT'
|
||||||
var self = this;
|
}).then(function() {
|
||||||
Discourse.ajax("/admin/users/" + (this.get('id')) + "/grant_moderation", {type: 'PUT'})
|
self.setProperties({
|
||||||
.then(null, function(e) {
|
moderator: true,
|
||||||
self.set('moderator', false);
|
can_grant_moderation: false,
|
||||||
self.set('can_grant_moderation', true);
|
can_revoke_moderation: true
|
||||||
self.set('can_revoke_moderation', false);
|
});
|
||||||
|
}).catch(function(e) {
|
||||||
var error;
|
let error;
|
||||||
if (e.responseJSON && e.responseJSON.error) {
|
if (e.responseJSON && e.responseJSON.error) {
|
||||||
error = e.responseJSON.error;
|
error = e.responseJSON.error;
|
||||||
}
|
}
|
||||||
@ -146,23 +133,26 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refreshBrowsers: function() {
|
refreshBrowsers() {
|
||||||
Discourse.ajax("/admin/users/" + (this.get('id')) + "/refresh_browsers", {type: 'POST'});
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/refresh_browsers", {
|
||||||
bootbox.alert(I18n.t("admin.user.refresh_browsers_message"));
|
type: 'POST'
|
||||||
|
}).finally(() => bootbox.alert(I18n.t("admin.user.refresh_browsers_message")));
|
||||||
},
|
},
|
||||||
|
|
||||||
approve: function() {
|
approve() {
|
||||||
this.set('can_approve', false);
|
const self = this;
|
||||||
this.set('approved', true);
|
return Discourse.ajax("/admin/users/" + this.get('id') + "/approve", {
|
||||||
this.set('approved_by', Discourse.User.current());
|
type: 'PUT'
|
||||||
Discourse.ajax("/admin/users/" + (this.get('id')) + "/approve", {type: 'PUT'});
|
}).then(function() {
|
||||||
|
self.setProperties({
|
||||||
|
can_approve: false,
|
||||||
|
approved: true,
|
||||||
|
approved_by: Discourse.User.current()
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
username_lower: (function() {
|
setOriginalTrustLevel() {
|
||||||
return this.get('username').toLowerCase();
|
|
||||||
}).property('username'),
|
|
||||||
|
|
||||||
setOriginalTrustLevel: function() {
|
|
||||||
this.set('originalTrustLevel', this.get('trust_level'));
|
this.set('originalTrustLevel', this.get('trust_level'));
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -172,16 +162,14 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
|
|
||||||
dirty: Discourse.computed.propertyNotEqual('originalTrustLevel', 'trustLevel.id'),
|
dirty: Discourse.computed.propertyNotEqual('originalTrustLevel', 'trustLevel.id'),
|
||||||
|
|
||||||
saveTrustLevel: function() {
|
saveTrustLevel() {
|
||||||
Discourse.ajax("/admin/users/" + this.id + "/trust_level", {
|
return Discourse.ajax("/admin/users/" + this.id + "/trust_level", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {level: this.get('trustLevel.id')}
|
data: { level: this.get('trustLevel.id') }
|
||||||
}).then(function () {
|
}).then(function() {
|
||||||
// succeeded
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failure
|
let error;
|
||||||
var error;
|
|
||||||
if (e.responseJSON && e.responseJSON.errors) {
|
if (e.responseJSON && e.responseJSON.errors) {
|
||||||
error = e.responseJSON.errors[0];
|
error = e.responseJSON.errors[0];
|
||||||
}
|
}
|
||||||
@ -190,20 +178,18 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
restoreTrustLevel: function() {
|
restoreTrustLevel() {
|
||||||
this.set('trustLevel.id', this.get('originalTrustLevel'));
|
this.set('trustLevel.id', this.get('originalTrustLevel'));
|
||||||
},
|
},
|
||||||
|
|
||||||
lockTrustLevel: function(locked) {
|
lockTrustLevel(locked) {
|
||||||
Discourse.ajax("/admin/users/" + this.id + "/trust_level_lock", {
|
return Discourse.ajax("/admin/users/" + this.id + "/trust_level_lock", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: { locked: !!locked }
|
data: { locked: !!locked }
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
// succeeded
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failure
|
let error;
|
||||||
var error;
|
|
||||||
if (e.responseJSON && e.responseJSON.errors) {
|
if (e.responseJSON && e.responseJSON.errors) {
|
||||||
error = e.responseJSON.errors[0];
|
error = e.responseJSON.errors[0];
|
||||||
}
|
}
|
||||||
@ -212,7 +198,7 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
canLockTrustLevel: function(){
|
canLockTrustLevel: function() {
|
||||||
return this.get('trust_level') < 4;
|
return this.get('trust_level') < 4;
|
||||||
}.property('trust_level'),
|
}.property('trust_level'),
|
||||||
|
|
||||||
@ -220,51 +206,45 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
canSuspend: Em.computed.not('staff'),
|
canSuspend: Em.computed.not('staff'),
|
||||||
|
|
||||||
suspendDuration: function() {
|
suspendDuration: function() {
|
||||||
var suspended_at = moment(this.suspended_at);
|
const suspended_at = moment(this.suspended_at),
|
||||||
var suspended_till = moment(this.suspended_till);
|
suspended_till = moment(this.suspended_till);
|
||||||
return suspended_at.format('L') + " - " + suspended_till.format('L');
|
return suspended_at.format('L') + " - " + suspended_till.format('L');
|
||||||
}.property('suspended_till', 'suspended_at'),
|
}.property('suspended_till', 'suspended_at'),
|
||||||
|
|
||||||
suspend: function(duration, reason) {
|
suspend(duration, reason) {
|
||||||
return Discourse.ajax("/admin/users/" + this.id + "/suspend", {
|
return Discourse.ajax("/admin/users/" + this.id + "/suspend", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {duration: duration, reason: reason}
|
data: { duration: duration, reason: reason }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
unsuspend: function() {
|
unsuspend() {
|
||||||
Discourse.ajax("/admin/users/" + this.id + "/unsuspend", {
|
return Discourse.ajax("/admin/users/" + this.id + "/unsuspend", {
|
||||||
type: 'PUT'
|
type: 'PUT'
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
// succeeded
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.unsuspend_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.unsuspend_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
log_out: function(){
|
log_out() {
|
||||||
Discourse.ajax("/admin/users/" + this.id + "/log_out", {
|
return Discourse.ajax("/admin/users/" + this.id + "/log_out", {
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: { username_or_email: this.get('username') }
|
data: { username_or_email: this.get('username') }
|
||||||
}).then(
|
}).then(function() {
|
||||||
function(){
|
bootbox.alert(I18n.t("admin.user.logged_out"));
|
||||||
bootbox.alert(I18n.t("admin.user.logged_out"));
|
});
|
||||||
}
|
},
|
||||||
);
|
|
||||||
},
|
impersonate() {
|
||||||
|
return Discourse.ajax("/admin/impersonate", {
|
||||||
impersonate: function() {
|
|
||||||
Discourse.ajax("/admin/impersonate", {
|
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
data: { username_or_email: this.get('username') }
|
data: { username_or_email: this.get('username') }
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
// succeeded
|
|
||||||
document.location = "/";
|
document.location = "/";
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
if (e.status === 404) {
|
if (e.status === 404) {
|
||||||
bootbox.alert(I18n.t('admin.impersonate.not_found'));
|
bootbox.alert(I18n.t('admin.impersonate.not_found'));
|
||||||
} else {
|
} else {
|
||||||
@ -273,56 +253,57 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
activate: function() {
|
activate() {
|
||||||
Discourse.ajax('/admin/users/' + this.id + '/activate', {type: 'PUT'}).then(function() {
|
return Discourse.ajax('/admin/users/' + this.id + '/activate', {
|
||||||
// succeeded
|
type: 'PUT'
|
||||||
|
}).then(function() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.activate_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.activate_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
deactivate: function() {
|
deactivate() {
|
||||||
Discourse.ajax('/admin/users/' + this.id + '/deactivate', {type: 'PUT'}).then(function() {
|
return Discourse.ajax('/admin/users/' + this.id + '/deactivate', {
|
||||||
// succeeded
|
type: 'PUT'
|
||||||
|
}).then(function() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.deactivate_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.deactivate_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
unblock: function() {
|
unblock() {
|
||||||
Discourse.ajax('/admin/users/' + this.id + '/unblock', {type: 'PUT'}).then(function() {
|
return Discourse.ajax('/admin/users/' + this.id + '/unblock', {
|
||||||
// succeeded
|
type: 'PUT'
|
||||||
|
}).then(function() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.unblock_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.unblock_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
block: function() {
|
block() {
|
||||||
Discourse.ajax('/admin/users/' + this.id + '/block', {type: 'PUT'}).then(function() {
|
return Discourse.ajax('/admin/users/' + this.id + '/block', {
|
||||||
// succeeded
|
type: 'PUT'
|
||||||
|
}).then(function() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.block_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.block_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
sendActivationEmail: function() {
|
sendActivationEmail() {
|
||||||
Discourse.ajax('/users/action/send_activation_email', {data: {username: this.get('username')}, type: 'POST'}).then(function() {
|
return Discourse.ajax('/users/action/send_activation_email', {
|
||||||
// succeeded
|
type: 'POST',
|
||||||
|
data: { username: this.get('username') }
|
||||||
|
}).then(function() {
|
||||||
bootbox.alert( I18n.t('admin.user.activation_email_sent') );
|
bootbox.alert( I18n.t('admin.user.activation_email_sent') );
|
||||||
}, function(e) {
|
}).catch(function(e) {
|
||||||
// failed
|
|
||||||
var error = I18n.t('admin.user.send_activation_email_failed', { error: "http: " + e.status + " - " + e.body });
|
var error = I18n.t('admin.user.send_activation_email_failed', { error: "http: " + e.status + " - " + e.body });
|
||||||
bootbox.alert(error);
|
bootbox.alert(error);
|
||||||
});
|
});
|
||||||
@ -330,11 +311,14 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
|
|
||||||
anonymizeForbidden: Em.computed.not("can_be_anonymized"),
|
anonymizeForbidden: Em.computed.not("can_be_anonymized"),
|
||||||
|
|
||||||
anonymize: function() {
|
anonymize() {
|
||||||
var user = this;
|
const user = this,
|
||||||
|
message = I18n.t("admin.user.anonymize_confirm");
|
||||||
|
|
||||||
var performAnonymize = function() {
|
const performAnonymize = function() {
|
||||||
Discourse.ajax("/admin/users/" + user.get('id') + '/anonymize.json', {type: 'PUT'}).then(function(data) {
|
return Discourse.ajax("/admin/users/" + user.get('id') + '/anonymize.json', {
|
||||||
|
type: 'PUT'
|
||||||
|
}).then(function(data) {
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
if (data.username) {
|
if (data.username) {
|
||||||
document.location = "/admin/users/" + data.username;
|
document.location = "/admin/users/" + data.username;
|
||||||
@ -347,26 +331,22 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
user.setProperties(data.user);
|
user.setProperties(data.user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, function() {
|
}).catch(function() {
|
||||||
bootbox.alert(I18n.t("admin.user.anonymize_failed"));
|
bootbox.alert(I18n.t("admin.user.anonymize_failed"));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var message = I18n.t("admin.user.anonymize_confirm");
|
const buttons = [{
|
||||||
|
|
||||||
var buttons = [{
|
|
||||||
"label": I18n.t("composer.cancel"),
|
"label": I18n.t("composer.cancel"),
|
||||||
"class": "cancel",
|
"class": "cancel",
|
||||||
"link": true
|
"link": true
|
||||||
}, {
|
}, {
|
||||||
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.anonymize_yes'),
|
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.anonymize_yes'),
|
||||||
"class": "btn btn-danger",
|
"class": "btn btn-danger",
|
||||||
"callback": function(){
|
"callback": function() { performAnonymize(); }
|
||||||
performAnonymize();
|
|
||||||
}
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
bootbox.dialog(message, buttons, {"classes": "delete-user-modal"});
|
bootbox.dialog(message, buttons, { "classes": "delete-user-modal" });
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteForbidden: Em.computed.not("canBeDeleted"),
|
deleteForbidden: Em.computed.not("canBeDeleted"),
|
||||||
@ -383,12 +363,13 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
}
|
}
|
||||||
}.property('deleteForbidden'),
|
}.property('deleteForbidden'),
|
||||||
|
|
||||||
destroy: function(opts) {
|
destroy(opts) {
|
||||||
var user = this;
|
const user = this,
|
||||||
var location = document.location.pathname;
|
message = I18n.t("admin.user.delete_confirm"),
|
||||||
|
location = document.location.pathname;
|
||||||
|
|
||||||
var performDestroy = function(block) {
|
const performDestroy = function(block) {
|
||||||
var formData = { context: location };
|
let formData = { context: location };
|
||||||
if (block) {
|
if (block) {
|
||||||
formData["block_email"] = true;
|
formData["block_email"] = true;
|
||||||
formData["block_urls"] = true;
|
formData["block_urls"] = true;
|
||||||
@ -397,7 +378,7 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
if (opts && opts.deletePosts) {
|
if (opts && opts.deletePosts) {
|
||||||
formData["delete_posts"] = true;
|
formData["delete_posts"] = true;
|
||||||
}
|
}
|
||||||
Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
return Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
data: formData
|
data: formData
|
||||||
}).then(function(data) {
|
}).then(function(data) {
|
||||||
@ -413,47 +394,42 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
user.setProperties(data.user);
|
user.setProperties(data.user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, function() {
|
}).catch(function() {
|
||||||
Discourse.AdminUser.find( user.get('username') ).then(function(u){ user.setProperties(u); });
|
Discourse.AdminUser.find( user.get('username') ).then(function(u){ user.setProperties(u); });
|
||||||
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var message = I18n.t("admin.user.delete_confirm");
|
const buttons = [{
|
||||||
|
|
||||||
var buttons = [{
|
|
||||||
"label": I18n.t("composer.cancel"),
|
"label": I18n.t("composer.cancel"),
|
||||||
"class": "cancel",
|
"class": "cancel",
|
||||||
"link": true
|
"link": true
|
||||||
}, {
|
}, {
|
||||||
"label": I18n.t('admin.user.delete_dont_block'),
|
"label": I18n.t('admin.user.delete_dont_block'),
|
||||||
"class": "btn",
|
"class": "btn",
|
||||||
"callback": function(){
|
"callback": function(){ performDestroy(false); }
|
||||||
performDestroy(false);
|
|
||||||
}
|
|
||||||
}, {
|
}, {
|
||||||
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.delete_and_block'),
|
"label": '<i class="fa fa-exclamation-triangle"></i>' + I18n.t('admin.user.delete_and_block'),
|
||||||
"class": "btn btn-danger",
|
"class": "btn btn-danger",
|
||||||
"callback": function(){
|
"callback": function(){ performDestroy(true); }
|
||||||
performDestroy(true);
|
|
||||||
}
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
bootbox.dialog(message, buttons, {"classes": "delete-user-modal"});
|
bootbox.dialog(message, buttons, { "classes": "delete-user-modal" });
|
||||||
},
|
},
|
||||||
|
|
||||||
deleteAsSpammer: function(successCallback) {
|
deleteAsSpammer(successCallback) {
|
||||||
var user = this;
|
const user = this;
|
||||||
|
|
||||||
user.checkEmail().then(function() {
|
user.checkEmail().then(function() {
|
||||||
var data = {
|
const data = {
|
||||||
posts: user.get('post_count'),
|
posts: user.get('post_count'),
|
||||||
topics: user.get('topic_count'),
|
topics: user.get('topic_count'),
|
||||||
email: user.get('email') || I18n.t("flagging.hidden_email_address"),
|
email: user.get('email') || I18n.t("flagging.hidden_email_address"),
|
||||||
ip_address: user.get('ip_address') || I18n.t("flagging.ip_address_missing")
|
ip_address: user.get('ip_address') || I18n.t("flagging.ip_address_missing")
|
||||||
};
|
};
|
||||||
var message = I18n.t('flagging.delete_confirm', data);
|
|
||||||
var buttons = [{
|
const message = I18n.t('flagging.delete_confirm', data),
|
||||||
|
buttons = [{
|
||||||
"label": I18n.t("composer.cancel"),
|
"label": I18n.t("composer.cancel"),
|
||||||
"class": "cancel-inline",
|
"class": "cancel-inline",
|
||||||
"link": true
|
"link": true
|
||||||
@ -461,7 +437,7 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("flagging.yes_delete_spammer"),
|
"label": '<i class="fa fa-exclamation-triangle"></i> ' + I18n.t("flagging.yes_delete_spammer"),
|
||||||
"class": "btn btn-danger",
|
"class": "btn btn-danger",
|
||||||
"callback": function() {
|
"callback": function() {
|
||||||
Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
return Discourse.ajax("/admin/users/" + user.get('id') + '.json', {
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
data: {
|
data: {
|
||||||
delete_posts: true,
|
delete_posts: true,
|
||||||
@ -477,23 +453,24 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
} else {
|
} else {
|
||||||
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
||||||
}
|
}
|
||||||
}, function() {
|
}).catch(function() {
|
||||||
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
bootbox.alert(I18n.t("admin.user.delete_failed"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
bootbox.dialog(message, buttons, {"classes": "flagging-delete-spammer"});
|
bootbox.dialog(message, buttons, {"classes": "flagging-delete-spammer"});
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
loadDetails: function() {
|
loadDetails() {
|
||||||
var model = this;
|
const user = this;
|
||||||
if (model.get('loadedDetails')) { return Ember.RSVP.resolve(model); }
|
|
||||||
|
|
||||||
return Discourse.AdminUser.find(model.get('username_lower')).then(function (result) {
|
if (user.get('loadedDetails')) { return Ember.RSVP.resolve(user); }
|
||||||
model.setProperties(result);
|
|
||||||
model.set('loadedDetails', true);
|
return Discourse.AdminUser.find(user.get('username_lower')).then(function (result) {
|
||||||
|
user.setProperties(result);
|
||||||
|
user.set('loadedDetails', true);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -517,29 +494,25 @@ Discourse.AdminUser = Discourse.User.extend({
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Discourse.AdminUser.reopenClass({
|
AdminUser.reopenClass({
|
||||||
|
|
||||||
bulkApprove: function(users) {
|
bulkApprove(users) {
|
||||||
_.each(users, function(user) {
|
_.each(users, function(user) {
|
||||||
user.set('approved', true);
|
user.setProperties({
|
||||||
user.set('can_approve', false);
|
approved: true,
|
||||||
return user.set('selected', false);
|
can_approve: false,
|
||||||
|
selected: false
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
bootbox.alert(I18n.t("admin.user.approve_bulk_success"));
|
|
||||||
|
|
||||||
return Discourse.ajax("/admin/users/approve-bulk", {
|
return Discourse.ajax("/admin/users/approve-bulk", {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
data: {
|
data: { users: users.map((u) => u.id) }
|
||||||
users: users.map(function(u) {
|
}).finally(() => bootbox.alert(I18n.t("admin.user.approve_bulk_success")));
|
||||||
return u.id;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
bulkReject: function(users) {
|
bulkReject(users) {
|
||||||
_.each(users, function(user){
|
_.each(users, function(user) {
|
||||||
user.set('can_approve', false);
|
user.set('can_approve', false);
|
||||||
user.set('selected', false);
|
user.set('selected', false);
|
||||||
});
|
});
|
||||||
@ -547,26 +520,26 @@ Discourse.AdminUser.reopenClass({
|
|||||||
return Discourse.ajax("/admin/users/reject-bulk", {
|
return Discourse.ajax("/admin/users/reject-bulk", {
|
||||||
type: 'DELETE',
|
type: 'DELETE',
|
||||||
data: {
|
data: {
|
||||||
users: users.map(function(u) { return u.id; }),
|
users: users.map((u) => u.id),
|
||||||
context: window.location.pathname
|
context: window.location.pathname
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
find: function(username) {
|
find(username) {
|
||||||
return Discourse.ajax("/admin/users/" + username + ".json").then(function (result) {
|
return Discourse.ajax("/admin/users/" + username + ".json").then(function (result) {
|
||||||
result.loadedDetails = true;
|
result.loadedDetails = true;
|
||||||
return Discourse.AdminUser.create(result);
|
return Discourse.AdminUser.create(result);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
findAll: function(query, filter) {
|
findAll(query, filter) {
|
||||||
return Discourse.ajax("/admin/users/list/" + query + ".json", {
|
return Discourse.ajax("/admin/users/list/" + query + ".json", {
|
||||||
data: filter
|
data: filter
|
||||||
}).then(function(users) {
|
}).then(function(users) {
|
||||||
return users.map(function(u) {
|
return users.map((u) => Discourse.AdminUser.create(u));
|
||||||
return Discourse.AdminUser.create(u);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default AdminUser;
|
@ -3,18 +3,18 @@
|
|||||||
<div class='user-controls'>
|
<div class='user-controls'>
|
||||||
{{#if active}}
|
{{#if active}}
|
||||||
{{#link-to 'user' model class="btn"}}
|
{{#link-to 'user' model class="btn"}}
|
||||||
<i class='fa fa-user'></i>
|
{{fa-icon "user"}}
|
||||||
{{i18n 'admin.user.show_public_profile'}}
|
{{i18n 'admin.user.show_public_profile'}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
{{#if can_impersonate}}
|
{{#if can_impersonate}}
|
||||||
<button class='btn btn-danger' {{action "impersonate" target="content"}} title="{{i18n 'admin.impersonate.help'}}">
|
<button class='btn btn-danger' {{action "impersonate" target="content"}} title="{{i18n 'admin.impersonate.help'}}">
|
||||||
<i class='fa fa-crosshairs'></i>
|
{{fa-icon "crosshairs"}}
|
||||||
{{i18n 'admin.impersonate.title'}}
|
{{i18n 'admin.impersonate.title'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if currentUser.admin}}
|
{{#if currentUser.admin}}
|
||||||
<button class='btn' {{action "log_out" target="content"}}>
|
<button class='btn' {{action "log_out" target="content"}}>
|
||||||
<i class='fa fa-power-off'></i>
|
{{fa-icon "power-off"}}
|
||||||
{{i18n 'admin.user.log_out'}}
|
{{i18n 'admin.user.log_out'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -26,7 +26,7 @@
|
|||||||
<div class='value'>{{username}}</div>
|
<div class='value'>{{username}}</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#link-to 'preferences.username' model class="btn"}}
|
{{#link-to 'preferences.username' model class="btn"}}
|
||||||
<i class='fa fa-pencil'></i>
|
{{fa-icon "pencil"}}
|
||||||
{{i18n 'user.change_username.title'}}
|
{{i18n 'user.change_username.title'}}
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</div>
|
</div>
|
||||||
@ -75,28 +75,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if editingTitle}}
|
{{#if editingTitle}}
|
||||||
<button class='btn' {{action "saveTitle"}}>{{i18n 'admin.user.save_title'}}</button>
|
{{d-button action="saveTitle" label="admin.user.save_title"}}
|
||||||
<a href="#" {{action "toggleTitleEdit"}}>{{i18n 'cancel'}}</a>
|
<a href {{action "toggleTitleEdit"}}>{{i18n 'cancel'}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<button class='btn' {{action "toggleTitleEdit"}}><i class="fa fa-pencil"></i>{{i18n 'admin.user.edit_title'}}</button>
|
{{d-button action="toggleTitleEdit" icon="pencil" label="admin.user.edit_title"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if currentUser.admin}}
|
{{#if currentUser.admin}}
|
||||||
<div class='display-row'>
|
<div class='display-row'>
|
||||||
<div class='field'>{{i18n 'admin.groups.title'}}</div>
|
<div class='field'>{{i18n 'admin.groups.automatic.title'}}</div>
|
||||||
|
<div class='value'>{{automaticGroups}}</div>
|
||||||
|
</div>
|
||||||
|
<div class='display-row'>
|
||||||
|
<div class='field'>{{i18n 'admin.groups.custom.title'}}</div>
|
||||||
<div class='value'>
|
<div class='value'>
|
||||||
{{admin-group-selector selected=model.groups available=availableGroups}}
|
{{admin-group-selector selected=customGroups available=availableGroups}}
|
||||||
</div>
|
</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if custom_groups}}
|
{{#if customGroups}}
|
||||||
{{i18n 'admin.groups.primary'}}
|
{{i18n 'admin.groups.primary'}}
|
||||||
{{combo-box content=custom_groups value=primary_group_id nameProperty="name" none="admin.groups.no_primary"}}
|
{{combo-box content=customGroups value=primary_group_id nameProperty="name" none="admin.groups.no_primary"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if primaryGroupDirty}}
|
{{#if primaryGroupDirty}}
|
||||||
<button class='btn ok no-text' {{action "savePrimaryGroup"}}><i class='fa fa-check'></i></button>
|
{{d-button icon="check" class="ok no-text" action="savePrimaryGroup"}}
|
||||||
<button class='btn cancel no-text' {{action "resetPrimaryGroup"}}><i class='fa fa-times'></i></button>
|
{{d-button icon="times" class="cancel no-text" action="resetPrimaryGroup"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -132,7 +136,7 @@
|
|||||||
{{i18n 'badges.badge_count' count=badge_count}}
|
{{i18n 'badges.badge_count' count=badge_count}}
|
||||||
</div>
|
</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#link-to 'adminUser.badges' this class="btn"}}<i class="fa fa-certificate"></i>{{i18n 'admin.badges.edit_badges'}}{{/link-to}}
|
{{#link-to 'adminUser.badges' this class="btn"}}{{fa-icon "certificate"}}{{i18n 'admin.badges.edit_badges'}}{{/link-to}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -165,13 +169,11 @@
|
|||||||
<div class='value'>
|
<div class='value'>
|
||||||
{{#if approved}}
|
{{#if approved}}
|
||||||
{{i18n 'admin.user.approved_by'}}
|
{{i18n 'admin.user.approved_by'}}
|
||||||
|
|
||||||
{{#link-to 'adminUser' approvedBy}}{{avatar approvedBy imageSize="small"}}{{/link-to}}
|
{{#link-to 'adminUser' approvedBy}}{{avatar approvedBy imageSize="small"}}{{/link-to}}
|
||||||
{{#link-to 'adminUser' approvedBy}}{{approvedBy.username}}{{/link-to}}
|
{{#link-to 'adminUser' approvedBy}}{{approvedBy.username}}{{/link-to}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{i18n 'no_value'}}
|
{{i18n 'no_value'}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if approved}}
|
{{#if approved}}
|
||||||
@ -179,7 +181,7 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
{{#if can_approve}}
|
{{#if can_approve}}
|
||||||
<button class='btn' {{action "approve" target="content"}}>
|
<button class='btn' {{action "approve" target="content"}}>
|
||||||
<i class='fa fa-check'></i>
|
{{fa-icon "check"}}
|
||||||
{{i18n 'admin.user.approve'}}
|
{{i18n 'admin.user.approve'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -206,13 +208,13 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
{{#if can_send_activation_email}}
|
{{#if can_send_activation_email}}
|
||||||
<button class='btn' {{action "sendActivationEmail" target="content"}}>
|
<button class='btn' {{action "sendActivationEmail" target="content"}}>
|
||||||
<i class='fa fa-envelope'></i>
|
{{fa-icon "envelope"}}
|
||||||
{{i18n 'admin.user.send_activation_email'}}
|
{{i18n 'admin.user.send_activation_email'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if can_activate}}
|
{{#if can_activate}}
|
||||||
<button class='btn' {{action "activate" target="content"}}>
|
<button class='btn' {{action "activate" target="content"}}>
|
||||||
<i class='fa fa-check'></i>
|
{{fa-icon "check"}}
|
||||||
{{i18n 'admin.user.activate'}}
|
{{i18n 'admin.user.activate'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -222,19 +224,18 @@
|
|||||||
|
|
||||||
<div class='display-row'>
|
<div class='display-row'>
|
||||||
<div class='field'>{{i18n 'admin.api.key'}}</div>
|
<div class='field'>{{i18n 'admin.api.key'}}</div>
|
||||||
|
|
||||||
{{#if api_key}}
|
{{#if api_key}}
|
||||||
<div class='long-value'>
|
<div class='long-value'>
|
||||||
{{api_key.key}}
|
{{api_key.key}}
|
||||||
<button class='btn' {{action "regenerateApiKey"}}><i class="fa fa-undo"></i>{{i18n 'admin.api.regenerate'}}</button>
|
{{d-button action="regenerateApiKey" icon="undo" label="admin.api.regenerate"}}
|
||||||
<button {{action "revokeApiKey"}} class="btn"><i class="fa fa-times"></i>{{i18n 'admin.api.revoke'}}</button>
|
{{d-button action="revokeApiKey" icon="times" label="admin.api.revoke"}}
|
||||||
</div>
|
</div>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class='value'>
|
<div class='value'>
|
||||||
—
|
—
|
||||||
</div>
|
</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
<button {{action "generateApiKey"}} class="btn"><i class="fa fa-key"></i>{{i18n 'admin.api.generate'}}</button>
|
{{d-button action="generateApiKey" icon="key" label="admin.api.generate"}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
@ -245,37 +246,36 @@
|
|||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if can_revoke_admin}}
|
{{#if can_revoke_admin}}
|
||||||
<button class='btn' {{action "revokeAdmin" target="content"}}>
|
<button class='btn' {{action "revokeAdmin" target="content"}}>
|
||||||
<i class='fa fa-shield'></i>
|
{{fa-icon "shield"}}
|
||||||
{{i18n 'admin.user.revoke_admin'}}
|
{{i18n 'admin.user.revoke_admin'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if can_grant_admin}}
|
{{#if can_grant_admin}}
|
||||||
<button class='btn' {{action "grantAdmin" target="content"}}>
|
<button class='btn' {{action "grantAdmin" target="content"}}>
|
||||||
<i class='fa fa-shield'></i>
|
{{fa-icon "shield"}}
|
||||||
{{i18n 'admin.user.grant_admin'}}
|
{{i18n 'admin.user.grant_admin'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='display-row'>
|
<div class='display-row'>
|
||||||
<div class='field'>{{i18n 'admin.user.moderator'}}</div>
|
<div class='field'>{{i18n 'admin.user.moderator'}}</div>
|
||||||
<div class='value'>{{moderator}}</div>
|
<div class='value'>{{moderator}}</div>
|
||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if can_revoke_moderation}}
|
{{#if can_revoke_moderation}}
|
||||||
<button class='btn' {{action "revokeModeration" target="content"}}>
|
<button class='btn' {{action "revokeModeration" target="content"}}>
|
||||||
<i class='fa fa-shield'></i>
|
{{fa-icon "shield"}}
|
||||||
{{i18n 'admin.user.revoke_moderation'}}
|
{{i18n 'admin.user.revoke_moderation'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if can_grant_moderation}}
|
{{#if can_grant_moderation}}
|
||||||
<button class='btn' {{action "grantModeration" target="content"}}>
|
<button class='btn' {{action "grantModeration" target="content"}}>
|
||||||
<i class='fa fa-shield'></i>
|
{{fa-icon "shield"}}
|
||||||
{{i18n 'admin.user.grant_moderation'}}
|
{{i18n 'admin.user.grant_moderation'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='display-row'>
|
<div class='display-row'>
|
||||||
@ -284,8 +284,8 @@
|
|||||||
{{combo-box content=trustLevels value=trust_level nameProperty="detailedName"}}
|
{{combo-box content=trustLevels value=trust_level nameProperty="detailedName"}}
|
||||||
{{#if dirty}}
|
{{#if dirty}}
|
||||||
<div>
|
<div>
|
||||||
<button class='btn ok no-text' {{action "saveTrustLevel" target="content"}}><i class='fa fa-check'></i></button>
|
<button class='btn ok no-text' {{action "saveTrustLevel" target="content"}}>{{fa-icon "check"}}</button>
|
||||||
<button class='btn cancel no-text' {{action "restoreTrustLevel" target="content"}}><i class='fa fa-times'></i></button>
|
<button class='btn cancel no-text' {{action "restoreTrustLevel" target="content"}}>{{fa-icon "times"}}</button>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
@ -300,7 +300,6 @@
|
|||||||
{{#if tl3Requirements}}
|
{{#if tl3Requirements}}
|
||||||
{{#link-to 'adminUser.tl3Requirements' this class="btn"}}{{i18n 'admin.user.trust_level_3_requirements'}}{{/link-to}}
|
{{#link-to 'adminUser.tl3Requirements' this class="btn"}}{{i18n 'admin.user.trust_level_3_requirements'}}{{/link-to}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -310,7 +309,7 @@
|
|||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if isSuspended}}
|
{{#if isSuspended}}
|
||||||
<button class='btn btn-danger' {{action "unsuspend" target="content"}}>
|
<button class='btn btn-danger' {{action "unsuspend" target="content"}}>
|
||||||
<i class='fa fa-ban'></i>
|
{{fa-icon "ban"}}
|
||||||
{{i18n 'admin.user.unsuspend'}}
|
{{i18n 'admin.user.unsuspend'}}
|
||||||
</button>
|
</button>
|
||||||
{{suspendDuration}}
|
{{suspendDuration}}
|
||||||
@ -318,7 +317,7 @@
|
|||||||
{{else}}
|
{{else}}
|
||||||
{{#if canSuspend}}
|
{{#if canSuspend}}
|
||||||
<button class='btn btn-danger' {{action "showSuspendModal" this}}>
|
<button class='btn btn-danger' {{action "showSuspendModal" this}}>
|
||||||
<i class='fa fa-ban'></i>
|
{{fa-icon "ban"}}
|
||||||
{{i18n 'admin.user.suspend'}}
|
{{i18n 'admin.user.suspend'}}
|
||||||
</button>
|
</button>
|
||||||
{{i18n 'admin.user.suspended_explanation'}}
|
{{i18n 'admin.user.suspended_explanation'}}
|
||||||
@ -347,7 +346,7 @@
|
|||||||
<div class='controls'>
|
<div class='controls'>
|
||||||
{{#if blocked}}
|
{{#if blocked}}
|
||||||
<button class='btn' {{action "unblock" target="content"}}>
|
<button class='btn' {{action "unblock" target="content"}}>
|
||||||
<i class='fa fa-thumbs-o-up'></i>
|
{{fa-icon "thumbs-o-up"}}
|
||||||
{{i18n 'admin.user.unblock'}}
|
{{i18n 'admin.user.unblock'}}
|
||||||
</button>
|
</button>
|
||||||
{{i18n 'admin.user.block_explanation'}}
|
{{i18n 'admin.user.block_explanation'}}
|
||||||
@ -386,7 +385,7 @@
|
|||||||
{{#if can_delete_all_posts}}
|
{{#if can_delete_all_posts}}
|
||||||
{{#if post_count}}
|
{{#if post_count}}
|
||||||
<button class='btn btn-danger' {{action "deleteAllPosts" target="content"}}>
|
<button class='btn btn-danger' {{action "deleteAllPosts" target="content"}}>
|
||||||
<i class='fa fa-trash-o'></i>
|
{{fa-icon "trash-o"}}
|
||||||
{{i18n 'admin.user.delete_all_posts'}}
|
{{i18n 'admin.user.delete_all_posts'}}
|
||||||
</button>
|
</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
@ -473,7 +472,9 @@
|
|||||||
{{#if deleteExplanation}}
|
{{#if deleteExplanation}}
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<br/>
|
<br/>
|
||||||
<div class="pull-right"><i class="fa fa-exclamation-triangle"></i> {{deleteExplanation}}</div>
|
<div class="pull-right">
|
||||||
|
{{fa-icon "exclamation-triangle"}} {{deleteExplanation}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</section>
|
</section>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
@ -1683,6 +1683,10 @@ en:
|
|||||||
automatic: "Automatic"
|
automatic: "Automatic"
|
||||||
automatic_membership_email_domains: "Users who register with an email domain that exactly matches one in this list will be automatically added to this group:"
|
automatic_membership_email_domains: "Users who register with an email domain that exactly matches one in this list will be automatically added to this group:"
|
||||||
automatic_membership_retroactive: "Apply the same email domain rule to add existing registered users"
|
automatic_membership_retroactive: "Apply the same email domain rule to add existing registered users"
|
||||||
|
custom:
|
||||||
|
title: "Custom Groups"
|
||||||
|
automatic:
|
||||||
|
title: "Automatic Groups"
|
||||||
|
|
||||||
api:
|
api:
|
||||||
generate_master: "Generate Master API Key"
|
generate_master: "Generate Master API Key"
|
||||||
|
Reference in New Issue
Block a user