add contact data enrichment && add templating on messages

This commit is contained in:
osaajani 2019-11-20 02:45:00 +01:00
parent 50c7e4298c
commit 9f98fb5ae3
16 changed files with 833 additions and 88 deletions

View File

@ -231,9 +231,6 @@ footer
.remove-scheduleds-number
{
display: inline-block;
position: absolute;
top: 2px;
right: 2px;
color: #bbbbbb;
font-size: 15px;
z-index: 999;
@ -245,6 +242,25 @@ footer
cursor: pointer;
}
.scheduled-preview-container
{
margin-top: 10px;
margin-bottom: 20px;
text-align: right;
}
.scheduled-preview-container label,
.scheduled-preview-container select
{
display: inline-block;
width: auto;
}
.scheduled-preview-text-modal .modal-title
{
font-weight: bold;
}
/* AUDIO RECEPTION MESSAGE */
#reception-sound
{
@ -260,17 +276,22 @@ footer
/* CONTACT */
#contact-datas-container input
.contact-datas-container input
{
display: inline-block;
}
#contact-datas-container .contact-data-name
.contact-datas-container .contact-data-name
{
width: 25%;
}
#contact-datas-container .contact-data-value
.contact-datas-container .contact-data-value
{
width: 50%;
}
.contact-datas-container .contact-datas-remove
{
color: #c9302c;
}

View File

@ -2,6 +2,7 @@
"require": {
"ingenerator/tokenista": "^1.1",
"ajani/flash-message": "^2.0",
"giggsey/libphonenumber-for-php": "^8.10"
"giggsey/libphonenumber-for-php": "^8.10",
"twig/twig": "^3.0"
}
}

183
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "697ec089fcf3d7f209de359fc23cd496",
"content-hash": "645ff432da0c81453a7f3f1df765195d",
"packages": [
{
"name": "ajani/flash-message",
@ -211,6 +211,187 @@
"token"
],
"time": "2018-02-26T14:16:22+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "550ebaac289296ce228a706d0867afc34687e3f4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4",
"reference": "550ebaac289296ce228a706d0867afc34687e3f4",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.12-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"time": "2019-08-06T08:03:45+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17",
"reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.12-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2019-08-06T08:03:45+00:00"
},
{
"name": "twig/twig",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26",
"reference": "9b58bb8ac7a41d72fbb5a7dc643e07923e5ccc26",
"shasum": ""
},
"require": {
"php": "^7.2.9",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3"
},
"require-dev": {
"psr/container": "^1.0",
"symfony/debug": "^3.4|^4.2|^5.0",
"symfony/phpunit-bridge": "^4.4@dev|^5.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"Twig\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Twig Team",
"homepage": "https://twig.symfony.com/contributors",
"role": "Contributors"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "https://twig.symfony.com",
"keywords": [
"templating"
],
"time": "2019-11-15T20:38:32+00:00"
}
],
"packages-dev": [],

View File

