add page for calls

This commit is contained in:
osaajani 2021-03-24 00:22:17 +01:00
parent 41c3b3b86e
commit c63f3bebba
9 changed files with 323 additions and 45 deletions

View File

@ -149,12 +149,12 @@ namespace adapters;
public static function meta_support_inbound_call_callback(): bool
{
return false;
return true;
}
public static function meta_support_end_call_callback(): bool
{
return false;
return true;
}
public function send(string $destination, string $text, bool $flash = false, bool $mms = false, array $medias = []) : array

View File

@ -0,0 +1,93 @@
<?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;
/**
* Page des calls.
*/
class Call extends \descartes\Controller
{
private $internal_call;
/**
* 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_call = new \controllers\internals\Call($bdd);
\controllers\internals\Tool::verifyconnect();
}
/**
* Page for showing calls list
*/
public function list()
{
$this->render('call/list');
}
/**
* Return calls list as json.
*/
public function list_json()
{
$entities = $this->internal_call->list_for_user($_SESSION['user']['id']);
foreach ($entities as &$entity)
{
switch ($entity['direction'])
{
case \models\Call::DIRECTION_INBOUND :
$entity['origin_formatted'] = \controllers\internals\Tool::phone_link($entity['origin']);
break;
case \models\Call::DIRECTION_OUTBOUND :
$entity['destination_formatted'] = \controllers\internals\Tool::phone_link($entity['destination']);
break;
}
}
header('Content-Type: application/json');
echo json_encode(['data' => $entities]);
}
/**
* Delete a list of calls
*
* @param array int $_GET['ids'] : Ids of calls to delete
* @param string $csrf : csrf token
*
* @return boolean;
*/
public function delete(string $csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Call', 'list'));
}
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
$this->internal_call->delete_for_user($_SESSION['user']['id'], $id);
}
return $this->redirect(\descartes\Router::url('Call', 'list'));
}
}

View File

