Skip to content

Commit

Permalink
Merge pull request #9510 from RocketChat/contextual-bar-mail-messages
Browse files Browse the repository at this point in the history
[NEW] Contextual bar mail messages
  • Loading branch information
rodrigok authored Jan 26, 2018
2 parents 59487fe + c607fe4 commit d230364
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -1,31 +1,49 @@
<template name="mailMessagesInstructions">
<main class="rc-user-info__scroll">
<div class="rc-input rc-input--usernames">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "To_users"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-svg" icon="at"}}
{{#if selectedMessages}}
<div class="mail-messages__instructions mail-messages__instructions--selected">
<div class="mail-messages__instructions-wrapper">
{{> icon block="mail-messages__instructions-icon" icon="modal-success"}}
<div class="mail-messages__instructions-text">
<span class="mail-messages__instructions-text-selected">{{selectedMessages.length}} Messages selected</span>
<span>Click here to clear the selection</span>
</div>
</div>
<div class="rc-tags">
{{#each user in selectedUsers}}
{{> tag user}}
{{/each}}
<input type="text" class="rc-tags__input" placeholder="{{_ "Username_Placeholder"}}" name="users" autocomplete="off"/>
</div>
{{else}}
<div class="mail-messages__instructions">
<div class="mail-messages__instructions-wrapper">
{{> icon block="mail-messages__instructions-icon" icon="hand-pointer"}}
<div class="mail-messages__instructions-text">
Click the messages you would like to send by e-mail
</div>
</div>
</div>
{{#with config}}
{{#if autocomplete 'isShowing'}}
<div class="fadeInDown">
{{/if}}
<div class="rc-input rc-input--usernames">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "To_users"}}</div>
<div class="rc-input__wrapper">
<div class="rc-input__icon">
{{> icon block="rc-input__icon-svg" icon="at"}}
</div>
<div class="rc-tags">
{{#each user in selectedUsers}}
{{> tag user}}
{{/each}}
<input type="text" class="rc-tags__input" placeholder="{{_ "Username_Placeholder"}}" name="users" autocomplete="off"/>
</div>
</div>
{{#with config}}
{{#if autocomplete 'isShowing'}}
{{#if autocomplete 'isLoaded'}}
{{> popupList data=config items=items}}
{{/if}}
</div>
{{/if}}
{{/with}}
</label>
</div>
<div class="rc-input rc-input--emails">
{{/if}}
{{/with}}
</label>
</div>
<div class="rc-input rc-input--emails">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "To_additional_emails"}}</div>
<div class="rc-input__wrapper">
Expand All @@ -52,6 +70,14 @@
</div>
</label>
</div>

{{#if errorMessage}}
<div class="mail-messages__instructions mail-messages__instructions--warning">
<div class="mail-messages__instructions-wrapper">
<div class="mail-messages__instructions-text">{{errorMessage}}</div>
</div>
</div>
{{/if}}
</main>
<div class="rc-user-info__flex rc-user-info__row">
<button class="rc-button rc-button--outline js-cancel" title="{{_ 'Cancel'}}">{{_ 'Cancel'}}</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* global AutoComplete Deps */

import _ from 'underscore';
import toastr from 'toastr';
import resetSelection from '../resetSelection';

Expand Down Expand Up @@ -79,6 +77,9 @@ Template.mailMessagesInstructions.helpers({
selectedEmails() {
return Template.instance().selectedEmails.get();
},
selectedMessages() {
return Template.instance().selectedMessages.get();
},
config() {
const filter = Template.instance().userFilter;
return {
Expand All @@ -99,90 +100,62 @@ Template.mailMessagesInstructions.helpers({
},
items() {
return Template.instance().ac.filteredList();
},
errorMessage() {
return Template.instance().errorMessage.get();
}
});

Template.mailMessagesInstructions.events({
'click .js-cancel'(e, t) {
'click .js-cancel, click .mail-messages__instructions--selected'(e, t) {
t.reset(true);
},
'click .js-send'(e, t) {
t.$('.error').hide();
const $btn = t.$('button.send');
const oldBtnValue = $btn.html();
$btn.html(TAPi18n.__('Sending'));
const selectedMessages = $('.messages-box .message.selected');
let error = false;
if (selectedMessages.length === 0) {
t.$('.error-select').show();
error = true;
'click .js-send'(e, instance) {
const selectedUsers = instance.selectedUsers;
const selectedEmails = instance.selectedEmails;
const $emailsInput = instance.$('[name="emails"]');
const selectedMessages = instance.selectedMessages;
const subject = instance.$('[name="subject"]').val();

if (!selectedUsers.get().length && !selectedEmails.get().length && $emailsInput.val().trim() === '') {
instance.errorMessage.set(t('Mail_Message_Missing_to'));
return false;
}
if (t.$('input[name=to_emails]').val().trim()) {
const rfcMailPatternWithName = /^(?:.*<)?([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)(?:>?)$/;
const emails = t.$('input[name=to_emails]').val().trim().split(',');
const erroredEmails = [];
emails.forEach((email) => {
if (!rfcMailPatternWithName.test(email.trim())) {
erroredEmails.push(email.trim());
}
});
t.erroredEmails.set(erroredEmails);
if (erroredEmails.length > 0) {
t.$('.error-invalid-emails').show();
error = true;

if ($emailsInput.val() !== '') {
if (isEmail($emailsInput.val())) {
const emailsArr = selectedEmails.get();
emailsArr.push({text: $emailsInput.val()});
$('[name="emails"]').val('');
selectedEmails.set(emailsArr);
} else {
instance.errorMessage.set(t('Mail_Message_Invalid_emails', $emailsInput.val()));
return false;
}
} else if (!t.selectedUsers.get().length) {
t.$('.error-missing-to').show();
error = true;
}
if (error) {
return $btn.html(oldBtnValue);

if (!selectedMessages.get().length) {
instance.errorMessage.set(t('Mail_Message_No_messages_selected_select_all'));
return false;
}

const data = {
rid: Session.get('openedRoom'),
to_users: t.selectedUsers.get(),
to_emails: t.$('input[name=to_emails]').val().trim(),
subject: t.$('input[name=subject]').val().trim(),
messages: selectedMessages.map(function(i, message) {
return message.id;
}).toArray(),
to_users: selectedUsers.get().map(user => user.username),
to_emails: selectedEmails.get().map(email => email.text).toString(),
subject,
messages: selectedMessages.get(),
language: localStorage.getItem('userLanguage')
};
return Meteor.call('mailMessages', data, function(err, result) {
$btn.html(oldBtnValue);

Meteor.call('mailMessages', data, function(err, result) {
if (err != null) {
return handleError(err);
}
console.log(result);
toastr.success(TAPi18n.__('Your_email_has_been_queued_for_sending'));
return t.reset();
});
},
'click .select-all'(e, t) {
t.$('.error-select').hide();
const view = Blaze.getView($('.messages-box')[0]);
if (view != null) {
if (typeof view.templateInstance === 'function') {
const chat = ChatMessage.find({
rid: Session.get('openedRoom')
});
view.templateInstance().selectedMessages = _.pluck(chat && chat.fetch(), '_id');
}
}
return $('.messages-box .message').addClass('selected');
},
'autocompleteselect #to_users'(event, instance, doc) {
instance.selectedUsers.set(instance.selectedUsers.get().concat(doc.username));
event.currentTarget.value = '';
return event.currentTarget.focus();
},
'click .remove-to-user'() {
let users = Template.instance().selectedUsers.get();
users = _.reject(Template.instance().selectedUsers.get(), (_id) => {
return _id === this.valueOf();
toastr.success(t('Your_email_has_been_queued_for_sending'));
instance.reset(true);
});
Template.instance().selectedUsers.set(users);
return $('#to_users').focus();
},
'click .rc-input--usernames .rc-tags__tag'({target}, t) {
const {username} = Blaze.getData(target);
Expand Down Expand Up @@ -263,11 +236,27 @@ Template.mailMessagesInstructions.onRendered(function() {
usersArr.push(item);
users.set(usersArr);
});

const selectedMessages = this.selectedMessages;

$('.messages-box .message').on('click', function() {
const id = this.id;
const messages = selectedMessages.get();

if ($(this).hasClass('selected')) {
selectedMessages.set(messages.filter(message => message !== id));
} else {
selectedMessages.set(messages.concat(id));
}
});
});

Template.mailMessagesInstructions.onCreated(function() {
resetSelection(true);

this.selectedEmails = new ReactiveVar([]);
this.selectedMessages = new ReactiveVar([]);
this.errorMessage = new ReactiveVar('');
this.selectedUsers = new ReactiveVar([]);
this.userFilter = new ReactiveVar('');

Expand Down Expand Up @@ -301,16 +290,13 @@ Template.mailMessagesInstructions.onCreated(function() {
]

});

this.ac.tmplInst = this;

this.selectedEmails = new ReactiveVar([]);

this.autoCompleteCollection = new Mongo.Collection(null);
this.erroredEmails = new ReactiveVar([]);
this.reset = (bool) => {
this.selectedUsers.set([]);
this.selectedEmails.set([]);
this.selectedMessages.set([]);
this.errorMessage.set('');
resetSelection(bool);
};
});
Expand Down
2 changes: 1 addition & 1 deletion packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@
"mail-messages_description": "Permission to use the mail messages option",
"Mail_Message_Invalid_emails": "You have provided one or more invalid emails: %s",
"Mail_Message_Missing_to": "You must select one or more users or provide one or more email addresses, separated by commas.",
"Mail_Message_No_messages_selected_select_all": "You haven't selected any messages. Would you like to <a href='#' class='select-all'>select all</a> visible messages?",
"Mail_Message_No_messages_selected_select_all": "You haven't selected any messages",
"Mail_Messages": "Mail Messages",
"Mail_Messages_Instructions": "Choose which messages you want to send via email by clicking the messages",
"Mail_Messages_Subject": "Here's a selected portion of %s messages",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,67 @@
color: #9ea2a8;
}
}

.contextual-bar__content.mail-messages {
& .rc-popup-list {
z-index: 1;
}

& .rc-input:not(:last-child) {
margin-bottom: 2rem;
}
}

.mail-messages__instructions {
display: flex;
border-width: 1px;
border-color: var(--rc-color-alert-message-primary);
background: var(--rc-color-alert-message-primary-background);
border-radius: 2px;
color: var(--rc-color-alert-message-primary);
padding: 1.25rem;
margin-bottom: 3rem;

&--selected {
background: var(--rc-color-alert-message-secondary-background);
border-color: var(--rc-color-alert-message-secondary);
color: var(--rc-color-alert-message-secondary);

cursor: pointer;
}

&--warning {
color: var(--rc-color-alert-message-warning);
border-color: var(--rc-color-alert-message-warning);
background: var(--rc-color-alert-message-warning-background);
}

&-wrapper {
display: flex;
margin: 0 -10px;
}

&-icon {
font-size: 2rem;
margin: 0 10px;

&--hand-pointer {
transform: rotate3d(0, 0, 1, -25deg);
margin: 0 15px;
fill: currentColor;
}
}

&-text {
font-size: 0.875rem;
font-weight: 600;
margin: 0 10px;
display: flex;
flex-direction: column;
line-height: 1.2rem;

&-selected {
font-weight: 400;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
--rc-color-button-primary: #1d74f5;
--rc-color-button-primary-light: #175cc4;

--rc-color-alert-message-primary: var(--rc-color-button-primary);
--rc-color-alert-message-primary-background: #f1f6ff;
--rc-color-alert-message-secondary: #7ca52b;
--rc-color-alert-message-secondary-background: #fafff1;
--rc-color-alert-message-warning: #d52d24;
--rc-color-alert-message-warning-background: #fff3f3;

--rc-color-primary: var(--color-dark);
--rc-color-primary-darkest: var(--color-darkest);
--rc-color-primary-dark: var(--color-dark-medium);
Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-ui-master/public/icons.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit d230364

Please sign in to comment.