@ -47,6 +47,17 @@ namespace controllers\internals;
{
return $this->get_model()->get_by_name_and_user($id_user, $name);
}
/**
* Return all contacts of a user.
* @param int $id_user : user id
* @return array
*/
public function gets_for_user (int $id_user)
{
return $this->get_model()->gets_for_user($id_user);
}
/**
@ -54,14 +65,16 @@ namespace controllers\internals;
* @param int $id_user : User id
* @param string $number : Contact number
* @param string $name : Contact name
* @param string $datas : Contact datas
* @return mixed bool|int : False if cannot create contact, id of the new contact else
*/
public function create($id_user, $number, $name)
public function create($id_user, $number, $name, $datas)
{
$contact = [
'id_user' => $id_user,
'number' => $number,
'name' => $name,
'datas' => $datas,
];
$result = $this->get_model()->insert($contact);
@ -83,15 +96,17 @@ namespace controllers\internals;
* @param int $id : Contact id
* @param string $number : Contact number
* @param string $name : Contact name
* @param ?string $datas : Contact datas
* @return int : number of modified rows
*/
public function update_for_user(int $id_user, int $id, string $number, string $name)
public function update_for_user(int $id_user, int $id, string $number, string $name, ?string $datas)
{
$datas = [
$contact = [
'number' => $number,
'name' => $name,
'datas' => $datas,
];
return $this->get_model()->update_for_user($id_user, $id, $datas);
return $this->get_model()->update_for_user($id_user, $id, $contact);
}
}

View File

@ -0,0 +1,87 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\internals;
/**
* Templating questions relative class
* Not a standard controller as it's not linked to a model in any way
*/
class Templating
{
/**
* Twig environment
*/
private $sandbox;
public function __construct ()
{
$tags = [
'if',
'for',
'apply',
];
$filters = [
'abs', 'capitalize', 'country_name', 'currency_name',
'currency_symbol', 'date', 'date_modify', 'default',
'first', 'format', 'format_currency', 'format_datetime',
'format_number', 'join', 'keys', 'language_name',
'last', 'length', 'locale_name', 'lower', 'number_format',
'replace', 'reverse', 'round', 'slice',
'sort', 'spaceless', 'split', 'timezone_name',
'title', 'trim', 'upper', 'url_encode',
];
$methods = [];
$properties = [];
$functions = [
'date', 'max', 'min', 'random',
'range',
];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
$this->sandbox = new \Twig\Extension\SandboxExtension($policy, true);
}
/**
* Render a string as a twig template
* @param string $template : Template string
* @param array $datas : Datas to pass to the template
* @return array : keys, success, error, result
*/
public function render (string $template, array $datas = [])
{
try
{
$loader = new \Twig\Loader\ArrayLoader([
'template' => $template,
]);
$twig = new \Twig\Environment($loader);
$result = $twig->render('template', $datas);
return [
'success' => true,
'result' => $result,
];
}
catch (\Exception $e)
{
return [
'success' => false,
'result' => $e->getMessage(),
];
}
}
}

View File

@ -99,6 +99,14 @@ namespace controllers\publics;
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
foreach ($contacts as &$contact)
{
if ($contact['datas'])
{
$contact['datas'] = json_decode($contact['datas']);
}
}
$this->render('contact/edit', [
'contacts' => $contacts,
]);
@ -123,6 +131,7 @@ namespace controllers\publics;
$name = $_POST['name'] ?? false;
$number = $_POST['number'] ?? false;
$id_user = $_SESSION['user']['id'];
$datas = empty($_POST['datas']) ? null : $_POST['datas'];
if (!$name || !$number)
{
@ -139,7 +148,25 @@ namespace controllers\publics;
return $this->redirect(\descartes\Router::url('Contact', 'add'));
}
if (!$this->internal_contact->create($id_user, $number, $name))
$clean_datas = null;
if ($datas)
{
$clean_datas = [];
foreach ($datas as $key => $value)
{
if ($value === "")
{
continue;
}
$key = mb_ereg_replace('[\W]', '', $key);
$clean_datas[$key] = (string) $value;
}
$clean_datas = json_encode($clean_datas);
}
if (!$this->internal_contact->create($id_user, $number, $name, $clean_datas))
{
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce contact.');
@ -168,15 +195,54 @@ namespace controllers\publics;
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$nb_contacts_update = 0;
foreach ($_POST['contacts'] as $contact)
if (!array($_POST['contacts']))
{
$nb_contacts_update += (int) $this->internal_contact->update_for_user($_SESSION['user']['id'], $contact['id'], $contact['number'], $contact['name']);
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}
$nb_contacts_update = 0;
foreach ($_POST['contacts'] as $id_contact => $contact)
{
$name = $contact['name'] ?? false;
$number = $contact['number'] ?? false;
$id_user = $_SESSION['user']['id'];
$datas = empty($contact['datas']) ? null : $contact['datas'];
if (!$name || !$number)
{
continue;
}
$number = \controllers\internals\Tool::parse_phone($number);
if (!$number)
{
continue;
}
$clean_datas = null;
if ($datas)
{
$clean_datas = [];
foreach ($datas as $key => $value)
{
if ($value === "")
{
continue;
}
$key = mb_ereg_replace('[\W]', '', $key);
$clean_datas[$key] = (string) $value;
}
$clean_datas = json_encode($clean_datas);
}
$nb_contacts_update += (int) $this->internal_contact->update_for_user($id_user, $id_contact, $number, $name, $clean_datas);
}
if ($nb_contacts_update !== \count($_POST['contacts']))
{
\FlashMessage\FlashMessage::push('danger', 'Certais contacts n\'ont pas pu êtres mis à jour.');
\FlashMessage\FlashMessage::push('danger', 'Certains contacts n\'ont pas pu êtres mis à jour.');
return $this->redirect(\descartes\Router::url('Contact', 'list'));
}

View File

@ -18,6 +18,7 @@ namespace controllers\publics;
{
private $internal_scheduled;
private $internal_phone;
private $internal_contact;
/**
* Cette fonction est appelée avant toute les autres :
@ -30,6 +31,7 @@ namespace controllers\publics;
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
$this->internal_phone = new \controllers\internals\Phone($bdd);
$this->internal_contact = new \controllers\internals\Contact($bdd);
\controllers\internals\Tool::verifyconnect();
}
@ -87,10 +89,12 @@ namespace controllers\publics;
$less_one_minute = new \DateInterval('PT1M');
$now->sub($less_one_minute);
$contacts = $this->internal_contact->gets_for_user($_SESSION['user']['id']);
$phones = $this->internal_phone->gets_for_user($_SESSION['user']['id']);
$this->render('scheduled/add', [
'now' => $now->format('Y-m-d H:i'),
'contacts' => $contacts,
'phones' => $phones,
]);
}
@ -110,6 +114,7 @@ namespace controllers\publics;
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
$all_contacts = $this->internal_contact->gets_for_user($_SESSION['user']['id']);
$phones = $this->internal_phone->gets_for_user($_SESSION['user']['id']);
$scheduleds = $this->internal_scheduled->gets_in_for_user($_SESSION['user']['id'], $ids);
@ -147,6 +152,7 @@ namespace controllers\publics;
$this->render('scheduled/edit', [
'scheduleds' => $scheduleds,
'phones' => $phones,
'contacts' => $all_contacts,
]);
}
@ -331,4 +337,5 @@ namespace controllers\publics;
\FlashMessage\FlashMessage::push('success', 'Tous les SMS ont été mis à jour.');
return $this->redirect(\descartes\Router::url('Scheduled', 'list'));
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of RaspiSMS.
*
* (c) Pierre-Lin Bonnemaison <plebwebsas@gmail.com>
*
* This source file is subject to the GPL-3.0 license that is bundled
* with this source code in the file LICENSE.
*/
namespace controllers\publics;
class Templating extends \descartes\Controller
{
private $internal_contact;
private $internal_templating;
/**
* Cette fonction est appelée avant toute les autres :
* Elle vérifie que l'utilisateur est bien connecté.
*
* @return void;
*/
public function __construct()
{
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_templating = new \controllers\internals\Templating();
\controllers\internals\Tool::verifyconnect();
}
/**
* Try to render a template as a message for preview
* @param string $_POST['template'] : Template string
* @param int $_POST['id_contact'] : Id of the contact to render the template for
* @return json string
*/
public function render_preview ()
{
$return = [
'success' => false,
'result' => 'Une erreur inconnue est survenue.',
];
$template = $_POST['template'] ?? false;
$id_contact = $_POST['id_contact'] ?? false;
if (!$template || !$id_contact)
{
$return['result'] = 'Veuillez remplir un message.';
echo json_encode($return);
return false;
}
$contact = $this->internal_contact->get_for_user($_SESSION['user']['id'], $id_contact);
if (!$contact)
{
$return['result'] = 'Ce contact n\'existe pas.';
echo json_encode($return);
return false;
}
if ($contact['datas'])
{
$contact['datas'] = json_decode($contact['datas'], true);
}
$datas = [
'contact' => $contact,
];
echo json_encode($this->internal_templating->render($template, $datas));
return true;
}
}

View File

@ -120,6 +120,10 @@
'delete' => '/smsstop/delete/{csrf}/',
],
'Templating' => [
'render_preview' => '/template/preview/',
],
'User' => [
'list' => [
'/user/',

View File

@ -53,13 +53,13 @@
</div>
<div class="form-group">
<label>Données du contact</label>
<p class="italic small" id="description-datas">
<p class="italic small help" id="description-datas">
Les données d'un contact vous permettent de l'enrichir afin de pouvoir accéder à ces données au sein d'un message via <a href="#">l'utilisation de templates.</a><br/>
Laissez vide si vous ne souhaitez pas renseigner d'informations supplémentaires pour le contact.
Laissez vide si vous ne souhaitez pas renseigner d'informations supplémentaires pour le contact. Utilisez uniquement des lettres, des chiffres et des underscore pour les noms de données, ni espace ni caractères spéciaux.
</p>
<div id="contact-datas-container">
<div class="contact-datas-container">
<div class="form-group">
<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée">
<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*">
:
<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée">
</div>
@ -88,40 +88,70 @@
});
jQuery('#contact-datas-container').on('input', '.contact-data-value', function (e)
jQuery('.contact-datas-container').on('input', '.contact-data-value, .contact-data-name', function (e)
{
var focus_group = jQuery(this).parent('.form-group');
var focus_input = this;
var input_name = focus_group.find('.contact-data-name');
var input_value = focus_group.find('.contact-data-value');
jQuery('#contact-datas-container .form-group').each(function (e)
jQuery('.contact-datas-container .form-group').each(function (e)
{
var current_input_name = jQuery(this).find('.contact-data-name');
var current_input_value = jQuery(this).find('.contact-data-value');
if (current_input_value.is(focus_input))
if (current_input_value.is(focus_input) || current_input_name.is(focus_input))
{
return true;
}
if (jQuery(current_input_name).val() !== '' || jQuery(current_input_value).val() !== '')
if (jQuery(current_input_name).val() === '' && jQuery(current_input_value).val() === '')
{
return true;
jQuery(this).remove();
}
jQuery(this).remove();
return true;
});
if (jQuery(focus_input).val() === '')
if (input_name.val() === '' || input_value.val() === '')
{
return true;
}
var template = '' +
'<div class="form-group">' +
'<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée">' +
'<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*">' +
' : ' +
'<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée">' +
' <a href="#" class="contact-datas-remove"><span class="fa fa-times"></span></a>' +
'</div>';
jQuery('#contact-datas-container').append(template);
jQuery('.contact-datas-container').append(template);
});
jQuery('.contact-datas-container').on('click', '.contact-datas-remove', function (e)
{
e.preventDefault();
if (jQuery('.contact-datas-container .form-group').length > 1)
{
jQuery(this).parent('.form-group').remove();
}
return false;
});
jQuery('form').on('submit', function (e)
{
e.preventDefault();
jQuery('.contact-datas-container .form-group').each(function ()
{
var name = jQuery(this).find('.contact-data-name').val();
name = name.replace(/\W/g, '');
name = 'datas[' + name + ']';
jQuery(this).find('.contact-data-value').attr('name', name);
});
e.currentTarget.submit();
});
});
</script>

View File

@ -53,6 +53,37 @@
<input name="" class="form-control phone-international-input" type="tel" contact-id="<?php $this->s($contact['id']); ?>" value="<?php $this->s($contact['number']); ?>">
</div>
</div>
<div class="form-group">
<label>Données du contact</label>
<p class="italic small help" id="description-datas">
Les données d'un contact vous permettent de l'enrichir afin de pouvoir accéder à ces données au sein d'un message via <a href="#">l'utilisation de templates.</a><br/>
Laissez vide si vous ne souhaitez pas renseigner d'informations supplémentaires pour le contact. Utilisez uniquement des lettres, des chiffres et des underscore pour les noms de données, ni espace ni caractères spéciaux.
</p>
<div class="contact-datas-container" data-id-contact="<?php $this->s($contact['id']); ?>">
<?php if (!$contact['datas']) { ?>
<div class="form-group">
<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*">
:
<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée">
</div>
<?php } else {?>
<?php foreach ($contact['datas'] as $name => $data) { ?>
<div class="form-group">
<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*" value="<?php $this->s($name); ?>">
:
<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée" value="<?php $this->s($data); ?>">
<a href="#" class="contact-datas-remove"><span class="fa fa-times"></span></a>
</div>
<?php } ?>
<div class="form-group">
<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*">
:
<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée">
<a href="#" class="contact-datas-remove"><span class="fa fa-times"></span></a>
</div>
<?php } ?>
</div>
</div>
<hr/>
<?php } ?>
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Contact', 'list'); ?>">Annuler</a>
@ -80,6 +111,78 @@
utilsScript: '<?php echo HTTP_PWD_JS; ?>/intlTelInput/utils.js'
});
});
jQuery('.contact-datas-container').on('input', '.contact-data-value, .contact-data-name', function (e)
{
var focus_group = jQuery(this).parent('.form-group');
var focus_input = this;
var input_name = focus_group.find('.contact-data-name');
var input_value = focus_group.find('.contact-data-value');
var datas_container = jQuery(this).parents('.contact-datas-container');
datas_container.find('.form-group').each(function (e)
{
console.log(this);
var current_input_name = jQuery(this).find('.contact-data-name');
var current_input_value = jQuery(this).find('.contact-data-value');
if (current_input_value.is(focus_input) || current_input_name.is(focus_input))
{
return true;
}
if (jQuery(current_input_name).val() === '' && jQuery(current_input_value).val() === '')
{
jQuery(this).remove();
}
return true;
});
if (input_name.val() === '' || input_value.val() === '')
{
return true;
}
var template = '' +
'<div class="form-group">' +
'<input name="" class="form-control contact-data-name" type="text" placeholder="Nom de la donnée" pattern="[a-zA-Z0-9_]*">' +
' : ' +
'<input name="" class="form-control contact-data-value" type="text" placeholder="Valeur de la donnée">' +
' <a href="#" class="contact-datas-remove"><span class="fa fa-times"></span></a>' +
'</div>';
datas_container.append(template);
});
jQuery('.contact-datas-container').on('click', '.contact-datas-remove', function (e)
{
e.preventDefault();
if (jQuery('.contact-datas-container .form-group').length > 1)
{
jQuery(this).parent('.form-group').remove();
}
return false;
});
jQuery('form').on('submit', function (e)
{
e.preventDefault();
jQuery('.contact-datas-container .form-group').each(function ()
{
var contact_id = jQuery(this).parents('.contact-datas-container').attr('data-id-contact');
var name = jQuery(this).find('.contact-data-name').val();
name = name.replace(/\W/g, '');
name = 'contacts[' + contact_id + '][datas][' + name + ']';
jQuery(this).find('.contact-data-value').attr('name', name);
});
e.currentTarget.submit();
});
});
</script>
<?php

