Compare commits

...

6 Commits

Author SHA1 Message Date
osaajani e0eed18794 fix few phpstan alerts 2021-01-14 03:58:28 +01:00
osaajani 4eaeefdcfa fix alt message for html was not activating html flag 2021-01-14 03:57:21 +01:00
osaajani ce4f5baaaa fix expression provider for exists 2021-01-14 03:52:54 +01:00
osaajani aac464704e fix style 2021-01-14 03:32:17 +01:00
osaajani cc233f726a update php-cs-fixer 2021-01-14 03:32:04 +01:00
osaajani 14cd233d92 Add api for create and delete phone 2021-01-14 03:25:58 +01:00
39 changed files with 326 additions and 111 deletions

View File

@ -355,6 +355,7 @@ class OctopushShortcodeAdapter implements AdapterInterface
$status = \models\Sended::STATUS_DELIVERED;
break;
case 'NOT_ALLOWED':
case 'INVALID_DESTINATION_ADDRESS':
case 'OUT_OF_DATE':
@ -363,6 +364,7 @@ class OctopushShortcodeAdapter implements AdapterInterface
$status = \models\Sended::STATUS_FAILED;
break;
default:
$status = \models\Sended::STATUS_UNKNOWN;

View File

@ -355,6 +355,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface
$status = \models\Sended::STATUS_DELIVERED;
break;
case 'NOT_ALLOWED':
case 'INVALID_DESTINATION_ADDRESS':
case 'OUT_OF_DATE':
@ -363,6 +364,7 @@ class OctopushVirtualNumberAdapter implements AdapterInterface
$status = \models\Sended::STATUS_FAILED;
break;
default:
$status = \models\Sended::STATUS_UNKNOWN;

View File

@ -347,11 +347,13 @@ namespace adapters;
$status = \models\Sended::STATUS_DELIVERED;
break;
case 2:
case 16:
$status = \models\Sended::STATUS_FAILED;
break;
default:
$status = \models\Sended::STATUS_UNKNOWN;

View File

@ -346,11 +346,13 @@ namespace adapters;
$status = \models\Sended::STATUS_DELIVERED;
break;
case 2:
case 16:
$status = \models\Sended::STATUS_FAILED;
break;
default:
$status = \models\Sended::STATUS_UNKNOWN;

View File

@ -257,10 +257,12 @@ namespace adapters;
$return['status'] = \models\Sended::STATUS_DELIVERED;
break;
case \models\Sended::STATUS_FAILED:
$return['status'] = \models\Sended::STATUS_FAILED;
break;
default:
$return['status'] = \models\Sended::STATUS_UNKNOWN;

View File

@ -325,10 +325,12 @@ class TwilioVirtualNumberAdapter implements AdapterInterface
$status = \models\Sended::STATUS_DELIVERED;
break;
case 'failed':
$status = \models\Sended::STATUS_FAILED;
break;
default:
$status = \models\Sended::STATUS_UNKNOWN;

View File

@ -117,8 +117,8 @@ namespace controllers\internals;
//Add metas of contact by adding contact without datas
$metas = clone $contact;
unset($metas->datas);
unset($metas->id_user);
$metas->datas = null;
$metas->id_user = null;
$datas = ['contact' => $contact->datas, 'contact_metas' => $metas];
$is_valid = $ruler->evaluate_condition($condition, $datas);

View File

