UX: user preferences allows users to choose which title to use from their badges and groups

This commit is contained in:
Neil Lalonde 2018-04-06 14:29:27 -04:00
parent 10dad5de63
commit f6cfff3cea
7 changed files with 76 additions and 9 deletions

View File

@ -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);

View File

@ -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;
} }
}); });

View File

@ -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')
}); });
} }
}); });

View File

@ -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}}

View File

@ -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"

View File

@ -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)

View File

@ -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