View File

@ -18,6 +18,10 @@
<?php } ?>
</script>
<?php } ?>
<?php if (!$_SESSION['user']['settings']['display_help']) { ?>
<style>.help {display: none;}</style>
<?php } ?>
</body>
</html>

View File

@ -40,7 +40,7 @@
<form action="<?php echo \descartes\Router::url('Phone', 'create', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
<div class="form-group">
<label>Numéro de téléphone</label>
<p class="italic small">
<p class="italic small help">
Le numéro de téléphone qui enverra et recevra les messages.
</p>
<div class="form-group">
@ -49,7 +49,7 @@
</div>
<div class="form-group">
<label>Adaptateur logiciel du téléphone : </label>
<p class="italic small" id="description-adapter">
<p class="italic small help" id="description-adapter">
L'adaptateur logiciel utilisé par RaspiSMS pour communiquer avec le téléphone. Pour plus d'information, consultez <a href="https://raspisms.raspberry-pi.fr/documentation" target="_blank">la documentation de RaspiSMS</a> concernant les adaptateurs logiciels.
</p>
<select name="adapter" class="form-control" id="adapter-select">
@ -67,7 +67,7 @@
</div>
<div class="form-group" id="adapter-datas-container">
<label>Configuration de l'adaptateur</label>
<p class="italic small" id="description-adapter-datas">
<p class="italic small help" id="description-adapter-datas">
Les données à fournir à l'adaptateur pour lui permettre de faire la liaison avec le téléphone. Par exemple des identifiants d'API.<br/>
</p>
<textarea id="adapter-datas" name="adapter_datas" class="form-control has-error"></textarea>

