UX: use "icon-picker" & "image-uploader" fields to set group flair. (#9779)

UX: use “icon-picker” & “image-uploader” fields to set group flair. (#9779)

diff --git a/app/assets/javascripts/discourse/app/components/group-flair-inputs.js b/app/assets/javascripts/discourse/app/components/group-flair-inputs.js
index 7b432e1..b5ecb07 100644
--- a/app/assets/javascripts/discourse/app/components/group-flair-inputs.js
+++ b/app/assets/javascripts/discourse/app/components/group-flair-inputs.js
@@ -2,11 +2,12 @@ import I18n from "I18n";
 import discourseComputed from "discourse-common/utils/decorators";
 import { debounce } from "@ember/runloop";
 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 { convertIconClass } from "discourse-common/lib/icon-library";
 import { ajax } from "discourse/lib/ajax";
 import { htmlSafe } from "@ember/template";
+import { action } from "@ember/object";
 
 export default Component.extend({
   classNames: ["group-flair-inputs"],
@@ -16,23 +17,26 @@ export default Component.extend({
     return Discourse.getURL("/images/avatar.png");
   },
 
-  @discourseComputed("model.flair_url")
-  flairPreviewIcon(flairURL) {
-    return flairURL && /fa(r|b?)-/.test(flairURL);
+  @discourseComputed("model.flair_type")
+  flairPreviewIcon(flairType) {
+    return flairType && flairType === "icon";
   },
 
-  @discourseComputed("model.flair_url", "flairPreviewIcon")
-  flairPreviewIconUrl(flairURL, flairPreviewIcon) {
-    return flairPreviewIcon ? convertIconClass(flairURL) : "";
+  @discourseComputed("model.flair_icon")
+  flairPreviewIconUrl(flairIcon) {
+    return flairIcon ? convertIconClass(flairIcon) : "";
   },
 
-  @observes("model.flair_url")
-  _loadSVGIcon() {
-    debounce(this, this._loadIcon, 1000);
+  @on("didInsertElement")
+  @observes("model.flair_icon")
+  _loadSVGIcon(flairIcon) {
+    if (flairIcon) {
+      debounce(this, this._loadIcon, 1000);
+    }
   },
 
   _loadIcon() {
-    const icon = convertIconClass(this.get("model.flair_url")),
+    const icon = convertIconClass(this.model.flair_icon),
       c = "#svg-sprites",
       h = "ajax-icon-holder",
       singleIconEl = `${c} .${h}`;
@@ -50,9 +54,14 @@ export default Component.extend({
     }
   },
 
-  @discourseComputed("model.flair_url", "flairPreviewIcon")
-  flairPreviewImage(flairURL, flairPreviewIcon) {
-    return flairURL && !flairPreviewIcon;
+  @discourseComputed("model.flair_type")
+  flairPreviewImage(flairType) {
+    return flairType && flairType === "image";
+  },
+
+  @discourseComputed("model.flair_url")
+  flairImageUrl(flairURL) {
+    return flairURL && flairURL.match(/\//) ? flairURL : null;
   },
 
   @discourseComputed(
@@ -91,5 +100,21 @@ export default Component.extend({
   flairPreviewLabel(flairPreviewImage) {
     const key = flairPreviewImage ? "image" : "icon";
     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
+    });
   }
 });
diff --git a/app/assets/javascripts/discourse/app/models/group.js b/app/assets/javascripts/discourse/app/models/group.js
index ea4d03d..1423414 100644
--- a/app/assets/javascripts/discourse/app/models/group.js
+++ b/app/assets/javascripts/discourse/app/models/group.js
@@ -188,7 +188,8 @@ const Group = RestModel.extend({
       primary_group: !!this.primary_group,
       grant_trust_level: this.grant_trust_level,
       incoming_email: this.incoming_email,
-      flair_url: this.flair_url,
+      flair_icon: null,
+      flair_upload_id: null,
       flair_bg_color: this.flairBackgroundHexColor,
       flair_color: this.flairHexColor,
       bio_raw: this.bio_raw,
@@ -201,6 +202,12 @@ const Group = RestModel.extend({
       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) {
       attrs["usernames"] = this.usernames;
       attrs["owner_usernames"] = this.ownerUsernames;
diff --git a/app/assets/javascripts/discourse/app/templates/components/group-flair-inputs.hbs b/app/assets/javascripts/discourse/app/templates/components/group-flair-inputs.hbs
index 36dfc26..f198b7b 100644
--- a/app/assets/javascripts/discourse/app/templates/components/group-flair-inputs.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/group-flair-inputs.hbs
@@ -1,13 +1,36 @@
 <div class="control-group">
   <label class="control-label" for="flair_url">{{i18n "groups.flair_url"}}</label>
 
-  {{text-field name="flair_url"
-      class="input-xxlarge"
-      value=model.flair_url
-      placeholderKey="groups.flair_url_placeholder"}}
-  <div class="control-instructions">
-    {{i18n "groups.flair_url_description"}}
+  <div class="radios">
+    <label class="radio-label" for="avatar-flair">
+      {{radio-button name="avatar-flair" value="icon" selection=model.flair_type}}
+      <b>{{i18n "groups.flair_type.icon"}}</b>
+    </label>
+
+    <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>
+
+  {{#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 class="control-group">
@@ -40,7 +63,7 @@
 
     {{#if flairPreviewImage}}
       <div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}}></div>
-    {{else}}
+    {{else if flairPreviewIcon}}
       <div class="avatar-flair demo {{flairPreviewClasses}}" style={{flairPreviewStyle}} role="presentation">
         {{d-icon flairPreviewIconUrl}}
       </div>
diff --git a/app/assets/javascripts/discourse/app/widgets/avatar-flair.js b/app/assets/javascripts/discourse/app/widgets/avatar-flair.js
index 0da095d..94e015f 100644
--- a/app/assets/javascripts/discourse/app/widgets/avatar-flair.js
+++ b/app/assets/javascripts/discourse/app/widgets/avatar-flair.js
@@ -8,7 +8,7 @@ createWidget("avatar-flair", {
   isIcon(attrs) {
     return (
       attrs.primary_group_flair_url &&
-      attrs.primary_group_flair_url.includes("fa-")
+      !attrs.primary_group_flair_url.includes("/")
     );
   },
 
diff --git a/app/assets/stylesheets/common/base/group.scss b/app/assets/stylesheets/common/base/group.scss
index 013acd0..998a82a 100644
--- a/app/assets/stylesheets/common/base/group.scss
+++ b/app/assets/stylesheets/common/base/group.scss
@@ -153,6 +153,22 @@ table.group-members {
       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 {
diff --git a/app/controllers/admin/groups_controller.rb b/app/controllers/admin/groups_controller.rb
index 50cef29..32114f3 100644
--- a/app/controllers/admin/groups_controller.rb
+++ b/app/controllers/admin/groups_controller.rb
@@ -163,7 +163,8 @@ class Admin::GroupsController < Admin::AdminController
       :primary_group,
       :grant_trust_level,
       :incoming_email,

[... diff too long, it was truncated ...]

GitHub sha: 8e561977

1 Like

This commit appears in #9779 which was approved by eviltrout. It was merged by vinothkannans.