Allow several email addresses for invitations

master
Daniel Berteaud 10 years ago
parent 428f7599dd
commit dfda2f03f4
  1. 2
      lib/Vroom/I18N/en.pm
  2. 2
      lib/Vroom/I18N/fr.pm
  3. 43
      public/js/vroom.js
  4. 2
      templates/default/configure_modal.html.ep
  5. 14
      templates/default/invite_modal.html.ep
  6. 75
      vroom.pl

@ -16,7 +16,7 @@ our %Lexicon = (
"ERROR_NOT_LOGGED_IN" => "Sorry, your not logged in", "ERROR_NOT_LOGGED_IN" => "Sorry, your not logged in",
"JS_REQUIRED" => "VROOM needs javascript to work properly", "JS_REQUIRED" => "VROOM needs javascript to work properly",
"EMAIL_INVITATION" => "Video conference invitation", "EMAIL_INVITATION" => "Video conference invitation",
"INVITE_SENT_TO_s" => "An invitation was sent to %s", "INVITE_SENT_TO_s" => "An invitation was sent to the following addresses\n%s",
"YOU_ARE_INVITED_TO_A_MEETING" => "You are awaited on a video conferecing room. " . "YOU_ARE_INVITED_TO_A_MEETING" => "You are awaited on a video conferecing room. " .
"Before joining it, make sure you have all the necessary", "Before joining it, make sure you have all the necessary",
"A_MODERN_BROWSER" => "A modern web browser, recent versions of Mozilla Firefox, Google Chrome or Opera will work", "A_MODERN_BROWSER" => "A modern web browser, recent versions of Mozilla Firefox, Google Chrome or Opera will work",

@ -40,7 +40,7 @@ our %Lexicon = (
"FROM" => "De la part de", "FROM" => "De la part de",
"GIVE_US_YOUR_FEEDBACK" => "Parlez-nous de votre expérience", "GIVE_US_YOUR_FEEDBACK" => "Parlez-nous de votre expérience",
"YOUR_FEEDBACK_HELPS_US" => "Votre retour d'expérience (bonne ou mauvaise) peut nous aider à améliorer ce service", "YOUR_FEEDBACK_HELPS_US" => "Votre retour d'expérience (bonne ou mauvaise) peut nous aider à améliorer ce service",
"INVITE_SENT_TO_s" => "Une invitation a été envoyée à %s", "INVITE_SENT_TO_s" => "Une invitation a été envoyée aux adresses suivantes\n%s",
"DATA_WIPED" => "Les données ont été supprimées", "DATA_WIPED" => "Les données ont été supprimées",
"ROOM_DATA_WIPED_BY_s" => "Les données du salon (historique du tchat, prise de notes) ont été supprimées par %s", "ROOM_DATA_WIPED_BY_s" => "Les données du salon (historique du tchat, prise de notes) ont été supprimées par %s",
"NOT_ENABLED" => "Cette fonctionalité n'est pas activée", "NOT_ENABLED" => "Cette fonctionalité n'est pas activée",

@ -175,22 +175,22 @@ function maxHeight(){
} }
// Create a new input field // Create a new input field
function addEmailInputField(val){ function addEmailInputField(form, val){
var parentEl = $('.email-list'), var parentEl = $('#' + form),
currentEntry = parentEl.find('.email-entry:last'), currentEntry = parentEl.find('.email-entry:last'),
newEntry = $(currentEntry.clone()).css('display', 'none').appendTo(parentEl); newEntry = $(currentEntry.clone()).css('display', 'none').appendTo(parentEl);
newEntry.find('input').val(val); newEntry.find('input').val(val);
newEntry.removeClass('has-error'); newEntry.removeClass('has-error');
adjustAddRemoveEmailButtons(); adjustAddRemoveEmailButtons(form);
newEntry.show(100); newEntry.show(100);
} }
// Adjust add and remove buttons foir email notifications // Adjust add and remove buttons foir email notifications
function adjustAddRemoveEmailButtons(){ function adjustAddRemoveEmailButtons(form){
$('.email-list').find('.email-entry:not(:last) .btn-add-email') $('#' + form).find('.email-entry:not(:last) .btn-add-email')
.removeClass('btn-primary').removeClass('btn-add-email') .removeClass('btn-primary').removeClass('btn-add-email')
.addClass('btn-danger').addClass('btn-remove-email') .addClass('btn-danger').addClass('btn-remove-email')
.html('<span class="glyphicon glyphicon-minus"></span>'); .html('<span class="glyphicon glyphicon-minus"></span>');
$('.email-list').find('.email-entry:last .btn-remove-email') $('#' + form).find('.email-entry:last .btn-remove-email')
.removeClass('btn-danger').removeClass('btn-remove-email') .removeClass('btn-danger').removeClass('btn-remove-email')
.addClass('btn-primary').addClass('btn-add-email') .addClass('btn-primary').addClass('btn-add-email')
.html('<span class="glyphicon glyphicon-plus"></span>'); .html('<span class="glyphicon glyphicon-plus"></span>');
@ -198,7 +198,7 @@ function adjustAddRemoveEmailButtons(){
// Add emails input fields // Add emails input fields
$(document).on('click','button.btn-add-email',function(e){ $(document).on('click','button.btn-add-email',function(e){
e.preventDefault(); e.preventDefault();
addEmailInputField(''); addEmailInputField($(this).parents('.email-list:first').attr('id'), '');
}); });
$(document).on('click','button.btn-remove-email',function(e){ $(document).on('click','button.btn-remove-email',function(e){
e.preventDefault(); e.preventDefault();
@ -506,7 +506,7 @@ function initAdmin(){
// We keep it so we can clone it again // We keep it so we can clone it again
$('.email-list').find('.email-entry:not(:first)').remove(); $('.email-list').find('.email-entry:not(:first)').remove();
$.each(data.notif, function(index, obj){ $.each(data.notif, function(index, obj){
addEmailInputField(obj.email); addEmailInputField('email-list-notification', obj.email);
}); });
// Now, remove the first one if the list is not empty // Now, remove the first one if the list is not empty
if (Object.keys(data.notif).length > 0){ if (Object.keys(data.notif).length > 0){
@ -652,7 +652,7 @@ function initVroom(room) {
// We keep it so we can clone it again // We keep it so we can clone it again
$('.email-list').find('.email-entry:not(:first)').remove(); $('.email-list').find('.email-entry:not(:first)').remove();
$.each(data.notif, function(index, obj){ $.each(data.notif, function(index, obj){
addEmailInputField(obj.email); addEmailInputField('email-list-notification', obj.email);
}); });
// Now, remove the first one if the list is not empty // Now, remove the first one if the list is not empty
if (Object.keys(data.notif).length > 0){ if (Object.keys(data.notif).length > 0){
@ -1597,20 +1597,35 @@ function initVroom(room) {
// Handle Email Invitation // Handle Email Invitation
$('#inviteEmail').submit(function(event) { $('#inviteEmail').submit(function(event) {
event.preventDefault(); event.preventDefault();
var rcpt = $('#recipient').val(); var rcpts = [],
message = $('#message').val(); message = $('#message').val();
$('input[name="invitation-recipients[]"]').each(function(){
rcpts.push($(this).val());
});
// Simple email address verification // Simple email address verification
// not fullproof, but email validation is a real nightmare // not fullproof, but email validation is a real nightmare
if (!rcpt.match(/\S+@\S+\.\S+/)){ var validEmail = true;
$.notify(locale.ERROR_MAIL_INVALID, 'error'); $('.email-list').find('input').each(function(index, input){
return; if (!$(input).val().match(/\S+@\S+\.\S+/) && $(input).val() !== ''){
$(input).parent().addClass('has-error');
//$(input).parent().notify(locale.ERROR_MAIL_INVALID, 'error');
validEmail = false;
// Break the each loop
return false;
}
else{
$(input).parent().removeClass('has-error');
}
});
if (!validEmail){
return false;
} }
$.ajax({ $.ajax({
data: { data: {
req: JSON.stringify({ req: JSON.stringify({
action: 'invite_email', action: 'invite_email',
param: { param: {
rcpt: rcpt, rcpts: rcpts,
message: message, message: message,
room: roomName room: roomName
} }

@ -85,7 +85,7 @@
<label class="col-sm-4 control-label" for="emailNotifications"> <label class="col-sm-4 control-label" for="emailNotifications">
<%=l 'NOTIFICATION_ON_JOIN' %> <%=l 'NOTIFICATION_ON_JOIN' %>
</label> </label>
<div class="col-sm-8 email-list"> <div class="col-sm-8 email-list" id="email-list-notification">
<div class="email-entry input-group col-sm-8"> <div class="email-entry input-group col-sm-8">
<input class="form-control" autocomplete="off" name="emails[]" type="text" placeholder="<%=l 'EMAIL_PLACEHOLDER' %>" /> <input class="form-control" autocomplete="off" name="emails[]" type="text" placeholder="<%=l 'EMAIL_PLACEHOLDER' %>" />
<span class="input-group-btn"> <span class="input-group-btn">

@ -10,13 +10,21 @@
</h4> </h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form id ="inviteEmail" class="form-horizontal" role="form"> <form id="inviteEmail" class="form-horizontal" role="form">
<div class="form-group"> <div class="form-group">
<label for="recipient" class="col-sm-4 control-label"> <label for="recipient" class="col-sm-4 control-label">
<%=l 'RECIPIENT' %> <%=l 'RECIPIENT' %>
</label> </label>
<div class="col-sm-8"> <div class="col-sm-8 email-list" id="email-list-invite">
<input type="email" id="recipient" class="form-control" placeholder="<%=l 'EMAIL_PLACEHOLDER' %>"/> <div class="email-entry input-group col-sm-8">
<input class="form-control" autocomplete="off" name="invitation-recipients[]" type="text" placeholder="<%=l 'EMAIL_PLACEHOLDER' %>" />
<span class="input-group-btn">
<button class="btn btn-primary btn-add-email" type="button">
<span class="glyphicon glyphicon-plus">
</span>
</button>
</span>
</div>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">

@ -1300,42 +1300,55 @@ any '/api' => sub {
} }
# Ok, now, we don't have to bother with authorization anymore # Ok, now, we don't have to bother with authorization anymore
if ($req->{action} eq 'invite_email'){ if ($req->{action} eq 'invite_email'){
if (!$req->{param}->{rcpt} || $req->{param}->{rcpt}!~ m/\S+@\S+\.\S+$/){ #if (!$req->{param}->{rcpts}){
return $self->render( # return $self->render(
json => { # json => {
status => 'error', # status => 'error',
msg => 'ERROR_MAIL_INVALID' # msg => $self->l('ERROR_MAIL_INVALID')
} # }
); # );
#}
my $rcpts = $req->{param}->{rcpts};
foreach my $addr (@$rcpts){
if (!$self->valid_email($addr) && $addr ne ''){
return $self->render(
json => {
status => 'error',
msg => $self->l('ERROR_MAIL_INVALID')
}
);
}
} }
my $token = $self->add_invitation( foreach my $addr (@$rcpts){
$req->{param}->{room}, my $token = $self->add_invitation(
$req->{param}->{rcpt} $req->{param}->{room},
); $addr
my $sent = $self->mail(
to => $req->{param}->{rcpt},
subject => $self->l("EMAIL_INVITATION"),
data => $self->render_mail('invite',
room => $req->{param}->{room},
message => $req->{param}->{message},
token => $token,
joinPass => ($room->{join_password}) ? 'yes' : 'no'
)
);
if ($token && $sent){
$self->app->log->info("Email invitation to join room " . $req->{param}->{room} . " sent to " . $req->{param}->{rcpt});
return $self->render(
json => {
status => 'success',
msg => sprintf($self->l('INVITE_SENT_TO_s'), $req->{param}->{rcpt})
}
); );
my $sent = $self->mail(
to => $addr,
subject => $self->l("EMAIL_INVITATION"),
data => $self->render_mail('invite',
room => $req->{param}->{room},
message => $req->{param}->{message},
token => $token,
joinPass => ($room->{join_password}) ? 'yes' : 'no'
)
);
if (!$token || !$sent){
return $self->render(
json => {
status => 'error',
msg => 'ERROR_OCCURRED'
}
);
}
$self->app->log->info("Email invitation to join room " . $req->{param}->{room} . " sent to " . $addr);
} }
return $self->render( return $self->render(
json => { json => {
status => 'error', status => 'success',
msg => 'ERROR_OCCURRED' msg => sprintf($self->l('INVITE_SENT_TO_s'), join("\n", @$rcpts))
} }
); );
} }
# Handle room lock/unlock # Handle room lock/unlock

Loading…
Cancel
Save