start add support for phone status + improve edit of phone for hidden phones

This commit is contained in:
osaajani 2023-02-18 16:39:07 +01:00
parent f9e64aee65
commit 38d350dfc2
19 changed files with 357 additions and 6 deletions

View File

@ -79,6 +79,11 @@ interface AdapterInterface
*/
public static function meta_support_read(): bool;
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool;
/**
* Does the implemented service support reception callback.
*/
@ -152,6 +157,15 @@ interface AdapterInterface
*/
public function test(): bool;
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string;
/**
* Method called on reception of a status update notification for a SMS.
*

View File

@ -111,6 +111,14 @@ namespace adapters;
return false;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -226,6 +234,16 @@ namespace adapters;
return [];
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public static function status_change_callback()
{
return null;

View File

@ -121,6 +121,14 @@ namespace adapters;
return true;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -301,6 +309,16 @@ namespace adapters;
return $response;
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
//Always return true as we cannot test because we would be needing a root account

View File

@ -209,6 +209,14 @@ class KannelAdapter implements AdapterInterface
return false;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -354,6 +362,16 @@ class KannelAdapter implements AdapterInterface
return [];
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -174,6 +174,14 @@ class OctopushShortcodeAdapter implements AdapterInterface
return false;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -325,6 +333,16 @@ class OctopushShortcodeAdapter implements AdapterInterface
return [];
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -173,6 +173,14 @@ class OctopushVirtualNumberAdapter implements AdapterInterface
return false;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -317,6 +325,16 @@ class OctopushVirtualNumberAdapter implements AdapterInterface
return [];
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -162,6 +162,14 @@ namespace adapters;
return true;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -327,6 +335,16 @@ namespace adapters;
}
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -166,6 +166,14 @@ namespace adapters;
return true;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -317,6 +325,16 @@ namespace adapters;
}
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -116,6 +116,14 @@ namespace adapters;
return true;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -287,6 +295,16 @@ namespace adapters;
}
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
return true;

View File

@ -160,6 +160,14 @@ class TwilioVirtualNumberAdapter implements AdapterInterface
return true;
}
/**
* Does the implemented service support updating phone status.
*/
public static function meta_support_phone_status(): bool
{
return false;
}
/**
* Does the implemented service support flash smss.
*/
@ -295,6 +303,16 @@ class TwilioVirtualNumberAdapter implements AdapterInterface
}
}
/**
* Method called to verify phone status
*
* @return string : Return one phone status among 'available', 'unavailable', 'no_credit'
*/
public function check_phone_status(): string
{
return \models\Phone::STATUS_AVAILABLE;
}
public function test(): bool
{
try

View File

@ -236,6 +236,19 @@ namespace controllers\internals;
return true;
}
/**
* Update a phone status.
*
* @param int $id : Phone id
* @param string $status : The new status of the phone
*
* @return bool : false on error, true on success
*/
public function update_status(int $id, string $status) : bool
{
return (bool) $this->get_model()->update($id, ['status' => $status]);
}
/**
* Get the model for the Controller.
*/

View File