@ -68,10 +68,11 @@ namespace controllers\internals;
}
/**
* Check if a user exists based on email
* Check if a user exists based on email.
*
* @param string $email : User email
* @return exit code 1 on false, 0 else
*
* @return void : exit code 1 on false, 0 else
*/
public function user_exists(string $email)
{
@ -79,6 +80,7 @@ namespace controllers\internals;
$internal_user = new \controllers\internals\User($bdd);
$user = $internal_user->get_by_email($email);
exit($user ? 0 : 1);
}
@ -105,11 +107,13 @@ namespace controllers\internals;
$api_key = $api_key ?? $internal_user->generate_random_api_key();
$success = $internal_user->update($user['id'], $email, $password, $admin, $api_key, $status, $encrypt_password);
echo json_encode(['id' => $user['id']]);
exit($success ? 0 : 1);
}
$new_user_id = $internal_user->create($email, $password, $admin, $api_key, $status, $encrypt_password);
echo json_encode(['id' => $new_user_id]);
exit($new_user_id ? 0 : 1);
}
@ -131,12 +135,12 @@ namespace controllers\internals;
}
$success = $internal_user->update_status($user['id'], $status);
exit($success ? 0 : 1);
}
/**
* Delete a user
* Delete a user.
*
* @param string $id : User id
*/
@ -146,6 +150,7 @@ namespace controllers\internals;
$internal_user = new \controllers\internals\User($bdd);
$success = $internal_user->delete($id);
exit($success ? 0 : 1);
}
}

View File

