mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 18:53:44 +08:00
FEATURE: add flair to avatars using new settings in the groups admin UI
This commit is contained in:
parent
72d7c055f4
commit
d079f69b7b
|
@ -1,5 +1,6 @@
|
|||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||
import { propertyEqual } from 'discourse/lib/computed';
|
||||
import { escapeExpression } from 'discourse/lib/utilities';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
needs: ['adminGroupsType'],
|
||||
|
@ -35,6 +36,23 @@ export default Ember.Controller.extend({
|
|||
];
|
||||
}.property(),
|
||||
|
||||
flairPreviewStyle: function() {
|
||||
var style = '';
|
||||
if (this.get('model.flair_url')) {
|
||||
style += 'background-image: url(' + escapeExpression(this.get('model.flair_url')) + '); ';
|
||||
}
|
||||
if (this.get('model.flairBackgroundHexColor')) {
|
||||
style += 'background-color: #' + this.get('model.flairBackgroundHexColor') + ';';
|
||||
}
|
||||
return style;
|
||||
}.property('model.flair_url', 'model.flairBackgroundHexColor'),
|
||||
|
||||
flairPreviewClasses: function() {
|
||||
if (this.get('model.flairBackgroundHexColor')) {
|
||||
return 'rounded';
|
||||
}
|
||||
}.property('model.flairBackgroundHexColor'),
|
||||
|
||||
actions: {
|
||||
next() {
|
||||
if (this.get("showingLast")) { return; }
|
||||
|
|
|
@ -101,6 +101,38 @@
|
|||
{{/if}}
|
||||
{{/unless}}
|
||||
|
||||
{{#unless model.automatic}}
|
||||
<div class="flair_inputs">
|
||||
<div class="flair_left">
|
||||
<div>
|
||||
<label for="flair_url">{{i18n 'admin.groups.flair_url'}}</label>
|
||||
{{text-field name="flair_url" value=model.flair_url placeholderKey="admin.groups.flair_url_placeholder"}}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="flair_bg_color">{{i18n 'admin.groups.flair_bg_color'}}</label>
|
||||
{{text-field name="flair_bg_color" class="flair_bg_color" value=model.flair_bg_color placeholderKey="admin.groups.flair_bg_color_placeholder"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if flairPreviewStyle}}
|
||||
<div class="flair_right">
|
||||
<div>
|
||||
<label>{{i18n 'admin.groups.flair_preview'}}</label>
|
||||
<div class="avatar-flair-preview">
|
||||
<div class="avatar-wrapper">
|
||||
<img alt width="45" height="45" src="https://avatars.discourse.org/v3/letter/a/a3d4f5/45.png" class="avatar actor" title="demo">
|
||||
</div>
|
||||
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}}></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="clearfix"></div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
|
||||
<div class='buttons'>
|
||||
<button {{action "save"}} disabled={{disableSave}} class='btn btn-primary'>{{i18n 'admin.customize.save'}}</button>
|
||||
{{#unless model.automatic}}
|
||||
|
|
|
@ -28,7 +28,9 @@ export function transformBasicPost(post) {
|
|||
isDeleted: post.deleted_at || post.user_deleted,
|
||||
deletedByAvatarTemplate: null,
|
||||
deletedByUsername: null,
|
||||
primary_group_name: post.primary_group_name,
|
||||
primaryGroupName: post.primary_group_name,
|
||||
primaryGroupFlairUrl: post.primary_group_flair_url,
|
||||
primaryGroupFlairBgColor: post.primary_group_flair_bg_color,
|
||||
wiki: post.wiki,
|
||||
firstPost: post.post_number === 1,
|
||||
post_number: post.post_number,
|
||||
|
|
|
@ -90,6 +90,11 @@ const Group = Discourse.Model.extend({
|
|||
});
|
||||
},
|
||||
|
||||
@computed('flair_bg_color')
|
||||
flairBackgroundHexColor() {
|
||||
return this.get('flair_bg_color') ? this.get('flair_bg_color').replace(new RegExp("[^0-9a-fA-F]", "g"), "") : null;
|
||||
},
|
||||
|
||||
asJSON() {
|
||||
return {
|
||||
name: this.get('name'),
|
||||
|
@ -101,6 +106,8 @@ const Group = Discourse.Model.extend({
|
|||
primary_group: !!this.get('primary_group'),
|
||||
grant_trust_level: this.get('grant_trust_level'),
|
||||
incoming_email: this.get("incoming_email"),
|
||||
flair_url: this.get('flair_url'),
|
||||
flair_bg_color: this.get('flairBackgroundHexColor'),
|
||||
};
|
||||
},
|
||||
|
||||
|
|
|
@ -77,6 +77,29 @@ createWidget('reply-to-tab', {
|
|||
}
|
||||
});
|
||||
|
||||
createWidget('post-avatar-flair', {
|
||||
tagName: 'div.avatar-flair',
|
||||
|
||||
title(attrs) {
|
||||
return attrs.primaryGroupName;
|
||||
},
|
||||
|
||||
buildClasses(attrs) {
|
||||
return 'avatar-flair-' + attrs.primaryGroupName + (attrs.primaryGroupFlairBgColor ? ' rounded' : '');
|
||||
},
|
||||
|
||||
buildAttributes(attrs) {
|
||||
var style = '';
|
||||
if (attrs.primaryGroupFlairUrl) {
|
||||
style += 'background-image: url(' + attrs.primaryGroupFlairUrl + '); ';
|
||||
}
|
||||
if (attrs.primaryGroupFlairBgColor) {
|
||||
style += 'background-color: #' + attrs.primaryGroupFlairBgColor + '; ';
|
||||
}
|
||||
return {style: style};
|
||||
}
|
||||
});
|
||||
|
||||
createWidget('post-avatar', {
|
||||
tagName: 'div.topic-avatar',
|
||||
|
||||
|
@ -93,11 +116,21 @@ createWidget('post-avatar', {
|
|||
template: attrs.avatar_template,
|
||||
username: attrs.username,
|
||||
url: attrs.usernameUrl,
|
||||
className: 'main-avatar'
|
||||
className: 'main-avatar',
|
||||
flairUrl: attrs.primaryGroupFlairUrl,
|
||||
flairBgColor: attrs.primaryGroupFlairBgColor
|
||||
});
|
||||
}
|
||||
|
||||
return [body, h('div.poster-avatar-extra')];
|
||||
const result = [body];
|
||||
|
||||
if (attrs.primaryGroupFlairUrl || attrs.primaryGroupFlairBgColor) {
|
||||
result.push(this.attach('post-avatar-flair', attrs));
|
||||
}
|
||||
|
||||
result.push(h('div.poster-avatar-extra'));
|
||||
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -406,7 +439,7 @@ export default createWidget('post', {
|
|||
if (attrs.topicOwner) { classNames.push('topic-owner'); }
|
||||
if (attrs.hidden) { classNames.push('post-hidden'); }
|
||||
if (attrs.deleted) { classNames.push('deleted'); }
|
||||
if (attrs.primary_group_name) { classNames.push(`group-${attrs.primary_group_name}`); }
|
||||
if (attrs.primaryGroupName) { classNames.push(`group-${attrs.primaryGroupName}`); }
|
||||
if (attrs.wiki) { classNames.push(`wiki`); }
|
||||
if (attrs.isWhisper) { classNames.push('whisper'); }
|
||||
if (attrs.isModeratorAction || (attrs.isWarning && attrs.firstPost)) {
|
||||
|
|
|
@ -35,7 +35,7 @@ export default createWidget('poster-name', {
|
|||
if (attrs.moderator) { classNames.push('moderator'); }
|
||||
if (attrs.new_user) { classNames.push('new-user'); }
|
||||
|
||||
const primaryGroupName = attrs.primary_group_name;
|
||||
const primaryGroupName = attrs.primaryGroupName;
|
||||
if (primaryGroupName && primaryGroupName.length) {
|
||||
classNames.push(primaryGroupName);
|
||||
}
|
||||
|
|
|
@ -684,6 +684,39 @@ section.details {
|
|||
width: 100%;
|
||||
border-color: dark-light-choose(scale-color($primary, $lightness: 75%), scale-color($secondary, $lightness: 25%));
|
||||
}
|
||||
.avatar-flair-preview {
|
||||
position: relative;
|
||||
width: 45px;
|
||||
|
||||
.avatar-flair.demo {
|
||||
top: 25px;
|
||||
&.rounded {
|
||||
top: 23px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-horizontal {
|
||||
.flair_inputs {
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
|
||||
.flair_left {
|
||||
float: left;
|
||||
width: 60%;
|
||||
input[name=flair_url] {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
.flair_right {
|
||||
float: left;
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.row.groups input[type='text'].flair_bg_color {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
// Customise area
|
||||
|
|
|
@ -153,6 +153,25 @@ aside.quote {
|
|||
}
|
||||
}
|
||||
|
||||
.topic-avatar .avatar-flair, .avatar-flair-preview .avatar-flair {
|
||||
display: block;
|
||||
background-size: 20px 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right: -6px;
|
||||
&.rounded {
|
||||
background-size: 18px 18px;
|
||||
border-radius: 12px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
top: 38px;
|
||||
right: -8px;
|
||||
}
|
||||
}
|
||||
.topic-avatar .poster-avatar-extra {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -637,7 +637,7 @@ $topic-avatar-width: 45px;
|
|||
width: $topic-avatar-width;
|
||||
float: left;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.gap {
|
||||
|
|
|
@ -65,6 +65,9 @@ class Admin::GroupsController < Admin::AdminController
|
|||
title = params[:title] if params[:title].present?
|
||||
group.title = group.automatic ? nil : title
|
||||
|
||||
group.flair_url = params[:flair_url].presence
|
||||
group.flair_bg_color = params[:flair_bg_color].presence
|
||||
|
||||
if group.save
|
||||
Group.reset_counters(group.id, :group_users)
|
||||
render_serialized(group, BasicGroupSerializer)
|
||||
|
|
|
@ -28,6 +28,7 @@ class Group < ActiveRecord::Base
|
|||
validates_uniqueness_of :name, case_sensitive: false
|
||||
validate :automatic_membership_email_domains_format_validator
|
||||
validate :incoming_email_validator
|
||||
validates :flair_url, url: true
|
||||
|
||||
AUTO_GROUPS = {
|
||||
:everyone => 0,
|
||||
|
|
|
@ -14,7 +14,9 @@ class BasicGroupSerializer < ApplicationSerializer
|
|||
:notification_level,
|
||||
:has_messages,
|
||||
:is_member,
|
||||
:mentionable
|
||||
:mentionable,
|
||||
:flair_url,
|
||||
:flair_bg_color
|
||||
|
||||
def include_incoming_email?
|
||||
scope.is_staff?
|
||||
|
|
|
@ -34,6 +34,8 @@ class PostSerializer < BasicPostSerializer
|
|||
:category_id,
|
||||
:display_username,
|
||||
:primary_group_name,
|
||||
:primary_group_flair_url,
|
||||
:primary_group_flair_bg_color,
|
||||
:version,
|
||||
:can_edit,
|
||||
:can_delete,
|
||||
|
@ -150,6 +152,16 @@ class PostSerializer < BasicPostSerializer
|
|||
end
|
||||
end
|
||||
|
||||
def primary_group_flair_url
|
||||
return nil unless object.user && object.user.primary_group_id
|
||||
object.user.primary_group.try(:flair_url)
|
||||
end
|
||||
|
||||
def primary_group_flair_bg_color
|
||||
return nil unless object.user && object.user.primary_group_id
|
||||
object.user.primary_group.try(:flair_bg_color)
|
||||
end
|
||||
|
||||
def link_counts
|
||||
return @single_post_link_counts if @single_post_link_counts.present?
|
||||
|
||||
|
|
|
@ -2402,6 +2402,11 @@ en:
|
|||
add_owners: Add owners
|
||||
incoming_email: "Custom incoming email address"
|
||||
incoming_email_placeholder: "enter email address"
|
||||
flair_url: "Avatar Flair URL"
|
||||
flair_url_placeholder: "(Optional) Image URL"
|
||||
flair_bg_color: "Avatar Flair Background Color"
|
||||
flair_bg_color_placeholder: "(Optional) Hex color value"
|
||||
flair_preview: "Preview"
|
||||
|
||||
|
||||
api:
|
||||
|
|
6
db/migrate/20160815210156_add_flair_url_to_groups.rb
Normal file
6
db/migrate/20160815210156_add_flair_url_to_groups.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class AddFlairUrlToGroups < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :groups, :flair_url, :string
|
||||
add_column :groups, :flair_bg_color, :string
|
||||
end
|
||||
end
|
11
lib/validators/url_validator.rb
Normal file
11
lib/validators/url_validator.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class UrlValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
if value.present?
|
||||
uri = URI.parse(value) rescue nil
|
||||
|
||||
unless uri
|
||||
record.errors[attribute] << (options[:message] || I18n.t('errors.messages.invalid'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -35,7 +35,9 @@ describe Admin::GroupsController do
|
|||
"notification_level"=>2,
|
||||
"has_messages"=>false,
|
||||
"is_member"=>true,
|
||||
"mentionable"=>false
|
||||
"mentionable"=>false,
|
||||
"flair_url"=>nil,
|
||||
"flair_bg_color"=>nil
|
||||
}])
|
||||
end
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ widgetTest('extra classes and glyphs', {
|
|||
admin: true,
|
||||
moderator: true,
|
||||
new_user: true,
|
||||
primary_group_name: 'fish'
|
||||
primaryGroupName: 'fish'
|
||||
});
|
||||
},
|
||||
test(assert) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user