@ -710,7 +710,7 @@ namespace controllers\publics;
$priority = $_POST['priority'] ?? $phone['priority'];
$priority = max(((int) $priority), 0);
$adapter = $_POST['adapter'] ?? $phone['adapter'];
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : json_decode($phone['adapter_data']);
$adapter_data = !empty($_POST['adapter_data']) ? $_POST['adapter_data'] : json_decode($phone['adapter_data'], true);
$adapter_data = is_array($adapter_data) ? $adapter_data : [$adapter_data];
$limits = $_POST['limits'] ?? $limits;
$limits = is_array($limits) ? $limits : [$limits];
@ -890,4 +890,44 @@ namespace controllers\publics;
return $this->json($return);
}
/**
* Trigger re-checking of a phone status
*
* @param int $id : Id of phone to re-check status
*/
public function post_update_phone_status ($id)
{
$return = self::DEFAULT_RETURN;
$phone = $this->internal_phone->get_for_user($this->user['id'], $id);
if (!$phone)
{
$return['error'] = self::ERROR_CODES['CANNOT_UPDATE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_UPDATE'];
$this->auto_http_code(false);
return $this->json($return);
}
//Check adapter is working correctly with thoses names and data
$adapter_classname = $phone['adapter'];
if (!call_user_func([$adapter_classname, 'meta_support_phone_status']))
{
$return['error'] = self::ERROR_CODES['CANNOT_UPDATE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_UPDATE'];
$this->auto_http_code(false);
return $this->json($return);
}
$adapter_instance = new $adapter_classname($phone['adapter_data']);
$new_status = $adapter_instance->check_phone_status();
$status_update = $this->internal_phone->update_status($id, $new_status);
$return['response'] = $new_status;
$this->auto_http_code(true);
return $this->json($return);
}
}

View File

@ -88,6 +88,11 @@ class Phone extends \descartes\Controller
{
$phone['callback_end_call'] = \descartes\Router::url('Callback', 'end_call', ['id_phone' => $phone['id']], ['api_key' => $api_key]);
}
if ($adapter['meta_support_phone_status'])
{
$phone['support_phone_status'] = true;
}
}
header('Content-Type: application/json');
@ -425,7 +430,14 @@ class Phone extends \descartes\Controller
continue;
}
if ($find_adapter['meta_hidden'])
$current_phone = $this->internal_phone->get_for_user($id_user, $id_phone);
if (!$current_phone)
{
continue;
}
// We can only use an hidden adapter if it was already the adapter we was using
if ($find_adapter['meta_hidden'] && $adapter != $current_phone['adapter'])
{
continue;
}
@ -499,4 +511,44 @@ class Phone extends \descartes\Controller
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
/**
* Re-check phone status
* @param array int $_GET['ids'] : ids of phones we want to update status
* @param $csrf : CSRF token
*/
public function update_status ($csrf)
{
if (!$this->verify_csrf($csrf))
{
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
return $this->redirect(\descartes\Router::url('Phone', 'add'));
}
$ids = $_GET['ids'] ?? [];
$id_user = $_SESSION['user']['id'];
foreach ($ids as $id)
{
$phone = $this->internal_phone->get_for_user($id_user, $id);
//Check adapter is working correctly with thoses names and data
$adapter_classname = $phone['adapter'];
if (!call_user_func([$adapter_classname, 'meta_support_phone_status']))
{
continue;
}
$adapter_instance = new $adapter_classname($phone['adapter_data']);
$new_status = $adapter_instance->check_phone_status();
$status_update = $this->internal_phone->update_status($id, $new_status);
}
\FlashMessage\FlashMessage::push('success', 'Les status des téléphones ont bien été mis à jour.');
return $this->redirect(\descartes\Router::url('Phone', 'list'));
}
}

View File

@ -0,0 +1,38 @@
<?php
use Phinx\Migration\AbstractMigration;
class AddStatusPhone extends AbstractMigration
{
/**
* Change Method.
*
* Write your reversible migrations using this method.
*
* More information on writing migrations is available here:
* https://book.cakephp.org/phinx/0/en/migrations.html
*
* The following commands can be used in this method and Phinx will
* automatically reverse them when rolling back:
*
* createTable
* renameTable
* addColumn
* addCustomColumn
* renameColumn
* addIndex
* addForeignKey
*
* Any other destructive changes will result in an error when trying to
* rollback the migration.
*
* Remember to call "create()" or "update()" and NOT "save()" when working
* with the Table class.
*/
public function change()
{
$table = $this->table('phone');
$table->addColumn('status', 'enum', ['values' => ['available', 'unavailable', 'no_credit'], 'default' => 'available']);
$table->update();
}
}

View File

