FEATURE: avatar flair can be font awesome icons

This commit is contained in:
Neil Lalonde 2016-08-26 17:15:37 -04:00
parent 58cb43884d
commit 2251104e32
14 changed files with 101 additions and 22 deletions

View File

@ -1,6 +1,7 @@
import { popupAjaxError } from 'discourse/lib/ajax-error'; import { popupAjaxError } from 'discourse/lib/ajax-error';
import { propertyEqual } from 'discourse/lib/computed'; import { propertyEqual } from 'discourse/lib/computed';
import { escapeExpression } from 'discourse/lib/utilities'; import { escapeExpression } from 'discourse/lib/utilities';
import computed from 'ember-addons/ember-computed-decorators';
export default Ember.Controller.extend({ export default Ember.Controller.extend({
needs: ['adminGroupsType'], needs: ['adminGroupsType'],
@ -36,26 +37,42 @@ export default Ember.Controller.extend({
]; ];
}.property(), }.property(),
demoAvatarUrl: function() { @computed
demoAvatarUrl() {
return Discourse.getURL('/images/avatar.png'); return Discourse.getURL('/images/avatar.png');
}.property(), },
flairPreviewStyle: function() { @computed('model.flair_url')
flairPreviewIcon() {
return this.get('model.flair_url') && this.get('model.flair_url').substr(0,3) === 'fa-';
},
@computed('flairPreviewIcon')
flairPreviewImage() {
return this.get('model.flair_url') && !this.get('flairPreviewIcon');
},
@computed('flairPreviewImage', 'model.flair_url', 'model.flairBackgroundHexColor', 'model.flairHexColor')
flairPreviewStyle() {
var style = ''; var style = '';
if (this.get('model.flair_url')) { if (this.get('flairPreviewImage')) {
style += 'background-image: url(' + escapeExpression(this.get('model.flair_url')) + '); '; style += 'background-image: url(' + escapeExpression(this.get('model.flair_url')) + '); ';
} }
if (this.get('model.flairBackgroundHexColor')) { if (this.get('model.flairBackgroundHexColor')) {
style += 'background-color: #' + this.get('model.flairBackgroundHexColor') + ';'; style += 'background-color: #' + this.get('model.flairBackgroundHexColor') + ';';
} }
if (this.get('model.flairHexColor')) {
style += 'color: #' + this.get('model.flairHexColor') + ';';
}
return style; return style;
}.property('model.flair_url', 'model.flairBackgroundHexColor'), },
flairPreviewClasses: function() { @computed('model.flairBackgroundHexColor')
flairPreviewClasses() {
if (this.get('model.flairBackgroundHexColor')) { if (this.get('model.flairBackgroundHexColor')) {
return 'rounded'; return 'rounded';
} }
}.property('model.flairBackgroundHexColor'), },
actions: { actions: {
next() { next() {

View File

@ -113,12 +113,35 @@
<label for="flair_bg_color">{{i18n 'admin.groups.flair_bg_color'}}</label> <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"}} {{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 flairPreviewIcon}}
<div>
<label for="flair_color">{{i18n 'admin.groups.flair_color'}}</label>
{{text-field name="flair_color" class="flair_color" value=model.flair_color placeholderKey="admin.groups.flair_color_placeholder"}}
</div>
{{/if}}
</div> </div>
{{#if flairPreviewStyle}} {{#if flairPreviewIcon}}
<div class="flair_right"> <div class="flair_right">
<div> <div>
<label>{{i18n 'admin.groups.flair_preview'}}</label> <label>{{i18n 'admin.groups.flair_preview'}} Icon</label>
<div class="avatar-flair-preview">
<div class="avatar-wrapper">
<img alt width="45" height="45" src="{{demoAvatarUrl}}" class="avatar actor">
</div>
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}}>
<i class="fa {{model.flair_url}}"></i>
</div>
</div>
</div>
</div>
{{/if}}
{{#if flairPreviewImage}}
<div class="flair_right">
<div>
<label>{{i18n 'admin.groups.flair_preview'}} Image</label>
<div class="avatar-flair-preview"> <div class="avatar-flair-preview">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img alt width="45" height="45" src="{{demoAvatarUrl}}" class="avatar actor"> <img alt width="45" height="45" src="{{demoAvatarUrl}}" class="avatar actor">

View File

@ -31,6 +31,7 @@ export function transformBasicPost(post) {
primaryGroupName: post.primary_group_name, primaryGroupName: post.primary_group_name,
primaryGroupFlairUrl: post.primary_group_flair_url, primaryGroupFlairUrl: post.primary_group_flair_url,
primaryGroupFlairBgColor: post.primary_group_flair_bg_color, primaryGroupFlairBgColor: post.primary_group_flair_bg_color,
primaryGroupFlairColor: post.primary_group_flair_color,
wiki: post.wiki, wiki: post.wiki,
firstPost: post.post_number === 1, firstPost: post.post_number === 1,
post_number: post.post_number, post_number: post.post_number,

View File

@ -95,6 +95,11 @@ const Group = Discourse.Model.extend({
return this.get('flair_bg_color') ? this.get('flair_bg_color').replace(new RegExp("[^0-9a-fA-F]", "g"), "") : null; return this.get('flair_bg_color') ? this.get('flair_bg_color').replace(new RegExp("[^0-9a-fA-F]", "g"), "") : null;
}, },
@computed('flair_color')
flairHexColor() {
return this.get('flair_color') ? this.get('flair_color').replace(new RegExp("[^0-9a-fA-F]", "g"), "") : null;
},
asJSON() { asJSON() {
return { return {
name: this.get('name'), name: this.get('name'),
@ -108,6 +113,7 @@ const Group = Discourse.Model.extend({
incoming_email: this.get("incoming_email"), incoming_email: this.get("incoming_email"),
flair_url: this.get('flair_url'), flair_url: this.get('flair_url'),
flair_bg_color: this.get('flairBackgroundHexColor'), flair_bg_color: this.get('flairBackgroundHexColor'),
flair_color: this.get('flairHexColor'),
}; };
}, },

View File

@ -80,6 +80,10 @@ createWidget('reply-to-tab', {
createWidget('post-avatar-flair', { createWidget('post-avatar-flair', {
tagName: 'div.avatar-flair', tagName: 'div.avatar-flair',
isIcon(attrs) {
return (attrs.primaryGroupFlairUrl && attrs.primaryGroupFlairUrl.substr(0,3) === 'fa-');
},
title(attrs) { title(attrs) {
return attrs.primaryGroupName; return attrs.primaryGroupName;
}, },
@ -90,13 +94,24 @@ createWidget('post-avatar-flair', {
buildAttributes(attrs) { buildAttributes(attrs) {
var style = ''; var style = '';
if (attrs.primaryGroupFlairUrl) { if (!this.isIcon(attrs)) {
style += 'background-image: url(' + Handlebars.Utils.escapeExpression(attrs.primaryGroupFlairUrl) + '); '; style += 'background-image: url(' + Handlebars.Utils.escapeExpression(attrs.primaryGroupFlairUrl) + '); ';
} }
if (attrs.primaryGroupFlairBgColor) { if (attrs.primaryGroupFlairBgColor) {
style += 'background-color: #' + Handlebars.Utils.escapeExpression(attrs.primaryGroupFlairBgColor) + '; '; style += 'background-color: #' + Handlebars.Utils.escapeExpression(attrs.primaryGroupFlairBgColor) + '; ';
} }
if (attrs.primaryGroupFlairColor) {
style += 'color: #' + Handlebars.Utils.escapeExpression(attrs.primaryGroupFlairColor) + '; ';
}
return {style: style}; return {style: style};
},
html(attrs) {
if (this.isIcon(attrs)) {
return [h('i', { className: 'fa ' + attrs.primaryGroupFlairUrl })];
} else {
return [];
}
} }
}); });

View File

@ -712,8 +712,10 @@ section.details {
} }
} }
} }
.row.groups input[type='text'].flair_bg_color { .row.groups {
width: 200px; input[type='text'].flair_bg_color, input[type='text'].flair_color {
width: 200px;
}
} }
// Customise area // Customise area

View File

@ -158,7 +158,9 @@ aside.quote {
} }
.topic-avatar .avatar-flair, .avatar-flair-preview .avatar-flair { .topic-avatar .avatar-flair, .avatar-flair-preview .avatar-flair {
display: block; display: flex;
align-items: center;
justify-content: center;
background-size: 20px 20px; background-size: 20px 20px;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;

View File

@ -67,6 +67,7 @@ class Admin::GroupsController < Admin::AdminController
group.flair_url = params[:flair_url].presence group.flair_url = params[:flair_url].presence
group.flair_bg_color = params[:flair_bg_color].presence group.flair_bg_color = params[:flair_bg_color].presence
group.flair_color = params[:flair_color].presence
if group.save if group.save
Group.reset_counters(group.id, :group_users) Group.reset_counters(group.id, :group_users)

View File

@ -28,7 +28,7 @@ class Group < ActiveRecord::Base
validates_uniqueness_of :name, case_sensitive: false validates_uniqueness_of :name, case_sensitive: false
validate :automatic_membership_email_domains_format_validator validate :automatic_membership_email_domains_format_validator
validate :incoming_email_validator validate :incoming_email_validator
validates :flair_url, url: true validates :flair_url, url: true, if: Proc.new { |g| g.flair_url && g.flair_url[0,3] != 'fa-' }
AUTO_GROUPS = { AUTO_GROUPS = {
:everyone => 0, :everyone => 0,

View File

@ -16,7 +16,8 @@ class BasicGroupSerializer < ApplicationSerializer
:is_member, :is_member,
:mentionable, :mentionable,
:flair_url, :flair_url,
:flair_bg_color :flair_bg_color,
:flair_color
def include_incoming_email? def include_incoming_email?
scope.is_staff? scope.is_staff?

View File

@ -36,6 +36,7 @@ class PostSerializer < BasicPostSerializer
:primary_group_name, :primary_group_name,
:primary_group_flair_url, :primary_group_flair_url,
:primary_group_flair_bg_color, :primary_group_flair_bg_color,
:primary_group_flair_color,
:version, :version,
:can_edit, :can_edit,
:can_delete, :can_delete,
@ -153,13 +154,15 @@ class PostSerializer < BasicPostSerializer
end end
def primary_group_flair_url def primary_group_flair_url
return nil unless object.user && object.user.primary_group_id object.user.try(:primary_group).try(:flair_url)
object.user.primary_group.try(:flair_url)
end end
def primary_group_flair_bg_color def primary_group_flair_bg_color
return nil unless object.user && object.user.primary_group_id object.user.try(:primary_group).try(:flair_bg_color)
object.user.primary_group.try(:flair_bg_color) end
def primary_group_flair_color
object.user.try(:primary_group).try(:flair_color)
end end
def link_counts def link_counts

View File

@ -2402,10 +2402,12 @@ en:
add_owners: Add owners add_owners: Add owners
incoming_email: "Custom incoming email address" incoming_email: "Custom incoming email address"
incoming_email_placeholder: "enter email address" incoming_email_placeholder: "enter email address"
flair_url: "Avatar Flair URL" flair_url: "Avatar Flair Image"
flair_url_placeholder: "(Optional) Image URL" flair_url_placeholder: "(Optional) Image URL or Font Awesome class"
flair_bg_color: "Avatar Flair Background Color" flair_bg_color: "Avatar Flair Background Color"
flair_bg_color_placeholder: "(Optional) Hex color value" flair_bg_color_placeholder: "(Optional) Hex color value"
flair_color: "Avatar Flair Color"
flair_color_placeholder: "(Optional) Hex color value"
flair_preview: "Preview" flair_preview: "Preview"

View File

@ -0,0 +1,5 @@
class AddFlairColorToGroups < ActiveRecord::Migration
def change
add_column :groups, :flair_color, :string
end
end

View File

@ -37,7 +37,8 @@ describe Admin::GroupsController do
"is_member"=>true, "is_member"=>true,
"mentionable"=>false, "mentionable"=>false,
"flair_url"=>nil, "flair_url"=>nil,
"flair_bg_color"=>nil "flair_bg_color"=>nil,
"flair_color"=>nil
}]) }])
end end