View File

@ -39,59 +39,93 @@
<div class="panel-body">
<form action="<?php echo \descartes\Router::url('Scheduled', 'create', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
<div class="form-group">
<label>Texte du SMS</label>
<textarea name="text" class="form-control" required></textarea>
</div>
<div class="form-group">
<label>Date d'envoi du SMS</label>
<input name="at" class="form-control form-datetime" type="text" value="<?php $this->s($now); ?>" readonly>
</div>
<div class="form-group">
<label>Numéros cibles</label>
<div class="form-group scheduleds-number-groupe-container">
<div class="form-group scheduleds-number-groupe">
<input name="" class="form-control phone-international-input" type="tel" >
<span class="remove-scheduleds-number fa fa-times"></span>
</div>
<div class="add-number-button fa fa-plus-circle"></div>
</div>
</div>
<div class="form-group">
<label>Contacts cibles</label>
<input class="add-contacts form-control" name="contacts[]"/>
</div>
<div class="form-group">
<label>Groupes cibles</label>
<input class="add-groupes form-control" name="groups[]"/>
</div>
<?php if ($_SESSION['user']['settings']['sms_flash']) { ?>
<div class="form-group">
<label>Envoyer comme un SMS Flash : </label>
<div class="form-group">
<input name="flash" type="radio" value="1" required /> Oui
<input name="flash" type="radio" value="0" required checked/> Non
</div>
</div>
<?php } ?>
<div class="form-group">
<label>Téléphone à employer : </label>
<select name="origin" class="form-control">
<option value="">N'importe lequel</option>
<?php foreach ($phones as $phone) { ?>
<option value="<?php $this->s($phone['number']); ?>"><?php $this->s($phone['number']); ?></option>
<?php } ?>
</select>
<label>Texte du SMS</label>
<?php if ($_SESSION['user']['settings']['templating']) { ?>
<p class="italic small help description-scheduled-text">
Vous pouvez utilisez des fonctionnalités de templating pour indiquer des valeures génériques qui seront remplacées par les données du contact au moment de l'envoie. Pour plus d'information, consultez la documentation sur <a href="#">l'utilisation des templates.</a><br/>
Vous pouvez obtenir une prévisualisation du résultat pour un contact en cliquant sur le boutton <b>"Prévisualiser"</b>.
</p>
<?php } ?>
<textarea name="text" class="form-control" required></textarea>
<?php if ($_SESSION['user']['settings']['templating']) { ?>
<div class="scheduled-preview-container">
<label>Prévisualiser pour : </label>
<select name="" class="form-control">
<?php foreach ($contacts as $contact) { ?>
<option value="<?php $this->s($contact['id']); ?>"><?php $this->s($contact['name']); ?></option>
<?php } ?>
</select>
<a class="btn btn-info preview-button" href="#">Prévisualiser</a>
</div>
<?php } ?>
</div>
<div class="form-group">
<label>Date d'envoi du SMS</label>
<input name="at" class="form-control form-datetime" type="text" value="<?php $this->s($now); ?>" readonly>
</div>
<div class="form-group">
<label>Numéros cibles</label>
<div class="form-group scheduleds-number-groupe-container">
<div class="form-group scheduleds-number-groupe">
<input name="" class="form-control phone-international-input" type="tel" >
<span class="remove-scheduleds-number fa fa-times"></span>
</div>
<div class="add-number-button fa fa-plus-circle"></div>
</div>
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Scheduled', 'list'); ?>">Annuler</a>
<input type="submit" class="btn btn-success" value="Enregistrer le SMS" />
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Contacts cibles</label>
<input class="add-contacts form-control" name="contacts[]"/>
</div>
<div class="form-group">
<label>Groupes cibles</label>
<input class="add-groupes form-control" name="groups[]"/>
</div>
<?php if ($_SESSION['user']['settings']['sms_flash']) { ?>
<div class="form-group">
<label>Envoyer comme un SMS Flash : </label>
<div class="form-group">
<input name="flash" type="radio" value="1" required /> Oui
<input name="flash" type="radio" value="0" required checked/> Non
</div>
</div>
<?php } ?>
<div class="form-group">
<label>Numéro à employer : </label>
<select name="origin" class="form-control">
<option value="">N'importe lequel</option>
<?php foreach ($phones as $phone) { ?>
<option value="<?php $this->s($phone['number']); ?>"><?php $this->s($phone['number']); ?></option>
<?php } ?>
</select>
</div>
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Scheduled', 'list'); ?>">Annuler</a>
<input type="submit" class="btn btn-success" value="Enregistrer le SMS" />
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" id="scheduled-preview-text-modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Prévisualisation du message</h4>
</div>
<div class="modal-body">
<pre></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script>
jQuery(document).ready(function()
{
@ -136,7 +170,7 @@
var newScheduledsNumberGroupe = '' +
'<div class="form-group scheduleds-number-groupe">' +
'<input name="" class="form-control phone-international-input" type="tel" id="' + random_id + '">' +
'<span class="remove-scheduleds-number fa fa-times"></span>' +
' <span class="remove-scheduleds-number fa fa-times"></span>' +
'</div>';
jQuery(this).before(newScheduledsNumberGroupe);
@ -169,6 +203,29 @@
'number_input': number_input,
'iti_number_input': iti_number_input,
});
jQuery('body').on('click', '.preview-button', function (e)
{
e.preventDefault();
var id_contact = jQuery(this).parents('.scheduled-preview-container').find('select').val();
var template = jQuery(this).parents('.form-group').find('textarea').val();
var datas = {
'id_contact' : id_contact,
'template' : template,
};
jQuery.ajax({
type: "POST",
url: HTTP_PWD + '/template/preview',
data: datas,
success: function (datas) {
jQuery('#scheduled-preview-text-modal').find('.modal-body pre').text(datas.result);
jQuery('#scheduled-preview-text-modal').modal({'keyboard': true});
},
dataType: 'json'
});
});
});
</script>
<?php