@ -33,43 +33,7 @@ class Phone extends \descartes\Controller
*/
public function list()
{
$id_user = $_SESSION['user']['id'];
$api_key = $_SESSION['user']['api_key'];
$phones = $this->internal_phone->list_for_user($id_user);
$adapters = [];
$adapters = $this->internal_adapter->list_adapters();
foreach ($adapters as $key => $adapter)
{
unset($adapters[$key]);
$adapters[$adapter['meta_classname']] = $adapter;
}
foreach ($phones as &$phone)
{
$adapter = $adapters[$phone['adapter']] ?? false;
if (!$adapter)
{
$phone['adapter'] = 'Inconnu';
continue;
}
$phone['adapter'] = $adapter['meta_name'];
if ($adapter['meta_support_reception'])
{
$phone['callback_reception'] = \descartes\Router::url('Callback', 'reception', ['adapter_uid' => $adapter['meta_uid'], 'id_phone' => $phone['id']], ['api_key' => $api_key]);
}
if ($adapter['meta_support_status_change'])
{
$phone['callback_status'] = \descartes\Router::url('Callback', 'update_sended_status', ['adapter_uid' => $adapter['meta_uid']], ['api_key' => $api_key]);
}
}
$this->render('phone/list', ['phones' => $phones]);
$this->render('phone/list');
}
/**
@ -111,6 +75,16 @@ class Phone extends \descartes\Controller
{
$phone['callback_status'] = \descartes\Router::url('Callback', 'update_sended_status', ['adapter_uid' => $adapter['meta_uid']], ['api_key' => $api_key]);
}
if ($adapter['meta_support_inbound_call_callback'])
{
$phone['callback_inbound_call'] = \descartes\Router::url('Callback', 'inbound_call', ['id_phone' => $phone['id']], ['api_key' => $api_key]);
}
if ($adapter['meta_support_end_call_callback'])
{
$phone['callback_end_call'] = \descartes\Router::url('Callback', 'end_call', ['id_phone' => $phone['id']], ['api_key' => $api_key]);
}
}
header('Content-Type: application/json');

View File

@ -18,6 +18,48 @@ namespace models;
{
const DIRECTION_INBOUND = 'inbound';
const DIRECTION_OUTBOUND = 'outbound';
/**
* Return a list of call for a user.
* Add a column contact_name and phone_name when available.
*
* @param int $id_user : user id
* @param ?int $limit : Number of entry to return or null
* @param ?int $offset : Number of entry to ignore or null
*
* @return array
*/
public function list_for_user(int $id_user, $limit, $offset)
{
$query = '
SELECT `call`.*, contact.name as contact_name, phone.name as phone_name
FROM `call`
LEFT JOIN contact
ON contact.number = `call`.destination
OR contact.number = `call`.origin
LEFT JOIN phone
ON phone.id = `call`.id_phone
WHERE `call`.id_user = :id_user
';
if (null !== $limit)
{
$limit = (int) $limit;
$query .= ' LIMIT ' . $limit;
if (null !== $offset)
{
$offset = (int) $offset;
$query .= ' OFFSET ' . $offset;
}
}
$params = [
'id_user' => $id_user,
];
return $this->_run_query($query, $params);
}
/**
* Get a call for a user by his phone and uid

View File

@ -58,10 +58,7 @@
],
'Event' => [
'list' => [
'/event/',
'/event/p/{page}/',
],
'list' => '/event/',
'list_json' => '/event/json/',
'delete' => '/event/delete/{csrf}/',
],
@ -155,6 +152,12 @@
'delete' => '/phone/delete/{csrf}/',
],
'Call' => [
'list' => '/call/',
'list_json' => '/call/json/',
'delete' => '/call/delete/{csrf}/',
],
'Webhook' => [
'list' => '/webhook/',
'list_json' => '/webhook/json/',
@ -169,6 +172,7 @@
'update_sended_status' => '/callback/status/{adapter_uid}/',
'reception' => '/callback/reception/{adapter_uid}/{id_phone}/',
'inbound_call' => '/callback/inbound_call/{id_phone}/',
'end_call' => '/callback/end_call/{id_phone}/',
],
'Api' => [

145
templates/call/list.php Normal file
View File

@ -0,0 +1,145 @@
<?php
//Template dashboard
$this->render('incs/head', ['title' => 'Appels - Show All'])
?>
<div id="wrapper">
<?php
$this->render('incs/nav', ['page' => 'calls'])
?>
<div id="page-wrapper">
<div class="container-fluid">
<!-- Page Heading -->
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">
Dashboard <small>Appels</small>
</h1>
<ol class="breadcrumb">
<li>
<i class="fa fa-dashboard"></i> <a href="<?php echo \descartes\Router::url('Dashboard', 'show'); ?>">Dashboard</a>
</li>
<li class="active">
<i class="fa fa-clock-o"></i> Appels
</li>
</ol>
</div>
</div>
<!-- /.row -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i> Liste des appels</h3>
</div>
<div class="panel-body">
<form method="GET">
<div class="table-events">
<table class="table table-bordered table-hover table-striped datatable" id="table-calls">
<thead>
<tr>
<th>Origine</th>
<th>Destinataire</th>
<th>Début de l'appel</th>
<th>Fin de l'appel</th>
<th>Direction</th>
<th class="checkcolumn">&#10003;</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div>
<div class="text-right col-xs-12 no-padding">
<strong>Action pour la séléction :</strong>
<button class="btn btn-default btn-confirm" type="submit" formaction="<?php echo \descartes\Router::url('Call', 'delete', ['csrf' => $_SESSION['csrf']]); ?>"><span class="fa fa-trash-o"></span> Supprimer</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
jQuery(document).ready(function ()
{
jQuery('.datatable').DataTable({
"pageLength": 25,
"bLengthChange": false,
"language": {
"url": HTTP_PWD + "/assets/js/datatables/french.json",
},
"columnDefs": [{
'targets': 'checkcolumn',
'orderable': false,
}],
"ajax": {
'url': '<?php echo \descartes\Router::url('Call', 'list_json'); ?>',
'dataSrc': 'data',
},
"columns" : [
{
data: 'origin',
render: function (data, type, row, meta) {
if (row.direction === 'outbound') {
return row.phone_name;
}
if (row.contact_name) {
return row.origin_formatted + ' (' + jQuery.fn.dataTable.render.text().display(row.contact_name) + ')';
}
return row.origin_formatted;
},
},
{
data: 'destination',
render: function (data, type, row, meta) {
if (row.direction === 'inbound') {
return row.phone_name;
}
if (row.contact_name) {
return row.destination_formatted + ' (' + jQuery.fn.dataTable.render.text().display(row.contact_name) + ')';
}
return row.destination_formatted;
},
},
{data: 'start', render: jQuery.fn.dataTable.render.text()},
{data: 'end', render: jQuery.fn.dataTable.render.text()},
{
data: 'direction',
render: function (data, type, row, meta) {
switch (data) {
case 'inbound':
return 'Appel entrant';
break;
case 'outbound':
return 'Appel sortant';
default:
return 'Inconnu';
}
},
},
{
data: 'id',
render: function (data, type, row, meta) {
return '<input name="ids[]" type="checkbox" value="' + data + '">';
},
},
],
"deferRender": true
});
});
</script>
<?php
$this->render('incs/footer');

View File

@ -1,7 +1,7 @@
<?php
//Template dashboard
$this->render('incs/head', ['title' => 'ConditionalGroupes Conditionnels - Show All'])
$this->render('incs/head', ['title' => 'Groupes Conditionnels - Show All'])
?>
<div id="wrapper">
<?php

View File

@ -71,10 +71,13 @@
</li>
<li>
<a href="javascript:;" data-toggle="collapse" data-target="#logs"><i class="fa fa-fw fa-file-text"></i> Logs <i class="fa fa-fw fa-caret-down"></i></a>
<ul id="logs" class="collapse <?php echo in_array($page, array('events', 'smsstop')) ? 'in' : ''; ?>">
<ul id="logs" class="collapse <?php echo in_array($page, array('events', 'smsstop', 'calls')) ? 'in' : ''; ?>">
<li <?php echo $page == 'smsstop' ? 'class="active"' : ''; ?>>
<a href="<?php echo \descartes\Router::url('SmsStop', 'list'); ?>"><i class="fa fa-fw fa-ban"></i> SMS STOP</a>
</li>
<li <?php echo $page == 'calls' ? 'class="active"' : ''; ?>>
<a href="<?php echo \descartes\Router::url('Call', 'list'); ?>"><i class="fa fa-fw fa-file-audio-o"></i> Appels</a>
</li>
<li <?php echo $page == 'events' ? 'class="active"' : ''; ?>>
<a href="<?php echo \descartes\Router::url('Event', 'list'); ?>"><i class="fa fa-fw fa-clock-o"></i> Évènements</a>
</li>

View File

@ -108,7 +108,24 @@ jQuery(document).ready(function ()
} else {
html += '<div>Non disponible.</div>';
}
html += '<br/>';
html += '<div class="bold">Notification d\'appel entrant : </div>';
if (row.callback_inbound_call) {
html += '<div><code>' + row.callback_inbound_call + '</code></div>';
} else {
html += '<div>Non disponible.</div>';
}
html += '<br/>';
html += '<div class="bold">Notification de fin d\'appel : </div>';
console.log(row);
if (row.callback_end_call) {
html += '<div><code>' + row.callback_end_call + '</code></div>';
} else {
html += '<div>Non disponible.</div>';
}
return html;
},