UX: user preferences allows users to choose which title to use from their badges and groups
This commit is contained in:
parent
10dad5de63
commit
f6cfff3cea
|
@ -7,12 +7,13 @@ import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||||
|
|
||||||
export default Ember.Controller.extend(CanCheckEmails, PreferencesTabController, {
|
export default Ember.Controller.extend(CanCheckEmails, PreferencesTabController, {
|
||||||
|
|
||||||
saveAttrNames: ['name'],
|
saveAttrNames: ['name', 'title'],
|
||||||
|
|
||||||
canEditName: setting('enable_names'),
|
canEditName: setting('enable_names'),
|
||||||
canSaveUser: true,
|
canSaveUser: true,
|
||||||
|
|
||||||
newNameInput: null,
|
newNameInput: null,
|
||||||
|
newTitleInput: null,
|
||||||
|
|
||||||
passwordProgress: null,
|
passwordProgress: null,
|
||||||
|
|
||||||
|
@ -30,9 +31,9 @@ export default Ember.Controller.extend(CanCheckEmails, PreferencesTabController,
|
||||||
return I18n.t(this.siteSettings.full_name_required ? 'user.name.instructions_required' : 'user.name.instructions');
|
return I18n.t(this.siteSettings.full_name_required ? 'user.name.instructions_required' : 'user.name.instructions');
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("model.has_title_badges")
|
@computed('model.availableTitles')
|
||||||
canSelectTitle(hasTitleBadges) {
|
canSelectTitle(availableTitles) {
|
||||||
return this.siteSettings.enable_badges && hasTitleBadges;
|
return availableTitles.length > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed()
|
@computed()
|
||||||
|
@ -52,6 +53,7 @@ export default Ember.Controller.extend(CanCheckEmails, PreferencesTabController,
|
||||||
const model = this.get('model');
|
const model = this.get('model');
|
||||||
|
|
||||||
model.set('name', this.get('newNameInput'));
|
model.set('name', this.get('newNameInput'));
|
||||||
|
model.set('title', this.get('newTitleInput'));
|
||||||
|
|
||||||
return model.save(this.get('saveAttrNames')).then(() => {
|
return model.save(this.get('saveAttrNames')).then(() => {
|
||||||
this.set('saved', true);
|
this.set('saved', true);
|
||||||
|
|
|
@ -218,6 +218,7 @@ const User = RestModel.extend({
|
||||||
'website',
|
'website',
|
||||||
'location',
|
'location',
|
||||||
'name',
|
'name',
|
||||||
|
'title',
|
||||||
'locale',
|
'locale',
|
||||||
'custom_fields',
|
'custom_fields',
|
||||||
'user_fields',
|
'user_fields',
|
||||||
|
@ -569,6 +570,25 @@ const User = RestModel.extend({
|
||||||
|
|
||||||
canManageGroup(group) {
|
canManageGroup(group) {
|
||||||
return group.get('automatic') ? false : (this.get('admin') || group.get('is_group_owner'));
|
return group.get('automatic') ? false : (this.get('admin') || group.get('is_group_owner'));
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('groups.@each.title', 'badges.@each')
|
||||||
|
availableTitles() {
|
||||||
|
let titles = [];
|
||||||
|
|
||||||
|
_.each(this.get('groups'), group => {
|
||||||
|
if (group.get('title')) {
|
||||||
|
titles.push(group.get('title'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_.each(this.get('badges'), badge => {
|
||||||
|
if (badge.get('allow_title')) {
|
||||||
|
titles.push(badge.get('name'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return titles;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
|
import UserBadge from 'discourse/models/user-badge';
|
||||||
import RestrictedUserRoute from "discourse/routes/restricted-user";
|
import RestrictedUserRoute from "discourse/routes/restricted-user";
|
||||||
|
|
||||||
export default RestrictedUserRoute.extend({
|
export default RestrictedUserRoute.extend({
|
||||||
showFooter: true,
|
showFooter: true,
|
||||||
|
|
||||||
|
model: function() {
|
||||||
|
const user = this.modelFor('user');
|
||||||
|
return UserBadge.findByUsername(this.modelFor('user').get('username')).then(userBadges => {
|
||||||
|
user.set('badges', userBadges.map(ub => ub.badge));
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
setupController(controller, user) {
|
setupController(controller, user) {
|
||||||
controller.reset();
|
controller.reset();
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
model: user,
|
model: user,
|
||||||
newNameInput: user.get('name')
|
newNameInput: user.get('name'),
|
||||||
|
newTitleInput: user.get('title')
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -100,8 +100,10 @@
|
||||||
<div class="control-group pref-title">
|
<div class="control-group pref-title">
|
||||||
<label class="control-label">{{i18n 'user.title.title'}}</label>
|
<label class="control-label">{{i18n 'user.title.title'}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<span class="static">{{model.title}}</span>
|
{{combo-box
|
||||||
{{#link-to "preferences.badgeTitle" class="btn btn-small btn-icon pad-left no-text"}}{{d-icon "pencil"}}{{/link-to}}
|
value=newTitleInput
|
||||||
|
content=model.availableTitles
|
||||||
|
none="user.title.none"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1014,6 +1014,7 @@ en:
|
||||||
header_title: "profile, messages, bookmarks and preferences"
|
header_title: "profile, messages, bookmarks and preferences"
|
||||||
title:
|
title:
|
||||||
title: "Title"
|
title: "Title"
|
||||||
|
none: "(none)"
|
||||||
|
|
||||||
filters:
|
filters:
|
||||||
all: "All"
|
all: "All"
|
||||||
|
|
|
@ -215,8 +215,11 @@ class Guardian
|
||||||
can_administer?(user) && !user.moderator?
|
can_administer?(user) && !user.moderator?
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_grant_title?(user)
|
def can_grant_title?(user, title = nil)
|
||||||
user && is_staff?
|
return true if user && is_staff?
|
||||||
|
return false if user != @user
|
||||||
|
return true if user.badges.where(name: title, allow_title: true).exists?
|
||||||
|
user.groups.where(title: title).exists?
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_change_primary_group?(user)
|
def can_change_primary_group?(user)
|
||||||
|
|
|
@ -2186,6 +2186,35 @@ describe Guardian do
|
||||||
it 'is false without a user to look at' do
|
it 'is false without a user to look at' do
|
||||||
expect(Guardian.new(admin).can_grant_title?(nil)).to be_falsey
|
expect(Guardian.new(admin).can_grant_title?(nil)).to be_falsey
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with title argument' do
|
||||||
|
let(:title_badge) { Fabricate(:badge, name: 'Helper', allow_title: true) }
|
||||||
|
let(:no_title_badge) { Fabricate(:badge, name: 'Writer', allow_title: false) }
|
||||||
|
let(:group) { Fabricate(:group, title: 'Groupie') }
|
||||||
|
|
||||||
|
it 'returns true if title belongs to a badge that user has' do
|
||||||
|
BadgeGranter.grant(title_badge, user)
|
||||||
|
expect(Guardian.new(user).can_grant_title?(user, title_badge.name)).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if title belongs to a badge that user doesn't have" do
|
||||||
|
expect(Guardian.new(user).can_grant_title?(user, title_badge.name)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if title belongs to a badge that user has but can't be used as a title" do
|
||||||
|
BadgeGranter.grant(no_title_badge, user)
|
||||||
|
expect(Guardian.new(user).can_grant_title?(user, no_title_badge.name)).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns true if title is from a group the user belongs to' do
|
||||||
|
group.add(user)
|
||||||
|
expect(Guardian.new(user).can_grant_title?(user, group.title)).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "returns false if title is from a group the user doesn't belong to" do
|
||||||
|
expect(Guardian.new(user).can_grant_title?(user, group.title)).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'can_change_trust_level?' do
|
describe 'can_change_trust_level?' do
|
||||||
|
|
Loading…
Reference in New Issue