View File

@ -40,8 +40,25 @@
<form action="<?php echo \descartes\Router::url('Scheduled', 'update', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
<?php foreach ($scheduleds as $scheduled) { ?>
<div class="form-group">
<label>Texte du SMS</label>
<label>Texte du SMS</label>
<?php if ($_SESSION['user']['settings']['templating']) { ?>
<p class="italic small help description-scheduled-text">
Vous pouvez utilisez des fonctionnalités de templating pour indiquer des valeures génériques qui seront remplacées par les données du contact au moment de l'envoie. Pour plus d'information, consultez la documentation sur <a href="#">l'utilisation des templates.</a><br/>
Vous pouvez obtenir une prévisualisation du résultat pour un contact en cliquant sur le boutton <b>"Prévisualiser"</b>.
</p>
<?php } ?>
<textarea name="scheduleds[<?php $this->s($scheduled['id']); ?>][text]" class="form-control" required><?php $this->s($scheduled['text'], true); ?></textarea>
<?php if ($_SESSION['user']['settings']['templating']) { ?>
<div class="scheduled-preview-container">
<label>Prévisualiser pour : </label>
<select name="" class="form-control">
<?php foreach ($contacts as $contact) { ?>
<option value="<?php $this->s($contact['id']); ?>"><?php $this->s($contact['name']); ?></option>
<?php } ?>
</select>
<a class="btn btn-info preview-button" href="#">Prévisualiser</a>
</div>
<?php } ?>
</div>
<div class="form-group">
<label>Date d'envoi du SMS</label>
@ -77,7 +94,7 @@
</div>
<?php } ?>
<div class="form-group">
<label>Téléphone à employer : </label>
<label>Numéro à employer : </label>
<select name="scheduleds[<?php $this->s($scheduled['id']); ?>][origin]" class="form-control">
<option <?php echo ($scheduled['origin'] ? '' : 'selected="selected"'); ?> value="">N'importe lequel</option>
<?php foreach ($phones as $phone) { ?>
@ -97,6 +114,22 @@
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" id="scheduled-preview-text-modal">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Prévisualisation du message</h4>
</div>
<div class="modal-body">
<pre></pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<script>
jQuery(document).ready(function()
{
@ -150,7 +183,7 @@
var newScheduledsNumberGroupe = '' +
'<div class="form-group scheduleds-number-groupe">' +
'<input name="" class="form-control phone-international-input" type="tel" scheduled-id="' + scheduledId + '" id="' + random_id + '">' +
'<span class="remove-scheduleds-number fa fa-times"></span>' +
' <span class="remove-scheduleds-number fa fa-times"></span>' +
'</div>';
jQuery(this).before(newScheduledsNumberGroupe);
@ -167,7 +200,28 @@
});
jQuery('body').on('click', '.preview-button', function (e)
{
e.preventDefault();
var id_contact = jQuery(this).parents('.scheduled-preview-container').find('select').val();
var template = jQuery(this).parents('.form-group').find('textarea').val();
var datas = {
'id_contact' : id_contact,
'template' : template,
};
jQuery.ajax({
type: "POST",
url: HTTP_PWD + '/template/preview',
data: datas,
success: function (datas) {
jQuery('#scheduled-preview-text-modal').find('.modal-body pre').text(datas.result);
jQuery('#scheduled-preview-text-modal').modal({'keyboard': true});
},
dataType: 'json'
});
});
});
</script>
<?php

View File

@ -108,6 +108,25 @@
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title"><i class="fa fa-question-circle fa-fw"></i> Affichage de l'aide</h4>
</div>
<div class="panel-body">
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'display_help', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
<div class="form-group">
<label>Afficher l'aide : </label>
<select name="setting_value" class="form-control">
<option value="0">Non</option>
<option value="1" <?php echo $_SESSION['user']['settings']['display_help'] ? 'selected' : ''; ?>>Oui</option>
</select>
</div>
<div class="text-center">
<button class="btn btn-success">Mettre à jour les données</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6">
<div class="panel panel-default">
@ -164,6 +183,25 @@
</form>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title"><i class="fa fa-code fa-fw"></i> Support du templating</h4>
</div>
<div class="panel-body">
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'templating', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
<div class="form-group">
<label>Templating activé : </label>
<select name="setting_value" class="form-control">
<option value="0">Non</option>
<option value="1" <?php echo $_SESSION['user']['settings']['templating'] ? 'selected' : ''; ?>>Oui</option>
</select>
</div>
<div class="text-center">
<button class="btn btn-success">Mettre à jour les données</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>