@ -14,6 +14,10 @@ namespace models;
class Phone extends StandardModel
{
const STATUS_AVAILABLE = 'available';
const STATUS_UNAVAILABLE = 'unavailable';
const STATUS_NO_CREDIT = 'no_credit';
/**
* Return all phones that belongs to active users
*

View File

@ -164,6 +164,7 @@
'delete' => '/phone/delete/{csrf}/',
'edit' => '/phone/edit/',
'update' => '/phone/update/{csrf}/',
'update_status' => '/phone/update_status/{csrf}/'
],
'Call' => [
@ -206,6 +207,9 @@
'post_update_phone' => [
'/api/phone/{id}/',
],
'post_update_phone_status' => [
'/api/phone/{id}/status/',
],
'delete_phone' => [
'/api/phone/{id}/',
],

View File

@ -111,7 +111,7 @@ jQuery(document).ready(function ()
{
data: '_',
render: function (data, type, row, meta) {
return '<a class="btn btn-info preview-button" href="#" data-id-group="' + jQuery.fn.dataTable.render.text().display(row.id) + '"><span class="fa fa-eye"></span></a>';
return '<a class="btn btn-info preview-button inline" href="#" data-id-group="' + jQuery.fn.dataTable.render.text().display(row.id) + '"><span class="fa fa-eye"></span></a>';
},
},
{

View File

@ -65,13 +65,15 @@
</p>
<select name="phones[<?php $this->s($phone['id']); ?>][adapter]" class="form-control adapter-select">
<?php foreach ($adapters as $adapter) { ?>
<?php if ($adapter['meta_hidden'] === false) { ?>
<?php if ($adapter['meta_hidden'] === false || $phone['adapter'] == $adapter['meta_classname']) { ?>
<option
value="<?= $adapter['meta_classname'] ?>"
data-description="<?php $this->s($adapter['meta_description']); ?>"
data-data-fields="<?php $this->s(json_encode($adapter['meta_data_fields'])); ?>"
<?php if ($phone['adapter'] == $adapter['meta_classname']) { ?>
data-phone-adapter-data="<?php $this->s($phone['adapter_data']); ?>"
<?php if (!$adapter['meta_hide_data']) { ?>
data-phone-adapter-data="<?php $this->s($phone['adapter_data']); ?>"
<?php } ?>
selected
<?php } ?>
>

View File

@ -58,6 +58,7 @@
</div>
<div class="text-right col-xs-6 no-padding">
<strong>Action pour la séléction :</strong>
<button class="btn btn-default" type="submit" formaction="<?php echo \descartes\Router::url('Phone', 'update_status', ['csrf' => $_SESSION['csrf']]); ?>"><span class="fa fa-refresh"></span> Rafraichir le status</button>
<button class="btn btn-default" type="submit" formaction="<?php echo \descartes\Router::url('Phone', 'edit'); ?>"><span class="fa fa-edit"></span> Modifier</button>
<button class="btn btn-default btn-confirm" type="submit" formaction="<?php echo \descartes\Router::url('Phone', 'delete', ['csrf' => $_SESSION['csrf']]); ?>"><span class="fa fa-trash-o"></span> Supprimer</button>
</div>
@ -90,7 +91,28 @@ jQuery(document).ready(function ()
},
"columns" : [
{data: 'id', render: jQuery.fn.dataTable.render.text()},
{data: 'name', render: jQuery.fn.dataTable.render.text()},
{
data: 'name',
render: function (data, type, row, meta) {
html = jQuery.fn.dataTable.render.text().display(data)
switch (row.status)
{
case 'available':
html += ' - <span class="text-success">Disponible</span>'
break;
case 'unavailable':
html += ' - <span class="text-danger">Indisponible</span>'
break;
case 'no_credit':
html += ' - <span class="text-warning">Plus de crédit</span>'
break;
}
return html
},
},
{data: 'priority', render: jQuery.fn.dataTable.render.text()},
{data: 'adapter', render: jQuery.fn.dataTable.render.text()},
{