UX: use "icon-picker" & "image-uploader" fields to set group flair. (#9779)
This commit is contained in:
parent
13d5ccedf5
commit
8e56197728
|
@ -2,11 +2,12 @@ import I18n from "I18n";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { debounce } from "@ember/runloop";
|
import { debounce } from "@ember/runloop";
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { observes } from "discourse-common/utils/decorators";
|
import { on, observes } from "discourse-common/utils/decorators";
|
||||||
import { escapeExpression } from "discourse/lib/utilities";
|
import { escapeExpression } from "discourse/lib/utilities";
|
||||||
import { convertIconClass } from "discourse-common/lib/icon-library";
|
import { convertIconClass } from "discourse-common/lib/icon-library";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { htmlSafe } from "@ember/template";
|
import { htmlSafe } from "@ember/template";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: ["group-flair-inputs"],
|
classNames: ["group-flair-inputs"],
|
||||||
|
@ -16,23 +17,26 @@ export default Component.extend({
|
||||||
return Discourse.getURL("/images/avatar.png");
|
return Discourse.getURL("/images/avatar.png");
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("model.flair_url")
|
@discourseComputed("model.flair_type")
|
||||||
flairPreviewIcon(flairURL) {
|
flairPreviewIcon(flairType) {
|
||||||
return flairURL && /fa(r|b?)-/.test(flairURL);
|
return flairType && flairType === "icon";
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("model.flair_url", "flairPreviewIcon")
|
@discourseComputed("model.flair_icon")
|
||||||
flairPreviewIconUrl(flairURL, flairPreviewIcon) {
|
flairPreviewIconUrl(flairIcon) {
|
||||||
return flairPreviewIcon ? convertIconClass(flairURL) : "";
|
return flairIcon ? convertIconClass(flairIcon) : "";
|
||||||
},
|
},
|
||||||
|
|
||||||
@observes("model.flair_url")
|
@on("didInsertElement")
|
||||||
_loadSVGIcon() {
|
@observes("model.flair_icon")
|
||||||
|
_loadSVGIcon(flairIcon) {
|
||||||
|
if (flairIcon) {
|
||||||
debounce(this, this._loadIcon, 1000);
|
debounce(this, this._loadIcon, 1000);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_loadIcon() {
|
_loadIcon() {
|
||||||
const icon = convertIconClass(this.get("model.flair_url")),
|
const icon = convertIconClass(this.model.flair_icon),
|
||||||
c = "#svg-sprites",
|
c = "#svg-sprites",
|
||||||
h = "ajax-icon-holder",
|
h = "ajax-icon-holder",
|
||||||
singleIconEl = `${c} .${h}`;
|
singleIconEl = `${c} .${h}`;
|
||||||
|
@ -50,9 +54,14 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("model.flair_url", "flairPreviewIcon")
|
@discourseComputed("model.flair_type")
|
||||||
flairPreviewImage(flairURL, flairPreviewIcon) {
|
flairPreviewImage(flairType) {
|
||||||
return flairURL && !flairPreviewIcon;
|
return flairType && flairType === "image";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("model.flair_url")
|
||||||
|
flairImageUrl(flairURL) {
|
||||||
|
return flairURL && flairURL.match(/\//) ? flairURL : null;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed(
|
@discourseComputed(
|
||||||
|
@ -91,5 +100,21 @@ export default Component.extend({
|
||||||
flairPreviewLabel(flairPreviewImage) {
|
flairPreviewLabel(flairPreviewImage) {
|
||||||
const key = flairPreviewImage ? "image" : "icon";
|
const key = flairPreviewImage ? "image" : "icon";
|
||||||
return I18n.t(`groups.flair_preview_${key}`);
|
return I18n.t(`groups.flair_preview_${key}`);
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
setFlairImage(upload) {
|
||||||
|
this.model.setProperties({
|
||||||
|
flair_url: Discourse.getURL(upload.url),
|
||||||
|
flair_upload_id: upload.id
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
removeFlairImage() {
|
||||||
|
this.model.setProperties({
|
||||||
|
flair_url: null,
|
||||||
|
flair_upload_id: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -188,7 +188,8 @@ const Group = RestModel.extend({
|
||||||
primary_group: !!this.primary_group,
|
primary_group: !!this.primary_group,
|
||||||
grant_trust_level: this.grant_trust_level,
|
grant_trust_level: this.grant_trust_level,
|
||||||
incoming_email: this.incoming_email,
|
incoming_email: this.incoming_email,
|
||||||
flair_url: this.flair_url,
|
flair_icon: null,
|
||||||
|
flair_upload_id: null,
|
||||||
flair_bg_color: this.flairBackgroundHexColor,
|
flair_bg_color: this.flairBackgroundHexColor,
|
||||||
flair_color: this.flairHexColor,
|
flair_color: this.flairHexColor,
|
||||||
bio_raw: this.bio_raw,
|
bio_raw: this.bio_raw,
|
||||||
|
@ -201,6 +202,12 @@ const Group = RestModel.extend({
|
||||||
publish_read_state: this.publish_read_state
|
publish_read_state: this.publish_read_state
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.flair_type === "icon") {
|
||||||
|
attrs["flair_icon"] = this.flair_icon;
|
||||||
|
} else if (this.flair_type === "image") {
|
||||||
|
attrs["flair_upload_id"] = this.flair_upload_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.id) {
|
if (!this.id) {
|
||||||
attrs["usernames"] = this.usernames;
|
attrs["usernames"] = this.usernames;
|
||||||
attrs["owner_usernames"] = this.ownerUsernames;
|
attrs["owner_usernames"] = this.ownerUsernames;
|
||||||
|
|
|
@ -1,13 +1,36 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="flair_url">{{i18n "groups.flair_url"}}</label>
|
<label class="control-label" for="flair_url">{{i18n "groups.flair_url"}}</label>
|
||||||
|
|
||||||
{{text-field name="flair_url"
|
<div class="radios">
|
||||||
class="input-xxlarge"
|
<label class="radio-label" for="avatar-flair">
|
||||||
value=model.flair_url
|
{{radio-button name="avatar-flair" value="icon" selection=model.flair_type}}
|
||||||
placeholderKey="groups.flair_url_placeholder"}}
|
<b>{{i18n "groups.flair_type.icon"}}</b>
|
||||||
<div class="control-instructions">
|
</label>
|
||||||
{{i18n "groups.flair_url_description"}}
|
|
||||||
|
<label class="radio-label" for="avatar-flair">
|
||||||
|
{{radio-button name="avatar-flair" value="image" selection=model.flair_type}}
|
||||||
|
<b>{{i18n "groups.flair_type.image"}}</b>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{#if flairPreviewIcon}}
|
||||||
|
{{icon-picker
|
||||||
|
name="icon"
|
||||||
|
value=model.flair_icon
|
||||||
|
options=(hash maximum=1)
|
||||||
|
onChange=(action (mut model.flair_icon))
|
||||||
|
}}
|
||||||
|
{{else if flairPreviewImage}}
|
||||||
|
{{image-uploader
|
||||||
|
imageUrl=flairImageUrl
|
||||||
|
onUploadDone=(action "setFlairImage")
|
||||||
|
onUploadDeleted=(action "removeFlairImage")
|
||||||
|
type="group_flair"
|
||||||
|
class="no-repeat contain-image"}}
|
||||||
|
<div class="control-instructions">
|
||||||
|
{{i18n "groups.flair_upload_description"}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
@ -40,7 +63,7 @@
|
||||||
|
|
||||||
{{#if flairPreviewImage}}
|
{{#if flairPreviewImage}}
|
||||||
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}}></div>
|
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}}></div>
|
||||||
{{else}}
|
{{else if flairPreviewIcon}}
|
||||||
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}} role="presentation">
|
<div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}} role="presentation">
|
||||||
{{d-icon flairPreviewIconUrl}}
|
{{d-icon flairPreviewIconUrl}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,7 +8,7 @@ createWidget("avatar-flair", {
|
||||||
isIcon(attrs) {
|
isIcon(attrs) {
|
||||||
return (
|
return (
|
||||||
attrs.primary_group_flair_url &&
|
attrs.primary_group_flair_url &&
|
||||||
attrs.primary_group_flair_url.includes("fa-")
|
!attrs.primary_group_flair_url.includes("/")
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,22 @@ table.group-members {
|
||||||
background-color: #f4f4f4;
|
background-color: #f4f4f4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.radios {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-label {
|
||||||
|
display: inline-flex;
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploaded-image-preview {
|
||||||
|
height: 75px;
|
||||||
|
width: 275px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.group-form-save {
|
.group-form-save {
|
||||||
|
|
|
@ -163,7 +163,8 @@ class Admin::GroupsController < Admin::AdminController
|
||||||
:primary_group,
|
:primary_group,
|
||||||
:grant_trust_level,
|
:grant_trust_level,
|
||||||
:incoming_email,
|
:incoming_email,
|
||||||
:flair_url,
|
:flair_icon,
|
||||||
|
:flair_upload_id,
|
||||||
:flair_bg_color,
|
:flair_bg_color,
|
||||||
:flair_color,
|
:flair_color,
|
||||||
:bio_raw,
|
:bio_raw,
|
||||||
|
|
|
@ -521,7 +521,8 @@ class GroupsController < ApplicationController
|
||||||
mentionable_level
|
mentionable_level
|
||||||
messageable_level
|
messageable_level
|
||||||
title
|
title
|
||||||
flair_url
|
flair_icon
|
||||||
|
flair_upload_id
|
||||||
flair_bg_color
|
flair_bg_color
|
||||||
flair_color
|
flair_color
|
||||||
bio_raw
|
bio_raw
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Jobs
|
||||||
|
class MigrateGroupFlairImages < ::Jobs::Onceoff
|
||||||
|
def execute_onceoff(args)
|
||||||
|
return if Group.column_names.exclude?("flair_url")
|
||||||
|
|
||||||
|
Group.where.not(flair_url: nil).each do |group|
|
||||||
|
if group.flair_upload.present?
|
||||||
|
g.update_column(:flair_url, nil)
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
old_url = group[:flair_url]
|
||||||
|
group_name = group.name
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
file = nil
|
||||||
|
sleep_interval = 5
|
||||||
|
|
||||||
|
loop do
|
||||||
|
url = UrlHelper.absolute_without_cdn(old_url)
|
||||||
|
|
||||||
|
begin
|
||||||
|
file = FileHelper.download(
|
||||||
|
url,
|
||||||
|
max_file_size: [
|
||||||
|
SiteSetting.max_image_size_kb.kilobytes,
|
||||||
|
20.megabytes
|
||||||
|
].max,
|
||||||
|
tmp_file_name: 'tmp_group_flair_upload',
|
||||||
|
skip_rate_limit: true,
|
||||||
|
follow_redirect: true
|
||||||
|
)
|
||||||
|
rescue OpenURI::HTTPError,
|
||||||
|
OpenSSL::SSL::SSLError,
|
||||||
|
Net::OpenTimeout,
|
||||||
|
Net::ReadTimeout,
|
||||||
|
Errno::ECONNREFUSED,
|
||||||
|
EOFError,
|
||||||
|
SocketError,
|
||||||
|
Discourse::InvalidParameters => e
|
||||||
|
|
||||||
|
logger.warn(
|
||||||
|
"Error encountered when trying to download file " +
|
||||||
|
"for group '#{group_name}'.\n#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
break if file || (file.blank? && count >= 3)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
"Failed to download upload from #{url} for group '#{group_name}'. Retrying..."
|
||||||
|
)
|
||||||
|
|
||||||
|
sleep(count * sleep_interval)
|
||||||
|
end
|
||||||
|
|
||||||
|
next if file.blank?
|
||||||
|
|
||||||
|
upload = UploadCreator.new(
|
||||||
|
file,
|
||||||
|
"group_#{group_name}",
|
||||||
|
origin: UrlHelper.absolute(old_url)
|
||||||
|
).create_for(Discourse.system_user.id)
|
||||||
|
|
||||||
|
group.update_columns(flair_upload_id: upload.id, flair_url: nil) if upload.present?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def logger
|
||||||
|
Rails.logger
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -68,6 +68,7 @@ module Jobs
|
||||||
.joins("LEFT JOIN custom_emojis ce ON ce.upload_id = uploads.id")
|
.joins("LEFT JOIN custom_emojis ce ON ce.upload_id = uploads.id")
|
||||||
.joins("LEFT JOIN theme_fields tf ON tf.upload_id = uploads.id")
|
.joins("LEFT JOIN theme_fields tf ON tf.upload_id = uploads.id")
|
||||||
.joins("LEFT JOIN user_exports ue ON ue.upload_id = uploads.id")
|
.joins("LEFT JOIN user_exports ue ON ue.upload_id = uploads.id")
|
||||||
|
.joins("LEFT JOIN groups g ON g.flair_upload_id = uploads.id")
|
||||||
.where("pu.upload_id IS NULL")
|
.where("pu.upload_id IS NULL")
|
||||||
.where("u.uploaded_avatar_id IS NULL")
|
.where("u.uploaded_avatar_id IS NULL")
|
||||||
.where("ua.gravatar_upload_id IS NULL AND ua.custom_upload_id IS NULL")
|
.where("ua.gravatar_upload_id IS NULL AND ua.custom_upload_id IS NULL")
|
||||||
|
@ -76,6 +77,7 @@ module Jobs
|
||||||
.where("ce.upload_id IS NULL")
|
.where("ce.upload_id IS NULL")
|
||||||
.where("tf.upload_id IS NULL")
|
.where("tf.upload_id IS NULL")
|
||||||
.where("ue.upload_id IS NULL")
|
.where("ue.upload_id IS NULL")
|
||||||
|
.where("g.flair_upload_id IS NULL")
|
||||||
.where("ss.value IS NULL")
|
.where("ss.value IS NULL")
|
||||||
|
|
||||||
result = result.where("uploads.url NOT IN (?)", ignore_urls) if ignore_urls.present?
|
result = result.where("uploads.url NOT IN (?)", ignore_urls) if ignore_urls.present?
|
||||||
|
|
|
@ -27,6 +27,8 @@ class Group < ActiveRecord::Base
|
||||||
has_many :category_reviews, class_name: 'Category', foreign_key: :reviewable_by_group_id, dependent: :nullify
|
has_many :category_reviews, class_name: 'Category', foreign_key: :reviewable_by_group_id, dependent: :nullify
|
||||||
has_many :reviewables, foreign_key: :reviewable_by_group_id, dependent: :nullify
|
has_many :reviewables, foreign_key: :reviewable_by_group_id, dependent: :nullify
|
||||||
|
|
||||||
|
belongs_to :flair_upload, class_name: 'Upload'
|
||||||
|
|
||||||
has_and_belongs_to_many :web_hooks
|
has_and_belongs_to_many :web_hooks
|
||||||
|
|
||||||
before_save :downcase_incoming_email
|
before_save :downcase_incoming_email
|
||||||
|
@ -62,7 +64,6 @@ class Group < ActiveRecord::Base
|
||||||
validate :automatic_membership_email_domains_format_validator
|
validate :automatic_membership_email_domains_format_validator
|
||||||
validate :incoming_email_validator
|
validate :incoming_email_validator
|
||||||
validate :can_allow_membership_requests, if: :allow_membership_requests
|
validate :can_allow_membership_requests, if: :allow_membership_requests
|
||||||
validates :flair_url, url: true, if: Proc.new { |g| g.flair_url && g.flair_url.exclude?('fa-') }
|
|
||||||
validate :validate_grant_trust_level, if: :will_save_change_to_grant_trust_level?
|
validate :validate_grant_trust_level, if: :will_save_change_to_grant_trust_level?
|
||||||
|
|
||||||
AUTO_GROUPS = {
|
AUTO_GROUPS = {
|
||||||
|
@ -741,6 +742,15 @@ class Group < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def flair_type
|
||||||
|
return :icon if flair_icon.present?
|
||||||
|
return :image if flair_upload_id.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def flair_url
|
||||||
|
flair_icon.presence || flair_upload&.url || self[:flair_url].presence
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def name_format_validator
|
def name_format_validator
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class GroupShowSerializer < BasicGroupSerializer
|
class GroupShowSerializer < BasicGroupSerializer
|
||||||
attributes :is_group_user, :is_group_owner, :is_group_owner_display, :mentionable, :messageable
|
attributes :is_group_user, :is_group_owner, :is_group_owner_display, :mentionable, :messageable, :flair_icon, :flair_type
|
||||||
|
|
||||||
def include_is_group_user?
|
def include_is_group_user?
|
||||||
authenticated?
|
authenticated?
|
||||||
|
@ -43,6 +43,14 @@ class GroupShowSerializer < BasicGroupSerializer
|
||||||
Group.messageable(scope.user).exists?(id: object.id)
|
Group.messageable(scope.user).exists?(id: object.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def include_flair_icon?
|
||||||
|
is_group_owner && flair_icon.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_flair_type?
|
||||||
|
is_group_owner && flair_type.present?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def authenticated?
|
def authenticated?
|
||||||
|
|
|
@ -751,14 +751,16 @@ en:
|
||||||
title: "Muted"
|
title: "Muted"
|
||||||
description: "You will not be notified of anything about messages in this group."
|
description: "You will not be notified of anything about messages in this group."
|
||||||
flair_url: "Avatar Flair Image"
|
flair_url: "Avatar Flair Image"
|
||||||
flair_url_placeholder: "(Optional) Image URL or Font Awesome class"
|
flair_upload_description: "Use square images no smaller than 20px by 20px."
|
||||||
flair_url_description: 'Use square images no smaller than 20px by 20px or FontAwesome icons (accepted formats: "fa-icon", "far fa-icon" or "fab fa-icon").'
|
|
||||||
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: "Avatar Flair Color"
|
||||||
flair_color_placeholder: "(Optional) Hex color value"
|
flair_color_placeholder: "(Optional) Hex color value"
|
||||||
flair_preview_icon: "Preview Icon"
|
flair_preview_icon: "Preview Icon"
|
||||||
flair_preview_image: "Preview Image"
|
flair_preview_image: "Preview Image"
|
||||||
|
flair_type:
|
||||||
|
icon: "Select an icon"
|
||||||
|
image: "Upload an image"
|
||||||
|
|
||||||
user_action_groups:
|
user_action_groups:
|
||||||
"1": "Likes"
|
"1": "Likes"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddMoreFlairColumnsToGroup < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
add_column :groups, :flair_icon, :string
|
||||||
|
add_column :groups, :flair_upload_id, :integer
|
||||||
|
|
||||||
|
reversible do |dir|
|
||||||
|
dir.up do
|
||||||
|
DB.exec(
|
||||||
|
<<~SQL
|
||||||
|
UPDATE groups SET flair_icon = REPLACE(REPLACE(flair_url, 'fas fa-', ''), ' fa-', '-')
|
||||||
|
WHERE flair_url LIKE 'fa%'
|
||||||
|
SQL
|
||||||
|
)
|
||||||
|
|
||||||
|
DB.exec(
|
||||||
|
<<~SQL
|
||||||
|
UPDATE groups g1
|
||||||
|
SET flair_upload_id = u.id
|
||||||
|
FROM groups g2
|
||||||
|
INNER JOIN uploads u ON g2.flair_url ~ CONCAT('\/', u.sha1, '[\.\w]*')
|
||||||
|
WHERE g1.id = g2.id
|
||||||
|
SQL
|
||||||
|
)
|
||||||
|
|
||||||
|
DB.exec(
|
||||||
|
<<~SQL
|
||||||
|
UPDATE groups SET flair_url = NULL
|
||||||
|
WHERE flair_icon IS NOT NULL OR flair_upload_id IS NOT NULL
|
||||||
|
SQL
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,7 +13,7 @@ class PrimaryGroupLookup
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.lookup_columns
|
def self.lookup_columns
|
||||||
@lookup_columns ||= %i{id name flair_url flair_bg_color flair_color}
|
@lookup_columns ||= %i{id name flair_icon flair_upload_id flair_bg_color flair_color}
|
||||||
end
|
end
|
||||||
|
|
||||||
def users
|
def users
|
||||||
|
@ -29,7 +29,7 @@ class PrimaryGroupLookup
|
||||||
group_ids = users_with_primary_group.map(&:primary_group_id)
|
group_ids = users_with_primary_group.map(&:primary_group_id)
|
||||||
group_ids.uniq!
|
group_ids.uniq!
|
||||||
|
|
||||||
Group.where(id: group_ids).select(self.class.lookup_columns)
|
Group.includes(:flair_upload).where(id: group_ids).select(self.class.lookup_columns)
|
||||||
.each { |g| group_lookup[g.id] = g }
|
.each { |g| group_lookup[g.id] = g }
|
||||||
|
|
||||||
hash = {}
|
hash = {}
|
||||||
|
|
|
@ -388,7 +388,7 @@ License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.group_icons
|
def self.group_icons
|
||||||
Group.where("flair_url LIKE '%fa-%'").pluck(:flair_url).uniq
|
Group.pluck(:flair_icon).uniq
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.theme_icons(theme_ids)
|
def self.theme_icons(theme_ids)
|
||||||
|
|
|
@ -216,12 +216,12 @@ describe SvgSprite do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "includes Font Awesome 4.7 icons as group flair" do
|
it "includes Font Awesome 4.7 icons as group flair" do
|
||||||
group = Fabricate(:group, flair_url: "fa-air-freshener")
|
group = Fabricate(:group, flair_icon: "fa-air-freshener")
|
||||||
expect(SvgSprite.bundle).to match(/air-freshener/)
|
expect(SvgSprite.bundle).to match(/air-freshener/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "includes Font Awesome 5 icons as group flair" do
|
it "includes Font Awesome 5 icons as group flair" do
|
||||||
group = Fabricate(:group, flair_url: "far fa-building")
|
group = Fabricate(:group, flair_icon: "far fa-building")
|
||||||
expect(SvgSprite.bundle).to match(/building/)
|
expect(SvgSprite.bundle).to match(/building/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe Jobs::MigrateGroupFlairImages do
|
||||||
|
let(:image_url) { "https://omg.aws.somestack/test.png" }
|
||||||
|
let(:group) { Fabricate(:group, flair_url: image_url) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
stub_request(:get, image_url).to_return(
|
||||||
|
status: 200, body: file_from_fixtures("smallest.png").read
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should migrate to the new group `flair_upload_id` column correctly' do
|
||||||
|
group
|
||||||
|
|
||||||
|
expect do
|
||||||
|
described_class.new.execute_onceoff({})
|
||||||
|
end.to change { Upload.count }.by(1)
|
||||||
|
|
||||||
|
group.reload
|
||||||
|
expect(group.flair_upload).to eq(Upload.last)
|
||||||
|
expect(group[:flair_url]).to eq(nil)
|
||||||
|
end
|
||||||
|
end
|
|
@ -674,7 +674,7 @@ describe GroupsController do
|
||||||
incoming_email: 'test@mail.org',
|
incoming_email: 'test@mail.org',
|
||||||
flair_bg_color: 'FFF',
|
flair_bg_color: 'FFF',
|
||||||
flair_color: 'BBB',
|
flair_color: 'BBB',
|
||||||
flair_url: 'fa-adjust',
|
flair_icon: 'fa-adjust',
|
||||||
bio_raw: 'testing',
|
bio_raw: 'testing',
|
||||||
full_name: 'awesome team',
|
full_name: 'awesome team',
|
||||||
public_admission: true,
|
public_admission: true,
|
||||||
|
|
Loading…
Reference in New Issue