@ -29,12 +29,12 @@ class ExpressionProvider implements ExpressionFunctionProviderInterface
});
//Exists must be personnalized because it inverse is_null
$exists = new ExpressionFunction('exists', function ($var)
$exists = new ExpressionFunction('exists', function ($str)
{
return sprintf('!is_null(%1$s)', $str);
return sprintf('isset(%1$s)', $str);
}, function ($arguments, $var)
{
return null !== $var;
return isset($var);
});
return [

View File

@ -52,7 +52,7 @@ class Mailer extends \descartes\Controller
* @param array $destinations : Destinations address
* @param string $subject : Message subject
* @param string $message : Message
* @param ?string $alt_message : Alt Message if no html support. Null if message is not html.
* @param ?string $alt_message : Alt Message for clients with no html support. Use default (null) if mail to send is textonly and not html.
* @param array $attachments : List of path to attachment files
*
* @return bool : false on error, true else
@ -79,7 +79,7 @@ class Mailer extends \descartes\Controller
if ($alt_message)
{
$mail->isHTML($html);
$mail->isHTML(true);
$mail->AltBody = $alt_message;
}

View File

@ -60,9 +60,9 @@ namespace controllers\internals;
* @param string $adapter : The adapter to use the phone
* @param string json $adapter_datas : A JSON string representing adapter's datas (for example credentials for an api)
*
* @return bool : false on error, true on success
* @return bool|int : false on error, new id on success
*/
public function create(int $id_user, string $name, string $adapter, string $adapter_datas): bool
public function create(int $id_user, string $name, string $adapter, string $adapter_datas)
{
$phone = [
'id_user' => $id_user,
@ -71,7 +71,7 @@ namespace controllers\internals;
'adapter_datas' => $adapter_datas,
];
return (bool) $this->get_model()->insert($phone);
return $this->get_model()->insert($phone);
}
/**

View File

@ -244,7 +244,7 @@ namespace controllers\internals;
if (!isset($users_phones[$scheduled['id_user']]))
{
$phones = $internal_phone->gets_for_user($scheduled['id_user']);
$users_phones[$scheduled['id_user']] = $phones ? $phones : [];
$users_phones[$scheduled['id_user']] = $phones ?: [];
}
$phone_to_use = null;
@ -338,12 +338,10 @@ namespace controllers\internals;
//Add metas of contact by adding contact without datas
$metas = $contact;
unset($metas['datas']);
unset($metas['id_user']);
unset($metas['datas'], $metas['id_user']);
$datas = ['contact' => $contact['datas'], 'contact_metas' => $metas];
$render = $internal_templating->render($scheduled['text'], $datas);
if (!$render['success'])

View File

@ -97,26 +97,32 @@ namespace controllers\internals;
$logo = 'fa-user';
break;
case 'CONTACT_ADD':
$logo = 'fa-user';
break;
case 'GROUP_ADD':
$logo = 'fa-group';
break;
case 'CONDITIONAL_GROUP_ADD':
$logo = 'fa-bullseye';
break;
case 'SCHEDULED_ADD':
$logo = 'fa-calendar';
break;
case 'COMMAND_ADD':
$logo = 'fa-terminal';
break;
default:
$logo = 'fa-question';
}
@ -169,7 +175,8 @@ namespace controllers\internals;
if (!isset($_SESSION['connect']) || !$_SESSION['connect'])
{
header('Location: /');
die();
exit();
}
}
@ -217,26 +224,32 @@ namespace controllers\internals;
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
break;
case UPLOAD_ERR_FORM_SIZE:
$result['content'] = 'Le fichier dépasse la limite de taille.';
break;
case UPLOAD_ERR_PARTIAL:
$result['content'] = 'L\'envoi du fichier a été interrompu.';
break;
case UPLOAD_ERR_NO_FILE:
$result['content'] = 'Aucun fichier n\'a été envoyé.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
break;
case UPLOAD_ERR_CANT_WRITE:
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
break;
case UPLOAD_ERR_EXTENSION:
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';
@ -284,26 +297,32 @@ namespace controllers\internals;
$result['content'] = 'Impossible de télécharger le fichier car il dépasse les ' . ini_get('upload_max_filesize') / (1000 * 1000) . ' Mégaoctets.';
break;
case UPLOAD_ERR_FORM_SIZE:
$result['content'] = 'Le fichier dépasse la limite de taille.';
break;
case UPLOAD_ERR_PARTIAL:
$result['content'] = 'L\'envoi du fichier a été interrompu.';
break;
case UPLOAD_ERR_NO_FILE:
$result['content'] = 'Aucun fichier n\'a été envoyé.';
break;
case UPLOAD_ERR_NO_TMP_DIR:
$result['content'] = 'Le serveur ne dispose pas de fichier temporaire permettant l\'envoi de fichiers.';
break;
case UPLOAD_ERR_CANT_WRITE:
$result['content'] = 'Impossible d\'envoyer le fichier car il n\'y a plus de place sur le serveur.';
break;
case UPLOAD_ERR_EXTENSION:
$result['content'] = 'Le serveur a interrompu l\'envoi du fichier.';

View File

@ -35,7 +35,7 @@ namespace controllers\publics;
];
const ERROR_MESSAGES = [
'INVALID_CREDENTIALS' => 'Invalid API Key. Please provide a valid API key as GET or POST parameter "api_key".',
'INVALID_CREDENTIALS' => 'Invalid API Key. Please provide a valid API key as GET or POST parameter "api_key" or a HTTP "X-Api-Key".',
'INVALID_PARAMETER' => 'You have specified an invalid parameter : ',
'MISSING_PARAMETER' => 'One require parameter is missing : ',
'CANNOT_CREATE' => 'Cannot create a new entry.',
@ -51,6 +51,7 @@ namespace controllers\publics;
private $internal_contact;
private $internal_group;
private $internal_conditional_group;
private $internal_adapter;
private $user;
/**
@ -71,6 +72,7 @@ namespace controllers\publics;
$this->internal_contact = new \controllers\internals\Contact($bdd);
$this->internal_group = new \controllers\internals\Group($bdd);
$this->internal_conditional_group = new \controllers\internals\ConditionalGroup($bdd);
$this->internal_adapter = new \controllers\internals\Adapter();
//If no user, quit with error
$this->user = false;
@ -303,4 +305,174 @@ namespace controllers\publics;
return $this->json($return);
}
/**
* Create a new phone.
*
* @param string $_POST['name'] : Phone name
* @param string $_POST['adapter'] : Phone adapter
* @param array $_POST['adapter_datas'] : Phone adapter datas
*
* @return int : id phone the new phone on success
*/
public function post_phone()
{
$return = self::DEFAULT_RETURN;
$name = $_POST['name'] ?? false;
$adapter = $_POST['adapter'] ?? false;
$adapter_datas = !empty($_POST['adapter_datas']) ? $_POST['adapter_datas'] : [];
if (!$name)
{
$return['error'] = self::ERROR_CODES['MISSING_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['MISSING_PARAMETER'] . ' You must specify phone name.';
$this->auto_http_code(false);
return $this->json($return);
}
if (!$adapter)
{
$return['error'] = self::ERROR_CODES['MISSING_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['MISSING_PARAMETER'] . ' You must specify adapter name.';
$this->auto_http_code(false);
return $this->json($return);
}
$name_exist = $this->internal_phone->get_by_name($name);
if ($name_exist)
{
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . ' This name is already used for another phone.';
$this->auto_http_code(false);
return $this->json($return);
}
$adapters = $this->internal_adapter->list_adapters();
$find_adapter = false;
foreach ($adapters as $metas)
{
if ($metas['meta_classname'] === $adapter)
{
$find_adapter = $metas;
break;
}
}
if (!$find_adapter)
{
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . ' adapter. Adapter "' . $adapter . '" does not exists.';
$this->auto_http_code(false);
return $this->json($return);
}
//If missing required data fields, error
foreach ($find_adapter['meta_datas_fields'] as $field)
{
if (false === $field['required'])
{
continue;
}
if (!empty($adapter_datas[$field['name']]))
{
continue;
}
$return['error'] = self::ERROR_CODES['MISSING_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['MISSING_PARAMETER'] . ' You must speicify param ' . $field['name'] . ' (' . $field['description'] . ') for this phone.';
$this->auto_http_code(false);
return $this->json($return);
}
//If field phone number is invalid
foreach ($find_adapter['meta_datas_fields'] as $field)
{
if (false === ($field['number'] ?? false))
{
continue;
}
if (!empty($adapter_datas[$field['name']]))
{
$adapter_datas[$field['name']] = \controllers\internals\Tool::parse_phone($adapter_datas[$field['name']]);
if ($adapter_datas[$field['name']])
{
continue;
}
}
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . ' field ' . $field['name'] . ' is not a valid phone number.';
$this->auto_http_code(false);
return $this->json($return);
}
$adapter_datas = json_encode($adapter_datas);
//Check adapter is working correctly with thoses names and datas
$adapter_classname = $find_adapter['meta_classname'];
$adapter_instance = new $adapter_classname($adapter_datas);
$adapter_working = $adapter_instance->test();
if (!$adapter_working)
{
$return['error'] = self::ERROR_CODES['CANNOT_CREATE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_CREATE'] . ' : Impossible to validate this phone, verify adapters parameters.';
$this->auto_http_code(false);
return $this->json($return);
}
$phone_id = $this->internal_phone->create($this->user['id'], $name, $adapter, $adapter_datas);
if (false === $phone_id)
{
$return['error'] = self::ERROR_CODES['CANNOT_CREATE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_CREATE'];
$this->auto_http_code(false);
return $this->json($return);
}
$return['response'] = $phone_id;
$this->auto_http_code(true);
return $this->json($return);
}
/**
* Delete a phone.
*
* @param int $id : Id of phond to delete
*
* @return bool : void
*/
public function delete_phone(int $id)
{
$return = self::DEFAULT_RETURN;
$success = $this->internal_phone->delete_for_user($this->user['id'], $id);
if (!$success)
{
$return['error'] = self::ERROR_CODES['CANNOT_DELETE'];
$return['message'] = self::ERROR_MESSAGES['CANNOT_DELETE'];
$this->auto_http_code(false);
return $this->json($return);
}
$return['response'] = true;
$this->auto_http_code(true);
return $this->json($return);
}
}

View File

@ -52,6 +52,7 @@ use Monolog\Logger;
http_response_code(401);
echo json_encode(['error' => 'Invalid API key. You must provide a valid GET or POST api_key param.']);
$this->logger->error('Callback call failed with invalid api key : ' . $api_key);
exit(1);
}

View File

@ -46,7 +46,7 @@ namespace controllers\publics;
}
/**
* Return commands as json
* Return commands as json.
*/
public function list_json()
{

View File

@ -50,7 +50,7 @@ namespace controllers\publics;
}
/**
* Return conditionnals groups as json
* Return conditionnals groups as json.
*/
public function list_json()
{

View File

@ -44,7 +44,7 @@ namespace controllers\publics;
}
/**
* Return contacts as json
* Return contacts as json.
*/
public function list_json()
{
@ -288,16 +288,19 @@ namespace controllers\publics;
//Try to import file
$invalid_type = false;
switch ($read_file['mime_type'])
{
case 'text/csv':
$result = $this->internal_contact->import_csv($id_user, $read_file['content']);
break;
case 'application/json':
$result = $this->internal_contact->import_json($id_user, $read_file['content']);
break;
default:
$invalid_type = true;
}
@ -338,16 +341,19 @@ namespace controllers\publics;
//Try to export contacts
$invalid_type = false;
switch ($format)
{
case 'csv':
$result = $this->internal_contact->export_csv($id_user);
break;
case 'json':
$result = $this->internal_contact->export_json($id_user);
break;
default:
$invalid_type = true;
}

View File

@ -50,7 +50,7 @@ namespace controllers\publics;
}
/**
* Return discussions as json
* Return discussions as json.
*/
public function list_json()
{

View File

@ -44,7 +44,7 @@ namespace controllers\publics;
}
/**
* Return events as json
* Return events as json.
*/
public function list_json()
{

View File

@ -45,9 +45,8 @@ namespace controllers\publics;
$this->render('group/list');
}
/**
* Return groups as json
* Return groups as json.
*/
public function list_json()
{

View File

@ -73,7 +73,7 @@ class Phone extends \descartes\Controller
}
/**
* Return phones as json with additionnals datas about callbacks
* Return phones as json with additionnals datas about callbacks.
*/
public function list_json()
{
@ -245,10 +245,6 @@ class Phone extends \descartes\Controller
}
}
var_dump($field);
var_dump($adapter_datas[$field['name']]);
die();
\FlashMessage\FlashMessage::push('danger', 'Vous avez fourni un numéro de téléphone avec un format invalide.');
return $this->redirect(\descartes\Router::url('Phone', 'add'));

View File

@ -45,7 +45,7 @@ namespace controllers\publics;
}
/**
* Return received as json
* Return received as json.
*/
public function list_json()
{
@ -68,7 +68,7 @@ namespace controllers\publics;
}
/**
* Return unred received as json
* Return unred received as json.
*/
public function list_unread_json()
{
@ -83,7 +83,7 @@ namespace controllers\publics;
}
/**
* Mark messages as
* Mark messages as.
*
* @param string $status : New status of the message, read or unread
* @param array int $_GET['ids'] : Ids of receiveds to delete
@ -91,7 +91,7 @@ namespace controllers\publics;
*
* @return boolean;
*/
public function mark_as ($status, $csrf)
public function mark_as($status, $csrf)
{
if (!$this->verify_csrf($csrf))
{
@ -103,11 +103,11 @@ namespace controllers\publics;
$ids = $_GET['ids'] ?? [];
foreach ($ids as $id)
{
if ($status === \models\Received::STATUS_UNREAD)
if (\models\Received::STATUS_UNREAD === $status)
{
$this->internal_received->mark_as_unread_for_user($_SESSION['user']['id'], $id);
}
elseif ($status === \models\Received::STATUS_READ)
elseif (\models\Received::STATUS_READ === $status)
{
$this->internal_received->mark_as_read_for_user($_SESSION['user']['id'], $id);
}

View File

@ -51,7 +51,7 @@ namespace controllers\publics;
}
/**
* Return scheduleds as json
* Return scheduleds as json.
*/
public function list_json()
{

View File

@ -18,6 +18,7 @@ namespace controllers\publics;
{
private $internal_sended;
private $internal_phone;
private $internal_contact;
/**
* Cette fonction est appelée avant toute les autres :
@ -46,7 +47,7 @@ namespace controllers\publics;
}
/**
* Return sendeds as json
* Return sendeds as json.
*/
public function list_json()
{
@ -60,7 +61,6 @@ namespace controllers\publics;
echo json_encode(['data' => $entities]);
}
/**
* Cette fonction va supprimer une liste de sendeds.
*

View File

@ -43,7 +43,7 @@ namespace controllers\publics;
}
/**
* Return smsstops as json
* Return smsstops as json.
*/
public function list_json()
{

View File

@ -70,8 +70,7 @@ namespace controllers\publics;
//Add metas of contact by adding contact without datas
$metas = $contact;
unset($metas['datas']);
unset($metas['id_user']);
unset($metas['datas'], $metas['id_user']);
$datas = [
'contact' => $contact['datas'],

View File

@ -46,7 +46,7 @@ class User extends \descartes\Controller
}
/**
* Return users as json
* Return users as json.
*/
public function list_json()
{

View File

@ -40,7 +40,7 @@ namespace controllers\publics;
}
/**
* Return commands as json
* Return commands as json.
*/
public function list_json()
{

View File

@ -125,6 +125,7 @@ abstract class AbstractDaemon
if (-1 === $sid)
{ //Error
$this->logger->critical("Cannot make the child process with pid {$pid} independent.");
exit(1);
}
@ -138,6 +139,7 @@ abstract class AbstractDaemon
if (!$success)
{
$this->logger->critical('Cannot create PID directory : ' . $this->pid_dir);
exit(2);
}
}

View File

@ -15,7 +15,7 @@ namespace models;
{
/**
* Return a list of groups for a user.
* Add a column nb_contacts
* Add a column nb_contacts.
*
* @param int $id_user : user id
* @param ?int $limit : Number of entry to return or null
@ -34,12 +34,12 @@ namespace models;
GROUP BY g.id
';
if ($limit !== null)
if (null !== $limit)
{
$limit = (int) $limit;
$query .= ' LIMIT ' . $limit;
if ($offset !== null)
if (null !== $offset)
{
$offset = (int) $offset;
$query .= ' OFFSET ' . $offset;
@ -52,6 +52,7 @@ namespace models;
return $this->_run_query($query, $params);
}
/**
* Return a group by his name for a user.
*

View File

@ -21,7 +21,7 @@ namespace models;
/**
* Return a list of received messages for a user.
* Add a column contact_name and phone_name when available
* 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
@ -42,12 +42,12 @@ namespace models;
WHERE received.id_user = :id_user
';
if ($limit !== null)
if (null !== $limit)
{
$limit = (int) $limit;
$query .= ' LIMIT ' . $limit;
if ($offset !== null)
if (null !== $offset)
{
$offset = (int) $offset;
$query .= ' OFFSET ' . $offset;
@ -61,10 +61,9 @@ namespace models;
return $this->_run_query($query, $params);
}
/**
* Return a list of unread received messages for a user.
* Add a column contact_name and phone_name when available
* 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
@ -86,12 +85,12 @@ namespace models;
AND status = :status
';
if ($limit !== null)
if (null !== $limit)
{
$limit = (int) $limit;
$query .= ' LIMIT ' . $limit;
if ($offset !== null)
if (null !== $offset)
{
$offset = (int) $offset;
$query .= ' OFFSET ' . $offset;

View File

@ -22,7 +22,7 @@ namespace models;
/**
* Return a list of sended messages for a user.
* Add a column contact_name and phone_name when available
* 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
@ -43,12 +43,12 @@ namespace models;
WHERE sended.id_user = :id_user
';
if ($limit !== null)
if (null !== $limit)
{
$limit = (int) $limit;
$query .= ' LIMIT ' . $limit;
if ($offset !== null)
if (null !== $offset)
{
$offset = (int) $offset;
$query .= ' OFFSET ' . $offset;

View File

@ -67,7 +67,7 @@ namespace models;
}
/**
* Delete a user
* Delete a user.
*
* @param int $id : Id de l'utilisateur a supprimer
*

View File

@ -182,6 +182,12 @@
'delete_scheduled' => [
'/api/scheduled/{id}/',
],
'post_phone' => [
'/api/phone/',
],
'delete_phone' => [
'/api/phone/{id}/',
],
],
);

View File

@ -88,7 +88,7 @@ jQuery(document).ready(function ()
"columns" : [
{data: 'id', render: jQuery.fn.dataTable.render.text()},
{data: 'name', render: jQuery.fn.dataTable.render.text()},
{data: 'name', render: jQuery.fn.dataTable.render.text()},
{data: 'adapter', render: jQuery.fn.dataTable.render.text()},
{
data: '_',
render: function (data, type, row, meta) {

Binary file not shown.