FEATURE: display warning on top of composer for group mentions

If users attempt to mention a group that is "mentionable" display a warning
informing them that people will be notified.
This commit is contained in:
Sam 2015-12-04 13:40:38 +11:00
parent 18c9d966a1
commit 7917316f6f
8 changed files with 69 additions and 3 deletions

View File

@ -114,6 +114,25 @@ export default Ember.Component.extend({
_renderUnseen: function($preview, unseen) {
fetchUnseenMentions($preview, unseen, this.siteSettings).then(() => {
linkSeenMentions($preview, this.siteSettings);
this._warnMentionedGroups($preview);
});
},
_warnMentionedGroups($preview) {
Ember.run.scheduleOnce('afterRender', () => {
this._warnedMentions = this._warnedMentions || [];
var found = [];
$preview.find('.mention-group.notify').each((idx,e) => {
const $e = $(e);
var name = $e.data('name');
found.push(name);
if (this._warnedMentions.indexOf(name) === -1){
this._warnedMentions.push(name);
this.sendAction('groupsMentioned', [{name: name, user_count: $e.data('mentionable-user-count')}]);
}
});
this._warnedMentions = found;
});
},
@ -370,6 +389,8 @@ export default Ember.Component.extend({
Ember.run.debounce(this, this._renderUnseen, $preview, unseen, 500);
}
this._warnMentionedGroups($preview);
const post = this.get('composer.post');
let refresh = false;

View File

@ -48,6 +48,23 @@ export default Ember.ArrayController.extend({
this.get('queuedForTyping').forEach(msg => this.send("popup", msg));
},
groupsMentioned(groups) {
// reset existing messages, this should always win it is critical
this.reset();
groups.forEach(group => {
const msg = I18n.t('composer.group_mentioned', {
group: "@" + group.name,
count: group.user_count,
group_link: Discourse.getURL(`/group/${group.name}/members`)
});
this.send("popup",
Em.Object.create({
templateName: 'composer/group-mentioned',
body: msg})
);
});
},
// Figure out if there are any messages that should be displayed above the composer.
queryFor(composer) {
if (this.get('checkedMessages')) { return; }

View File

@ -171,6 +171,12 @@ export default Ember.Controller.extend({
}
},
groupsMentioned(groups) {
if (!this.get('model.creatingPrivateMessage') && !this.get('model.topic.isPrivateMessage')) {
this.get('controllers.composer-messages').groupsMentioned(groups);
}
}
},
categories: function() {

View File

@ -1,8 +1,13 @@
function replaceSpan($e, username, opts) {
if (opts && opts.group) {
var extra = "", extraClass = "";
if (opts.mentionable) {
extra = " data-name='" + username + "' data-mentionable-user-count='" + opts.mentionable.user_count + "' ";
extraClass = " notify";
}
$e.replaceWith("<a href='" +
Discourse.getURL("/groups/") + username +
"' class='mention-group'>@" + username + "</a>");
"' class='mention-group" + extraClass + "'" + extra + ">@" + username + "</a>");
} else {
$e.replaceWith("<a href='" +
Discourse.getURL("/users/") + username.toLowerCase() +
@ -12,6 +17,7 @@ function replaceSpan($e, username, opts) {
const found = [];
const foundGroups = [];
const mentionableGroups = [];
const checked = [];
function updateFound($mentions, usernames) {
@ -22,7 +28,8 @@ function updateFound($mentions, usernames) {
if (found.indexOf(username.toLowerCase()) !== -1) {
replaceSpan($e, username);
} else if (foundGroups.indexOf(username) !== -1) {
replaceSpan($e, username, {group: true});
const mentionable = _(mentionableGroups).where({name: username}).first();
replaceSpan($e, username, {group: true, mentionable: mentionable});
} else if (checked.indexOf(username) !== -1) {
$e.addClass('mention-tested');
}
@ -48,6 +55,8 @@ export function fetchUnseenMentions($elem, usernames) {
return Discourse.ajax("/users/is_local_username", { data: { usernames } }).then(function(r) {
found.push.apply(found, r.valid);
foundGroups.push.apply(foundGroups, r.valid_groups);
mentionableGroups.push.apply(mentionableGroups, r.mentionable_groups);
checked.push.apply(checked, usernames);
return r;
});
}

View File

@ -82,6 +82,7 @@
canWhisper=canWhisper
draftStatus=model.draftStatus
isUploading=isUploading
groupsMentioned="groupsMentioned"
importQuote="importQuote"
showOptions="showOptions"
showUploadSelector="showUploadSelector"}}

View File

@ -0,0 +1,2 @@
<a href {{action "closeMessage" this}} class='close'><i class='fa fa-times-circle'></i></a>
{{{body}}}

View File

@ -206,13 +206,21 @@ class UsersController < ApplicationController
usernames.each(&:downcase!)
groups = Group.where(name: usernames).pluck(:name)
mentionable_groups =
if current_user
Group.mentionable(current_user)
.where(name: usernames)
.pluck(:name, :user_count)
.map{ |name,user_count| {name: name, user_count: user_count} }
end
usernames -= groups
result = User.where(staged: false)
.where(username_lower: usernames)
.pluck(:username_lower)
render json: {valid: result, valid_groups: groups}
render json: {valid: result, valid_groups: groups, mentionable_groups: mentionable_groups}
end
def render_available_true

View File

@ -850,6 +850,8 @@ en:
similar_topics: "Your topic is similar to..."
drafts_offline: "drafts offline"
group_mentioned: "By using {{group}}, you are about to notify <a href='{{group_link}}'>{{count}} people</a>."
error:
title_missing: "Title is required"
title_too_short: "Title must be at least {{min}} characters"