Add multiple new functions :
- A new adapter for Odyssey Messaging - Feature to associate a tag to sms campaign - Support for phone groups - Support of phone status - Support for phone priority - Support for phone limits - Settings to enable phone priority and phone limits
This commit is contained in:
commit
eba0b83b87
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,511 @@
|
|||
<?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 adapters;
|
||||
|
||||
use DateTime;
|
||||
|
||||
/**
|
||||
* Odyssey Messaging SMS service
|
||||
*/
|
||||
class OdysseyMessagingAdapter implements AdapterInterface
|
||||
{
|
||||
const EVENT_TYPES = [
|
||||
'OPT_OUT' => 1,
|
||||
'SYSTEM_ERROR' => 2,
|
||||
'END_OF_ITEM' => 3,
|
||||
'END_OF_JOB' => 4,
|
||||
'JOB_STATUS_CHANGED' => 5,
|
||||
'REAL_TIME_STATUS' => 6,
|
||||
'RETRIEVE_FILE' => 7,
|
||||
'INBOUND_SMS' => 8,
|
||||
'ITEM_STATUS_CHANGED' => 9,
|
||||
'DATA_COLLECTION_FILLED' => 10,
|
||||
];
|
||||
|
||||
/**
|
||||
* Data used to configure interaction with the implemented service. (e.g : Api credentials, ports numbers, etc.).
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Odyssey login.
|
||||
*/
|
||||
private $login;
|
||||
|
||||
/**
|
||||
* Odyssey password.
|
||||
*/
|
||||
private $password;
|
||||
|
||||
/**
|
||||
* Sender name to use instead of shortcode.
|
||||
*/
|
||||
private $sender;
|
||||
|
||||
/**
|
||||
* Odyssey api baseurl.
|
||||
*/
|
||||
private $api_url = 'https://api.odyssey-services.fr/api/v1';
|
||||
|
||||
/**
|
||||
* Adapter constructor, called when instanciated by RaspiSMS.
|
||||
*
|
||||
* @param json string $data : JSON string of the data to configure interaction with the implemented service
|
||||
*/
|
||||
public function __construct(string $data)
|
||||
{
|
||||
$this->data = json_decode($data, true);
|
||||
|
||||
$this->login = $this->data['login'];
|
||||
$this->password = $this->data['password'];
|
||||
|
||||
$this->sender = $this->data['sender'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classname of the adapter.
|
||||
*/
|
||||
public static function meta_classname(): string
|
||||
{
|
||||
return __CLASS__;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uniq name of the adapter
|
||||
* It should be the classname of the adapter un snakecase.
|
||||
*/
|
||||
public static function meta_uid(): string
|
||||
{
|
||||
return 'odyssey_messaging_adapter';
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this adapter be hidden in user interface for phone creation and
|
||||
* available to creation through API only.
|
||||
*/
|
||||
public static function meta_hidden(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should this adapter data be hidden after creation
|
||||
* this help to prevent API credentials to other service leak if an attacker gain access to RaspiSMS through user credentials.
|
||||
*/
|
||||
public static function meta_hide_data(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the adapter.
|
||||
* It should probably be the name of the service it adapt (e.g : Gammu SMSD, OVH SMS, SIM800L, etc.).
|
||||
*/
|
||||
public static function meta_name(): string
|
||||
{
|
||||
return 'Odyssey Messaging';
|
||||
}
|
||||
|
||||
/**
|
||||
* Description of the adapter.
|
||||
* A short description of the service the adapter implements.
|
||||
*/
|
||||
public static function meta_description(): string
|
||||
{
|
||||
return '
|
||||
Envoi de SMS avec <a target="_blank" href="https://www.odyssey-messaging.com/">Odyssey Messaging</a>.
|
||||
Pour plus d\'information sur l\'utilisation de ce type de téléphone, reportez-vous à <a href="https://documentation.raspisms.fr/users/adapters/odyssey_messaging.html" target="_blank">la documentation sur le téléphone "Odyssey Messaging".</a>
|
||||
';
|
||||
}
|
||||
|
||||
/**
|
||||
* List of entries we want in data for the adapter.
|
||||
*
|
||||
* @return array : Every line is a field as an array with keys : name, title, description, required
|
||||
*/
|
||||
public static function meta_data_fields(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'name' => 'login',
|
||||
'title' => 'Odyssey login',
|
||||
'description' => 'Login du compte Odyssey à employer.',
|
||||
'required' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'password',
|
||||
'title' => 'Mot de passe',
|
||||
'description' => 'Mot de passe du compte Odyssey à employer.',
|
||||
'required' => true,
|
||||
],
|
||||
[
|
||||
'name' => 'sender',
|
||||
'title' => 'Nom de l\'expéditeur',
|
||||
'description' => 'Nom de l\'expéditeur à afficher à la place du numéro (11 caractères max).<br/>
|
||||
<b>Laissez vide pour ne pas utiliser d\'expéditeur nommé.</b><br/>
|
||||
<b>Si vous utilisez un expéditeur nommé, le destinataire ne pourra pas répondre.</b>',
|
||||
'required' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the implemented service support reading smss.
|
||||
*/
|
||||
public static function meta_support_read(): bool
|
||||
{
|
||||
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.
|
||||
*/
|
||||
public static function meta_support_flash(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the implemented service support status change.
|
||||
*/
|
||||
public static function meta_support_status_change(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the implemented service support reception callback.
|
||||
*/
|
||||
public static function meta_support_reception(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the implemented service support mms reception.
|
||||
*/
|
||||
public static function meta_support_mms_reception(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the implemented service support mms sending.
|
||||
*/
|
||||
public static function meta_support_mms_sending(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function meta_support_inbound_call_callback(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function meta_support_end_call_callback(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function send(string $destination, string $text, bool $flash = false, bool $mms = false, array $medias = []): array
|
||||
{
|
||||
$response = [
|
||||
'error' => false,
|
||||
'error_message' => null,
|
||||
'uid' => null,
|
||||
];
|
||||
|
||||
try
|
||||
{
|
||||
$credentials = base64_encode($this->login . ':' . $this->password);
|
||||
$headers = [
|
||||
'Authorization: Basic ' . $credentials,
|
||||
'Content-Type: application/json',
|
||||
];
|
||||
|
||||
$data = [
|
||||
'JobType' => 'SMS',
|
||||
'Text' => $text,
|
||||
'TrackingID' => uniqid(),
|
||||
'AdhocRecipients' => [['Name' => uniqid(), 'Address' => str_replace('+', '00', $destination)]],
|
||||
];
|
||||
|
||||
if ($this->sender)
|
||||
{
|
||||
$data['Parameter'] = ['Sender' => $this->sender, 'Media' => 1];
|
||||
}
|
||||
|
||||
$data = json_encode($data);
|
||||
|
||||
$endpoint = $this->api_url . '/SMSJobs';
|
||||
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($curl, CURLOPT_POST, true);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
|
||||
$curl_response = curl_exec($curl);
|
||||
$http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
curl_close($curl);
|
||||
|
||||
if (false === $curl_response)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'HTTP query failed.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response_decode = json_decode($curl_response, true);
|
||||
if (null === $response_decode)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Invalid JSON for response.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
if (200 !== $http_code)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Response indicate error : ' . $response_decode['Message'] . ' -> """' . json_encode($response_decode['ModelState']) . '""" AND HTTP CODE -> ' . $http_code;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$uid = $response_decode['JobNumber'] ?? false;
|
||||
if (!$uid)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Cannot extract SMS uid';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['uid'] = $uid;
|
||||
|
||||
return $response;
|
||||
}
|
||||
catch (\Throwable $t)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = $t->getMessage();
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
||||
public function read(): array
|
||||
{
|
||||
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
|
||||
{
|
||||
if ($this->data['sender'] && (mb_strlen($this->data['sender']) < 3 || mb_strlen($this->data['sender'] > 11)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty($this->data['sms_type']) && !in_array($this->data['sms_type'], ['premium', 'low cost']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$credentials = base64_encode($this->login . ':' . $this->password);
|
||||
$headers = [
|
||||
'Authorization: Basic ' . $credentials,
|
||||
'Content-Type: application/json',
|
||||
];
|
||||
|
||||
//Check service name
|
||||
$endpoint = $this->api_url . '/JobTypes';
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $endpoint);
|
||||
curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
|
||||
$response = curl_exec($curl);
|
||||
$http_code = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
curl_close($curl);
|
||||
|
||||
if (200 !== $http_code)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (\Throwable $t)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static function status_change_callback()
|
||||
{
|
||||
header('Connection: close');
|
||||
header('Content-Encoding: none');
|
||||
header('Content-Length: 0');
|
||||
|
||||
$input = file_get_contents('php://input');
|
||||
$content = json_decode($input, true);
|
||||
if (null === $content)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$event_type = $content['EventType'] ?? false;
|
||||
if ($event_type != self::EVENT_TYPES['ITEM_STATUS_CHANGED'])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$uid = $content['JobNumber'] ?? false;
|
||||
$status = $content['Outcome'] ?? false;
|
||||
|
||||
if (false === $uid || false === $status)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch ($status)
|
||||
{
|
||||
case 'S':
|
||||
$status = \models\Sended::STATUS_DELIVERED;
|
||||
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
$status = \models\Sended::STATUS_UNKNOWN;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$status = \models\Sended::STATUS_FAILED;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ['uid' => $uid, 'status' => $status];
|
||||
}
|
||||
|
||||
public static function reception_callback(): array
|
||||
{
|
||||
$response = [
|
||||
'error' => false,
|
||||
'error_message' => null,
|
||||
'sms' => null,
|
||||
];
|
||||
|
||||
header('Connection: close');
|
||||
header('Content-Encoding: none');
|
||||
header('Content-Length: 0');
|
||||
|
||||
$input = file_get_contents('php://input');
|
||||
$content = json_decode($input, true);
|
||||
if (null === $content)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Cannot read input data from callback request.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$event_type = $content['EventType'] ?? false;
|
||||
if ($event_type != self::EVENT_TYPES['INBOUND_SMS'])
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Invalid event type : ' . $event_type . '.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$number = $content['From'] ?? false;
|
||||
$text = $content['Message'] ?? false;
|
||||
$at = $content['EventDateTime'] ?? false;
|
||||
|
||||
if (!$number || !$text || !$at)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'One required data of the callback is missing.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$matches = null;
|
||||
$match = preg_match('#/Date\(([0-9]+)\+([0-9]+)\)/#', $at, $matches);
|
||||
$timestamp = ($matches[1] ?? null);
|
||||
if (!$match || !$timestamp)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Invalid date.';
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$at = DateTime::createFromFormat('U', $timestamp / 1000);
|
||||
$at = $at->format('Y-m-d H:i:s');
|
||||
|
||||
$origin = \controllers\internals\Tool::parse_phone($number);
|
||||
if (!$origin)
|
||||
{
|
||||
$response['error'] = true;
|
||||
$response['error_message'] = 'Invalid origin number : ' . $number;
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
$response['sms'] = [
|
||||
'at' => $at,
|
||||
'text' => $text,
|
||||
'origin' => $origin,
|
||||
];
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function inbound_call_callback(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function end_call_callback(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*!
|
||||
* Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
/* FONT PATH
|
||||
* -------------------------- */
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src: url('../fonts/fontawesome-webfont.eot?v=4.2.0');
|
||||
src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');
|
||||
src: url('../fonts/fontawesome-webfont.eot?v=4.7.0');
|
||||
src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
@ -64,6 +64,19 @@
|
|||
border: solid 0.08em #eeeeee;
|
||||
border-radius: .1em;
|
||||
}
|
||||
.fa-pull-left {
|
||||
float: left;
|
||||
}
|
||||
.fa-pull-right {
|
||||
float: right;
|
||||
}
|
||||
.fa.fa-pull-left {
|
||||
margin-right: .3em;
|
||||
}
|
||||
.fa.fa-pull-right {
|
||||
margin-left: .3em;
|
||||
}
|
||||
/* Deprecated as of 4.4.0 */
|
||||
.pull-right {
|
||||
float: right;
|
||||
}
|
||||
|
@ -80,6 +93,10 @@
|
|||
-webkit-animation: fa-spin 2s infinite linear;
|
||||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
.fa-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
|
@ -101,31 +118,31 @@
|
|||
}
|
||||
}
|
||||
.fa-rotate-90 {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.fa-rotate-180 {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
.fa-rotate-270 {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
|
||||
-webkit-transform: rotate(270deg);
|
||||
-ms-transform: rotate(270deg);
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
.fa-flip-horizontal {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
|
||||
-webkit-transform: scale(-1, 1);
|
||||
-ms-transform: scale(-1, 1);
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
.fa-flip-vertical {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
|
||||
-webkit-transform: scale(1, -1);
|
||||
-ms-transform: scale(1, -1);
|
||||
transform: scale(1, -1);
|
||||
|
@ -610,6 +627,7 @@
|
|||
.fa-twitter:before {
|
||||
content: "\f099";
|
||||
}
|
||||
.fa-facebook-f:before,
|
||||
.fa-facebook:before {
|
||||
content: "\f09a";
|
||||
}
|
||||
|
@ -622,6 +640,7 @@
|
|||
.fa-credit-card:before {
|
||||
content: "\f09d";
|
||||
}
|
||||
.fa-feed:before,
|
||||
.fa-rss:before {
|
||||
content: "\f09e";
|
||||
}
|
||||
|
@ -1259,7 +1278,8 @@
|
|||
.fa-male:before {
|
||||
content: "\f183";
|
||||
}
|
||||
.fa-gittip:before {
|
||||
.fa-gittip:before,
|
||||
.fa-gratipay:before {
|
||||
content: "\f184";
|
||||
}
|
||||
.fa-sun-o:before {
|
||||
|
@ -1363,7 +1383,7 @@
|
|||
.fa-digg:before {
|
||||
content: "\f1a6";
|
||||
}
|
||||
.fa-pied-piper:before {
|
||||
.fa-pied-piper-pp:before {
|
||||
content: "\f1a7";
|
||||
}
|
||||
.fa-pied-piper-alt:before {
|
||||
|
@ -1489,6 +1509,7 @@
|
|||
content: "\f1ce";
|
||||
}
|
||||
.fa-ra:before,
|
||||
.fa-resistance:before,
|
||||
.fa-rebel:before {
|
||||
content: "\f1d0";
|
||||
}
|
||||
|
@ -1502,6 +1523,8 @@
|
|||
.fa-git:before {
|
||||
content: "\f1d3";
|
||||
}
|
||||
.fa-y-combinator-square:before,
|
||||
.fa-yc-square:before,
|
||||
.fa-hacker-news:before {
|
||||
content: "\f1d4";
|
||||
}
|
||||
|
@ -1670,3 +1693,645 @@
|
|||
.fa-meanpath:before {
|
||||
content: "\f20c";
|
||||
}
|
||||
.fa-buysellads:before {
|
||||
content: "\f20d";
|
||||
}
|
||||
.fa-connectdevelop:before {
|
||||
content: "\f20e";
|
||||
}
|
||||
.fa-dashcube:before {
|
||||
content: "\f210";
|
||||
}
|
||||
.fa-forumbee:before {
|
||||
content: "\f211";
|
||||
}
|
||||
.fa-leanpub:before {
|
||||
content: "\f212";
|
||||
}
|
||||
.fa-sellsy:before {
|
||||
content: "\f213";
|
||||
}
|
||||
.fa-shirtsinbulk:before {
|
||||
content: "\f214";
|
||||
}
|
||||
.fa-simplybuilt:before {
|
||||
content: "\f215";
|
||||
}
|
||||
.fa-skyatlas:before {
|
||||
content: "\f216";
|
||||
}
|
||||
.fa-cart-plus:before {
|
||||
content: "\f217";
|
||||
}
|
||||
.fa-cart-arrow-down:before {
|
||||
content: "\f218";
|
||||
}
|
||||
.fa-diamond:before {
|
||||
content: "\f219";
|
||||
}
|
||||
.fa-ship:before {
|
||||
content: "\f21a";
|
||||
}
|
||||
.fa-user-secret:before {
|
||||
content: "\f21b";
|
||||
}
|
||||
.fa-motorcycle:before {
|
||||
content: "\f21c";
|
||||
}
|
||||
.fa-street-view:before {
|
||||
content: "\f21d";
|
||||
}
|
||||
.fa-heartbeat:before {
|
||||
content: "\f21e";
|
||||
}
|
||||
.fa-venus:before {
|
||||
content: "\f221";
|
||||
}
|
||||
.fa-mars:before {
|
||||
content: "\f222";
|
||||
}
|
||||
.fa-mercury:before {
|
||||
content: "\f223";
|
||||
}
|
||||
.fa-intersex:before,
|
||||
.fa-transgender:before {
|
||||
content: "\f224";
|
||||
}
|
||||
.fa-transgender-alt:before {
|
||||
content: "\f225";
|
||||
}
|
||||
.fa-venus-double:before {
|
||||
content: "\f226";
|
||||
}
|
||||
.fa-mars-double:before {
|
||||
content: "\f227";
|
||||
}
|
||||
.fa-venus-mars:before {
|
||||
content: "\f228";
|
||||
}
|
||||
.fa-mars-stroke:before {
|
||||
content: "\f229";
|
||||
}
|
||||
.fa-mars-stroke-v:before {
|
||||
content: "\f22a";
|
||||
}
|
||||
.fa-mars-stroke-h:before {
|
||||
content: "\f22b";
|
||||
}
|
||||
.fa-neuter:before {
|
||||
content: "\f22c";
|
||||
}
|
||||
.fa-genderless:before {
|
||||
content: "\f22d";
|
||||
}
|
||||
.fa-facebook-official:before {
|
||||
content: "\f230";
|
||||
}
|
||||
.fa-pinterest-p:before {
|
||||
content: "\f231";
|
||||
}
|
||||
.fa-whatsapp:before {
|
||||
content: "\f232";
|
||||
}
|
||||
.fa-server:before {
|
||||
content: "\f233";
|
||||
}
|
||||
.fa-user-plus:before {
|
||||
content: "\f234";
|
||||
}
|
||||
.fa-user-times:before {
|
||||
content: "\f235";
|
||||
}
|
||||
.fa-hotel:before,
|
||||
.fa-bed:before {
|
||||
content: "\f236";
|
||||
}
|
||||
.fa-viacoin:before {
|
||||
content: "\f237";
|
||||
}
|
||||
.fa-train:before {
|
||||
content: "\f238";
|
||||
}
|
||||
.fa-subway:before {
|
||||
content: "\f239";
|
||||
}
|
||||
.fa-medium:before {
|
||||
content: "\f23a";
|
||||
}
|
||||
.fa-yc:before,
|
||||
.fa-y-combinator:before {
|
||||
content: "\f23b";
|
||||
}
|
||||
.fa-optin-monster:before {
|
||||
content: "\f23c";
|
||||
}
|
||||
.fa-opencart:before {
|
||||
content: "\f23d";
|
||||
}
|
||||
.fa-expeditedssl:before {
|
||||
content: "\f23e";
|
||||
}
|
||||
.fa-battery-4:before,
|
||||
.fa-battery:before,
|
||||
.fa-battery-full:before {
|
||||
content: "\f240";
|
||||
}
|
||||
.fa-battery-3:before,
|
||||
.fa-battery-three-quarters:before {
|
||||
content: "\f241";
|
||||
}
|
||||
.fa-battery-2:before,
|
||||
.fa-battery-half:before {
|
||||
content: "\f242";
|
||||
}
|
||||
.fa-battery-1:before,
|
||||
.fa-battery-quarter:before {
|
||||
content: "\f243";
|
||||
}
|
||||
.fa-battery-0:before,
|
||||
.fa-battery-empty:before {
|
||||
content: "\f244";
|
||||
}
|
||||
.fa-mouse-pointer:before {
|
||||
content: "\f245";
|
||||
}
|
||||
.fa-i-cursor:before {
|
||||
content: "\f246";
|
||||
}
|
||||
.fa-object-group:before {
|
||||
content: "\f247";
|
||||
}
|
||||
.fa-object-ungroup:before {
|
||||
content: "\f248";
|
||||
}
|
||||
.fa-sticky-note:before {
|
||||
content: "\f249";
|
||||
}
|
||||
.fa-sticky-note-o:before {
|
||||
content: "\f24a";
|
||||
}
|
||||
.fa-cc-jcb:before {
|
||||
content: "\f24b";
|
||||
}
|
||||
.fa-cc-diners-club:before {
|
||||
content: "\f24c";
|
||||
}
|
||||
.fa-clone:before {
|
||||
content: "\f24d";
|
||||
}
|
||||
.fa-balance-scale:before {
|
||||
content: "\f24e";
|
||||
}
|
||||
.fa-hourglass-o:before {
|
||||
content: "\f250";
|
||||
}
|
||||
.fa-hourglass-1:before,
|
||||
.fa-hourglass-start:before {
|
||||
content: "\f251";
|
||||
}
|
||||
.fa-hourglass-2:before,
|
||||
.fa-hourglass-half:before {
|
||||
content: "\f252";
|
||||
}
|
||||
.fa-hourglass-3:before,
|
||||
.fa-hourglass-end:before {
|
||||
content: "\f253";
|
||||
}
|
||||
.fa-hourglass:before {
|
||||
content: "\f254";
|
||||
}
|
||||
.fa-hand-grab-o:before,
|
||||
.fa-hand-rock-o:before {
|
||||
content: "\f255";
|
||||
}
|
||||
.fa-hand-stop-o:before,
|
||||
.fa-hand-paper-o:before {
|
||||
content: "\f256";
|
||||
}
|
||||
.fa-hand-scissors-o:before {
|
||||
content: "\f257";
|
||||
}
|
||||
.fa-hand-lizard-o:before {
|
||||
content: "\f258";
|
||||
}
|
||||
.fa-hand-spock-o:before {
|
||||
content: "\f259";
|
||||
}
|
||||
.fa-hand-pointer-o:before {
|
||||
content: "\f25a";
|
||||
}
|
||||
.fa-hand-peace-o:before {
|
||||
content: "\f25b";
|
||||
}
|
||||
.fa-trademark:before {
|
||||
content: "\f25c";
|
||||
}
|
||||
.fa-registered:before {
|
||||
content: "\f25d";
|
||||
}
|
||||
.fa-creative-commons:before {
|
||||
content: "\f25e";
|
||||
}
|
||||
.fa-gg:before {
|
||||
content: "\f260";
|
||||
}
|
||||
.fa-gg-circle:before {
|
||||
content: "\f261";
|
||||
}
|
||||
.fa-tripadvisor:before {
|
||||
content: "\f262";
|
||||
}
|
||||
.fa-odnoklassniki:before {
|
||||
content: "\f263";
|
||||
}
|
||||
.fa-odnoklassniki-square:before {
|
||||
content: "\f264";
|
||||
}
|
||||
.fa-get-pocket:before {
|
||||
content: "\f265";
|
||||
}
|
||||
.fa-wikipedia-w:before {
|
||||
content: "\f266";
|
||||
}
|
||||
.fa-safari:before {
|
||||
content: "\f267";
|
||||
}
|
||||
.fa-chrome:before {
|
||||
content: "\f268";
|
||||
}
|
||||
.fa-firefox:before {
|
||||
content: "\f269";
|
||||
}
|
||||
.fa-opera:before {
|
||||
content: "\f26a";
|
||||
}
|
||||
.fa-internet-explorer:before {
|
||||
content: "\f26b";
|
||||
}
|
||||
.fa-tv:before,
|
||||
.fa-television:before {
|
||||
content: "\f26c";
|
||||
}
|
||||
.fa-contao:before {
|
||||
content: "\f26d";
|
||||
}
|
||||
.fa-500px:before {
|
||||
content: "\f26e";
|
||||
}
|
||||
.fa-amazon:before {
|
||||
content: "\f270";
|
||||
}
|
||||
.fa-calendar-plus-o:before {
|
||||
content: "\f271";
|
||||
}
|
||||
.fa-calendar-minus-o:before {
|
||||
content: "\f272";
|
||||
}
|
||||
.fa-calendar-times-o:before {
|
||||
content: "\f273";
|
||||
}
|
||||
.fa-calendar-check-o:before {
|
||||
content: "\f274";
|
||||
}
|
||||
.fa-industry:before {
|
||||
content: "\f275";
|
||||
}
|
||||
.fa-map-pin:before {
|
||||
content: "\f276";
|
||||
}
|
||||
.fa-map-signs:before {
|
||||
content: "\f277";
|
||||
}
|
||||
.fa-map-o:before {
|
||||
content: "\f278";
|
||||
}
|
||||
.fa-map:before {
|
||||
content: "\f279";
|
||||
}
|
||||
.fa-commenting:before {
|
||||
content: "\f27a";
|
||||
}
|
||||
.fa-commenting-o:before {
|
||||
content: "\f27b";
|
||||
}
|
||||
.fa-houzz:before {
|
||||
content: "\f27c";
|
||||
}
|
||||
.fa-vimeo:before {
|
||||
content: "\f27d";
|
||||
}
|
||||
.fa-black-tie:before {
|
||||
content: "\f27e";
|
||||
}
|
||||
.fa-fonticons:before {
|
||||
content: "\f280";
|
||||
}
|
||||
.fa-reddit-alien:before {
|
||||
content: "\f281";
|
||||
}
|
||||
.fa-edge:before {
|
||||
content: "\f282";
|
||||
}
|
||||
.fa-credit-card-alt:before {
|
||||
content: "\f283";
|
||||
}
|
||||
.fa-codiepie:before {
|
||||
content: "\f284";
|
||||
}
|
||||
.fa-modx:before {
|
||||
content: "\f285";
|
||||
}
|
||||
.fa-fort-awesome:before {
|
||||
content: "\f286";
|
||||
}
|
||||
.fa-usb:before {
|
||||
content: "\f287";
|
||||
}
|
||||
.fa-product-hunt:before {
|
||||
content: "\f288";
|
||||
}
|
||||
.fa-mixcloud:before {
|
||||
content: "\f289";
|
||||
}
|
||||
.fa-scribd:before {
|
||||
content: "\f28a";
|
||||
}
|
||||
.fa-pause-circle:before {
|
||||
content: "\f28b";
|
||||
}
|
||||
.fa-pause-circle-o:before {
|
||||
content: "\f28c";
|
||||
}
|
||||
.fa-stop-circle:before {
|
||||
content: "\f28d";
|
||||
}
|
||||
.fa-stop-circle-o:before {
|
||||
content: "\f28e";
|
||||
}
|
||||
.fa-shopping-bag:before {
|
||||
content: "\f290";
|
||||
}
|
||||
.fa-shopping-basket:before {
|
||||
content: "\f291";
|
||||
}
|
||||
.fa-hashtag:before {
|
||||
content: "\f292";
|
||||
}
|
||||
.fa-bluetooth:before {
|
||||
content: "\f293";
|
||||
}
|
||||
.fa-bluetooth-b:before {
|
||||
content: "\f294";
|
||||
}
|
||||
.fa-percent:before {
|
||||
content: "\f295";
|
||||
}
|
||||
.fa-gitlab:before {
|
||||
content: "\f296";
|
||||
}
|
||||
.fa-wpbeginner:before {
|
||||
content: "\f297";
|
||||
}
|
||||
.fa-wpforms:before {
|
||||
content: "\f298";
|
||||
}
|
||||
.fa-envira:before {
|
||||
content: "\f299";
|
||||
}
|
||||
.fa-universal-access:before {
|
||||
content: "\f29a";
|
||||
}
|
||||
.fa-wheelchair-alt:before {
|
||||
content: "\f29b";
|
||||
}
|
||||
.fa-question-circle-o:before {
|
||||
content: "\f29c";
|
||||
}
|
||||
.fa-blind:before {
|
||||
content: "\f29d";
|
||||
}
|
||||
.fa-audio-description:before {
|
||||
content: "\f29e";
|
||||
}
|
||||
.fa-volume-control-phone:before {
|
||||
content: "\f2a0";
|
||||
}
|
||||
.fa-braille:before {
|
||||
content: "\f2a1";
|
||||
}
|
||||
.fa-assistive-listening-systems:before {
|
||||
content: "\f2a2";
|
||||
}
|
||||
.fa-asl-interpreting:before,
|
||||
.fa-american-sign-language-interpreting:before {
|
||||
content: "\f2a3";
|
||||
}
|
||||
.fa-deafness:before,
|
||||
.fa-hard-of-hearing:before,
|
||||
.fa-deaf:before {
|
||||
content: "\f2a4";
|
||||
}
|
||||
.fa-glide:before {
|
||||
content: "\f2a5";
|
||||
}
|
||||
.fa-glide-g:before {
|
||||
content: "\f2a6";
|
||||
}
|
||||
.fa-signing:before,
|
||||
.fa-sign-language:before {
|
||||
content: "\f2a7";
|
||||
}
|
||||
.fa-low-vision:before {
|
||||
content: "\f2a8";
|
||||
}
|
||||
.fa-viadeo:before {
|
||||
content: "\f2a9";
|
||||
}
|
||||
.fa-viadeo-square:before {
|
||||
content: "\f2aa";
|
||||
}
|
||||
.fa-snapchat:before {
|
||||
content: "\f2ab";
|
||||
}
|
||||
.fa-snapchat-ghost:before {
|
||||
content: "\f2ac";
|
||||
}
|
||||
.fa-snapchat-square:before {
|
||||
content: "\f2ad";
|
||||
}
|
||||
.fa-pied-piper:before {
|
||||
content: "\f2ae";
|
||||
}
|
||||
.fa-first-order:before {
|
||||
content: "\f2b0";
|
||||
}
|
||||
.fa-yoast:before {
|
||||
content: "\f2b1";
|
||||
}
|
||||
.fa-themeisle:before {
|
||||
content: "\f2b2";
|
||||
}
|
||||
.fa-google-plus-circle:before,
|
||||
.fa-google-plus-official:before {
|
||||
content: "\f2b3";
|
||||
}
|
||||
.fa-fa:before,
|
||||
.fa-font-awesome:before {
|
||||
content: "\f2b4";
|
||||
}
|
||||
.fa-handshake-o:before {
|
||||
content: "\f2b5";
|
||||
}
|
||||
.fa-envelope-open:before {
|
||||
content: "\f2b6";
|
||||
}
|
||||
.fa-envelope-open-o:before {
|
||||
content: "\f2b7";
|
||||
}
|
||||
.fa-linode:before {
|
||||
content: "\f2b8";
|
||||
}
|
||||
.fa-address-book:before {
|
||||
content: "\f2b9";
|
||||
}
|
||||
.fa-address-book-o:before {
|
||||
content: "\f2ba";
|
||||
}
|
||||
.fa-vcard:before,
|
||||
.fa-address-card:before {
|
||||
content: "\f2bb";
|
||||
}
|
||||
.fa-vcard-o:before,
|
||||
.fa-address-card-o:before {
|
||||
content: "\f2bc";
|
||||
}
|
||||
.fa-user-circle:before {
|
||||
content: "\f2bd";
|
||||
}
|
||||
.fa-user-circle-o:before {
|
||||
content: "\f2be";
|
||||
}
|
||||
.fa-user-o:before {
|
||||
content: "\f2c0";
|
||||
}
|
||||
.fa-id-badge:before {
|
||||
content: "\f2c1";
|
||||
}
|
||||
.fa-drivers-license:before,
|
||||
.fa-id-card:before {
|
||||
content: "\f2c2";
|
||||
}
|
||||
.fa-drivers-license-o:before,
|
||||
.fa-id-card-o:before {
|
||||
content: "\f2c3";
|
||||
}
|
||||
.fa-quora:before {
|
||||
content: "\f2c4";
|
||||
}
|
||||
.fa-free-code-camp:before {
|
||||
content: "\f2c5";
|
||||
}
|
||||
.fa-telegram:before {
|
||||
content: "\f2c6";
|
||||
}
|
||||
.fa-thermometer-4:before,
|
||||
.fa-thermometer:before,
|
||||
.fa-thermometer-full:before {
|
||||
content: "\f2c7";
|
||||
}
|
||||
.fa-thermometer-3:before,
|
||||
.fa-thermometer-three-quarters:before {
|
||||
content: "\f2c8";
|
||||
}
|
||||
.fa-thermometer-2:before,
|
||||
.fa-thermometer-half:before {
|
||||
content: "\f2c9";
|
||||
}
|
||||
.fa-thermometer-1:before,
|
||||
.fa-thermometer-quarter:before {
|
||||
content: "\f2ca";
|
||||
}
|
||||
.fa-thermometer-0:before,
|
||||
.fa-thermometer-empty:before {
|
||||
content: "\f2cb";
|
||||
}
|
||||
.fa-shower:before {
|
||||
content: "\f2cc";
|
||||
}
|
||||
.fa-bathtub:before,
|
||||
.fa-s15:before,
|
||||
.fa-bath:before {
|
||||
content: "\f2cd";
|
||||
}
|
||||
.fa-podcast:before {
|
||||
content: "\f2ce";
|
||||
}
|
||||
.fa-window-maximize:before {
|
||||
content: "\f2d0";
|
||||
}
|
||||
.fa-window-minimize:before {
|
||||
content: "\f2d1";
|
||||
}
|
||||
.fa-window-restore:before {
|
||||
content: "\f2d2";
|
||||
}
|
||||
.fa-times-rectangle:before,
|
||||
.fa-window-close:before {
|
||||
content: "\f2d3";
|
||||
}
|
||||
.fa-times-rectangle-o:before,
|
||||
.fa-window-close-o:before {
|
||||
content: "\f2d4";
|
||||
}
|
||||
.fa-bandcamp:before {
|
||||
content: "\f2d5";
|
||||
}
|
||||
.fa-grav:before {
|
||||
content: "\f2d6";
|
||||
}
|
||||
.fa-etsy:before {
|
||||
content: "\f2d7";
|
||||
}
|
||||
.fa-imdb:before {
|
||||
content: "\f2d8";
|
||||
}
|
||||
.fa-ravelry:before {
|
||||
content: "\f2d9";
|
||||
}
|
||||
.fa-eercast:before {
|
||||
content: "\f2da";
|
||||
}
|
||||
.fa-microchip:before {
|
||||
content: "\f2db";
|
||||
}
|
||||
.fa-snowflake-o:before {
|
||||
content: "\f2dc";
|
||||
}
|
||||
.fa-superpowers:before {
|
||||
content: "\f2dd";
|
||||
}
|
||||
.fa-wpexplorer:before {
|
||||
content: "\f2de";
|
||||
}
|
||||
.fa-meetup:before {
|
||||
content: "\f2e0";
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
border: 0;
|
||||
}
|
||||
.sr-only-focusable:active,
|
||||
.sr-only-focusable:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 280 KiB After Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,4 +1,4 @@
|
|||
// Spinning Icons
|
||||
// Animated Icons
|
||||
// --------------------------
|
||||
|
||||
.@{fa-css-prefix}-spin {
|
||||
|
@ -6,6 +6,11 @@
|
|||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
|
@ -7,6 +7,15 @@
|
|||
border-radius: .1em;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pull-left { float: left; }
|
||||
.@{fa-css-prefix}-pull-right { float: right; }
|
||||
|
||||
.@{fa-css-prefix} {
|
||||
&.@{fa-css-prefix}-pull-left { margin-right: .3em; }
|
||||
&.@{fa-css-prefix}-pull-right { margin-left: .3em; }
|
||||
}
|
||||
|
||||
/* Deprecated as of 4.4.0 */
|
||||
.pull-right { float: right; }
|
||||
.pull-left { float: left; }
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
.@{fa-css-prefix} {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
|
||||
font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
|
||||
|
@ -11,7 +11,8 @@
|
|||
@import "fixed-width.less";
|
||||
@import "list.less";
|
||||
@import "bordered-pulled.less";
|
||||
@import "spinning.less";
|
||||
@import "animated.less";
|
||||
@import "rotated-flipped.less";
|
||||
@import "stacked.less";
|
||||
@import "icons.less";
|
||||
@import "screen-reader.less";
|
||||
|
|
|
@ -158,10 +158,12 @@
|
|||
.@{fa-css-prefix}-bookmark-o:before { content: @fa-var-bookmark-o; }
|
||||
.@{fa-css-prefix}-phone-square:before { content: @fa-var-phone-square; }
|
||||
.@{fa-css-prefix}-twitter:before { content: @fa-var-twitter; }
|
||||
.@{fa-css-prefix}-facebook-f:before,
|
||||
.@{fa-css-prefix}-facebook:before { content: @fa-var-facebook; }
|
||||
.@{fa-css-prefix}-github:before { content: @fa-var-github; }
|
||||
.@{fa-css-prefix}-unlock:before { content: @fa-var-unlock; }
|
||||
.@{fa-css-prefix}-credit-card:before { content: @fa-var-credit-card; }
|
||||
.@{fa-css-prefix}-feed:before,
|
||||
.@{fa-css-prefix}-rss:before { content: @fa-var-rss; }
|
||||
.@{fa-css-prefix}-hdd-o:before { content: @fa-var-hdd-o; }
|
||||
.@{fa-css-prefix}-bullhorn:before { content: @fa-var-bullhorn; }
|
||||
|
@ -397,7 +399,8 @@
|
|||
.@{fa-css-prefix}-trello:before { content: @fa-var-trello; }
|
||||
.@{fa-css-prefix}-female:before { content: @fa-var-female; }
|
||||
.@{fa-css-prefix}-male:before { content: @fa-var-male; }
|
||||
.@{fa-css-prefix}-gittip:before { content: @fa-var-gittip; }
|
||||
.@{fa-css-prefix}-gittip:before,
|
||||
.@{fa-css-prefix}-gratipay:before { content: @fa-var-gratipay; }
|
||||
.@{fa-css-prefix}-sun-o:before { content: @fa-var-sun-o; }
|
||||
.@{fa-css-prefix}-moon-o:before { content: @fa-var-moon-o; }
|
||||
.@{fa-css-prefix}-archive:before { content: @fa-var-archive; }
|
||||
|
@ -435,7 +438,7 @@
|
|||
.@{fa-css-prefix}-stumbleupon:before { content: @fa-var-stumbleupon; }
|
||||
.@{fa-css-prefix}-delicious:before { content: @fa-var-delicious; }
|
||||
.@{fa-css-prefix}-digg:before { content: @fa-var-digg; }
|
||||
.@{fa-css-prefix}-pied-piper:before { content: @fa-var-pied-piper; }
|
||||
.@{fa-css-prefix}-pied-piper-pp:before { content: @fa-var-pied-piper-pp; }
|
||||
.@{fa-css-prefix}-pied-piper-alt:before { content: @fa-var-pied-piper-alt; }
|
||||
.@{fa-css-prefix}-drupal:before { content: @fa-var-drupal; }
|
||||
.@{fa-css-prefix}-joomla:before { content: @fa-var-joomla; }
|
||||
|
@ -485,11 +488,14 @@
|
|||
.@{fa-css-prefix}-life-ring:before { content: @fa-var-life-ring; }
|
||||
.@{fa-css-prefix}-circle-o-notch:before { content: @fa-var-circle-o-notch; }
|
||||
.@{fa-css-prefix}-ra:before,
|
||||
.@{fa-css-prefix}-resistance:before,
|
||||
.@{fa-css-prefix}-rebel:before { content: @fa-var-rebel; }
|
||||
.@{fa-css-prefix}-ge:before,
|
||||
.@{fa-css-prefix}-empire:before { content: @fa-var-empire; }
|
||||
.@{fa-css-prefix}-git-square:before { content: @fa-var-git-square; }
|
||||
.@{fa-css-prefix}-git:before { content: @fa-var-git; }
|
||||
.@{fa-css-prefix}-y-combinator-square:before,
|
||||
.@{fa-css-prefix}-yc-square:before,
|
||||
.@{fa-css-prefix}-hacker-news:before { content: @fa-var-hacker-news; }
|
||||
.@{fa-css-prefix}-tencent-weibo:before { content: @fa-var-tencent-weibo; }
|
||||
.@{fa-css-prefix}-qq:before { content: @fa-var-qq; }
|
||||
|
@ -550,3 +556,234 @@
|
|||
.@{fa-css-prefix}-sheqel:before,
|
||||
.@{fa-css-prefix}-ils:before { content: @fa-var-ils; }
|
||||
.@{fa-css-prefix}-meanpath:before { content: @fa-var-meanpath; }
|
||||
.@{fa-css-prefix}-buysellads:before { content: @fa-var-buysellads; }
|
||||
.@{fa-css-prefix}-connectdevelop:before { content: @fa-var-connectdevelop; }
|
||||
.@{fa-css-prefix}-dashcube:before { content: @fa-var-dashcube; }
|
||||
.@{fa-css-prefix}-forumbee:before { content: @fa-var-forumbee; }
|
||||
.@{fa-css-prefix}-leanpub:before { content: @fa-var-leanpub; }
|
||||
.@{fa-css-prefix}-sellsy:before { content: @fa-var-sellsy; }
|
||||
.@{fa-css-prefix}-shirtsinbulk:before { content: @fa-var-shirtsinbulk; }
|
||||
.@{fa-css-prefix}-simplybuilt:before { content: @fa-var-simplybuilt; }
|
||||
.@{fa-css-prefix}-skyatlas:before { content: @fa-var-skyatlas; }
|
||||
.@{fa-css-prefix}-cart-plus:before { content: @fa-var-cart-plus; }
|
||||
.@{fa-css-prefix}-cart-arrow-down:before { content: @fa-var-cart-arrow-down; }
|
||||
.@{fa-css-prefix}-diamond:before { content: @fa-var-diamond; }
|
||||
.@{fa-css-prefix}-ship:before { content: @fa-var-ship; }
|
||||
.@{fa-css-prefix}-user-secret:before { content: @fa-var-user-secret; }
|
||||
.@{fa-css-prefix}-motorcycle:before { content: @fa-var-motorcycle; }
|
||||
.@{fa-css-prefix}-street-view:before { content: @fa-var-street-view; }
|
||||
.@{fa-css-prefix}-heartbeat:before { content: @fa-var-heartbeat; }
|
||||
.@{fa-css-prefix}-venus:before { content: @fa-var-venus; }
|
||||
.@{fa-css-prefix}-mars:before { content: @fa-var-mars; }
|
||||
.@{fa-css-prefix}-mercury:before { content: @fa-var-mercury; }
|
||||
.@{fa-css-prefix}-intersex:before,
|
||||
.@{fa-css-prefix}-transgender:before { content: @fa-var-transgender; }
|
||||
.@{fa-css-prefix}-transgender-alt:before { content: @fa-var-transgender-alt; }
|
||||
.@{fa-css-prefix}-venus-double:before { content: @fa-var-venus-double; }
|
||||
.@{fa-css-prefix}-mars-double:before { content: @fa-var-mars-double; }
|
||||
.@{fa-css-prefix}-venus-mars:before { content: @fa-var-venus-mars; }
|
||||
.@{fa-css-prefix}-mars-stroke:before { content: @fa-var-mars-stroke; }
|
||||
.@{fa-css-prefix}-mars-stroke-v:before { content: @fa-var-mars-stroke-v; }
|
||||
.@{fa-css-prefix}-mars-stroke-h:before { content: @fa-var-mars-stroke-h; }
|
||||
.@{fa-css-prefix}-neuter:before { content: @fa-var-neuter; }
|
||||
.@{fa-css-prefix}-genderless:before { content: @fa-var-genderless; }
|
||||
.@{fa-css-prefix}-facebook-official:before { content: @fa-var-facebook-official; }
|
||||
.@{fa-css-prefix}-pinterest-p:before { content: @fa-var-pinterest-p; }
|
||||
.@{fa-css-prefix}-whatsapp:before { content: @fa-var-whatsapp; }
|
||||
.@{fa-css-prefix}-server:before { content: @fa-var-server; }
|
||||
.@{fa-css-prefix}-user-plus:before { content: @fa-var-user-plus; }
|
||||
.@{fa-css-prefix}-user-times:before { content: @fa-var-user-times; }
|
||||
.@{fa-css-prefix}-hotel:before,
|
||||
.@{fa-css-prefix}-bed:before { content: @fa-var-bed; }
|
||||
.@{fa-css-prefix}-viacoin:before { content: @fa-var-viacoin; }
|
||||
.@{fa-css-prefix}-train:before { content: @fa-var-train; }
|
||||
.@{fa-css-prefix}-subway:before { content: @fa-var-subway; }
|
||||
.@{fa-css-prefix}-medium:before { content: @fa-var-medium; }
|
||||
.@{fa-css-prefix}-yc:before,
|
||||
.@{fa-css-prefix}-y-combinator:before { content: @fa-var-y-combinator; }
|
||||
.@{fa-css-prefix}-optin-monster:before { content: @fa-var-optin-monster; }
|
||||
.@{fa-css-prefix}-opencart:before { content: @fa-var-opencart; }
|
||||
.@{fa-css-prefix}-expeditedssl:before { content: @fa-var-expeditedssl; }
|
||||
.@{fa-css-prefix}-battery-4:before,
|
||||
.@{fa-css-prefix}-battery:before,
|
||||
.@{fa-css-prefix}-battery-full:before { content: @fa-var-battery-full; }
|
||||
.@{fa-css-prefix}-battery-3:before,
|
||||
.@{fa-css-prefix}-battery-three-quarters:before { content: @fa-var-battery-three-quarters; }
|
||||
.@{fa-css-prefix}-battery-2:before,
|
||||
.@{fa-css-prefix}-battery-half:before { content: @fa-var-battery-half; }
|
||||
.@{fa-css-prefix}-battery-1:before,
|
||||
.@{fa-css-prefix}-battery-quarter:before { content: @fa-var-battery-quarter; }
|
||||
.@{fa-css-prefix}-battery-0:before,
|
||||
.@{fa-css-prefix}-battery-empty:before { content: @fa-var-battery-empty; }
|
||||
.@{fa-css-prefix}-mouse-pointer:before { content: @fa-var-mouse-pointer; }
|
||||
.@{fa-css-prefix}-i-cursor:before { content: @fa-var-i-cursor; }
|
||||
.@{fa-css-prefix}-object-group:before { content: @fa-var-object-group; }
|
||||
.@{fa-css-prefix}-object-ungroup:before { content: @fa-var-object-ungroup; }
|
||||
.@{fa-css-prefix}-sticky-note:before { content: @fa-var-sticky-note; }
|
||||
.@{fa-css-prefix}-sticky-note-o:before { content: @fa-var-sticky-note-o; }
|
||||
.@{fa-css-prefix}-cc-jcb:before { content: @fa-var-cc-jcb; }
|
||||
.@{fa-css-prefix}-cc-diners-club:before { content: @fa-var-cc-diners-club; }
|
||||
.@{fa-css-prefix}-clone:before { content: @fa-var-clone; }
|
||||
.@{fa-css-prefix}-balance-scale:before { content: @fa-var-balance-scale; }
|
||||
.@{fa-css-prefix}-hourglass-o:before { content: @fa-var-hourglass-o; }
|
||||
.@{fa-css-prefix}-hourglass-1:before,
|
||||
.@{fa-css-prefix}-hourglass-start:before { content: @fa-var-hourglass-start; }
|
||||
.@{fa-css-prefix}-hourglass-2:before,
|
||||
.@{fa-css-prefix}-hourglass-half:before { content: @fa-var-hourglass-half; }
|
||||
.@{fa-css-prefix}-hourglass-3:before,
|
||||
.@{fa-css-prefix}-hourglass-end:before { content: @fa-var-hourglass-end; }
|
||||
.@{fa-css-prefix}-hourglass:before { content: @fa-var-hourglass; }
|
||||
.@{fa-css-prefix}-hand-grab-o:before,
|
||||
.@{fa-css-prefix}-hand-rock-o:before { content: @fa-var-hand-rock-o; }
|
||||
.@{fa-css-prefix}-hand-stop-o:before,
|
||||
.@{fa-css-prefix}-hand-paper-o:before { content: @fa-var-hand-paper-o; }
|
||||
.@{fa-css-prefix}-hand-scissors-o:before { content: @fa-var-hand-scissors-o; }
|
||||
.@{fa-css-prefix}-hand-lizard-o:before { content: @fa-var-hand-lizard-o; }
|
||||
.@{fa-css-prefix}-hand-spock-o:before { content: @fa-var-hand-spock-o; }
|
||||
.@{fa-css-prefix}-hand-pointer-o:before { content: @fa-var-hand-pointer-o; }
|
||||
.@{fa-css-prefix}-hand-peace-o:before { content: @fa-var-hand-peace-o; }
|
||||
.@{fa-css-prefix}-trademark:before { content: @fa-var-trademark; }
|
||||
.@{fa-css-prefix}-registered:before { content: @fa-var-registered; }
|
||||
.@{fa-css-prefix}-creative-commons:before { content: @fa-var-creative-commons; }
|
||||
.@{fa-css-prefix}-gg:before { content: @fa-var-gg; }
|
||||
.@{fa-css-prefix}-gg-circle:before { content: @fa-var-gg-circle; }
|
||||
.@{fa-css-prefix}-tripadvisor:before { content: @fa-var-tripadvisor; }
|
||||
.@{fa-css-prefix}-odnoklassniki:before { content: @fa-var-odnoklassniki; }
|
||||
.@{fa-css-prefix}-odnoklassniki-square:before { content: @fa-var-odnoklassniki-square; }
|
||||
.@{fa-css-prefix}-get-pocket:before { content: @fa-var-get-pocket; }
|
||||
.@{fa-css-prefix}-wikipedia-w:before { content: @fa-var-wikipedia-w; }
|
||||
.@{fa-css-prefix}-safari:before { content: @fa-var-safari; }
|
||||
.@{fa-css-prefix}-chrome:before { content: @fa-var-chrome; }
|
||||
.@{fa-css-prefix}-firefox:before { content: @fa-var-firefox; }
|
||||
.@{fa-css-prefix}-opera:before { content: @fa-var-opera; }
|
||||
.@{fa-css-prefix}-internet-explorer:before { content: @fa-var-internet-explorer; }
|
||||
.@{fa-css-prefix}-tv:before,
|
||||
.@{fa-css-prefix}-television:before { content: @fa-var-television; }
|
||||
.@{fa-css-prefix}-contao:before { content: @fa-var-contao; }
|
||||
.@{fa-css-prefix}-500px:before { content: @fa-var-500px; }
|
||||
.@{fa-css-prefix}-amazon:before { content: @fa-var-amazon; }
|
||||
.@{fa-css-prefix}-calendar-plus-o:before { content: @fa-var-calendar-plus-o; }
|
||||
.@{fa-css-prefix}-calendar-minus-o:before { content: @fa-var-calendar-minus-o; }
|
||||
.@{fa-css-prefix}-calendar-times-o:before { content: @fa-var-calendar-times-o; }
|
||||
.@{fa-css-prefix}-calendar-check-o:before { content: @fa-var-calendar-check-o; }
|
||||
.@{fa-css-prefix}-industry:before { content: @fa-var-industry; }
|
||||
.@{fa-css-prefix}-map-pin:before { content: @fa-var-map-pin; }
|
||||
.@{fa-css-prefix}-map-signs:before { content: @fa-var-map-signs; }
|
||||
.@{fa-css-prefix}-map-o:before { content: @fa-var-map-o; }
|
||||
.@{fa-css-prefix}-map:before { content: @fa-var-map; }
|
||||
.@{fa-css-prefix}-commenting:before { content: @fa-var-commenting; }
|
||||
.@{fa-css-prefix}-commenting-o:before { content: @fa-var-commenting-o; }
|
||||
.@{fa-css-prefix}-houzz:before { content: @fa-var-houzz; }
|
||||
.@{fa-css-prefix}-vimeo:before { content: @fa-var-vimeo; }
|
||||
.@{fa-css-prefix}-black-tie:before { content: @fa-var-black-tie; }
|
||||
.@{fa-css-prefix}-fonticons:before { content: @fa-var-fonticons; }
|
||||
.@{fa-css-prefix}-reddit-alien:before { content: @fa-var-reddit-alien; }
|
||||
.@{fa-css-prefix}-edge:before { content: @fa-var-edge; }
|
||||
.@{fa-css-prefix}-credit-card-alt:before { content: @fa-var-credit-card-alt; }
|
||||
.@{fa-css-prefix}-codiepie:before { content: @fa-var-codiepie; }
|
||||
.@{fa-css-prefix}-modx:before { content: @fa-var-modx; }
|
||||
.@{fa-css-prefix}-fort-awesome:before { content: @fa-var-fort-awesome; }
|
||||
.@{fa-css-prefix}-usb:before { content: @fa-var-usb; }
|
||||
.@{fa-css-prefix}-product-hunt:before { content: @fa-var-product-hunt; }
|
||||
.@{fa-css-prefix}-mixcloud:before { content: @fa-var-mixcloud; }
|
||||
.@{fa-css-prefix}-scribd:before { content: @fa-var-scribd; }
|
||||
.@{fa-css-prefix}-pause-circle:before { content: @fa-var-pause-circle; }
|
||||
.@{fa-css-prefix}-pause-circle-o:before { content: @fa-var-pause-circle-o; }
|
||||
.@{fa-css-prefix}-stop-circle:before { content: @fa-var-stop-circle; }
|
||||
.@{fa-css-prefix}-stop-circle-o:before { content: @fa-var-stop-circle-o; }
|
||||
.@{fa-css-prefix}-shopping-bag:before { content: @fa-var-shopping-bag; }
|
||||
.@{fa-css-prefix}-shopping-basket:before { content: @fa-var-shopping-basket; }
|
||||
.@{fa-css-prefix}-hashtag:before { content: @fa-var-hashtag; }
|
||||
.@{fa-css-prefix}-bluetooth:before { content: @fa-var-bluetooth; }
|
||||
.@{fa-css-prefix}-bluetooth-b:before { content: @fa-var-bluetooth-b; }
|
||||
.@{fa-css-prefix}-percent:before { content: @fa-var-percent; }
|
||||
.@{fa-css-prefix}-gitlab:before { content: @fa-var-gitlab; }
|
||||
.@{fa-css-prefix}-wpbeginner:before { content: @fa-var-wpbeginner; }
|
||||
.@{fa-css-prefix}-wpforms:before { content: @fa-var-wpforms; }
|
||||
.@{fa-css-prefix}-envira:before { content: @fa-var-envira; }
|
||||
.@{fa-css-prefix}-universal-access:before { content: @fa-var-universal-access; }
|
||||
.@{fa-css-prefix}-wheelchair-alt:before { content: @fa-var-wheelchair-alt; }
|
||||
.@{fa-css-prefix}-question-circle-o:before { content: @fa-var-question-circle-o; }
|
||||
.@{fa-css-prefix}-blind:before { content: @fa-var-blind; }
|
||||
.@{fa-css-prefix}-audio-description:before { content: @fa-var-audio-description; }
|
||||
.@{fa-css-prefix}-volume-control-phone:before { content: @fa-var-volume-control-phone; }
|
||||
.@{fa-css-prefix}-braille:before { content: @fa-var-braille; }
|
||||
.@{fa-css-prefix}-assistive-listening-systems:before { content: @fa-var-assistive-listening-systems; }
|
||||
.@{fa-css-prefix}-asl-interpreting:before,
|
||||
.@{fa-css-prefix}-american-sign-language-interpreting:before { content: @fa-var-american-sign-language-interpreting; }
|
||||
.@{fa-css-prefix}-deafness:before,
|
||||
.@{fa-css-prefix}-hard-of-hearing:before,
|
||||
.@{fa-css-prefix}-deaf:before { content: @fa-var-deaf; }
|
||||
.@{fa-css-prefix}-glide:before { content: @fa-var-glide; }
|
||||
.@{fa-css-prefix}-glide-g:before { content: @fa-var-glide-g; }
|
||||
.@{fa-css-prefix}-signing:before,
|
||||
.@{fa-css-prefix}-sign-language:before { content: @fa-var-sign-language; }
|
||||
.@{fa-css-prefix}-low-vision:before { content: @fa-var-low-vision; }
|
||||
.@{fa-css-prefix}-viadeo:before { content: @fa-var-viadeo; }
|
||||
.@{fa-css-prefix}-viadeo-square:before { content: @fa-var-viadeo-square; }
|
||||
.@{fa-css-prefix}-snapchat:before { content: @fa-var-snapchat; }
|
||||
.@{fa-css-prefix}-snapchat-ghost:before { content: @fa-var-snapchat-ghost; }
|
||||
.@{fa-css-prefix}-snapchat-square:before { content: @fa-var-snapchat-square; }
|
||||
.@{fa-css-prefix}-pied-piper:before { content: @fa-var-pied-piper; }
|
||||
.@{fa-css-prefix}-first-order:before { content: @fa-var-first-order; }
|
||||
.@{fa-css-prefix}-yoast:before { content: @fa-var-yoast; }
|
||||
.@{fa-css-prefix}-themeisle:before { content: @fa-var-themeisle; }
|
||||
.@{fa-css-prefix}-google-plus-circle:before,
|
||||
.@{fa-css-prefix}-google-plus-official:before { content: @fa-var-google-plus-official; }
|
||||
.@{fa-css-prefix}-fa:before,
|
||||
.@{fa-css-prefix}-font-awesome:before { content: @fa-var-font-awesome; }
|
||||
.@{fa-css-prefix}-handshake-o:before { content: @fa-var-handshake-o; }
|
||||
.@{fa-css-prefix}-envelope-open:before { content: @fa-var-envelope-open; }
|
||||
.@{fa-css-prefix}-envelope-open-o:before { content: @fa-var-envelope-open-o; }
|
||||
.@{fa-css-prefix}-linode:before { content: @fa-var-linode; }
|
||||
.@{fa-css-prefix}-address-book:before { content: @fa-var-address-book; }
|
||||
.@{fa-css-prefix}-address-book-o:before { content: @fa-var-address-book-o; }
|
||||
.@{fa-css-prefix}-vcard:before,
|
||||
.@{fa-css-prefix}-address-card:before { content: @fa-var-address-card; }
|
||||
.@{fa-css-prefix}-vcard-o:before,
|
||||
.@{fa-css-prefix}-address-card-o:before { content: @fa-var-address-card-o; }
|
||||
.@{fa-css-prefix}-user-circle:before { content: @fa-var-user-circle; }
|
||||
.@{fa-css-prefix}-user-circle-o:before { content: @fa-var-user-circle-o; }
|
||||
.@{fa-css-prefix}-user-o:before { content: @fa-var-user-o; }
|
||||
.@{fa-css-prefix}-id-badge:before { content: @fa-var-id-badge; }
|
||||
.@{fa-css-prefix}-drivers-license:before,
|
||||
.@{fa-css-prefix}-id-card:before { content: @fa-var-id-card; }
|
||||
.@{fa-css-prefix}-drivers-license-o:before,
|
||||
.@{fa-css-prefix}-id-card-o:before { content: @fa-var-id-card-o; }
|
||||
.@{fa-css-prefix}-quora:before { content: @fa-var-quora; }
|
||||
.@{fa-css-prefix}-free-code-camp:before { content: @fa-var-free-code-camp; }
|
||||
.@{fa-css-prefix}-telegram:before { content: @fa-var-telegram; }
|
||||
.@{fa-css-prefix}-thermometer-4:before,
|
||||
.@{fa-css-prefix}-thermometer:before,
|
||||
.@{fa-css-prefix}-thermometer-full:before { content: @fa-var-thermometer-full; }
|
||||
.@{fa-css-prefix}-thermometer-3:before,
|
||||
.@{fa-css-prefix}-thermometer-three-quarters:before { content: @fa-var-thermometer-three-quarters; }
|
||||
.@{fa-css-prefix}-thermometer-2:before,
|
||||
.@{fa-css-prefix}-thermometer-half:before { content: @fa-var-thermometer-half; }
|
||||
.@{fa-css-prefix}-thermometer-1:before,
|
||||
.@{fa-css-prefix}-thermometer-quarter:before { content: @fa-var-thermometer-quarter; }
|
||||
.@{fa-css-prefix}-thermometer-0:before,
|
||||
.@{fa-css-prefix}-thermometer-empty:before { content: @fa-var-thermometer-empty; }
|
||||
.@{fa-css-prefix}-shower:before { content: @fa-var-shower; }
|
||||
.@{fa-css-prefix}-bathtub:before,
|
||||
.@{fa-css-prefix}-s15:before,
|
||||
.@{fa-css-prefix}-bath:before { content: @fa-var-bath; }
|
||||
.@{fa-css-prefix}-podcast:before { content: @fa-var-podcast; }
|
||||
.@{fa-css-prefix}-window-maximize:before { content: @fa-var-window-maximize; }
|
||||
.@{fa-css-prefix}-window-minimize:before { content: @fa-var-window-minimize; }
|
||||
.@{fa-css-prefix}-window-restore:before { content: @fa-var-window-restore; }
|
||||
.@{fa-css-prefix}-times-rectangle:before,
|
||||
.@{fa-css-prefix}-window-close:before { content: @fa-var-window-close; }
|
||||
.@{fa-css-prefix}-times-rectangle-o:before,
|
||||
.@{fa-css-prefix}-window-close-o:before { content: @fa-var-window-close-o; }
|
||||
.@{fa-css-prefix}-bandcamp:before { content: @fa-var-bandcamp; }
|
||||
.@{fa-css-prefix}-grav:before { content: @fa-var-grav; }
|
||||
.@{fa-css-prefix}-etsy:before { content: @fa-var-etsy; }
|
||||
.@{fa-css-prefix}-imdb:before { content: @fa-var-imdb; }
|
||||
.@{fa-css-prefix}-ravelry:before { content: @fa-var-ravelry; }
|
||||
.@{fa-css-prefix}-eercast:before { content: @fa-var-eercast; }
|
||||
.@{fa-css-prefix}-microchip:before { content: @fa-var-microchip; }
|
||||
.@{fa-css-prefix}-snowflake-o:before { content: @fa-var-snowflake-o; }
|
||||
.@{fa-css-prefix}-superpowers:before { content: @fa-var-superpowers; }
|
||||
.@{fa-css-prefix}-wpexplorer:before { content: @fa-var-wpexplorer; }
|
||||
.@{fa-css-prefix}-meetup:before { content: @fa-var-meetup; }
|
||||
|
|
|
@ -3,23 +3,58 @@
|
|||
|
||||
.fa-icon() {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
|
||||
font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
}
|
||||
|
||||
.fa-icon-rotate(@degrees, @rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})";
|
||||
-webkit-transform: rotate(@degrees);
|
||||
-ms-transform: rotate(@degrees);
|
||||
transform: rotate(@degrees);
|
||||
}
|
||||
|
||||
.fa-icon-flip(@horiz, @vert, @rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=@rotation, mirror=1);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)";
|
||||
-webkit-transform: scale(@horiz, @vert);
|
||||
-ms-transform: scale(@horiz, @vert);
|
||||
transform: scale(@horiz, @vert);
|
||||
}
|
||||
|
||||
|
||||
// Only display content to screen readers. A la Bootstrap 4.
|
||||
//
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content/
|
||||
|
||||
.sr-only() {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// Use in conjunction with .sr-only to only display content when it's focused.
|
||||
//
|
||||
// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
|
||||
//
|
||||
// Credit: HTML5 Boilerplate
|
||||
|
||||
.sr-only-focusable() {
|
||||
&:active,
|
||||
&:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
font-family: 'FontAwesome';
|
||||
src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}');
|
||||
src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'),
|
||||
url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg');
|
||||
// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
// src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Screen Readers
|
||||
// -------------------------
|
||||
|
||||
.sr-only { .sr-only(); }
|
||||
.sr-only-focusable { .sr-only-focusable(); }
|
|
@ -2,20 +2,29 @@
|
|||
// --------------------------
|
||||
|
||||
@fa-font-path: "../fonts";
|
||||
//@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts"; // for referencing Bootstrap CDN font files directly
|
||||
@fa-font-size-base: 14px;
|
||||
@fa-line-height-base: 1;
|
||||
//@fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts"; // for referencing Bootstrap CDN font files directly
|
||||
@fa-css-prefix: fa;
|
||||
@fa-version: "4.2.0";
|
||||
@fa-version: "4.7.0";
|
||||
@fa-border-color: #eee;
|
||||
@fa-inverse: #fff;
|
||||
@fa-li-width: (30em / 14);
|
||||
|
||||
@fa-var-500px: "\f26e";
|
||||
@fa-var-address-book: "\f2b9";
|
||||
@fa-var-address-book-o: "\f2ba";
|
||||
@fa-var-address-card: "\f2bb";
|
||||
@fa-var-address-card-o: "\f2bc";
|
||||
@fa-var-adjust: "\f042";
|
||||
@fa-var-adn: "\f170";
|
||||
@fa-var-align-center: "\f037";
|
||||
@fa-var-align-justify: "\f039";
|
||||
@fa-var-align-left: "\f036";
|
||||
@fa-var-align-right: "\f038";
|
||||
@fa-var-amazon: "\f270";
|
||||
@fa-var-ambulance: "\f0f9";
|
||||
@fa-var-american-sign-language-interpreting: "\f2a3";
|
||||
@fa-var-anchor: "\f13d";
|
||||
@fa-var-android: "\f17b";
|
||||
@fa-var-angellist: "\f209";
|
||||
|
@ -46,16 +55,35 @@
|
|||
@fa-var-arrows-alt: "\f0b2";
|
||||
@fa-var-arrows-h: "\f07e";
|
||||
@fa-var-arrows-v: "\f07d";
|
||||
@fa-var-asl-interpreting: "\f2a3";
|
||||
@fa-var-assistive-listening-systems: "\f2a2";
|
||||
@fa-var-asterisk: "\f069";
|
||||
@fa-var-at: "\f1fa";
|
||||
@fa-var-audio-description: "\f29e";
|
||||
@fa-var-automobile: "\f1b9";
|
||||
@fa-var-backward: "\f04a";
|
||||
@fa-var-balance-scale: "\f24e";
|
||||
@fa-var-ban: "\f05e";
|
||||
@fa-var-bandcamp: "\f2d5";
|
||||
@fa-var-bank: "\f19c";
|
||||
@fa-var-bar-chart: "\f080";
|
||||
@fa-var-bar-chart-o: "\f080";
|
||||
@fa-var-barcode: "\f02a";
|
||||
@fa-var-bars: "\f0c9";
|
||||
@fa-var-bath: "\f2cd";
|
||||
@fa-var-bathtub: "\f2cd";
|
||||
@fa-var-battery: "\f240";
|
||||
@fa-var-battery-0: "\f244";
|
||||
@fa-var-battery-1: "\f243";
|
||||
@fa-var-battery-2: "\f242";
|
||||
@fa-var-battery-3: "\f241";
|
||||
@fa-var-battery-4: "\f240";
|
||||
@fa-var-battery-empty: "\f244";
|
||||
@fa-var-battery-full: "\f240";
|
||||
@fa-var-battery-half: "\f242";
|
||||
@fa-var-battery-quarter: "\f243";
|
||||
@fa-var-battery-three-quarters: "\f241";
|
||||
@fa-var-bed: "\f236";
|
||||
@fa-var-beer: "\f0fc";
|
||||
@fa-var-behance: "\f1b4";
|
||||
@fa-var-behance-square: "\f1b5";
|
||||
|
@ -69,12 +97,17 @@
|
|||
@fa-var-bitbucket: "\f171";
|
||||
@fa-var-bitbucket-square: "\f172";
|
||||
@fa-var-bitcoin: "\f15a";
|
||||
@fa-var-black-tie: "\f27e";
|
||||
@fa-var-blind: "\f29d";
|
||||
@fa-var-bluetooth: "\f293";
|
||||
@fa-var-bluetooth-b: "\f294";
|
||||
@fa-var-bold: "\f032";
|
||||
@fa-var-bolt: "\f0e7";
|
||||
@fa-var-bomb: "\f1e2";
|
||||
@fa-var-book: "\f02d";
|
||||
@fa-var-bookmark: "\f02e";
|
||||
@fa-var-bookmark-o: "\f097";
|
||||
@fa-var-braille: "\f2a1";
|
||||
@fa-var-briefcase: "\f0b1";
|
||||
@fa-var-btc: "\f15a";
|
||||
@fa-var-bug: "\f188";
|
||||
|
@ -83,10 +116,15 @@
|
|||
@fa-var-bullhorn: "\f0a1";
|
||||
@fa-var-bullseye: "\f140";
|
||||
@fa-var-bus: "\f207";
|
||||
@fa-var-buysellads: "\f20d";
|
||||
@fa-var-cab: "\f1ba";
|
||||
@fa-var-calculator: "\f1ec";
|
||||
@fa-var-calendar: "\f073";
|
||||
@fa-var-calendar-check-o: "\f274";
|
||||
@fa-var-calendar-minus-o: "\f272";
|
||||
@fa-var-calendar-o: "\f133";
|
||||
@fa-var-calendar-plus-o: "\f271";
|
||||
@fa-var-calendar-times-o: "\f273";
|
||||
@fa-var-camera: "\f030";
|
||||
@fa-var-camera-retro: "\f083";
|
||||
@fa-var-car: "\f1b9";
|
||||
|
@ -98,9 +136,13 @@
|
|||
@fa-var-caret-square-o-right: "\f152";
|
||||
@fa-var-caret-square-o-up: "\f151";
|
||||
@fa-var-caret-up: "\f0d8";
|
||||
@fa-var-cart-arrow-down: "\f218";
|
||||
@fa-var-cart-plus: "\f217";
|
||||
@fa-var-cc: "\f20a";
|
||||
@fa-var-cc-amex: "\f1f3";
|
||||
@fa-var-cc-diners-club: "\f24c";
|
||||
@fa-var-cc-discover: "\f1f2";
|
||||
@fa-var-cc-jcb: "\f24b";
|
||||
@fa-var-cc-mastercard: "\f1f1";
|
||||
@fa-var-cc-paypal: "\f1f4";
|
||||
@fa-var-cc-stripe: "\f1f5";
|
||||
|
@ -122,12 +164,14 @@
|
|||
@fa-var-chevron-right: "\f054";
|
||||
@fa-var-chevron-up: "\f077";
|
||||
@fa-var-child: "\f1ae";
|
||||
@fa-var-chrome: "\f268";
|
||||
@fa-var-circle: "\f111";
|
||||
@fa-var-circle-o: "\f10c";
|
||||
@fa-var-circle-o-notch: "\f1ce";
|
||||
@fa-var-circle-thin: "\f1db";
|
||||
@fa-var-clipboard: "\f0ea";
|
||||
@fa-var-clock-o: "\f017";
|
||||
@fa-var-clone: "\f24d";
|
||||
@fa-var-close: "\f00d";
|
||||
@fa-var-cloud: "\f0c2";
|
||||
@fa-var-cloud-download: "\f0ed";
|
||||
|
@ -136,19 +180,26 @@
|
|||
@fa-var-code: "\f121";
|
||||
@fa-var-code-fork: "\f126";
|
||||
@fa-var-codepen: "\f1cb";
|
||||
@fa-var-codiepie: "\f284";
|
||||
@fa-var-coffee: "\f0f4";
|
||||
@fa-var-cog: "\f013";
|
||||
@fa-var-cogs: "\f085";
|
||||
@fa-var-columns: "\f0db";
|
||||
@fa-var-comment: "\f075";
|
||||
@fa-var-comment-o: "\f0e5";
|
||||
@fa-var-commenting: "\f27a";
|
||||
@fa-var-commenting-o: "\f27b";
|
||||
@fa-var-comments: "\f086";
|
||||
@fa-var-comments-o: "\f0e6";
|
||||
@fa-var-compass: "\f14e";
|
||||
@fa-var-compress: "\f066";
|
||||
@fa-var-connectdevelop: "\f20e";
|
||||
@fa-var-contao: "\f26d";
|
||||
@fa-var-copy: "\f0c5";
|
||||
@fa-var-copyright: "\f1f9";
|
||||
@fa-var-creative-commons: "\f25e";
|
||||
@fa-var-credit-card: "\f09d";
|
||||
@fa-var-credit-card-alt: "\f283";
|
||||
@fa-var-crop: "\f125";
|
||||
@fa-var-crosshairs: "\f05b";
|
||||
@fa-var-css3: "\f13c";
|
||||
|
@ -157,27 +208,39 @@
|
|||
@fa-var-cut: "\f0c4";
|
||||
@fa-var-cutlery: "\f0f5";
|
||||
@fa-var-dashboard: "\f0e4";
|
||||
@fa-var-dashcube: "\f210";
|
||||
@fa-var-database: "\f1c0";
|
||||
@fa-var-deaf: "\f2a4";
|
||||
@fa-var-deafness: "\f2a4";
|
||||
@fa-var-dedent: "\f03b";
|
||||
@fa-var-delicious: "\f1a5";
|
||||
@fa-var-desktop: "\f108";
|
||||
@fa-var-deviantart: "\f1bd";
|
||||
@fa-var-diamond: "\f219";
|
||||
@fa-var-digg: "\f1a6";
|
||||
@fa-var-dollar: "\f155";
|
||||
@fa-var-dot-circle-o: "\f192";
|
||||
@fa-var-download: "\f019";
|
||||
@fa-var-dribbble: "\f17d";
|
||||
@fa-var-drivers-license: "\f2c2";
|
||||
@fa-var-drivers-license-o: "\f2c3";
|
||||
@fa-var-dropbox: "\f16b";
|
||||
@fa-var-drupal: "\f1a9";
|
||||
@fa-var-edge: "\f282";
|
||||
@fa-var-edit: "\f044";
|
||||
@fa-var-eercast: "\f2da";
|
||||
@fa-var-eject: "\f052";
|
||||
@fa-var-ellipsis-h: "\f141";
|
||||
@fa-var-ellipsis-v: "\f142";
|
||||
@fa-var-empire: "\f1d1";
|
||||
@fa-var-envelope: "\f0e0";
|
||||
@fa-var-envelope-o: "\f003";
|
||||
@fa-var-envelope-open: "\f2b6";
|
||||
@fa-var-envelope-open-o: "\f2b7";
|
||||
@fa-var-envelope-square: "\f199";
|
||||
@fa-var-envira: "\f299";
|
||||
@fa-var-eraser: "\f12d";
|
||||
@fa-var-etsy: "\f2d7";
|
||||
@fa-var-eur: "\f153";
|
||||
@fa-var-euro: "\f153";
|
||||
@fa-var-exchange: "\f0ec";
|
||||
|
@ -185,16 +248,21 @@
|
|||
@fa-var-exclamation-circle: "\f06a";
|
||||
@fa-var-exclamation-triangle: "\f071";
|
||||
@fa-var-expand: "\f065";
|
||||
@fa-var-expeditedssl: "\f23e";
|
||||
@fa-var-external-link: "\f08e";
|
||||
@fa-var-external-link-square: "\f14c";
|
||||
@fa-var-eye: "\f06e";
|
||||
@fa-var-eye-slash: "\f070";
|
||||
@fa-var-eyedropper: "\f1fb";
|
||||
@fa-var-fa: "\f2b4";
|
||||
@fa-var-facebook: "\f09a";
|
||||
@fa-var-facebook-f: "\f09a";
|
||||
@fa-var-facebook-official: "\f230";
|
||||
@fa-var-facebook-square: "\f082";
|
||||
@fa-var-fast-backward: "\f049";
|
||||
@fa-var-fast-forward: "\f050";
|
||||
@fa-var-fax: "\f1ac";
|
||||
@fa-var-feed: "\f09e";
|
||||
@fa-var-female: "\f182";
|
||||
@fa-var-fighter-jet: "\f0fb";
|
||||
@fa-var-file: "\f15b";
|
||||
|
@ -220,6 +288,8 @@
|
|||
@fa-var-filter: "\f0b0";
|
||||
@fa-var-fire: "\f06d";
|
||||
@fa-var-fire-extinguisher: "\f134";
|
||||
@fa-var-firefox: "\f269";
|
||||
@fa-var-first-order: "\f2b0";
|
||||
@fa-var-flag: "\f024";
|
||||
@fa-var-flag-checkered: "\f11e";
|
||||
@fa-var-flag-o: "\f11d";
|
||||
|
@ -232,8 +302,13 @@
|
|||
@fa-var-folder-open: "\f07c";
|
||||
@fa-var-folder-open-o: "\f115";
|
||||
@fa-var-font: "\f031";
|
||||
@fa-var-font-awesome: "\f2b4";
|
||||
@fa-var-fonticons: "\f280";
|
||||
@fa-var-fort-awesome: "\f286";
|
||||
@fa-var-forumbee: "\f211";
|
||||
@fa-var-forward: "\f04e";
|
||||
@fa-var-foursquare: "\f180";
|
||||
@fa-var-free-code-camp: "\f2c5";
|
||||
@fa-var-frown-o: "\f119";
|
||||
@fa-var-futbol-o: "\f1e3";
|
||||
@fa-var-gamepad: "\f11b";
|
||||
|
@ -242,45 +317,87 @@
|
|||
@fa-var-ge: "\f1d1";
|
||||
@fa-var-gear: "\f013";
|
||||
@fa-var-gears: "\f085";
|
||||
@fa-var-genderless: "\f22d";
|
||||
@fa-var-get-pocket: "\f265";
|
||||
@fa-var-gg: "\f260";
|
||||
@fa-var-gg-circle: "\f261";
|
||||
@fa-var-gift: "\f06b";
|
||||
@fa-var-git: "\f1d3";
|
||||
@fa-var-git-square: "\f1d2";
|
||||
@fa-var-github: "\f09b";
|
||||
@fa-var-github-alt: "\f113";
|
||||
@fa-var-github-square: "\f092";
|
||||
@fa-var-gitlab: "\f296";
|
||||
@fa-var-gittip: "\f184";
|
||||
@fa-var-glass: "\f000";
|
||||
@fa-var-glide: "\f2a5";
|
||||
@fa-var-glide-g: "\f2a6";
|
||||
@fa-var-globe: "\f0ac";
|
||||
@fa-var-google: "\f1a0";
|
||||
@fa-var-google-plus: "\f0d5";
|
||||
@fa-var-google-plus-circle: "\f2b3";
|
||||
@fa-var-google-plus-official: "\f2b3";
|
||||
@fa-var-google-plus-square: "\f0d4";
|
||||
@fa-var-google-wallet: "\f1ee";
|
||||
@fa-var-graduation-cap: "\f19d";
|
||||
@fa-var-gratipay: "\f184";
|
||||
@fa-var-grav: "\f2d6";
|
||||
@fa-var-group: "\f0c0";
|
||||
@fa-var-h-square: "\f0fd";
|
||||
@fa-var-hacker-news: "\f1d4";
|
||||
@fa-var-hand-grab-o: "\f255";
|
||||
@fa-var-hand-lizard-o: "\f258";
|
||||
@fa-var-hand-o-down: "\f0a7";
|
||||
@fa-var-hand-o-left: "\f0a5";
|
||||
@fa-var-hand-o-right: "\f0a4";
|
||||
@fa-var-hand-o-up: "\f0a6";
|
||||
@fa-var-hand-paper-o: "\f256";
|
||||
@fa-var-hand-peace-o: "\f25b";
|
||||
@fa-var-hand-pointer-o: "\f25a";
|
||||
@fa-var-hand-rock-o: "\f255";
|
||||
@fa-var-hand-scissors-o: "\f257";
|
||||
@fa-var-hand-spock-o: "\f259";
|
||||
@fa-var-hand-stop-o: "\f256";
|
||||
@fa-var-handshake-o: "\f2b5";
|
||||
@fa-var-hard-of-hearing: "\f2a4";
|
||||
@fa-var-hashtag: "\f292";
|
||||
@fa-var-hdd-o: "\f0a0";
|
||||
@fa-var-header: "\f1dc";
|
||||
@fa-var-headphones: "\f025";
|
||||
@fa-var-heart: "\f004";
|
||||
@fa-var-heart-o: "\f08a";
|
||||
@fa-var-heartbeat: "\f21e";
|
||||
@fa-var-history: "\f1da";
|
||||
@fa-var-home: "\f015";
|
||||
@fa-var-hospital-o: "\f0f8";
|
||||
@fa-var-hotel: "\f236";
|
||||
@fa-var-hourglass: "\f254";
|
||||
@fa-var-hourglass-1: "\f251";
|
||||
@fa-var-hourglass-2: "\f252";
|
||||
@fa-var-hourglass-3: "\f253";
|
||||
@fa-var-hourglass-end: "\f253";
|
||||
@fa-var-hourglass-half: "\f252";
|
||||
@fa-var-hourglass-o: "\f250";
|
||||
@fa-var-hourglass-start: "\f251";
|
||||
@fa-var-houzz: "\f27c";
|
||||
@fa-var-html5: "\f13b";
|
||||
@fa-var-i-cursor: "\f246";
|
||||
@fa-var-id-badge: "\f2c1";
|
||||
@fa-var-id-card: "\f2c2";
|
||||
@fa-var-id-card-o: "\f2c3";
|
||||
@fa-var-ils: "\f20b";
|
||||
@fa-var-image: "\f03e";
|
||||
@fa-var-imdb: "\f2d8";
|
||||
@fa-var-inbox: "\f01c";
|
||||
@fa-var-indent: "\f03c";
|
||||
@fa-var-industry: "\f275";
|
||||
@fa-var-info: "\f129";
|
||||
@fa-var-info-circle: "\f05a";
|
||||
@fa-var-inr: "\f156";
|
||||
@fa-var-instagram: "\f16d";
|
||||
@fa-var-institution: "\f19c";
|
||||
@fa-var-internet-explorer: "\f26b";
|
||||
@fa-var-intersex: "\f224";
|
||||
@fa-var-ioxhost: "\f208";
|
||||
@fa-var-italic: "\f033";
|
||||
@fa-var-joomla: "\f1aa";
|
||||
|
@ -294,6 +411,7 @@
|
|||
@fa-var-lastfm: "\f202";
|
||||
@fa-var-lastfm-square: "\f203";
|
||||
@fa-var-leaf: "\f06c";
|
||||
@fa-var-leanpub: "\f212";
|
||||
@fa-var-legal: "\f0e3";
|
||||
@fa-var-lemon-o: "\f094";
|
||||
@fa-var-level-down: "\f149";
|
||||
|
@ -307,6 +425,7 @@
|
|||
@fa-var-link: "\f0c1";
|
||||
@fa-var-linkedin: "\f0e1";
|
||||
@fa-var-linkedin-square: "\f08c";
|
||||
@fa-var-linode: "\f2b8";
|
||||
@fa-var-linux: "\f17c";
|
||||
@fa-var-list: "\f03a";
|
||||
@fa-var-list-alt: "\f022";
|
||||
|
@ -318,32 +437,58 @@
|
|||
@fa-var-long-arrow-left: "\f177";
|
||||
@fa-var-long-arrow-right: "\f178";
|
||||
@fa-var-long-arrow-up: "\f176";
|
||||
@fa-var-low-vision: "\f2a8";
|
||||
@fa-var-magic: "\f0d0";
|
||||
@fa-var-magnet: "\f076";
|
||||
@fa-var-mail-forward: "\f064";
|
||||
@fa-var-mail-reply: "\f112";
|
||||
@fa-var-mail-reply-all: "\f122";
|
||||
@fa-var-male: "\f183";
|
||||
@fa-var-map: "\f279";
|
||||
@fa-var-map-marker: "\f041";
|
||||
@fa-var-map-o: "\f278";
|
||||
@fa-var-map-pin: "\f276";
|
||||
@fa-var-map-signs: "\f277";
|
||||
@fa-var-mars: "\f222";
|
||||
@fa-var-mars-double: "\f227";
|
||||
@fa-var-mars-stroke: "\f229";
|
||||
@fa-var-mars-stroke-h: "\f22b";
|
||||
@fa-var-mars-stroke-v: "\f22a";
|
||||
@fa-var-maxcdn: "\f136";
|
||||
@fa-var-meanpath: "\f20c";
|
||||
@fa-var-medium: "\f23a";
|
||||
@fa-var-medkit: "\f0fa";
|
||||
@fa-var-meetup: "\f2e0";
|
||||
@fa-var-meh-o: "\f11a";
|
||||
@fa-var-mercury: "\f223";
|
||||
@fa-var-microchip: "\f2db";
|
||||
@fa-var-microphone: "\f130";
|
||||
@fa-var-microphone-slash: "\f131";
|
||||
@fa-var-minus: "\f068";
|
||||
@fa-var-minus-circle: "\f056";
|
||||
@fa-var-minus-square: "\f146";
|
||||
@fa-var-minus-square-o: "\f147";
|
||||
@fa-var-mixcloud: "\f289";
|
||||
@fa-var-mobile: "\f10b";
|
||||
@fa-var-mobile-phone: "\f10b";
|
||||
@fa-var-modx: "\f285";
|
||||
@fa-var-money: "\f0d6";
|
||||
@fa-var-moon-o: "\f186";
|
||||
@fa-var-mortar-board: "\f19d";
|
||||
@fa-var-motorcycle: "\f21c";
|
||||
@fa-var-mouse-pointer: "\f245";
|
||||
@fa-var-music: "\f001";
|
||||
@fa-var-navicon: "\f0c9";
|
||||
@fa-var-neuter: "\f22c";
|
||||
@fa-var-newspaper-o: "\f1ea";
|
||||
@fa-var-object-group: "\f247";
|
||||
@fa-var-object-ungroup: "\f248";
|
||||
@fa-var-odnoklassniki: "\f263";
|
||||
@fa-var-odnoklassniki-square: "\f264";
|
||||
@fa-var-opencart: "\f23d";
|
||||
@fa-var-openid: "\f19b";
|
||||
@fa-var-opera: "\f26a";
|
||||
@fa-var-optin-monster: "\f23c";
|
||||
@fa-var-outdent: "\f03b";
|
||||
@fa-var-pagelines: "\f18c";
|
||||
@fa-var-paint-brush: "\f1fc";
|
||||
|
@ -353,19 +498,24 @@
|
|||
@fa-var-paragraph: "\f1dd";
|
||||
@fa-var-paste: "\f0ea";
|
||||
@fa-var-pause: "\f04c";
|
||||
@fa-var-pause-circle: "\f28b";
|
||||
@fa-var-pause-circle-o: "\f28c";
|
||||
@fa-var-paw: "\f1b0";
|
||||
@fa-var-paypal: "\f1ed";
|
||||
@fa-var-pencil: "\f040";
|
||||
@fa-var-pencil-square: "\f14b";
|
||||
@fa-var-pencil-square-o: "\f044";
|
||||
@fa-var-percent: "\f295";
|
||||
@fa-var-phone: "\f095";
|
||||
@fa-var-phone-square: "\f098";
|
||||
@fa-var-photo: "\f03e";
|
||||
@fa-var-picture-o: "\f03e";
|
||||
@fa-var-pie-chart: "\f200";
|
||||
@fa-var-pied-piper: "\f1a7";
|
||||
@fa-var-pied-piper: "\f2ae";
|
||||
@fa-var-pied-piper-alt: "\f1a8";
|
||||
@fa-var-pied-piper-pp: "\f1a7";
|
||||
@fa-var-pinterest: "\f0d2";
|
||||
@fa-var-pinterest-p: "\f231";
|
||||
@fa-var-pinterest-square: "\f0d3";
|
||||
@fa-var-plane: "\f072";
|
||||
@fa-var-play: "\f04b";
|
||||
|
@ -376,28 +526,36 @@
|
|||
@fa-var-plus-circle: "\f055";
|
||||
@fa-var-plus-square: "\f0fe";
|
||||
@fa-var-plus-square-o: "\f196";
|
||||
@fa-var-podcast: "\f2ce";
|
||||
@fa-var-power-off: "\f011";
|
||||
@fa-var-print: "\f02f";
|
||||
@fa-var-product-hunt: "\f288";
|
||||
@fa-var-puzzle-piece: "\f12e";
|
||||
@fa-var-qq: "\f1d6";
|
||||
@fa-var-qrcode: "\f029";
|
||||
@fa-var-question: "\f128";
|
||||
@fa-var-question-circle: "\f059";
|
||||
@fa-var-question-circle-o: "\f29c";
|
||||
@fa-var-quora: "\f2c4";
|
||||
@fa-var-quote-left: "\f10d";
|
||||
@fa-var-quote-right: "\f10e";
|
||||
@fa-var-ra: "\f1d0";
|
||||
@fa-var-random: "\f074";
|
||||
@fa-var-ravelry: "\f2d9";
|
||||
@fa-var-rebel: "\f1d0";
|
||||
@fa-var-recycle: "\f1b8";
|
||||
@fa-var-reddit: "\f1a1";
|
||||
@fa-var-reddit-alien: "\f281";
|
||||
@fa-var-reddit-square: "\f1a2";
|
||||
@fa-var-refresh: "\f021";
|
||||
@fa-var-registered: "\f25d";
|
||||
@fa-var-remove: "\f00d";
|
||||
@fa-var-renren: "\f18b";
|
||||
@fa-var-reorder: "\f0c9";
|
||||
@fa-var-repeat: "\f01e";
|
||||
@fa-var-reply: "\f112";
|
||||
@fa-var-reply-all: "\f122";
|
||||
@fa-var-resistance: "\f1d0";
|
||||
@fa-var-retweet: "\f079";
|
||||
@fa-var-rmb: "\f157";
|
||||
@fa-var-road: "\f018";
|
||||
|
@ -410,13 +568,18 @@
|
|||
@fa-var-rub: "\f158";
|
||||
@fa-var-ruble: "\f158";
|
||||
@fa-var-rupee: "\f156";
|
||||
@fa-var-s15: "\f2cd";
|
||||
@fa-var-safari: "\f267";
|
||||
@fa-var-save: "\f0c7";
|
||||
@fa-var-scissors: "\f0c4";
|
||||
@fa-var-scribd: "\f28a";
|
||||
@fa-var-search: "\f002";
|
||||
@fa-var-search-minus: "\f010";
|
||||
@fa-var-search-plus: "\f00e";
|
||||
@fa-var-sellsy: "\f213";
|
||||
@fa-var-send: "\f1d8";
|
||||
@fa-var-send-o: "\f1d9";
|
||||
@fa-var-server: "\f233";
|
||||
@fa-var-share: "\f064";
|
||||
@fa-var-share-alt: "\f1e0";
|
||||
@fa-var-share-alt-square: "\f1e1";
|
||||
|
@ -425,16 +588,29 @@
|
|||
@fa-var-shekel: "\f20b";
|
||||
@fa-var-sheqel: "\f20b";
|
||||
@fa-var-shield: "\f132";
|
||||
@fa-var-ship: "\f21a";
|
||||
@fa-var-shirtsinbulk: "\f214";
|
||||
@fa-var-shopping-bag: "\f290";
|
||||
@fa-var-shopping-basket: "\f291";
|
||||
@fa-var-shopping-cart: "\f07a";
|
||||
@fa-var-shower: "\f2cc";
|
||||
@fa-var-sign-in: "\f090";
|
||||
@fa-var-sign-language: "\f2a7";
|
||||
@fa-var-sign-out: "\f08b";
|
||||
@fa-var-signal: "\f012";
|
||||
@fa-var-signing: "\f2a7";
|
||||
@fa-var-simplybuilt: "\f215";
|
||||
@fa-var-sitemap: "\f0e8";
|
||||
@fa-var-skyatlas: "\f216";
|
||||
@fa-var-skype: "\f17e";
|
||||
@fa-var-slack: "\f198";
|
||||
@fa-var-sliders: "\f1de";
|
||||
@fa-var-slideshare: "\f1e7";
|
||||
@fa-var-smile-o: "\f118";
|
||||
@fa-var-snapchat: "\f2ab";
|
||||
@fa-var-snapchat-ghost: "\f2ac";
|
||||
@fa-var-snapchat-square: "\f2ad";
|
||||
@fa-var-snowflake-o: "\f2dc";
|
||||
@fa-var-soccer-ball-o: "\f1e3";
|
||||
@fa-var-sort: "\f0dc";
|
||||
@fa-var-sort-alpha-asc: "\f15d";
|
||||
|
@ -467,13 +643,20 @@
|
|||
@fa-var-step-backward: "\f048";
|
||||
@fa-var-step-forward: "\f051";
|
||||
@fa-var-stethoscope: "\f0f1";
|
||||
@fa-var-sticky-note: "\f249";
|
||||
@fa-var-sticky-note-o: "\f24a";
|
||||
@fa-var-stop: "\f04d";
|
||||
@fa-var-stop-circle: "\f28d";
|
||||
@fa-var-stop-circle-o: "\f28e";
|
||||
@fa-var-street-view: "\f21d";
|
||||
@fa-var-strikethrough: "\f0cc";
|
||||
@fa-var-stumbleupon: "\f1a4";
|
||||
@fa-var-stumbleupon-circle: "\f1a3";
|
||||
@fa-var-subscript: "\f12c";
|
||||
@fa-var-subway: "\f239";
|
||||
@fa-var-suitcase: "\f0f2";
|
||||
@fa-var-sun-o: "\f185";
|
||||
@fa-var-superpowers: "\f2dd";
|
||||
@fa-var-superscript: "\f12b";
|
||||
@fa-var-support: "\f1cd";
|
||||
@fa-var-table: "\f0ce";
|
||||
|
@ -483,6 +666,8 @@
|
|||
@fa-var-tags: "\f02c";
|
||||
@fa-var-tasks: "\f0ae";
|
||||
@fa-var-taxi: "\f1ba";
|
||||
@fa-var-telegram: "\f2c6";
|
||||
@fa-var-television: "\f26c";
|
||||
@fa-var-tencent-weibo: "\f1d5";
|
||||
@fa-var-terminal: "\f120";
|
||||
@fa-var-text-height: "\f034";
|
||||
|
@ -490,6 +675,18 @@
|
|||
@fa-var-th: "\f00a";
|
||||
@fa-var-th-large: "\f009";
|
||||
@fa-var-th-list: "\f00b";
|
||||
@fa-var-themeisle: "\f2b2";
|
||||
@fa-var-thermometer: "\f2c7";
|
||||
@fa-var-thermometer-0: "\f2cb";
|
||||
@fa-var-thermometer-1: "\f2ca";
|
||||
@fa-var-thermometer-2: "\f2c9";
|
||||
@fa-var-thermometer-3: "\f2c8";
|
||||
@fa-var-thermometer-4: "\f2c7";
|
||||
@fa-var-thermometer-empty: "\f2cb";
|
||||
@fa-var-thermometer-full: "\f2c7";
|
||||
@fa-var-thermometer-half: "\f2c9";
|
||||
@fa-var-thermometer-quarter: "\f2ca";
|
||||
@fa-var-thermometer-three-quarters: "\f2c8";
|
||||
@fa-var-thumb-tack: "\f08d";
|
||||
@fa-var-thumbs-down: "\f165";
|
||||
@fa-var-thumbs-o-down: "\f088";
|
||||
|
@ -499,6 +696,8 @@
|
|||
@fa-var-times: "\f00d";
|
||||
@fa-var-times-circle: "\f057";
|
||||
@fa-var-times-circle-o: "\f05c";
|
||||
@fa-var-times-rectangle: "\f2d3";
|
||||
@fa-var-times-rectangle-o: "\f2d4";
|
||||
@fa-var-tint: "\f043";
|
||||
@fa-var-toggle-down: "\f150";
|
||||
@fa-var-toggle-left: "\f191";
|
||||
|
@ -506,10 +705,15 @@
|
|||
@fa-var-toggle-on: "\f205";
|
||||
@fa-var-toggle-right: "\f152";
|
||||
@fa-var-toggle-up: "\f151";
|
||||
@fa-var-trademark: "\f25c";
|
||||
@fa-var-train: "\f238";
|
||||
@fa-var-transgender: "\f224";
|
||||
@fa-var-transgender-alt: "\f225";
|
||||
@fa-var-trash: "\f1f8";
|
||||
@fa-var-trash-o: "\f014";
|
||||
@fa-var-tree: "\f1bb";
|
||||
@fa-var-trello: "\f181";
|
||||
@fa-var-tripadvisor: "\f262";
|
||||
@fa-var-trophy: "\f091";
|
||||
@fa-var-truck: "\f0d1";
|
||||
@fa-var-try: "\f195";
|
||||
|
@ -517,26 +721,45 @@
|
|||
@fa-var-tumblr: "\f173";
|
||||
@fa-var-tumblr-square: "\f174";
|
||||
@fa-var-turkish-lira: "\f195";
|
||||
@fa-var-tv: "\f26c";
|
||||
@fa-var-twitch: "\f1e8";
|
||||
@fa-var-twitter: "\f099";
|
||||
@fa-var-twitter-square: "\f081";
|
||||
@fa-var-umbrella: "\f0e9";
|
||||
@fa-var-underline: "\f0cd";
|
||||
@fa-var-undo: "\f0e2";
|
||||
@fa-var-universal-access: "\f29a";
|
||||
@fa-var-university: "\f19c";
|
||||
@fa-var-unlink: "\f127";
|
||||
@fa-var-unlock: "\f09c";
|
||||
@fa-var-unlock-alt: "\f13e";
|
||||
@fa-var-unsorted: "\f0dc";
|
||||
@fa-var-upload: "\f093";
|
||||
@fa-var-usb: "\f287";
|
||||
@fa-var-usd: "\f155";
|
||||
@fa-var-user: "\f007";
|
||||
@fa-var-user-circle: "\f2bd";
|
||||
@fa-var-user-circle-o: "\f2be";
|
||||
@fa-var-user-md: "\f0f0";
|
||||
@fa-var-user-o: "\f2c0";
|
||||
@fa-var-user-plus: "\f234";
|
||||
@fa-var-user-secret: "\f21b";
|
||||
@fa-var-user-times: "\f235";
|
||||
@fa-var-users: "\f0c0";
|
||||
@fa-var-vcard: "\f2bb";
|
||||
@fa-var-vcard-o: "\f2bc";
|
||||
@fa-var-venus: "\f221";
|
||||
@fa-var-venus-double: "\f226";
|
||||
@fa-var-venus-mars: "\f228";
|
||||
@fa-var-viacoin: "\f237";
|
||||
@fa-var-viadeo: "\f2a9";
|
||||
@fa-var-viadeo-square: "\f2aa";
|
||||
@fa-var-video-camera: "\f03d";
|
||||
@fa-var-vimeo: "\f27d";
|
||||
@fa-var-vimeo-square: "\f194";
|
||||
@fa-var-vine: "\f1ca";
|
||||
@fa-var-vk: "\f189";
|
||||
@fa-var-volume-control-phone: "\f2a0";
|
||||
@fa-var-volume-down: "\f027";
|
||||
@fa-var-volume-off: "\f026";
|
||||
@fa-var-volume-up: "\f028";
|
||||
|
@ -544,17 +767,33 @@
|
|||
@fa-var-wechat: "\f1d7";
|
||||
@fa-var-weibo: "\f18a";
|
||||
@fa-var-weixin: "\f1d7";
|
||||
@fa-var-whatsapp: "\f232";
|
||||
@fa-var-wheelchair: "\f193";
|
||||
@fa-var-wheelchair-alt: "\f29b";
|
||||
@fa-var-wifi: "\f1eb";
|
||||
@fa-var-wikipedia-w: "\f266";
|
||||
@fa-var-window-close: "\f2d3";
|
||||
@fa-var-window-close-o: "\f2d4";
|
||||
@fa-var-window-maximize: "\f2d0";
|
||||
@fa-var-window-minimize: "\f2d1";
|
||||
@fa-var-window-restore: "\f2d2";
|
||||
@fa-var-windows: "\f17a";
|
||||
@fa-var-won: "\f159";
|
||||
@fa-var-wordpress: "\f19a";
|
||||
@fa-var-wpbeginner: "\f297";
|
||||
@fa-var-wpexplorer: "\f2de";
|
||||
@fa-var-wpforms: "\f298";
|
||||
@fa-var-wrench: "\f0ad";
|
||||
@fa-var-xing: "\f168";
|
||||
@fa-var-xing-square: "\f169";
|
||||
@fa-var-y-combinator: "\f23b";
|
||||
@fa-var-y-combinator-square: "\f1d4";
|
||||
@fa-var-yahoo: "\f19e";
|
||||
@fa-var-yc: "\f23b";
|
||||
@fa-var-yc-square: "\f1d4";
|
||||
@fa-var-yelp: "\f1e9";
|
||||
@fa-var-yen: "\f157";
|
||||
@fa-var-yoast: "\f2b1";
|
||||
@fa-var-youtube: "\f167";
|
||||
@fa-var-youtube-play: "\f16a";
|
||||
@fa-var-youtube-square: "\f166";
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
animation: fa-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pulse {
|
||||
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||
animation: fa-spin 1s infinite steps(8);
|
||||
}
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
|
@ -7,6 +7,15 @@
|
|||
border-radius: .1em;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-left { float: left; }
|
||||
.#{$fa-css-prefix}-pull-right { float: right; }
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
&.#{$fa-css-prefix}-pull-left { margin-right: .3em; }
|
||||
&.#{$fa-css-prefix}-pull-right { margin-left: .3em; }
|
||||
}
|
||||
|
||||
/* Deprecated as of 4.4.0 */
|
||||
.pull-right { float: right; }
|
||||
.pull-left { float: left; }
|
||||
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
.#{$fa-css-prefix} {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
|
||||
font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
}
|
||||
|
|
|
@ -158,10 +158,12 @@
|
|||
.#{$fa-css-prefix}-bookmark-o:before { content: $fa-var-bookmark-o; }
|
||||
.#{$fa-css-prefix}-phone-square:before { content: $fa-var-phone-square; }
|
||||
.#{$fa-css-prefix}-twitter:before { content: $fa-var-twitter; }
|
||||
.#{$fa-css-prefix}-facebook-f:before,
|
||||
.#{$fa-css-prefix}-facebook:before { content: $fa-var-facebook; }
|
||||
.#{$fa-css-prefix}-github:before { content: $fa-var-github; }
|
||||
.#{$fa-css-prefix}-unlock:before { content: $fa-var-unlock; }
|
||||
.#{$fa-css-prefix}-credit-card:before { content: $fa-var-credit-card; }
|
||||
.#{$fa-css-prefix}-feed:before,
|
||||
.#{$fa-css-prefix}-rss:before { content: $fa-var-rss; }
|
||||
.#{$fa-css-prefix}-hdd-o:before { content: $fa-var-hdd-o; }
|
||||
.#{$fa-css-prefix}-bullhorn:before { content: $fa-var-bullhorn; }
|
||||
|
@ -397,7 +399,8 @@
|
|||
.#{$fa-css-prefix}-trello:before { content: $fa-var-trello; }
|
||||
.#{$fa-css-prefix}-female:before { content: $fa-var-female; }
|
||||
.#{$fa-css-prefix}-male:before { content: $fa-var-male; }
|
||||
.#{$fa-css-prefix}-gittip:before { content: $fa-var-gittip; }
|
||||
.#{$fa-css-prefix}-gittip:before,
|
||||
.#{$fa-css-prefix}-gratipay:before { content: $fa-var-gratipay; }
|
||||
.#{$fa-css-prefix}-sun-o:before { content: $fa-var-sun-o; }
|
||||
.#{$fa-css-prefix}-moon-o:before { content: $fa-var-moon-o; }
|
||||
.#{$fa-css-prefix}-archive:before { content: $fa-var-archive; }
|
||||
|
@ -435,7 +438,7 @@
|
|||
.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; }
|
||||
.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; }
|
||||
.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; }
|
||||
.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; }
|
||||
.#{$fa-css-prefix}-pied-piper-pp:before { content: $fa-var-pied-piper-pp; }
|
||||
.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; }
|
||||
.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; }
|
||||
.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; }
|
||||
|
@ -485,11 +488,14 @@
|
|||
.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; }
|
||||
.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; }
|
||||
.#{$fa-css-prefix}-ra:before,
|
||||
.#{$fa-css-prefix}-resistance:before,
|
||||
.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; }
|
||||
.#{$fa-css-prefix}-ge:before,
|
||||
.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; }
|
||||
.#{$fa-css-prefix}-git-square:before { content: $fa-var-git-square; }
|
||||
.#{$fa-css-prefix}-git:before { content: $fa-var-git; }
|
||||
.#{$fa-css-prefix}-y-combinator-square:before,
|
||||
.#{$fa-css-prefix}-yc-square:before,
|
||||
.#{$fa-css-prefix}-hacker-news:before { content: $fa-var-hacker-news; }
|
||||
.#{$fa-css-prefix}-tencent-weibo:before { content: $fa-var-tencent-weibo; }
|
||||
.#{$fa-css-prefix}-qq:before { content: $fa-var-qq; }
|
||||
|
@ -550,3 +556,234 @@
|
|||
.#{$fa-css-prefix}-sheqel:before,
|
||||
.#{$fa-css-prefix}-ils:before { content: $fa-var-ils; }
|
||||
.#{$fa-css-prefix}-meanpath:before { content: $fa-var-meanpath; }
|
||||
.#{$fa-css-prefix}-buysellads:before { content: $fa-var-buysellads; }
|
||||
.#{$fa-css-prefix}-connectdevelop:before { content: $fa-var-connectdevelop; }
|
||||
.#{$fa-css-prefix}-dashcube:before { content: $fa-var-dashcube; }
|
||||
.#{$fa-css-prefix}-forumbee:before { content: $fa-var-forumbee; }
|
||||
.#{$fa-css-prefix}-leanpub:before { content: $fa-var-leanpub; }
|
||||
.#{$fa-css-prefix}-sellsy:before { content: $fa-var-sellsy; }
|
||||
.#{$fa-css-prefix}-shirtsinbulk:before { content: $fa-var-shirtsinbulk; }
|
||||
.#{$fa-css-prefix}-simplybuilt:before { content: $fa-var-simplybuilt; }
|
||||
.#{$fa-css-prefix}-skyatlas:before { content: $fa-var-skyatlas; }
|
||||
.#{$fa-css-prefix}-cart-plus:before { content: $fa-var-cart-plus; }
|
||||
.#{$fa-css-prefix}-cart-arrow-down:before { content: $fa-var-cart-arrow-down; }
|
||||
.#{$fa-css-prefix}-diamond:before { content: $fa-var-diamond; }
|
||||
.#{$fa-css-prefix}-ship:before { content: $fa-var-ship; }
|
||||
.#{$fa-css-prefix}-user-secret:before { content: $fa-var-user-secret; }
|
||||
.#{$fa-css-prefix}-motorcycle:before { content: $fa-var-motorcycle; }
|
||||
.#{$fa-css-prefix}-street-view:before { content: $fa-var-street-view; }
|
||||
.#{$fa-css-prefix}-heartbeat:before { content: $fa-var-heartbeat; }
|
||||
.#{$fa-css-prefix}-venus:before { content: $fa-var-venus; }
|
||||
.#{$fa-css-prefix}-mars:before { content: $fa-var-mars; }
|
||||
.#{$fa-css-prefix}-mercury:before { content: $fa-var-mercury; }
|
||||
.#{$fa-css-prefix}-intersex:before,
|
||||
.#{$fa-css-prefix}-transgender:before { content: $fa-var-transgender; }
|
||||
.#{$fa-css-prefix}-transgender-alt:before { content: $fa-var-transgender-alt; }
|
||||
.#{$fa-css-prefix}-venus-double:before { content: $fa-var-venus-double; }
|
||||
.#{$fa-css-prefix}-mars-double:before { content: $fa-var-mars-double; }
|
||||
.#{$fa-css-prefix}-venus-mars:before { content: $fa-var-venus-mars; }
|
||||
.#{$fa-css-prefix}-mars-stroke:before { content: $fa-var-mars-stroke; }
|
||||
.#{$fa-css-prefix}-mars-stroke-v:before { content: $fa-var-mars-stroke-v; }
|
||||
.#{$fa-css-prefix}-mars-stroke-h:before { content: $fa-var-mars-stroke-h; }
|
||||
.#{$fa-css-prefix}-neuter:before { content: $fa-var-neuter; }
|
||||
.#{$fa-css-prefix}-genderless:before { content: $fa-var-genderless; }
|
||||
.#{$fa-css-prefix}-facebook-official:before { content: $fa-var-facebook-official; }
|
||||
.#{$fa-css-prefix}-pinterest-p:before { content: $fa-var-pinterest-p; }
|
||||
.#{$fa-css-prefix}-whatsapp:before { content: $fa-var-whatsapp; }
|
||||
.#{$fa-css-prefix}-server:before { content: $fa-var-server; }
|
||||
.#{$fa-css-prefix}-user-plus:before { content: $fa-var-user-plus; }
|
||||
.#{$fa-css-prefix}-user-times:before { content: $fa-var-user-times; }
|
||||
.#{$fa-css-prefix}-hotel:before,
|
||||
.#{$fa-css-prefix}-bed:before { content: $fa-var-bed; }
|
||||
.#{$fa-css-prefix}-viacoin:before { content: $fa-var-viacoin; }
|
||||
.#{$fa-css-prefix}-train:before { content: $fa-var-train; }
|
||||
.#{$fa-css-prefix}-subway:before { content: $fa-var-subway; }
|
||||
.#{$fa-css-prefix}-medium:before { content: $fa-var-medium; }
|
||||
.#{$fa-css-prefix}-yc:before,
|
||||
.#{$fa-css-prefix}-y-combinator:before { content: $fa-var-y-combinator; }
|
||||
.#{$fa-css-prefix}-optin-monster:before { content: $fa-var-optin-monster; }
|
||||
.#{$fa-css-prefix}-opencart:before { content: $fa-var-opencart; }
|
||||
.#{$fa-css-prefix}-expeditedssl:before { content: $fa-var-expeditedssl; }
|
||||
.#{$fa-css-prefix}-battery-4:before,
|
||||
.#{$fa-css-prefix}-battery:before,
|
||||
.#{$fa-css-prefix}-battery-full:before { content: $fa-var-battery-full; }
|
||||
.#{$fa-css-prefix}-battery-3:before,
|
||||
.#{$fa-css-prefix}-battery-three-quarters:before { content: $fa-var-battery-three-quarters; }
|
||||
.#{$fa-css-prefix}-battery-2:before,
|
||||
.#{$fa-css-prefix}-battery-half:before { content: $fa-var-battery-half; }
|
||||
.#{$fa-css-prefix}-battery-1:before,
|
||||
.#{$fa-css-prefix}-battery-quarter:before { content: $fa-var-battery-quarter; }
|
||||
.#{$fa-css-prefix}-battery-0:before,
|
||||
.#{$fa-css-prefix}-battery-empty:before { content: $fa-var-battery-empty; }
|
||||
.#{$fa-css-prefix}-mouse-pointer:before { content: $fa-var-mouse-pointer; }
|
||||
.#{$fa-css-prefix}-i-cursor:before { content: $fa-var-i-cursor; }
|
||||
.#{$fa-css-prefix}-object-group:before { content: $fa-var-object-group; }
|
||||
.#{$fa-css-prefix}-object-ungroup:before { content: $fa-var-object-ungroup; }
|
||||
.#{$fa-css-prefix}-sticky-note:before { content: $fa-var-sticky-note; }
|
||||
.#{$fa-css-prefix}-sticky-note-o:before { content: $fa-var-sticky-note-o; }
|
||||
.#{$fa-css-prefix}-cc-jcb:before { content: $fa-var-cc-jcb; }
|
||||
.#{$fa-css-prefix}-cc-diners-club:before { content: $fa-var-cc-diners-club; }
|
||||
.#{$fa-css-prefix}-clone:before { content: $fa-var-clone; }
|
||||
.#{$fa-css-prefix}-balance-scale:before { content: $fa-var-balance-scale; }
|
||||
.#{$fa-css-prefix}-hourglass-o:before { content: $fa-var-hourglass-o; }
|
||||
.#{$fa-css-prefix}-hourglass-1:before,
|
||||
.#{$fa-css-prefix}-hourglass-start:before { content: $fa-var-hourglass-start; }
|
||||
.#{$fa-css-prefix}-hourglass-2:before,
|
||||
.#{$fa-css-prefix}-hourglass-half:before { content: $fa-var-hourglass-half; }
|
||||
.#{$fa-css-prefix}-hourglass-3:before,
|
||||
.#{$fa-css-prefix}-hourglass-end:before { content: $fa-var-hourglass-end; }
|
||||
.#{$fa-css-prefix}-hourglass:before { content: $fa-var-hourglass; }
|
||||
.#{$fa-css-prefix}-hand-grab-o:before,
|
||||
.#{$fa-css-prefix}-hand-rock-o:before { content: $fa-var-hand-rock-o; }
|
||||
.#{$fa-css-prefix}-hand-stop-o:before,
|
||||
.#{$fa-css-prefix}-hand-paper-o:before { content: $fa-var-hand-paper-o; }
|
||||
.#{$fa-css-prefix}-hand-scissors-o:before { content: $fa-var-hand-scissors-o; }
|
||||
.#{$fa-css-prefix}-hand-lizard-o:before { content: $fa-var-hand-lizard-o; }
|
||||
.#{$fa-css-prefix}-hand-spock-o:before { content: $fa-var-hand-spock-o; }
|
||||
.#{$fa-css-prefix}-hand-pointer-o:before { content: $fa-var-hand-pointer-o; }
|
||||
.#{$fa-css-prefix}-hand-peace-o:before { content: $fa-var-hand-peace-o; }
|
||||
.#{$fa-css-prefix}-trademark:before { content: $fa-var-trademark; }
|
||||
.#{$fa-css-prefix}-registered:before { content: $fa-var-registered; }
|
||||
.#{$fa-css-prefix}-creative-commons:before { content: $fa-var-creative-commons; }
|
||||
.#{$fa-css-prefix}-gg:before { content: $fa-var-gg; }
|
||||
.#{$fa-css-prefix}-gg-circle:before { content: $fa-var-gg-circle; }
|
||||
.#{$fa-css-prefix}-tripadvisor:before { content: $fa-var-tripadvisor; }
|
||||
.#{$fa-css-prefix}-odnoklassniki:before { content: $fa-var-odnoklassniki; }
|
||||
.#{$fa-css-prefix}-odnoklassniki-square:before { content: $fa-var-odnoklassniki-square; }
|
||||
.#{$fa-css-prefix}-get-pocket:before { content: $fa-var-get-pocket; }
|
||||
.#{$fa-css-prefix}-wikipedia-w:before { content: $fa-var-wikipedia-w; }
|
||||
.#{$fa-css-prefix}-safari:before { content: $fa-var-safari; }
|
||||
.#{$fa-css-prefix}-chrome:before { content: $fa-var-chrome; }
|
||||
.#{$fa-css-prefix}-firefox:before { content: $fa-var-firefox; }
|
||||
.#{$fa-css-prefix}-opera:before { content: $fa-var-opera; }
|
||||
.#{$fa-css-prefix}-internet-explorer:before { content: $fa-var-internet-explorer; }
|
||||
.#{$fa-css-prefix}-tv:before,
|
||||
.#{$fa-css-prefix}-television:before { content: $fa-var-television; }
|
||||
.#{$fa-css-prefix}-contao:before { content: $fa-var-contao; }
|
||||
.#{$fa-css-prefix}-500px:before { content: $fa-var-500px; }
|
||||
.#{$fa-css-prefix}-amazon:before { content: $fa-var-amazon; }
|
||||
.#{$fa-css-prefix}-calendar-plus-o:before { content: $fa-var-calendar-plus-o; }
|
||||
.#{$fa-css-prefix}-calendar-minus-o:before { content: $fa-var-calendar-minus-o; }
|
||||
.#{$fa-css-prefix}-calendar-times-o:before { content: $fa-var-calendar-times-o; }
|
||||
.#{$fa-css-prefix}-calendar-check-o:before { content: $fa-var-calendar-check-o; }
|
||||
.#{$fa-css-prefix}-industry:before { content: $fa-var-industry; }
|
||||
.#{$fa-css-prefix}-map-pin:before { content: $fa-var-map-pin; }
|
||||
.#{$fa-css-prefix}-map-signs:before { content: $fa-var-map-signs; }
|
||||
.#{$fa-css-prefix}-map-o:before { content: $fa-var-map-o; }
|
||||
.#{$fa-css-prefix}-map:before { content: $fa-var-map; }
|
||||
.#{$fa-css-prefix}-commenting:before { content: $fa-var-commenting; }
|
||||
.#{$fa-css-prefix}-commenting-o:before { content: $fa-var-commenting-o; }
|
||||
.#{$fa-css-prefix}-houzz:before { content: $fa-var-houzz; }
|
||||
.#{$fa-css-prefix}-vimeo:before { content: $fa-var-vimeo; }
|
||||
.#{$fa-css-prefix}-black-tie:before { content: $fa-var-black-tie; }
|
||||
.#{$fa-css-prefix}-fonticons:before { content: $fa-var-fonticons; }
|
||||
.#{$fa-css-prefix}-reddit-alien:before { content: $fa-var-reddit-alien; }
|
||||
.#{$fa-css-prefix}-edge:before { content: $fa-var-edge; }
|
||||
.#{$fa-css-prefix}-credit-card-alt:before { content: $fa-var-credit-card-alt; }
|
||||
.#{$fa-css-prefix}-codiepie:before { content: $fa-var-codiepie; }
|
||||
.#{$fa-css-prefix}-modx:before { content: $fa-var-modx; }
|
||||
.#{$fa-css-prefix}-fort-awesome:before { content: $fa-var-fort-awesome; }
|
||||
.#{$fa-css-prefix}-usb:before { content: $fa-var-usb; }
|
||||
.#{$fa-css-prefix}-product-hunt:before { content: $fa-var-product-hunt; }
|
||||
.#{$fa-css-prefix}-mixcloud:before { content: $fa-var-mixcloud; }
|
||||
.#{$fa-css-prefix}-scribd:before { content: $fa-var-scribd; }
|
||||
.#{$fa-css-prefix}-pause-circle:before { content: $fa-var-pause-circle; }
|
||||
.#{$fa-css-prefix}-pause-circle-o:before { content: $fa-var-pause-circle-o; }
|
||||
.#{$fa-css-prefix}-stop-circle:before { content: $fa-var-stop-circle; }
|
||||
.#{$fa-css-prefix}-stop-circle-o:before { content: $fa-var-stop-circle-o; }
|
||||
.#{$fa-css-prefix}-shopping-bag:before { content: $fa-var-shopping-bag; }
|
||||
.#{$fa-css-prefix}-shopping-basket:before { content: $fa-var-shopping-basket; }
|
||||
.#{$fa-css-prefix}-hashtag:before { content: $fa-var-hashtag; }
|
||||
.#{$fa-css-prefix}-bluetooth:before { content: $fa-var-bluetooth; }
|
||||
.#{$fa-css-prefix}-bluetooth-b:before { content: $fa-var-bluetooth-b; }
|
||||
.#{$fa-css-prefix}-percent:before { content: $fa-var-percent; }
|
||||
.#{$fa-css-prefix}-gitlab:before { content: $fa-var-gitlab; }
|
||||
.#{$fa-css-prefix}-wpbeginner:before { content: $fa-var-wpbeginner; }
|
||||
.#{$fa-css-prefix}-wpforms:before { content: $fa-var-wpforms; }
|
||||
.#{$fa-css-prefix}-envira:before { content: $fa-var-envira; }
|
||||
.#{$fa-css-prefix}-universal-access:before { content: $fa-var-universal-access; }
|
||||
.#{$fa-css-prefix}-wheelchair-alt:before { content: $fa-var-wheelchair-alt; }
|
||||
.#{$fa-css-prefix}-question-circle-o:before { content: $fa-var-question-circle-o; }
|
||||
.#{$fa-css-prefix}-blind:before { content: $fa-var-blind; }
|
||||
.#{$fa-css-prefix}-audio-description:before { content: $fa-var-audio-description; }
|
||||
.#{$fa-css-prefix}-volume-control-phone:before { content: $fa-var-volume-control-phone; }
|
||||
.#{$fa-css-prefix}-braille:before { content: $fa-var-braille; }
|
||||
.#{$fa-css-prefix}-assistive-listening-systems:before { content: $fa-var-assistive-listening-systems; }
|
||||
.#{$fa-css-prefix}-asl-interpreting:before,
|
||||
.#{$fa-css-prefix}-american-sign-language-interpreting:before { content: $fa-var-american-sign-language-interpreting; }
|
||||
.#{$fa-css-prefix}-deafness:before,
|
||||
.#{$fa-css-prefix}-hard-of-hearing:before,
|
||||
.#{$fa-css-prefix}-deaf:before { content: $fa-var-deaf; }
|
||||
.#{$fa-css-prefix}-glide:before { content: $fa-var-glide; }
|
||||
.#{$fa-css-prefix}-glide-g:before { content: $fa-var-glide-g; }
|
||||
.#{$fa-css-prefix}-signing:before,
|
||||
.#{$fa-css-prefix}-sign-language:before { content: $fa-var-sign-language; }
|
||||
.#{$fa-css-prefix}-low-vision:before { content: $fa-var-low-vision; }
|
||||
.#{$fa-css-prefix}-viadeo:before { content: $fa-var-viadeo; }
|
||||
.#{$fa-css-prefix}-viadeo-square:before { content: $fa-var-viadeo-square; }
|
||||
.#{$fa-css-prefix}-snapchat:before { content: $fa-var-snapchat; }
|
||||
.#{$fa-css-prefix}-snapchat-ghost:before { content: $fa-var-snapchat-ghost; }
|
||||
.#{$fa-css-prefix}-snapchat-square:before { content: $fa-var-snapchat-square; }
|
||||
.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; }
|
||||
.#{$fa-css-prefix}-first-order:before { content: $fa-var-first-order; }
|
||||
.#{$fa-css-prefix}-yoast:before { content: $fa-var-yoast; }
|
||||
.#{$fa-css-prefix}-themeisle:before { content: $fa-var-themeisle; }
|
||||
.#{$fa-css-prefix}-google-plus-circle:before,
|
||||
.#{$fa-css-prefix}-google-plus-official:before { content: $fa-var-google-plus-official; }
|
||||
.#{$fa-css-prefix}-fa:before,
|
||||
.#{$fa-css-prefix}-font-awesome:before { content: $fa-var-font-awesome; }
|
||||
.#{$fa-css-prefix}-handshake-o:before { content: $fa-var-handshake-o; }
|
||||
.#{$fa-css-prefix}-envelope-open:before { content: $fa-var-envelope-open; }
|
||||
.#{$fa-css-prefix}-envelope-open-o:before { content: $fa-var-envelope-open-o; }
|
||||
.#{$fa-css-prefix}-linode:before { content: $fa-var-linode; }
|
||||
.#{$fa-css-prefix}-address-book:before { content: $fa-var-address-book; }
|
||||
.#{$fa-css-prefix}-address-book-o:before { content: $fa-var-address-book-o; }
|
||||
.#{$fa-css-prefix}-vcard:before,
|
||||
.#{$fa-css-prefix}-address-card:before { content: $fa-var-address-card; }
|
||||
.#{$fa-css-prefix}-vcard-o:before,
|
||||
.#{$fa-css-prefix}-address-card-o:before { content: $fa-var-address-card-o; }
|
||||
.#{$fa-css-prefix}-user-circle:before { content: $fa-var-user-circle; }
|
||||
.#{$fa-css-prefix}-user-circle-o:before { content: $fa-var-user-circle-o; }
|
||||
.#{$fa-css-prefix}-user-o:before { content: $fa-var-user-o; }
|
||||
.#{$fa-css-prefix}-id-badge:before { content: $fa-var-id-badge; }
|
||||
.#{$fa-css-prefix}-drivers-license:before,
|
||||
.#{$fa-css-prefix}-id-card:before { content: $fa-var-id-card; }
|
||||
.#{$fa-css-prefix}-drivers-license-o:before,
|
||||
.#{$fa-css-prefix}-id-card-o:before { content: $fa-var-id-card-o; }
|
||||
.#{$fa-css-prefix}-quora:before { content: $fa-var-quora; }
|
||||
.#{$fa-css-prefix}-free-code-camp:before { content: $fa-var-free-code-camp; }
|
||||
.#{$fa-css-prefix}-telegram:before { content: $fa-var-telegram; }
|
||||
.#{$fa-css-prefix}-thermometer-4:before,
|
||||
.#{$fa-css-prefix}-thermometer:before,
|
||||
.#{$fa-css-prefix}-thermometer-full:before { content: $fa-var-thermometer-full; }
|
||||
.#{$fa-css-prefix}-thermometer-3:before,
|
||||
.#{$fa-css-prefix}-thermometer-three-quarters:before { content: $fa-var-thermometer-three-quarters; }
|
||||
.#{$fa-css-prefix}-thermometer-2:before,
|
||||
.#{$fa-css-prefix}-thermometer-half:before { content: $fa-var-thermometer-half; }
|
||||
.#{$fa-css-prefix}-thermometer-1:before,
|
||||
.#{$fa-css-prefix}-thermometer-quarter:before { content: $fa-var-thermometer-quarter; }
|
||||
.#{$fa-css-prefix}-thermometer-0:before,
|
||||
.#{$fa-css-prefix}-thermometer-empty:before { content: $fa-var-thermometer-empty; }
|
||||
.#{$fa-css-prefix}-shower:before { content: $fa-var-shower; }
|
||||
.#{$fa-css-prefix}-bathtub:before,
|
||||
.#{$fa-css-prefix}-s15:before,
|
||||
.#{$fa-css-prefix}-bath:before { content: $fa-var-bath; }
|
||||
.#{$fa-css-prefix}-podcast:before { content: $fa-var-podcast; }
|
||||
.#{$fa-css-prefix}-window-maximize:before { content: $fa-var-window-maximize; }
|
||||
.#{$fa-css-prefix}-window-minimize:before { content: $fa-var-window-minimize; }
|
||||
.#{$fa-css-prefix}-window-restore:before { content: $fa-var-window-restore; }
|
||||
.#{$fa-css-prefix}-times-rectangle:before,
|
||||
.#{$fa-css-prefix}-window-close:before { content: $fa-var-window-close; }
|
||||
.#{$fa-css-prefix}-times-rectangle-o:before,
|
||||
.#{$fa-css-prefix}-window-close-o:before { content: $fa-var-window-close-o; }
|
||||
.#{$fa-css-prefix}-bandcamp:before { content: $fa-var-bandcamp; }
|
||||
.#{$fa-css-prefix}-grav:before { content: $fa-var-grav; }
|
||||
.#{$fa-css-prefix}-etsy:before { content: $fa-var-etsy; }
|
||||
.#{$fa-css-prefix}-imdb:before { content: $fa-var-imdb; }
|
||||
.#{$fa-css-prefix}-ravelry:before { content: $fa-var-ravelry; }
|
||||
.#{$fa-css-prefix}-eercast:before { content: $fa-var-eercast; }
|
||||
.#{$fa-css-prefix}-microchip:before { content: $fa-var-microchip; }
|
||||
.#{$fa-css-prefix}-snowflake-o:before { content: $fa-var-snowflake-o; }
|
||||
.#{$fa-css-prefix}-superpowers:before { content: $fa-var-superpowers; }
|
||||
.#{$fa-css-prefix}-wpexplorer:before { content: $fa-var-wpexplorer; }
|
||||
.#{$fa-css-prefix}-meetup:before { content: $fa-var-meetup; }
|
||||
|
|
|
@ -3,23 +3,58 @@
|
|||
|
||||
@mixin fa-icon() {
|
||||
display: inline-block;
|
||||
font: normal normal normal 14px/1 FontAwesome; // shortening font declaration
|
||||
font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration
|
||||
font-size: inherit; // can't have font-size inherit on line above, so need to override
|
||||
text-rendering: auto; // optimizelegibility throws things off #1094
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
}
|
||||
|
||||
@mixin fa-icon-rotate($degrees, $rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
|
||||
-webkit-transform: rotate($degrees);
|
||||
-ms-transform: rotate($degrees);
|
||||
transform: rotate($degrees);
|
||||
}
|
||||
|
||||
@mixin fa-icon-flip($horiz, $vert, $rotation) {
|
||||
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
|
||||
-webkit-transform: scale($horiz, $vert);
|
||||
-ms-transform: scale($horiz, $vert);
|
||||
transform: scale($horiz, $vert);
|
||||
}
|
||||
|
||||
|
||||
// Only display content to screen readers. A la Bootstrap 4.
|
||||
//
|
||||
// See: http://a11yproject.com/posts/how-to-hide-content/
|
||||
|
||||
@mixin sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
border: 0;
|
||||
}
|
||||
|
||||
// Use in conjunction with .sr-only to only display content when it's focused.
|
||||
//
|
||||
// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
|
||||
//
|
||||
// Credit: HTML5 Boilerplate
|
||||
|
||||
@mixin sr-only-focusable {
|
||||
&:active,
|
||||
&:focus {
|
||||
position: static;
|
||||
width: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
clip: auto;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
font-family: 'FontAwesome';
|
||||
src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}');
|
||||
src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'),
|
||||
url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg');
|
||||
//src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
// src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
// Screen Readers
|
||||
// -------------------------
|
||||
|
||||
.sr-only { @include sr-only(); }
|
||||
.sr-only-focusable { @include sr-only-focusable(); }
|
|
@ -2,20 +2,29 @@
|
|||
// --------------------------
|
||||
|
||||
$fa-font-path: "../fonts" !default;
|
||||
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.2.0/fonts" !default; // for referencing Bootstrap CDN font files directly
|
||||
$fa-font-size-base: 14px !default;
|
||||
$fa-line-height-base: 1 !default;
|
||||
//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
|
||||
$fa-css-prefix: fa !default;
|
||||
$fa-version: "4.2.0" !default;
|
||||
$fa-version: "4.7.0" !default;
|
||||
$fa-border-color: #eee !default;
|
||||
$fa-inverse: #fff !default;
|
||||
$fa-li-width: (30em / 14) !default;
|
||||
|
||||
$fa-var-500px: "\f26e";
|
||||
$fa-var-address-book: "\f2b9";
|
||||
$fa-var-address-book-o: "\f2ba";
|
||||
$fa-var-address-card: "\f2bb";
|
||||
$fa-var-address-card-o: "\f2bc";
|
||||
$fa-var-adjust: "\f042";
|
||||
$fa-var-adn: "\f170";
|
||||
$fa-var-align-center: "\f037";
|
||||
$fa-var-align-justify: "\f039";
|
||||
$fa-var-align-left: "\f036";
|
||||
$fa-var-align-right: "\f038";
|
||||
$fa-var-amazon: "\f270";
|
||||
$fa-var-ambulance: "\f0f9";
|
||||
$fa-var-american-sign-language-interpreting: "\f2a3";
|
||||
$fa-var-anchor: "\f13d";
|
||||
$fa-var-android: "\f17b";
|
||||
$fa-var-angellist: "\f209";
|
||||
|
@ -46,16 +55,35 @@ $fa-var-arrows: "\f047";
|
|||
$fa-var-arrows-alt: "\f0b2";
|
||||
$fa-var-arrows-h: "\f07e";
|
||||
$fa-var-arrows-v: "\f07d";
|
||||
$fa-var-asl-interpreting: "\f2a3";
|
||||
$fa-var-assistive-listening-systems: "\f2a2";
|
||||
$fa-var-asterisk: "\f069";
|
||||
$fa-var-at: "\f1fa";
|
||||
$fa-var-audio-description: "\f29e";
|
||||
$fa-var-automobile: "\f1b9";
|
||||
$fa-var-backward: "\f04a";
|
||||
$fa-var-balance-scale: "\f24e";
|
||||
$fa-var-ban: "\f05e";
|
||||
$fa-var-bandcamp: "\f2d5";
|
||||
$fa-var-bank: "\f19c";
|
||||
$fa-var-bar-chart: "\f080";
|
||||
$fa-var-bar-chart-o: "\f080";
|
||||
$fa-var-barcode: "\f02a";
|
||||
$fa-var-bars: "\f0c9";
|
||||
$fa-var-bath: "\f2cd";
|
||||
$fa-var-bathtub: "\f2cd";
|
||||
$fa-var-battery: "\f240";
|
||||
$fa-var-battery-0: "\f244";
|
||||
$fa-var-battery-1: "\f243";
|
||||
$fa-var-battery-2: "\f242";
|
||||
$fa-var-battery-3: "\f241";
|
||||
$fa-var-battery-4: "\f240";
|
||||
$fa-var-battery-empty: "\f244";
|
||||
$fa-var-battery-full: "\f240";
|
||||
$fa-var-battery-half: "\f242";
|
||||
$fa-var-battery-quarter: "\f243";
|
||||
$fa-var-battery-three-quarters: "\f241";
|
||||
$fa-var-bed: "\f236";
|
||||
$fa-var-beer: "\f0fc";
|
||||
$fa-var-behance: "\f1b4";
|
||||
$fa-var-behance-square: "\f1b5";
|
||||
|
@ -69,12 +97,17 @@ $fa-var-birthday-cake: "\f1fd";
|
|||
$fa-var-bitbucket: "\f171";
|
||||
$fa-var-bitbucket-square: "\f172";
|
||||
$fa-var-bitcoin: "\f15a";
|
||||
$fa-var-black-tie: "\f27e";
|
||||
$fa-var-blind: "\f29d";
|
||||
$fa-var-bluetooth: "\f293";
|
||||
$fa-var-bluetooth-b: "\f294";
|
||||
$fa-var-bold: "\f032";
|
||||
$fa-var-bolt: "\f0e7";
|
||||
$fa-var-bomb: "\f1e2";
|
||||
$fa-var-book: "\f02d";
|
||||
$fa-var-bookmark: "\f02e";
|
||||
$fa-var-bookmark-o: "\f097";
|
||||
$fa-var-braille: "\f2a1";
|
||||
$fa-var-briefcase: "\f0b1";
|
||||
$fa-var-btc: "\f15a";
|
||||
$fa-var-bug: "\f188";
|
||||
|
@ -83,10 +116,15 @@ $fa-var-building-o: "\f0f7";
|
|||
$fa-var-bullhorn: "\f0a1";
|
||||
$fa-var-bullseye: "\f140";
|
||||
$fa-var-bus: "\f207";
|
||||
$fa-var-buysellads: "\f20d";
|
||||
$fa-var-cab: "\f1ba";
|
||||
$fa-var-calculator: "\f1ec";
|
||||
$fa-var-calendar: "\f073";
|
||||
$fa-var-calendar-check-o: "\f274";
|
||||
$fa-var-calendar-minus-o: "\f272";
|
||||
$fa-var-calendar-o: "\f133";
|
||||
$fa-var-calendar-plus-o: "\f271";
|
||||
$fa-var-calendar-times-o: "\f273";
|
||||
$fa-var-camera: "\f030";
|
||||
$fa-var-camera-retro: "\f083";
|
||||
$fa-var-car: "\f1b9";
|
||||
|
@ -98,9 +136,13 @@ $fa-var-caret-square-o-left: "\f191";
|
|||
$fa-var-caret-square-o-right: "\f152";
|
||||
$fa-var-caret-square-o-up: "\f151";
|
||||
$fa-var-caret-up: "\f0d8";
|
||||
$fa-var-cart-arrow-down: "\f218";
|
||||
$fa-var-cart-plus: "\f217";
|
||||
$fa-var-cc: "\f20a";
|
||||
$fa-var-cc-amex: "\f1f3";
|
||||
$fa-var-cc-diners-club: "\f24c";
|
||||
$fa-var-cc-discover: "\f1f2";
|
||||
$fa-var-cc-jcb: "\f24b";
|
||||
$fa-var-cc-mastercard: "\f1f1";
|
||||
$fa-var-cc-paypal: "\f1f4";
|
||||
$fa-var-cc-stripe: "\f1f5";
|
||||
|
@ -122,12 +164,14 @@ $fa-var-chevron-left: "\f053";
|
|||
$fa-var-chevron-right: "\f054";
|
||||
$fa-var-chevron-up: "\f077";
|
||||
$fa-var-child: "\f1ae";
|
||||
$fa-var-chrome: "\f268";
|
||||
$fa-var-circle: "\f111";
|
||||
$fa-var-circle-o: "\f10c";
|
||||
$fa-var-circle-o-notch: "\f1ce";
|
||||
$fa-var-circle-thin: "\f1db";
|
||||
$fa-var-clipboard: "\f0ea";
|
||||
$fa-var-clock-o: "\f017";
|
||||
$fa-var-clone: "\f24d";
|
||||
$fa-var-close: "\f00d";
|
||||
$fa-var-cloud: "\f0c2";
|
||||
$fa-var-cloud-download: "\f0ed";
|
||||
|
@ -136,19 +180,26 @@ $fa-var-cny: "\f157";
|
|||
$fa-var-code: "\f121";
|
||||
$fa-var-code-fork: "\f126";
|
||||
$fa-var-codepen: "\f1cb";
|
||||
$fa-var-codiepie: "\f284";
|
||||
$fa-var-coffee: "\f0f4";
|
||||
$fa-var-cog: "\f013";
|
||||
$fa-var-cogs: "\f085";
|
||||
$fa-var-columns: "\f0db";
|
||||
$fa-var-comment: "\f075";
|
||||
$fa-var-comment-o: "\f0e5";
|
||||
$fa-var-commenting: "\f27a";
|
||||
$fa-var-commenting-o: "\f27b";
|
||||
$fa-var-comments: "\f086";
|
||||
$fa-var-comments-o: "\f0e6";
|
||||
$fa-var-compass: "\f14e";
|
||||
$fa-var-compress: "\f066";
|
||||
$fa-var-connectdevelop: "\f20e";
|
||||
$fa-var-contao: "\f26d";
|
||||
$fa-var-copy: "\f0c5";
|
||||
$fa-var-copyright: "\f1f9";
|
||||
$fa-var-creative-commons: "\f25e";
|
||||
$fa-var-credit-card: "\f09d";
|
||||
$fa-var-credit-card-alt: "\f283";
|
||||
$fa-var-crop: "\f125";
|
||||
$fa-var-crosshairs: "\f05b";
|
||||
$fa-var-css3: "\f13c";
|
||||
|
@ -157,27 +208,39 @@ $fa-var-cubes: "\f1b3";
|
|||
$fa-var-cut: "\f0c4";
|
||||
$fa-var-cutlery: "\f0f5";
|
||||
$fa-var-dashboard: "\f0e4";
|
||||
$fa-var-dashcube: "\f210";
|
||||
$fa-var-database: "\f1c0";
|
||||
$fa-var-deaf: "\f2a4";
|
||||
$fa-var-deafness: "\f2a4";
|
||||
$fa-var-dedent: "\f03b";
|
||||
$fa-var-delicious: "\f1a5";
|
||||
$fa-var-desktop: "\f108";
|
||||
$fa-var-deviantart: "\f1bd";
|
||||
$fa-var-diamond: "\f219";
|
||||
$fa-var-digg: "\f1a6";
|
||||
$fa-var-dollar: "\f155";
|
||||
$fa-var-dot-circle-o: "\f192";
|
||||
$fa-var-download: "\f019";
|
||||
$fa-var-dribbble: "\f17d";
|
||||
$fa-var-drivers-license: "\f2c2";
|
||||
$fa-var-drivers-license-o: "\f2c3";
|
||||
$fa-var-dropbox: "\f16b";
|
||||
$fa-var-drupal: "\f1a9";
|
||||
$fa-var-edge: "\f282";
|
||||
$fa-var-edit: "\f044";
|
||||
$fa-var-eercast: "\f2da";
|
||||
$fa-var-eject: "\f052";
|
||||
$fa-var-ellipsis-h: "\f141";
|
||||
$fa-var-ellipsis-v: "\f142";
|
||||
$fa-var-empire: "\f1d1";
|
||||
$fa-var-envelope: "\f0e0";
|
||||
$fa-var-envelope-o: "\f003";
|
||||
$fa-var-envelope-open: "\f2b6";
|
||||
$fa-var-envelope-open-o: "\f2b7";
|
||||
$fa-var-envelope-square: "\f199";
|
||||
$fa-var-envira: "\f299";
|
||||
$fa-var-eraser: "\f12d";
|
||||
$fa-var-etsy: "\f2d7";
|
||||
$fa-var-eur: "\f153";
|
||||
$fa-var-euro: "\f153";
|
||||
$fa-var-exchange: "\f0ec";
|
||||
|
@ -185,16 +248,21 @@ $fa-var-exclamation: "\f12a";
|
|||
$fa-var-exclamation-circle: "\f06a";
|
||||
$fa-var-exclamation-triangle: "\f071";
|
||||
$fa-var-expand: "\f065";
|
||||
$fa-var-expeditedssl: "\f23e";
|
||||
$fa-var-external-link: "\f08e";
|
||||
$fa-var-external-link-square: "\f14c";
|
||||
$fa-var-eye: "\f06e";
|
||||
$fa-var-eye-slash: "\f070";
|
||||
$fa-var-eyedropper: "\f1fb";
|
||||
$fa-var-fa: "\f2b4";
|
||||
$fa-var-facebook: "\f09a";
|
||||
$fa-var-facebook-f: "\f09a";
|
||||
$fa-var-facebook-official: "\f230";
|
||||
$fa-var-facebook-square: "\f082";
|
||||
$fa-var-fast-backward: "\f049";
|
||||
$fa-var-fast-forward: "\f050";
|
||||
$fa-var-fax: "\f1ac";
|
||||
$fa-var-feed: "\f09e";
|
||||
$fa-var-female: "\f182";
|
||||
$fa-var-fighter-jet: "\f0fb";
|
||||
$fa-var-file: "\f15b";
|
||||
|
@ -220,6 +288,8 @@ $fa-var-film: "\f008";
|
|||
$fa-var-filter: "\f0b0";
|
||||
$fa-var-fire: "\f06d";
|
||||
$fa-var-fire-extinguisher: "\f134";
|
||||
$fa-var-firefox: "\f269";
|
||||
$fa-var-first-order: "\f2b0";
|
||||
$fa-var-flag: "\f024";
|
||||
$fa-var-flag-checkered: "\f11e";
|
||||
$fa-var-flag-o: "\f11d";
|
||||
|
@ -232,8 +302,13 @@ $fa-var-folder-o: "\f114";
|
|||
$fa-var-folder-open: "\f07c";
|
||||
$fa-var-folder-open-o: "\f115";
|
||||
$fa-var-font: "\f031";
|
||||
$fa-var-font-awesome: "\f2b4";
|
||||
$fa-var-fonticons: "\f280";
|
||||
$fa-var-fort-awesome: "\f286";
|
||||
$fa-var-forumbee: "\f211";
|
||||
$fa-var-forward: "\f04e";
|
||||
$fa-var-foursquare: "\f180";
|
||||
$fa-var-free-code-camp: "\f2c5";
|
||||
$fa-var-frown-o: "\f119";
|
||||
$fa-var-futbol-o: "\f1e3";
|
||||
$fa-var-gamepad: "\f11b";
|
||||
|
@ -242,45 +317,87 @@ $fa-var-gbp: "\f154";
|
|||
$fa-var-ge: "\f1d1";
|
||||
$fa-var-gear: "\f013";
|
||||
$fa-var-gears: "\f085";
|
||||
$fa-var-genderless: "\f22d";
|
||||
$fa-var-get-pocket: "\f265";
|
||||
$fa-var-gg: "\f260";
|
||||
$fa-var-gg-circle: "\f261";
|
||||
$fa-var-gift: "\f06b";
|
||||
$fa-var-git: "\f1d3";
|
||||
$fa-var-git-square: "\f1d2";
|
||||
$fa-var-github: "\f09b";
|
||||
$fa-var-github-alt: "\f113";
|
||||
$fa-var-github-square: "\f092";
|
||||
$fa-var-gitlab: "\f296";
|
||||
$fa-var-gittip: "\f184";
|
||||
$fa-var-glass: "\f000";
|
||||
$fa-var-glide: "\f2a5";
|
||||
$fa-var-glide-g: "\f2a6";
|
||||
$fa-var-globe: "\f0ac";
|
||||
$fa-var-google: "\f1a0";
|
||||
$fa-var-google-plus: "\f0d5";
|
||||
$fa-var-google-plus-circle: "\f2b3";
|
||||
$fa-var-google-plus-official: "\f2b3";
|
||||
$fa-var-google-plus-square: "\f0d4";
|
||||
$fa-var-google-wallet: "\f1ee";
|
||||
$fa-var-graduation-cap: "\f19d";
|
||||
$fa-var-gratipay: "\f184";
|
||||
$fa-var-grav: "\f2d6";
|
||||
$fa-var-group: "\f0c0";
|
||||
$fa-var-h-square: "\f0fd";
|
||||
$fa-var-hacker-news: "\f1d4";
|
||||
$fa-var-hand-grab-o: "\f255";
|
||||
$fa-var-hand-lizard-o: "\f258";
|
||||
$fa-var-hand-o-down: "\f0a7";
|
||||
$fa-var-hand-o-left: "\f0a5";
|
||||
$fa-var-hand-o-right: "\f0a4";
|
||||
$fa-var-hand-o-up: "\f0a6";
|
||||
$fa-var-hand-paper-o: "\f256";
|
||||
$fa-var-hand-peace-o: "\f25b";
|
||||
$fa-var-hand-pointer-o: "\f25a";
|
||||
$fa-var-hand-rock-o: "\f255";
|
||||
$fa-var-hand-scissors-o: "\f257";
|
||||
$fa-var-hand-spock-o: "\f259";
|
||||
$fa-var-hand-stop-o: "\f256";
|
||||
$fa-var-handshake-o: "\f2b5";
|
||||
$fa-var-hard-of-hearing: "\f2a4";
|
||||
$fa-var-hashtag: "\f292";
|
||||
$fa-var-hdd-o: "\f0a0";
|
||||
$fa-var-header: "\f1dc";
|
||||
$fa-var-headphones: "\f025";
|
||||
$fa-var-heart: "\f004";
|
||||
$fa-var-heart-o: "\f08a";
|
||||
$fa-var-heartbeat: "\f21e";
|
||||
$fa-var-history: "\f1da";
|
||||
$fa-var-home: "\f015";
|
||||
$fa-var-hospital-o: "\f0f8";
|
||||
$fa-var-hotel: "\f236";
|
||||
$fa-var-hourglass: "\f254";
|
||||
$fa-var-hourglass-1: "\f251";
|
||||
$fa-var-hourglass-2: "\f252";
|
||||
$fa-var-hourglass-3: "\f253";
|
||||
$fa-var-hourglass-end: "\f253";
|
||||
$fa-var-hourglass-half: "\f252";
|
||||
$fa-var-hourglass-o: "\f250";
|
||||
$fa-var-hourglass-start: "\f251";
|
||||
$fa-var-houzz: "\f27c";
|
||||
$fa-var-html5: "\f13b";
|
||||
$fa-var-i-cursor: "\f246";
|
||||
$fa-var-id-badge: "\f2c1";
|
||||
$fa-var-id-card: "\f2c2";
|
||||
$fa-var-id-card-o: "\f2c3";
|
||||
$fa-var-ils: "\f20b";
|
||||
$fa-var-image: "\f03e";
|
||||
$fa-var-imdb: "\f2d8";
|
||||
$fa-var-inbox: "\f01c";
|
||||
$fa-var-indent: "\f03c";
|
||||
$fa-var-industry: "\f275";
|
||||
$fa-var-info: "\f129";
|
||||
$fa-var-info-circle: "\f05a";
|
||||
$fa-var-inr: "\f156";
|
||||
$fa-var-instagram: "\f16d";
|
||||
$fa-var-institution: "\f19c";
|
||||
$fa-var-internet-explorer: "\f26b";
|
||||
$fa-var-intersex: "\f224";
|
||||
$fa-var-ioxhost: "\f208";
|
||||
$fa-var-italic: "\f033";
|
||||
$fa-var-joomla: "\f1aa";
|
||||
|
@ -294,6 +411,7 @@ $fa-var-laptop: "\f109";
|
|||
$fa-var-lastfm: "\f202";
|
||||
$fa-var-lastfm-square: "\f203";
|
||||
$fa-var-leaf: "\f06c";
|
||||
$fa-var-leanpub: "\f212";
|
||||
$fa-var-legal: "\f0e3";
|
||||
$fa-var-lemon-o: "\f094";
|
||||
$fa-var-level-down: "\f149";
|
||||
|
@ -307,6 +425,7 @@ $fa-var-line-chart: "\f201";
|
|||
$fa-var-link: "\f0c1";
|
||||
$fa-var-linkedin: "\f0e1";
|
||||
$fa-var-linkedin-square: "\f08c";
|
||||
$fa-var-linode: "\f2b8";
|
||||
$fa-var-linux: "\f17c";
|
||||
$fa-var-list: "\f03a";
|
||||
$fa-var-list-alt: "\f022";
|
||||
|
@ -318,32 +437,58 @@ $fa-var-long-arrow-down: "\f175";
|
|||
$fa-var-long-arrow-left: "\f177";
|
||||
$fa-var-long-arrow-right: "\f178";
|
||||
$fa-var-long-arrow-up: "\f176";
|
||||
$fa-var-low-vision: "\f2a8";
|
||||
$fa-var-magic: "\f0d0";
|
||||
$fa-var-magnet: "\f076";
|
||||
$fa-var-mail-forward: "\f064";
|
||||
$fa-var-mail-reply: "\f112";
|
||||
$fa-var-mail-reply-all: "\f122";
|
||||
$fa-var-male: "\f183";
|
||||
$fa-var-map: "\f279";
|
||||
$fa-var-map-marker: "\f041";
|
||||
$fa-var-map-o: "\f278";
|
||||
$fa-var-map-pin: "\f276";
|
||||
$fa-var-map-signs: "\f277";
|
||||
$fa-var-mars: "\f222";
|
||||
$fa-var-mars-double: "\f227";
|
||||
$fa-var-mars-stroke: "\f229";
|
||||
$fa-var-mars-stroke-h: "\f22b";
|
||||
$fa-var-mars-stroke-v: "\f22a";
|
||||
$fa-var-maxcdn: "\f136";
|
||||
$fa-var-meanpath: "\f20c";
|
||||
$fa-var-medium: "\f23a";
|
||||
$fa-var-medkit: "\f0fa";
|
||||
$fa-var-meetup: "\f2e0";
|
||||
$fa-var-meh-o: "\f11a";
|
||||
$fa-var-mercury: "\f223";
|
||||
$fa-var-microchip: "\f2db";
|
||||
$fa-var-microphone: "\f130";
|
||||
$fa-var-microphone-slash: "\f131";
|
||||
$fa-var-minus: "\f068";
|
||||
$fa-var-minus-circle: "\f056";
|
||||
$fa-var-minus-square: "\f146";
|
||||
$fa-var-minus-square-o: "\f147";
|
||||
$fa-var-mixcloud: "\f289";
|
||||
$fa-var-mobile: "\f10b";
|
||||
$fa-var-mobile-phone: "\f10b";
|
||||
$fa-var-modx: "\f285";
|
||||
$fa-var-money: "\f0d6";
|
||||
$fa-var-moon-o: "\f186";
|
||||
$fa-var-mortar-board: "\f19d";
|
||||
$fa-var-motorcycle: "\f21c";
|
||||
$fa-var-mouse-pointer: "\f245";
|
||||
$fa-var-music: "\f001";
|
||||
$fa-var-navicon: "\f0c9";
|
||||
$fa-var-neuter: "\f22c";
|
||||
$fa-var-newspaper-o: "\f1ea";
|
||||
$fa-var-object-group: "\f247";
|
||||
$fa-var-object-ungroup: "\f248";
|
||||
$fa-var-odnoklassniki: "\f263";
|
||||
$fa-var-odnoklassniki-square: "\f264";
|
||||
$fa-var-opencart: "\f23d";
|
||||
$fa-var-openid: "\f19b";
|
||||
$fa-var-opera: "\f26a";
|
||||
$fa-var-optin-monster: "\f23c";
|
||||
$fa-var-outdent: "\f03b";
|
||||
$fa-var-pagelines: "\f18c";
|
||||
$fa-var-paint-brush: "\f1fc";
|
||||
|
@ -353,19 +498,24 @@ $fa-var-paperclip: "\f0c6";
|
|||
$fa-var-paragraph: "\f1dd";
|
||||
$fa-var-paste: "\f0ea";
|
||||
$fa-var-pause: "\f04c";
|
||||
$fa-var-pause-circle: "\f28b";
|
||||
$fa-var-pause-circle-o: "\f28c";
|
||||
$fa-var-paw: "\f1b0";
|
||||
$fa-var-paypal: "\f1ed";
|
||||
$fa-var-pencil: "\f040";
|
||||
$fa-var-pencil-square: "\f14b";
|
||||
$fa-var-pencil-square-o: "\f044";
|
||||
$fa-var-percent: "\f295";
|
||||
$fa-var-phone: "\f095";
|
||||
$fa-var-phone-square: "\f098";
|
||||
$fa-var-photo: "\f03e";
|
||||
$fa-var-picture-o: "\f03e";
|
||||
$fa-var-pie-chart: "\f200";
|
||||
$fa-var-pied-piper: "\f1a7";
|
||||
$fa-var-pied-piper: "\f2ae";
|
||||
$fa-var-pied-piper-alt: "\f1a8";
|
||||
$fa-var-pied-piper-pp: "\f1a7";
|
||||
$fa-var-pinterest: "\f0d2";
|
||||
$fa-var-pinterest-p: "\f231";
|
||||
$fa-var-pinterest-square: "\f0d3";
|
||||
$fa-var-plane: "\f072";
|
||||
$fa-var-play: "\f04b";
|
||||
|
@ -376,28 +526,36 @@ $fa-var-plus: "\f067";
|
|||
$fa-var-plus-circle: "\f055";
|
||||
$fa-var-plus-square: "\f0fe";
|
||||
$fa-var-plus-square-o: "\f196";
|
||||
$fa-var-podcast: "\f2ce";
|
||||
$fa-var-power-off: "\f011";
|
||||
$fa-var-print: "\f02f";
|
||||
$fa-var-product-hunt: "\f288";
|
||||
$fa-var-puzzle-piece: "\f12e";
|
||||
$fa-var-qq: "\f1d6";
|
||||
$fa-var-qrcode: "\f029";
|
||||
$fa-var-question: "\f128";
|
||||
$fa-var-question-circle: "\f059";
|
||||
$fa-var-question-circle-o: "\f29c";
|
||||
$fa-var-quora: "\f2c4";
|
||||
$fa-var-quote-left: "\f10d";
|
||||
$fa-var-quote-right: "\f10e";
|
||||
$fa-var-ra: "\f1d0";
|
||||
$fa-var-random: "\f074";
|
||||
$fa-var-ravelry: "\f2d9";
|
||||
$fa-var-rebel: "\f1d0";
|
||||
$fa-var-recycle: "\f1b8";
|
||||
$fa-var-reddit: "\f1a1";
|
||||
$fa-var-reddit-alien: "\f281";
|
||||
$fa-var-reddit-square: "\f1a2";
|
||||
$fa-var-refresh: "\f021";
|
||||
$fa-var-registered: "\f25d";
|
||||
$fa-var-remove: "\f00d";
|
||||
$fa-var-renren: "\f18b";
|
||||
$fa-var-reorder: "\f0c9";
|
||||
$fa-var-repeat: "\f01e";
|
||||
$fa-var-reply: "\f112";
|
||||
$fa-var-reply-all: "\f122";
|
||||
$fa-var-resistance: "\f1d0";
|
||||
$fa-var-retweet: "\f079";
|
||||
$fa-var-rmb: "\f157";
|
||||
$fa-var-road: "\f018";
|
||||
|
@ -410,13 +568,18 @@ $fa-var-rss-square: "\f143";
|
|||
$fa-var-rub: "\f158";
|
||||
$fa-var-ruble: "\f158";
|
||||
$fa-var-rupee: "\f156";
|
||||
$fa-var-s15: "\f2cd";
|
||||
$fa-var-safari: "\f267";
|
||||
$fa-var-save: "\f0c7";
|
||||
$fa-var-scissors: "\f0c4";
|
||||
$fa-var-scribd: "\f28a";
|
||||
$fa-var-search: "\f002";
|
||||
$fa-var-search-minus: "\f010";
|
||||
$fa-var-search-plus: "\f00e";
|
||||
$fa-var-sellsy: "\f213";
|
||||
$fa-var-send: "\f1d8";
|
||||
$fa-var-send-o: "\f1d9";
|
||||
$fa-var-server: "\f233";
|
||||
$fa-var-share: "\f064";
|
||||
$fa-var-share-alt: "\f1e0";
|
||||
$fa-var-share-alt-square: "\f1e1";
|
||||
|
@ -425,16 +588,29 @@ $fa-var-share-square-o: "\f045";
|
|||
$fa-var-shekel: "\f20b";
|
||||
$fa-var-sheqel: "\f20b";
|
||||
$fa-var-shield: "\f132";
|
||||
$fa-var-ship: "\f21a";
|
||||
$fa-var-shirtsinbulk: "\f214";
|
||||
$fa-var-shopping-bag: "\f290";
|
||||
$fa-var-shopping-basket: "\f291";
|
||||
$fa-var-shopping-cart: "\f07a";
|
||||
$fa-var-shower: "\f2cc";
|
||||
$fa-var-sign-in: "\f090";
|
||||
$fa-var-sign-language: "\f2a7";
|
||||
$fa-var-sign-out: "\f08b";
|
||||
$fa-var-signal: "\f012";
|
||||
$fa-var-signing: "\f2a7";
|
||||
$fa-var-simplybuilt: "\f215";
|
||||
$fa-var-sitemap: "\f0e8";
|
||||
$fa-var-skyatlas: "\f216";
|
||||
$fa-var-skype: "\f17e";
|
||||
$fa-var-slack: "\f198";
|
||||
$fa-var-sliders: "\f1de";
|
||||
$fa-var-slideshare: "\f1e7";
|
||||
$fa-var-smile-o: "\f118";
|
||||
$fa-var-snapchat: "\f2ab";
|
||||
$fa-var-snapchat-ghost: "\f2ac";
|
||||
$fa-var-snapchat-square: "\f2ad";
|
||||
$fa-var-snowflake-o: "\f2dc";
|
||||
$fa-var-soccer-ball-o: "\f1e3";
|
||||
$fa-var-sort: "\f0dc";
|
||||
$fa-var-sort-alpha-asc: "\f15d";
|
||||
|
@ -467,13 +643,20 @@ $fa-var-steam-square: "\f1b7";
|
|||
$fa-var-step-backward: "\f048";
|
||||
$fa-var-step-forward: "\f051";
|
||||
$fa-var-stethoscope: "\f0f1";
|
||||
$fa-var-sticky-note: "\f249";
|
||||
$fa-var-sticky-note-o: "\f24a";
|
||||
$fa-var-stop: "\f04d";
|
||||
$fa-var-stop-circle: "\f28d";
|
||||
$fa-var-stop-circle-o: "\f28e";
|
||||
$fa-var-street-view: "\f21d";
|
||||
$fa-var-strikethrough: "\f0cc";
|
||||
$fa-var-stumbleupon: "\f1a4";
|
||||
$fa-var-stumbleupon-circle: "\f1a3";
|
||||
$fa-var-subscript: "\f12c";
|
||||
$fa-var-subway: "\f239";
|
||||
$fa-var-suitcase: "\f0f2";
|
||||
$fa-var-sun-o: "\f185";
|
||||
$fa-var-superpowers: "\f2dd";
|
||||
$fa-var-superscript: "\f12b";
|
||||
$fa-var-support: "\f1cd";
|
||||
$fa-var-table: "\f0ce";
|
||||
|
@ -483,6 +666,8 @@ $fa-var-tag: "\f02b";
|
|||
$fa-var-tags: "\f02c";
|
||||
$fa-var-tasks: "\f0ae";
|
||||
$fa-var-taxi: "\f1ba";
|
||||
$fa-var-telegram: "\f2c6";
|
||||
$fa-var-television: "\f26c";
|
||||
$fa-var-tencent-weibo: "\f1d5";
|
||||
$fa-var-terminal: "\f120";
|
||||
$fa-var-text-height: "\f034";
|
||||
|
@ -490,6 +675,18 @@ $fa-var-text-width: "\f035";
|
|||
$fa-var-th: "\f00a";
|
||||
$fa-var-th-large: "\f009";
|
||||
$fa-var-th-list: "\f00b";
|
||||
$fa-var-themeisle: "\f2b2";
|
||||
$fa-var-thermometer: "\f2c7";
|
||||
$fa-var-thermometer-0: "\f2cb";
|
||||
$fa-var-thermometer-1: "\f2ca";
|
||||
$fa-var-thermometer-2: "\f2c9";
|
||||
$fa-var-thermometer-3: "\f2c8";
|
||||
$fa-var-thermometer-4: "\f2c7";
|
||||
$fa-var-thermometer-empty: "\f2cb";
|
||||
$fa-var-thermometer-full: "\f2c7";
|
||||
$fa-var-thermometer-half: "\f2c9";
|
||||
$fa-var-thermometer-quarter: "\f2ca";
|
||||
$fa-var-thermometer-three-quarters: "\f2c8";
|
||||
$fa-var-thumb-tack: "\f08d";
|
||||
$fa-var-thumbs-down: "\f165";
|
||||
$fa-var-thumbs-o-down: "\f088";
|
||||
|
@ -499,6 +696,8 @@ $fa-var-ticket: "\f145";
|
|||
$fa-var-times: "\f00d";
|
||||
$fa-var-times-circle: "\f057";
|
||||
$fa-var-times-circle-o: "\f05c";
|
||||
$fa-var-times-rectangle: "\f2d3";
|
||||
$fa-var-times-rectangle-o: "\f2d4";
|
||||
$fa-var-tint: "\f043";
|
||||
$fa-var-toggle-down: "\f150";
|
||||
$fa-var-toggle-left: "\f191";
|
||||
|
@ -506,10 +705,15 @@ $fa-var-toggle-off: "\f204";
|
|||
$fa-var-toggle-on: "\f205";
|
||||
$fa-var-toggle-right: "\f152";
|
||||
$fa-var-toggle-up: "\f151";
|
||||
$fa-var-trademark: "\f25c";
|
||||
$fa-var-train: "\f238";
|
||||
$fa-var-transgender: "\f224";
|
||||
$fa-var-transgender-alt: "\f225";
|
||||
$fa-var-trash: "\f1f8";
|
||||
$fa-var-trash-o: "\f014";
|
||||
$fa-var-tree: "\f1bb";
|
||||
$fa-var-trello: "\f181";
|
||||
$fa-var-tripadvisor: "\f262";
|
||||
$fa-var-trophy: "\f091";
|
||||
$fa-var-truck: "\f0d1";
|
||||
$fa-var-try: "\f195";
|
||||
|
@ -517,26 +721,45 @@ $fa-var-tty: "\f1e4";
|
|||
$fa-var-tumblr: "\f173";
|
||||
$fa-var-tumblr-square: "\f174";
|
||||
$fa-var-turkish-lira: "\f195";
|
||||
$fa-var-tv: "\f26c";
|
||||
$fa-var-twitch: "\f1e8";
|
||||
$fa-var-twitter: "\f099";
|
||||
$fa-var-twitter-square: "\f081";
|
||||
$fa-var-umbrella: "\f0e9";
|
||||
$fa-var-underline: "\f0cd";
|
||||
$fa-var-undo: "\f0e2";
|
||||
$fa-var-universal-access: "\f29a";
|
||||
$fa-var-university: "\f19c";
|
||||
$fa-var-unlink: "\f127";
|
||||
$fa-var-unlock: "\f09c";
|
||||
$fa-var-unlock-alt: "\f13e";
|
||||
$fa-var-unsorted: "\f0dc";
|
||||
$fa-var-upload: "\f093";
|
||||
$fa-var-usb: "\f287";
|
||||
$fa-var-usd: "\f155";
|
||||
$fa-var-user: "\f007";
|
||||
$fa-var-user-circle: "\f2bd";
|
||||
$fa-var-user-circle-o: "\f2be";
|
||||
$fa-var-user-md: "\f0f0";
|
||||
$fa-var-user-o: "\f2c0";
|
||||
$fa-var-user-plus: "\f234";
|
||||
$fa-var-user-secret: "\f21b";
|
||||
$fa-var-user-times: "\f235";
|
||||
$fa-var-users: "\f0c0";
|
||||
$fa-var-vcard: "\f2bb";
|
||||
$fa-var-vcard-o: "\f2bc";
|
||||
$fa-var-venus: "\f221";
|
||||
$fa-var-venus-double: "\f226";
|
||||
$fa-var-venus-mars: "\f228";
|
||||
$fa-var-viacoin: "\f237";
|
||||
$fa-var-viadeo: "\f2a9";
|
||||
$fa-var-viadeo-square: "\f2aa";
|
||||
$fa-var-video-camera: "\f03d";
|
||||
$fa-var-vimeo: "\f27d";
|
||||
$fa-var-vimeo-square: "\f194";
|
||||
$fa-var-vine: "\f1ca";
|
||||
$fa-var-vk: "\f189";
|
||||
$fa-var-volume-control-phone: "\f2a0";
|
||||
$fa-var-volume-down: "\f027";
|
||||
$fa-var-volume-off: "\f026";
|
||||
$fa-var-volume-up: "\f028";
|
||||
|
@ -544,17 +767,33 @@ $fa-var-warning: "\f071";
|
|||
$fa-var-wechat: "\f1d7";
|
||||
$fa-var-weibo: "\f18a";
|
||||
$fa-var-weixin: "\f1d7";
|
||||
$fa-var-whatsapp: "\f232";
|
||||
$fa-var-wheelchair: "\f193";
|
||||
$fa-var-wheelchair-alt: "\f29b";
|
||||
$fa-var-wifi: "\f1eb";
|
||||
$fa-var-wikipedia-w: "\f266";
|
||||
$fa-var-window-close: "\f2d3";
|
||||
$fa-var-window-close-o: "\f2d4";
|
||||
$fa-var-window-maximize: "\f2d0";
|
||||
$fa-var-window-minimize: "\f2d1";
|
||||
$fa-var-window-restore: "\f2d2";
|
||||
$fa-var-windows: "\f17a";
|
||||
$fa-var-won: "\f159";
|
||||
$fa-var-wordpress: "\f19a";
|
||||
$fa-var-wpbeginner: "\f297";
|
||||
$fa-var-wpexplorer: "\f2de";
|
||||
$fa-var-wpforms: "\f298";
|
||||
$fa-var-wrench: "\f0ad";
|
||||
$fa-var-xing: "\f168";
|
||||
$fa-var-xing-square: "\f169";
|
||||
$fa-var-y-combinator: "\f23b";
|
||||
$fa-var-y-combinator-square: "\f1d4";
|
||||
$fa-var-yahoo: "\f19e";
|
||||
$fa-var-yc: "\f23b";
|
||||
$fa-var-yc-square: "\f1d4";
|
||||
$fa-var-yelp: "\f1e9";
|
||||
$fa-var-yen: "\f157";
|
||||
$fa-var-yoast: "\f2b1";
|
||||
$fa-var-youtube: "\f167";
|
||||
$fa-var-youtube-play: "\f16a";
|
||||
$fa-var-youtube-square: "\f166";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/
|
||||
|
||||
|
@ -11,7 +11,8 @@
|
|||
@import "fixed-width";
|
||||
@import "list";
|
||||
@import "bordered-pulled";
|
||||
@import "spinning";
|
||||
@import "animated";
|
||||
@import "rotated-flipped";
|
||||
@import "stacked";
|
||||
@import "icons";
|
||||
@import "screen-reader";
|
||||
|
|
|
@ -48,7 +48,7 @@ class Media extends StandardController
|
|||
|
||||
if (!file_put_contents($new_file_path, 'a'))
|
||||
{
|
||||
throw new \Exception('pute de merde');
|
||||
throw new \Exception('Cannot write file ' . $new_file_path);
|
||||
}
|
||||
|
||||
if (!rename($tmpfile_path, $new_file_path))
|
||||
|
@ -56,16 +56,6 @@ class Media extends StandardController
|
|||
throw new \Exception('Cannot create file ' . $new_file_path);
|
||||
}
|
||||
|
||||
if (!chown($new_file_path, fileowner($user_path)))
|
||||
{
|
||||
throw new \Exception('Cannot give file ' . $new_file_path . ' to user : ' . fileowner($user_path));
|
||||
}
|
||||
|
||||
if (!chgrp($new_file_path, filegroup($user_path)))
|
||||
{
|
||||
throw new \Exception('Cannot give file ' . $new_file_path . ' to group : ' . filegroup($user_path));
|
||||
}
|
||||
|
||||
if (!chmod($new_file_path, self::DEFAULT_CHMOD))
|
||||
{
|
||||
throw new \Exception('Cannot give file ' . $new_file_path . ' rights : ' . self::DEFAULT_CHMOD);
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
<?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;
|
||||
|
||||
/**
|
||||
* Classe des groups.
|
||||
*/
|
||||
class PhoneGroup extends StandardController
|
||||
{
|
||||
protected $model;
|
||||
|
||||
/**
|
||||
* Create a new phone group for a user.
|
||||
*
|
||||
* @param int $id_user : user id
|
||||
* @param stirng $name : Group name
|
||||
* @param array $phones_ids : Ids of the phones of the group
|
||||
*
|
||||
* @return mixed bool|int : false on error, new group id
|
||||
*/
|
||||
public function create(int $id_user, string $name, array $phones_ids)
|
||||
{
|
||||
$group = [
|
||||
'id_user' => $id_user,
|
||||
'name' => $name,
|
||||
];
|
||||
|
||||
$id_group = $this->get_model()->insert($group);
|
||||
if (!$id_group)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$internal_phone = new Phone($this->bdd);
|
||||
foreach ($phones_ids as $phone_id)
|
||||
{
|
||||
$phone = $internal_phone->get_for_user($id_user, $phone_id);
|
||||
if (!$phone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->get_model()->insert_phone_group_phone_relation($id_group, $phone_id);
|
||||
}
|
||||
|
||||
$internal_event = new Event($this->bdd);
|
||||
$internal_event->create($id_user, 'PHONE_GROUP_ADD', 'Ajout phone group : ' . $name);
|
||||
|
||||
return $id_group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a phone group for a user.
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param int $id_group : Group id
|
||||
* @param stirng $name : Group name
|
||||
* @param array $phones_ids : Ids of the phones of the group
|
||||
*
|
||||
* @return bool : False on error, true on success
|
||||
*/
|
||||
public function update_for_user(int $id_user, int $id_group, string $name, array $phones_ids)
|
||||
{
|
||||
$group = [
|
||||
'name' => $name,
|
||||
];
|
||||
|
||||
$result = $this->get_model()->update_for_user($id_user, $id_group, $group);
|
||||
|
||||
$this->get_model()->delete_phone_group_phone_relations($id_group);
|
||||
|
||||
$internal_phone = new Phone($this->bdd);
|
||||
$nb_phone_insert = 0;
|
||||
foreach ($phones_ids as $phone_id)
|
||||
{
|
||||
$phone = $internal_phone->get_for_user($id_user, $phone_id);
|
||||
if (!$phone)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->get_model()->insert_phone_group_phone_relation($id_group, $phone_id))
|
||||
{
|
||||
++$nb_phone_insert;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$result && $nb_phone_insert !== \count($phones_ids))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a group by his name for a user.
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param string $name : Group name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_by_name_for_user(int $id_user, string $name)
|
||||
{
|
||||
return $this->get_model()->get_by_name_for_user($id_user, $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get groups phones.
|
||||
*
|
||||
* @param int $id_group : Group id
|
||||
*
|
||||
* @return array : phones of the group
|
||||
*/
|
||||
public function get_phones($id_group)
|
||||
{
|
||||
return $this->get_model()->get_phones($id_group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the model for the Controller.
|
||||
*/
|
||||
protected function get_model(): \models\PhoneGroup
|
||||
{
|
||||
$this->model = $this->model ?? new \models\PhoneGroup($this->bdd);
|
||||
|
||||
return $this->model;
|
||||
}
|
||||
}
|
|
@ -23,27 +23,31 @@ use Monolog\Logger;
|
|||
*
|
||||
* @param int $id_user : User to insert scheduled for
|
||||
* @param $at : Scheduled date to send
|
||||
* @param string $text : Text of the message
|
||||
* @param ?int $id_phone : Id of the phone to send message with, null by default
|
||||
* @param bool $flash : Is the sms a flash sms, by default false
|
||||
* @param bool $mms : Is the sms a mms, by default false
|
||||
* @param array $numbers : Array of numbers to send message to, a number is an array ['number' => '+33XXX', 'data' => '{"key":"value", ...}']
|
||||
* @param array $contacts_ids : Contact ids to send message to
|
||||
* @param array $groups_ids : Group ids to send message to
|
||||
* @param array $conditional_group_ids : Conditional Groups ids to send message to
|
||||
* @param array $media_ids : Ids of the medias to link to scheduled message
|
||||
* @param string $text : Text of the message
|
||||
* @param ?int $id_phone : Id of the phone to send message with, null by default
|
||||
* @param ?int $id_phone_group : Id of the phone group to send message with, null by default
|
||||
* @param bool $flash : Is the sms a flash sms, by default false
|
||||
* @param bool $mms : Is the sms a mms, by default false
|
||||
* @param ?string $tag : A string tag to associate to sended SMS
|
||||
* @param array $numbers : Array of numbers to send message to, a number is an array ['number' => '+33XXX', 'data' => '{"key":"value", ...}']
|
||||
* @param array $contacts_ids : Contact ids to send message to
|
||||
* @param array $groups_ids : Group ids to send message to
|
||||
* @param array $conditional_group_ids : Conditional Groups ids to send message to
|
||||
* @param array $media_ids : Ids of the medias to link to scheduled message
|
||||
*
|
||||
* @return bool : false on error, new id on success
|
||||
*/
|
||||
public function create(int $id_user, $at, string $text, ?int $id_phone = null, bool $flash = false, bool $mms = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [], array $media_ids = [])
|
||||
public function create(int $id_user, $at, string $text, ?int $id_phone = null, ?int $id_phone_group = null, bool $flash = false, bool $mms = false, ?string $tag = null, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [], array $media_ids = [])
|
||||
{
|
||||
$scheduled = [
|
||||
'id_user' => $id_user,
|
||||
'at' => $at,
|
||||
'text' => $text,
|
||||
'id_phone' => $id_phone,
|
||||
'id_phone_group' => $id_phone_group,
|
||||
'flash' => $flash,
|
||||
'mms' => $mms,
|
||||
'tag' => $tag,
|
||||
];
|
||||
|
||||
if ('' === $text)
|
||||
|
@ -62,6 +66,17 @@ use Monolog\Logger;
|
|||
}
|
||||
}
|
||||
|
||||
if (null !== $id_phone_group)
|
||||
{
|
||||
$internal_phone_group = new PhoneGroup($this->bdd);
|
||||
$find_phone_group = $internal_phone_group->get_for_user($id_user, $id_phone_group);
|
||||
|
||||
if (!$find_phone_group)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Use transaction to garanty atomicity
|
||||
$this->bdd->beginTransaction();
|
||||
|
||||
|
@ -147,8 +162,10 @@ use Monolog\Logger;
|
|||
* @param $at : Scheduled date to send
|
||||
* @param string $text : Text of the message
|
||||
* @param ?int $id_phone : Id of the phone to send message with, null by default
|
||||
* @param ?int $id_phone_group : Id of the phone group to send message with, null by default
|
||||
* @param bool $flash : Is the sms a flash sms, by default false
|
||||
* @param bool $mms : Is the sms a mms, by default false
|
||||
* @param ?string $tag : A string tag to associate to sended SMS
|
||||
* @param array $numbers : Array of numbers to send message to, a number is an array ['number' => '+33XXX', 'data' => '{"key":"value", ...}']
|
||||
* @param array $contacts_ids : Contact ids to send message to
|
||||
* @param array $groups_ids : Group ids to send message to
|
||||
|
@ -157,15 +174,17 @@ use Monolog\Logger;
|
|||
*
|
||||
* @return bool : false on error, true on success
|
||||
*/
|
||||
public function update_for_user(int $id_user, int $id_scheduled, $at, string $text, ?string $id_phone = null, bool $flash = false, bool $mms = false, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [], array $media_ids = [])
|
||||
public function update_for_user(int $id_user, int $id_scheduled, $at, string $text, ?int $id_phone = null, ?int $id_phone_group = null, bool $flash = false, bool $mms = false, ?string $tag = null, array $numbers = [], array $contacts_ids = [], array $groups_ids = [], array $conditional_group_ids = [], array $media_ids = [])
|
||||
{
|
||||
$scheduled = [
|
||||
'id_user' => $id_user,
|
||||
'at' => $at,
|
||||
'text' => $text,
|
||||
'id_phone' => $id_phone,
|
||||
'id_phone_group' => $id_phone_group,
|
||||
'mms' => $mms,
|
||||
'flash' => $flash,
|
||||
'tag' => $tag,
|
||||
];
|
||||
|
||||
if (null !== $id_phone)
|
||||
|
@ -179,6 +198,17 @@ use Monolog\Logger;
|
|||
}
|
||||
}
|
||||
|
||||
if (null !== $id_phone_group)
|
||||
{
|
||||
$internal_phone_group = new PhoneGroup($this->bdd);
|
||||
$find_phone_group = $internal_phone_group->get_for_user($id_user, $id_phone_group);
|
||||
|
||||
if (!$find_phone_group)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//Ensure atomicity
|
||||
$this->bdd->beginTransaction();
|
||||
|
||||
|
@ -413,13 +443,14 @@ use Monolog\Logger;
|
|||
$internal_group = new \controllers\internals\Group($this->bdd);
|
||||
$internal_conditional_group = new \controllers\internals\ConditionalGroup($this->bdd);
|
||||
$internal_phone = new \controllers\internals\Phone($this->bdd);
|
||||
$internal_phone_group = new \controllers\internals\PhoneGroup($this->bdd);
|
||||
$internal_smsstop = new \controllers\internals\SmsStop($this->bdd);
|
||||
$internal_sended = new \controllers\internals\Sended($this->bdd);
|
||||
|
||||
$users_smsstops = [];
|
||||
$users_settings = [];
|
||||
$users_phones = [];
|
||||
$users_mms_phones = [];
|
||||
$users_phone_groups = [];
|
||||
|
||||
$now = new \DateTime();
|
||||
$now = $now->format('Y-m-d H:i:s');
|
||||
|
@ -457,7 +488,6 @@ use Monolog\Logger;
|
|||
if (!isset($users_phones[$id_user]))
|
||||
{
|
||||
$users_phones[$id_user] = [];
|
||||
$users_mms_phones[$id_user] = [];
|
||||
|
||||
$phones = $internal_phone->gets_for_user($id_user);
|
||||
foreach ($phones as &$phone)
|
||||
|
@ -475,25 +505,25 @@ use Monolog\Logger;
|
|||
$phone['remaining_volume'] = $remaining_volume;
|
||||
$users_phones[$id_user][$phone['id']] = $phone;
|
||||
}
|
||||
|
||||
$mms_phones = $internal_phone->gets_phone_supporting_mms_for_user($id_user, $internal_phone::MMS_SENDING);
|
||||
foreach ($mms_phones as &$mms_phone)
|
||||
{
|
||||
$limits = $internal_phone->get_limits($mms_phone['id']);
|
||||
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $internal_sended->count_since_for_phone_and_user($id_user, $mms_phone['id'], $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
|
||||
$mms_phone['remaining_volume'] = $remaining_volume;
|
||||
$users_mms_phones[$id_user][$mms_phone['id']] = $mms_phone;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($users_phone_groups[$id_user]))
|
||||
{
|
||||
$users_phone_groups[$id_user] = [];
|
||||
|
||||
$phone_groups = $internal_phone_group->gets_for_user($id_user);
|
||||
foreach ($phone_groups as $phone_group)
|
||||
{
|
||||
$phones = $internal_phone_group->get_phones($phone_group['id']);
|
||||
$phone_group['phones'] = [];
|
||||
foreach ($phones as $phone)
|
||||
{
|
||||
$phone_group['phones'][] = $phone['id'];
|
||||
}
|
||||
|
||||
$users_phone_groups[$id_user][$phone_group['id']] = $phone_group;
|
||||
}
|
||||
}
|
||||
|
||||
//Add medias to mms
|
||||
$scheduled['medias'] = [];
|
||||
|
@ -509,6 +539,12 @@ use Monolog\Logger;
|
|||
$phone_to_use = $users_phones[$id_user][$scheduled['id_phone']] ?? null;
|
||||
}
|
||||
|
||||
$phone_group_to_use = null;
|
||||
if ($scheduled['id_phone_group'])
|
||||
{
|
||||
$phone_group_to_use = $users_phone_groups[$id_user][$scheduled['id_phone_group']] ?? null;
|
||||
}
|
||||
|
||||
|
||||
// We turn all contacts, groups and conditional groups into just contacts
|
||||
$contacts = $this->get_contacts($id_scheduled);
|
||||
|
@ -620,36 +656,63 @@ use Monolog\Logger;
|
|||
if (null === $phone_to_use)
|
||||
{
|
||||
$phones_subset = $users_phones[$id_user];
|
||||
if ($scheduled['mms'])
|
||||
|
||||
if ($phone_group_to_use)
|
||||
{
|
||||
$phones_subset = $users_mms_phones[$id_user] ?: $phones_subset;
|
||||
$phones_subset = array_filter($phones_subset, function ($phone) use ($phone_group_to_use) {
|
||||
return in_array($phone['id'], $phone_group_to_use['phones']);
|
||||
});
|
||||
}
|
||||
|
||||
if ($scheduled['mms'])
|
||||
{
|
||||
$mms_only = array_filter($phones_subset, function ($phone) {
|
||||
return $phone['adapter']::meta_support_mms_sending();
|
||||
});
|
||||
|
||||
$phones_subset = $mms_only ?: $phones_subset;
|
||||
}
|
||||
|
||||
// Keep only available phones
|
||||
$remaining_volume_phones = array_filter($phones_subset, function ($phone) {
|
||||
return $phone['remaining_volume'] > 0;
|
||||
return $phone['status'] == \models\Phone::STATUS_AVAILABLE;
|
||||
});
|
||||
$phones_subset = $remaining_volume_phones ?: $phones_subset;
|
||||
|
||||
$max_priority_phones = [];
|
||||
$max_priority = PHP_INT_MIN;
|
||||
foreach ($phones_subset as $phone)
|
||||
|
||||
// Keep only phones with remaining volume
|
||||
if ((int) ($users_settings[$id_user]['phone_limit'] ?? false))
|
||||
{
|
||||
if ($phone['priority'] < $max_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elseif ($phone['priority'] == $max_priority)
|
||||
{
|
||||
$max_priority_phones[] = $phone;
|
||||
}
|
||||
elseif ($phone['priority'] > $max_priority)
|
||||
{
|
||||
$max_priority_phones = [$phone];
|
||||
$max_priority = $phone['priority'];
|
||||
}
|
||||
$remaining_volume_phones = array_filter($phones_subset, function ($phone) {
|
||||
return $phone['remaining_volume'] > 0;
|
||||
});
|
||||
$phones_subset = $remaining_volume_phones ?: $phones_subset;
|
||||
}
|
||||
|
||||
if ((int) ($users_settings[$id_user]['phone_priority'] ?? false))
|
||||
{
|
||||
$max_priority_phones = [];
|
||||
$max_priority = PHP_INT_MIN;
|
||||
foreach ($phones_subset as $phone)
|
||||
{
|
||||
if ($phone['priority'] < $max_priority)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
elseif ($phone['priority'] == $max_priority)
|
||||
{
|
||||
$max_priority_phones[] = $phone;
|
||||
}
|
||||
elseif ($phone['priority'] > $max_priority)
|
||||
{
|
||||
$max_priority_phones = [$phone];
|
||||
$max_priority = $phone['priority'];
|
||||
}
|
||||
}
|
||||
|
||||
$phones_subset = $max_priority_phones;
|
||||
}
|
||||
|
||||
$phones_subset = $max_priority_phones;
|
||||
if ($phones_subset)
|
||||
{
|
||||
$random_phone = $phones_subset[array_rand($phones_subset)];
|
||||
|
@ -670,16 +733,13 @@ use Monolog\Logger;
|
|||
'destination' => $target['number'],
|
||||
'flash' => $scheduled['flash'],
|
||||
'mms' => $scheduled['mms'],
|
||||
'tag' => $scheduled['tag'],
|
||||
'medias' => $scheduled['medias'],
|
||||
'text' => $text,
|
||||
];
|
||||
|
||||
// Consume one sms from remaining volume of phone, dont forget to do the same for the entry in mms phones
|
||||
// Consume one sms from remaining volume of phone
|
||||
$users_phones[$id_user][$id_phone]['remaining_volume'] --;
|
||||
if ($users_mms_phones[$id_user][$id_phone] ?? false)
|
||||
{
|
||||
$users_mms_phones[$id_user][$id_phone] --;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace controllers\internals;
|
||||
|
||||
use Exception;
|
||||
|
||||
class Sended extends StandardController
|
||||
{
|
||||
protected $model;
|
||||
|
@ -44,13 +46,14 @@ namespace controllers\internals;
|
|||
* @param string $adapter : Name of the adapter service used to send the message
|
||||
* @param bool $flash : Is the sms a flash
|
||||
* @param bool $mms : Is the sms a MMS. By default false.
|
||||
* @param ?string $tag : A string tag to associate to sended SMS
|
||||
* @param array $medias : Array of medias to link to the MMS
|
||||
* @param ?int $originating_scheduled : Id of the scheduled message that was responsible for sending this message. By default null.
|
||||
* @param string $status : Status of a the sms. By default \models\Sended::STATUS_UNKNOWN
|
||||
*
|
||||
* @return mixed : false on error, new sended id else
|
||||
*/
|
||||
public function create(int $id_user, int $id_phone, $at, string $text, string $destination, string $uid, string $adapter, bool $flash = false, bool $mms = false, array $medias = [], ?int $originating_scheduled = null, ?string $status = \models\Sended::STATUS_UNKNOWN)
|
||||
public function create(int $id_user, int $id_phone, $at, string $text, string $destination, string $uid, string $adapter, bool $flash = false, bool $mms = false, ?string $tag = null, array $medias = [], ?int $originating_scheduled = null, ?string $status = \models\Sended::STATUS_UNKNOWN)
|
||||
{
|
||||
$sended = [
|
||||
'id_user' => $id_user,
|
||||
|
@ -62,6 +65,7 @@ namespace controllers\internals;
|
|||
'adapter' => $adapter,
|
||||
'flash' => $flash,
|
||||
'mms' => $mms,
|
||||
'tag' => $tag,
|
||||
'status' => $status,
|
||||
'originating_scheduled' => $originating_scheduled,
|
||||
];
|
||||
|
@ -184,13 +188,15 @@ namespace controllers\internals;
|
|||
*
|
||||
* @param int $id_user : User id
|
||||
* @param int $id_phone : Phone id we want the number of sended message for
|
||||
* @param \DateTime $since : Date since which we want sended number
|
||||
* @param ?\DateTime $since : Date since which we want sended number. Default to null.
|
||||
* @param ?\DateTime $before : Date up to which we want sended number. Default to null.
|
||||
* @param ?string $tag_like : Tag to filter sms by, this is not a = but a LIKE operator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, \DateTime $since): int
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, ?\DateTime $since, ?\DateTime $before = null, ?string $tag_like = null): int
|
||||
{
|
||||
return $this->get_model()->count_since_for_phone_and_user($id_user, $id_phone, $since);
|
||||
return $this->get_model()->count_since_for_phone_and_user($id_user, $id_phone, $since, $before, $tag_like);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -236,6 +242,7 @@ namespace controllers\internals;
|
|||
* @param $text : Text of the message
|
||||
* @param string $destination : Number of the receiver
|
||||
* @param bool $flash : Is the sms a flash. By default false.
|
||||
* @param ?string $tag : A string tag to associate to sended SMS
|
||||
* @param bool $mms : Is the sms a MMS. By default false.
|
||||
* @param array $medias : Array of medias to link to the MMS
|
||||
* @param string $status : Status of a the sms. By default \models\Sended::STATUS_UNKNOWN
|
||||
|
@ -246,13 +253,16 @@ namespace controllers\internals;
|
|||
* ?string 'error_message' => null if success, error message else
|
||||
* ]
|
||||
*/
|
||||
public function send(\adapters\AdapterInterface $adapter, int $id_user, int $id_phone, string $text, string $destination, bool $flash = false, bool $mms = false, array $medias = [], $originating_scheduled = null, string $status = \models\Sended::STATUS_UNKNOWN): array
|
||||
public function send(\adapters\AdapterInterface $adapter, int $id_user, int $id_phone, string $text, string $destination, bool $flash = false, bool $mms = false, ?string $tag = null, array $medias = [], $originating_scheduled = null, string $status = \models\Sended::STATUS_UNKNOWN): array
|
||||
{
|
||||
$return = [
|
||||
'error' => false,
|
||||
'error_message' => null,
|
||||
];
|
||||
|
||||
$internal_setting = new Setting();
|
||||
$user_settings = $internal_setting->gets_for_user($id_user);
|
||||
|
||||
$at = (new \DateTime())->format('Y-m-d H:i:s');
|
||||
$media_uris = [];
|
||||
foreach ($medias as $media)
|
||||
|
@ -275,71 +285,87 @@ namespace controllers\internals;
|
|||
$text .= "\n" . join(' - ', $media_urls);
|
||||
}
|
||||
|
||||
//If we reached our max quota, do not send the message
|
||||
$internal_quota = new Quota($this->bdd);
|
||||
$nb_credits = $internal_quota::compute_credits_for_message($text); //Calculate how much credit the message require
|
||||
if (!$internal_quota->has_enough_credit($id_user, $nb_credits))
|
||||
try
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = 'Not enough credit to send message.';
|
||||
}
|
||||
//If we reached our max quota, do not send the message
|
||||
$internal_quota = new Quota($this->bdd);
|
||||
$nb_credits = $internal_quota::compute_credits_for_message($text); //Calculate how much credit the message require
|
||||
if (!$internal_quota->has_enough_credit($id_user, $nb_credits))
|
||||
{
|
||||
throw new Exception('Not enough credit to send message.');
|
||||
}
|
||||
|
||||
//If we reached limit for this phone, do not send the message
|
||||
$internal_phone = new Phone($this->bdd);
|
||||
$internal_sended = new Sended($this->bdd);
|
||||
$limits = $internal_phone->get_limits($id_phone);
|
||||
// If this phone status indicate it is not available
|
||||
$internal_phone = new Phone($this->bdd);
|
||||
$phone = $internal_phone->get_for_user($id_user, $id_phone);
|
||||
if (!$phone || $phone['status'] != \models\Phone::STATUS_AVAILABLE)
|
||||
{
|
||||
throw new Exception('Invalid phone status : ' . $phone['status']);
|
||||
}
|
||||
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $internal_sended->count_since_for_phone_and_user($id_user, $id_phone, $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
//If we reached limit for this phone and phone limits are enabled, do not send the message
|
||||
if ((int) ($user_settings['phone_limit'] ?? false))
|
||||
{
|
||||
$limits = $internal_phone->get_limits($id_phone);
|
||||
|
||||
if ($remaining_volume < 1)
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = 'Phone send limit have been reached.';
|
||||
}
|
||||
$remaining_volume = PHP_INT_MAX;
|
||||
foreach ($limits as $limit)
|
||||
{
|
||||
$startpoint = new \DateTime($limit['startpoint']);
|
||||
$consumed = $this->count_since_for_phone_and_user($id_user, $id_phone, $startpoint);
|
||||
$remaining_volume = min(($limit['volume'] - $consumed), $remaining_volume);
|
||||
}
|
||||
|
||||
if ($remaining_volume < 1)
|
||||
{
|
||||
throw new Exception('Phone send limit have been reached.');
|
||||
}
|
||||
}
|
||||
|
||||
$uid = uniqid();
|
||||
if (!$return['error'])
|
||||
{
|
||||
$response = $adapter->send($destination, $text, $flash, $mms, $media_uris);
|
||||
$uid = $response['uid'] ?? $uid;
|
||||
|
||||
if ($response['error'])
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = $response['error_message'];
|
||||
}
|
||||
else // If send with success, consume credit
|
||||
{
|
||||
$internal_quota->consume_credit($id_user, $nb_credits);
|
||||
throw new Exception($response['error_message']);
|
||||
}
|
||||
|
||||
$uid = $response['uid'];
|
||||
$status = \models\Sended::STATUS_UNKNOWN;
|
||||
|
||||
// If send with success, consume credit
|
||||
$internal_quota->consume_credit($id_user, $nb_credits);
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
$return['error'] = true;
|
||||
$return['error_message'] = $e->getMessage();
|
||||
|
||||
// If we fail to send or not, we will always save message as sended, only the status will change.
|
||||
$status = $return['error'] ? \models\Sended::STATUS_FAILED : \models\Sended::STATUS_UNKNOWN;
|
||||
$sended_id = $this->create($id_user, $id_phone, $at, $text, $destination, $uid, $adapter->meta_classname(), $flash, $mms, $medias, $originating_scheduled, $status);
|
||||
$status = \models\Sended::STATUS_FAILED;
|
||||
|
||||
$webhook_body = [
|
||||
'id' => $sended_id,
|
||||
'at' => $at,
|
||||
'status' => $status,
|
||||
'text' => $text,
|
||||
'destination' => $destination,
|
||||
'origin' => $id_phone,
|
||||
'mms' => $mms,
|
||||
'medias' => $medias,
|
||||
'originating_scheduled' => $originating_scheduled,
|
||||
];
|
||||
return $return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
$uid = $uid ?? uniqid();
|
||||
$sended_id = $this->create($id_user, $id_phone, $at, $text, $destination, $uid, $adapter->meta_classname(), $flash, $mms, $tag, $medias, $originating_scheduled, $status);
|
||||
|
||||
$internal_webhook = new Webhook($this->bdd);
|
||||
$internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $webhook_body);
|
||||
$webhook_body = [
|
||||
'id' => $sended_id,
|
||||
'at' => $at,
|
||||
'status' => $status,
|
||||
'text' => $text,
|
||||
'destination' => $destination,
|
||||
'origin' => $id_phone,
|
||||
'mms' => $mms,
|
||||
'medias' => $medias,
|
||||
'originating_scheduled' => $originating_scheduled,
|
||||
];
|
||||
|
||||
return $return;
|
||||
$internal_webhook = new Webhook($this->bdd);
|
||||
$internal_webhook->trigger($id_user, \models\Webhook::TYPE_SEND_SMS, $webhook_body);
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -49,6 +49,7 @@ namespace controllers\publics;
|
|||
|
||||
private $internal_user;
|
||||
private $internal_phone;
|
||||
private $internal_phone_group;
|
||||
private $internal_received;
|
||||
private $internal_sended;
|
||||
private $internal_scheduled;
|
||||
|
@ -72,6 +73,7 @@ namespace controllers\publics;
|
|||
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
|
||||
$this->internal_user = new \controllers\internals\User($bdd);
|
||||
$this->internal_phone = new \controllers\internals\Phone($bdd);
|
||||
$this->internal_phone_group = new \controllers\internals\PhoneGroup($bdd);
|
||||
$this->internal_received = new \controllers\internals\Received($bdd);
|
||||
$this->internal_sended = new \controllers\internals\Sended($bdd);
|
||||
$this->internal_scheduled = new \controllers\internals\Scheduled($bdd);
|
||||
|
@ -118,14 +120,14 @@ namespace controllers\publics;
|
|||
/**
|
||||
* List all entries of a certain type for the current user, sorted by id.
|
||||
*
|
||||
* @param string $entry_type : Type of entries we want to list ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone', 'media']
|
||||
* @param string $entry_type : Type of entries we want to list ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone', 'phone_group', 'media']
|
||||
* @param int $page : Pagination number, Default = 0. Group of 25 results.
|
||||
*
|
||||
* @return : List of entries
|
||||
*/
|
||||
public function get_entries(string $entry_type, int $page = 0)
|
||||
{
|
||||
$entry_types = ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone', 'media'];
|
||||
$entry_types = ['sended', 'received', 'scheduled', 'contact', 'group', 'conditional_group', 'phone', 'phone_group', 'media'];
|
||||
|
||||
if (!\in_array($entry_type, $entry_types, true))
|
||||
{
|
||||
|
@ -191,6 +193,26 @@ namespace controllers\publics;
|
|||
unset($entries[$key]['adapter_data']);
|
||||
}
|
||||
}
|
||||
// Special case for phone group we must add phones because its a join
|
||||
elseif ('phone_group' === $entry_type)
|
||||
{
|
||||
foreach ($entries as $key => $entry)
|
||||
{
|
||||
$phones = $this->internal_phone_group->get_phones($entry['id']);
|
||||
// Hide meta data of phones if needed
|
||||
foreach ($phones as &$phone)
|
||||
{
|
||||
if (!$phone['adapter']::meta_hide_data())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($phone['adapter_data']);
|
||||
}
|
||||
|
||||
$entries[$key]['phones'] = $phones;
|
||||
}
|
||||
}
|
||||
|
||||
$return = self::DEFAULT_RETURN;
|
||||
$return['response'] = $entries;
|
||||
|
@ -210,14 +232,84 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return info about volume of sms sended for a period
|
||||
*
|
||||
* @param ?string $_POST['start'] : Date from which to get sms volume, format Y-m-d H:i:s. Default to null.
|
||||
* @param ?string $_POST['end'] : Date up to which to get sms volume, format Y-m-d H:i:s. Default to null.
|
||||
* @param ?string $_POST['tag'] : Tag to filter SMS by. If set, only sended sms with a matching tag will be counted. Default to null.
|
||||
*
|
||||
* @return : List of entries
|
||||
*/
|
||||
public function get_usage()
|
||||
{
|
||||
$start = $_GET['start'] ?? null;
|
||||
$end = $_GET['end'] ?? null;
|
||||
$tag = $_GET['tag'] ?? null;
|
||||
|
||||
$return = self::DEFAULT_RETURN;
|
||||
|
||||
if ($start)
|
||||
{
|
||||
if (!\controllers\internals\Tool::validate_date($start, 'Y-m-d H:i:s'))
|
||||
{
|
||||
$return = self::DEFAULT_RETURN;
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'start must be a date of format "Y-m-d H:i:s".';
|
||||
$this->auto_http_code(false);
|
||||
|
||||
return $this->json($return);
|
||||
}
|
||||
|
||||
$start = new \DateTime($start);
|
||||
}
|
||||
|
||||
if ($end)
|
||||
{
|
||||
if (!\controllers\internals\Tool::validate_date($end, 'Y-m-d H:i:s'))
|
||||
{
|
||||
$return = self::DEFAULT_RETURN;
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'end must be a date of format "Y-m-d H:i:s".';
|
||||
$this->auto_http_code(false);
|
||||
|
||||
return $this->json($return);
|
||||
}
|
||||
|
||||
$end = new \DateTime($end);
|
||||
}
|
||||
|
||||
$total_sended = 0;
|
||||
$phones_volumes = [];
|
||||
|
||||
$phones = $this->internal_phone->gets_for_user($this->user['id']);
|
||||
foreach ($phones as $phone)
|
||||
{
|
||||
$nb_sended = $this->internal_sended->count_since_for_phone_and_user($this->user['id'], $phone['id'], $start, $end, $tag);
|
||||
$total_sended += $nb_sended;
|
||||
$phones_volumes[$phone['id']] = $nb_sended;
|
||||
}
|
||||
|
||||
$return['response'] = [
|
||||
'total' => $total_sended,
|
||||
'phones_volumes' => $phones_volumes,
|
||||
];
|
||||
|
||||
$this->auto_http_code(true);
|
||||
|
||||
return $this->json($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a message to be send.
|
||||
*
|
||||
* @param string $_POST['at'] : Date to send message at format Y-m-d H:i:s
|
||||
* @param string $_POST['text'] : Text of the message to send
|
||||
* @param string $_POST['id_phone'] : Default null. Id of phone to send the message from. If null use a random phone
|
||||
* @param string $_POST['id_phone'] : Default null. Id of phone to send the message from. If null and id_phone_group null, use a random phone
|
||||
* @param string $_POST['id_phone_group'] : Default null. Id of phone group to send the message from. If null abd id_phone null, use a random phone
|
||||
* @param string $_POST['flash'] : Default false. Is the sms a flash sms.
|
||||
* @param string $_POST['mms'] : Default false. Is the sms a mms.
|
||||
* @param string $_POST['tag'] : Default null. Tag to associate to every sms of the campaign.
|
||||
* @param string $_POST['numbers'] : Array of numbers to send message to
|
||||
* @param string $_POST['contacts'] : Array of ids of contacts to send message to
|
||||
* @param string $_POST['groups'] : Array of ids of groups to send message to
|
||||
|
@ -231,8 +323,10 @@ namespace controllers\publics;
|
|||
$at = $_POST['at'] ?? false;
|
||||
$text = $_POST['text'] ?? false;
|
||||
$id_phone = empty($_POST['id_phone']) ? null : $_POST['id_phone'];
|
||||
$id_phone_group = empty($_POST['id_phone_group']) ? null : $_POST['id_phone_group'];
|
||||
$flash = (bool) ($_POST['flash'] ?? false);
|
||||
$mms = (bool) ($_POST['mms'] ?? false);
|
||||
$tag = $_POST['tag'] ?? null;
|
||||
$numbers = $_POST['numbers'] ?? [];
|
||||
$contacts = $_POST['contacts'] ?? [];
|
||||
$groups = $_POST['groups'] ?? [];
|
||||
|
@ -417,6 +511,16 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
if ($id_phone && $id_phone_group)
|
||||
{
|
||||
$return = self::DEFAULT_RETURN;
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'id_phone, id_phone_group : You must specify at most one of id_phone or id_phone_group, not both.';
|
||||
$this->auto_http_code(false);
|
||||
|
||||
return $this->json($return);
|
||||
}
|
||||
|
||||
$phone = null;
|
||||
if ($id_phone)
|
||||
{
|
||||
|
@ -433,6 +537,22 @@ namespace controllers\publics;
|
|||
return $this->json($return);
|
||||
}
|
||||
|
||||
$phone_group = null;
|
||||
if ($id_phone_group)
|
||||
{
|
||||
$phone_group = $this->internal_phone_group->get_for_user($this->user['id'], $id_phone_group);
|
||||
}
|
||||
|
||||
if ($id_phone_group && !$phone_group)
|
||||
{
|
||||
$return = self::DEFAULT_RETURN;
|
||||
$return['error'] = self::ERROR_CODES['INVALID_PARAMETER'];
|
||||
$return['message'] = self::ERROR_MESSAGES['INVALID_PARAMETER'] . 'id_phone_group : You must specify an id_phone_group number among thoses of user phone groups.';
|
||||
$this->auto_http_code(false);
|
||||
|
||||
return $this->json($return);
|
||||
}
|
||||
|
||||
if ($mms)
|
||||
{
|
||||
foreach ($files_arrays as $file)
|
||||
|
@ -455,7 +575,7 @@ namespace controllers\publics;
|
|||
}
|
||||
}
|
||||
|
||||
$scheduled_id = $this->internal_scheduled->create($this->user['id'], $at, $text, $id_phone, $flash, $mms, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
$scheduled_id = $this->internal_scheduled->create($this->user['id'], $at, $text, $id_phone, $id_phone_group, $flash, $mms, $tag, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
if (!$scheduled_id)
|
||||
{
|
||||
$return = self::DEFAULT_RETURN;
|
||||
|
@ -710,7 +830,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 +1010,35 @@ 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'];
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ namespace controllers\publics;
|
|||
$at = $now;
|
||||
$text = $_POST['text'] ?? '';
|
||||
$destination = $_POST['destination'] ?? false;
|
||||
$tag = $_POST['tag'] ?? null;
|
||||
$id_phone = $_POST['id_phone'] ?? false;
|
||||
$files = $_FILES['medias'] ?? false;
|
||||
|
||||
|
@ -315,7 +316,7 @@ namespace controllers\publics;
|
|||
//Destinations must be an array of number
|
||||
$destinations = [['number' => $destination, 'data' => '[]']];
|
||||
|
||||
if (!$this->internal_scheduled->create($id_user, $at, $text, $id_phone, false, $mms, $destinations, [], [], [], $media_ids))
|
||||
if (!$this->internal_scheduled->create($id_user, $at, $text, $id_phone, null, false, $mms, $tag, $destinations, [], [], [], $media_ids))
|
||||
{
|
||||
$return['success'] = false;
|
||||
$return['message'] = 'Impossible de créer le Sms';
|
||||
|
|
|
@ -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,53 @@ 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'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of phones as a JSON array
|
||||
*/
|
||||
public function json_list()
|
||||
{
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($this->internal_phone->list_for_user($_SESSION['user']['id']));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,245 @@
|
|||
<?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 of phone groups.
|
||||
*/
|
||||
class PhoneGroup extends \descartes\Controller
|
||||
{
|
||||
private $internal_phone_group;
|
||||
private $internal_phone;
|
||||
private $internal_event;
|
||||
|
||||
/**
|
||||
* Call before any other func to check user is connected
|
||||
*
|
||||
* @return void;
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$bdd = \descartes\Model::_connect(DATABASE_HOST, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD);
|
||||
|
||||
$this->internal_phone_group = new \controllers\internals\PhoneGroup($bdd);
|
||||
$this->internal_phone = new \controllers\internals\Phone($bdd);
|
||||
$this->internal_event = new \controllers\internals\Event($bdd);
|
||||
|
||||
\controllers\internals\Tool::verifyconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all groups as an array for administration.
|
||||
*/
|
||||
public function list()
|
||||
{
|
||||
$this->render('phone_group/list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return groups as json.
|
||||
*/
|
||||
public function list_json()
|
||||
{
|
||||
$entities = $this->internal_phone_group->list_for_user($_SESSION['user']['id']);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['data' => $entities]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a list of phone groups
|
||||
*
|
||||
* @param array int $_GET['ids'] : Ids of phone groups to delete
|
||||
* @param mixed $csrf
|
||||
*
|
||||
* @return boolean;
|
||||
*/
|
||||
public function delete($csrf)
|
||||
{
|
||||
if (!$this->verify_csrf($csrf))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
$ids = $_GET['ids'] ?? [];
|
||||
foreach ($ids as $id)
|
||||
{
|
||||
$this->internal_phone_group->delete_for_user($_SESSION['user']['id'], $id);
|
||||
}
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the creation page of a group
|
||||
*/
|
||||
public function add()
|
||||
{
|
||||
$this->render('phone_group/add');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the edition page for phone groups
|
||||
*
|
||||
* @param array $_GET['ids'] : Ids of phone groups to edit
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$ids = $_GET['ids'] ?? [];
|
||||
|
||||
$groups = $this->internal_phone_group->gets_in_for_user($_SESSION['user']['id'], $ids);
|
||||
|
||||
foreach ($groups as $key => $group)
|
||||
{
|
||||
$groups[$key]['phones'] = $this->internal_phone_group->get_phones($group['id']);
|
||||
}
|
||||
|
||||
$this->render('phone_group/edit', [
|
||||
'phone_groups' => $groups,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new phone group
|
||||
*
|
||||
* @param $csrf : CSRF token
|
||||
* @param string $_POST['name'] : Name of phone group
|
||||
* @param array $_POST['phones'] : Ids of phones to put in the group
|
||||
*/
|
||||
public function create($csrf)
|
||||
{
|
||||
if (!$this->verify_csrf($csrf))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'add'));
|
||||
}
|
||||
|
||||
$name = $_POST['name'] ?? false;
|
||||
$phones_ids = $_POST['phones'] ?? false;
|
||||
|
||||
if (!$name || !$phones_ids)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Des champs sont manquants !');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'add'));
|
||||
}
|
||||
|
||||
$id_group = $this->internal_phone_group->create($_SESSION['user']['id'], $name, $phones_ids);
|
||||
if (!$id_group)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer ce groupe.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'add'));
|
||||
}
|
||||
|
||||
\FlashMessage\FlashMessage::push('success', 'Le groupe a bien été créé.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a list of phone groups
|
||||
*
|
||||
* @param $csrf : CSRF token
|
||||
* @param array $_POST['phone_groups'] : An array of phone groups with group id as keys
|
||||
*
|
||||
* @return boolean;
|
||||
*/
|
||||
public function update($csrf)
|
||||
{
|
||||
if (!$this->verify_csrf($csrf))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Jeton CSRF invalid !');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
$groups = $_POST['phone_groups'] ?? [];
|
||||
|
||||
$nb_groups_update = 0;
|
||||
foreach ($groups as $id => $group)
|
||||
{
|
||||
foreach ($group['phones_ids'] as $key => $value)
|
||||
{
|
||||
$group['phones_ids'][$key] = (int) $value;
|
||||
}
|
||||
|
||||
$nb_groups_update += (int) $this->internal_phone_group->update_for_user($_SESSION['user']['id'], $id, $group['name'], $group['phones_ids']);
|
||||
}
|
||||
|
||||
if ($nb_groups_update !== \count($groups))
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Certains groupes n\'ont pas pu êtres mis à jour.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
\FlashMessage\FlashMessage::push('success', 'Tous les groupes ont été modifiés avec succès.');
|
||||
|
||||
return $this->redirect(\descartes\Router::url('PhoneGroup', 'list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return phones of a group as json array
|
||||
* @param int $id_group = PhoneGroup id
|
||||
*
|
||||
* @return json
|
||||
*/
|
||||
public function preview (int $id_group)
|
||||
{
|
||||
$return = [
|
||||
'success' => false,
|
||||
'result' => 'Une erreur inconnue est survenue.',
|
||||
];
|
||||
|
||||
$group = $this->internal_phone_group->get_for_user($_SESSION['user']['id'], $id_group);
|
||||
|
||||
if (!$group)
|
||||
{
|
||||
$return['result'] = 'Ce groupe n\'existe pas.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$phones = $this->internal_phone_group->get_phones($id_group);
|
||||
if (!$phones)
|
||||
{
|
||||
$return['result'] = 'Aucun téléphone dans le groupe.';
|
||||
echo json_encode($return);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($phones as &$phone)
|
||||
{
|
||||
$phone['adapter_name'] = call_user_func([$phone['adapter'], 'meta_name']);
|
||||
}
|
||||
|
||||
$return['success'] = true;
|
||||
$return['result'] = $phones;
|
||||
echo json_encode($return);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cette fonction retourne la liste des groups sous forme JSON.
|
||||
*/
|
||||
public function json_list()
|
||||
{
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($this->internal_phone_group->list_for_user($_SESSION['user']['id']));
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ namespace controllers\publics;
|
|||
{
|
||||
private $internal_scheduled;
|
||||
private $internal_phone;
|
||||
private $internal_phone_group;
|
||||
private $internal_contact;
|
||||
private $internal_group;
|
||||
private $internal_conditional_group;
|
||||
|
@ -34,6 +35,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_phone_group = new \controllers\internals\PhoneGroup($bdd);
|
||||
$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);
|
||||
|
@ -118,6 +120,7 @@ namespace controllers\publics;
|
|||
|
||||
$contacts = $this->internal_contact->gets_for_user($id_user);
|
||||
$phones = $this->internal_phone->gets_for_user($id_user);
|
||||
$phone_groups = $this->internal_phone_group->gets_for_user($id_user);
|
||||
|
||||
$contact_ids = (isset($_GET['contact_ids']) && \is_array($_GET['contact_ids'])) ? $_GET['contact_ids'] : [];
|
||||
$group_ids = (isset($_GET['group_ids']) && \is_array($_GET['group_ids'])) ? $_GET['group_ids'] : [];
|
||||
|
@ -153,6 +156,7 @@ namespace controllers\publics;
|
|||
'now' => $now->format('Y-m-d H:i'),
|
||||
'contacts' => $contacts,
|
||||
'phones' => $phones,
|
||||
'phone_groups' => $phone_groups,
|
||||
'prefilled_contacts' => $prefilled_contacts,
|
||||
'prefilled_groups' => $prefilled_groups,
|
||||
'prefilled_conditional_groups' => $prefilled_conditional_groups,
|
||||
|
@ -179,6 +183,7 @@ namespace controllers\publics;
|
|||
|
||||
$all_contacts = $this->internal_contact->gets_for_user($_SESSION['user']['id']);
|
||||
$phones = $this->internal_phone->gets_for_user($_SESSION['user']['id']);
|
||||
$phone_groups = $this->internal_phone_group->gets_for_user($id_user);
|
||||
$scheduleds = $this->internal_scheduled->gets_in_for_user($_SESSION['user']['id'], $ids);
|
||||
|
||||
//Pour chaque message on ajoute les numéros, les contacts & les groups
|
||||
|
@ -226,6 +231,7 @@ namespace controllers\publics;
|
|||
$this->render('scheduled/edit', [
|
||||
'scheduleds' => $scheduleds,
|
||||
'phones' => $phones,
|
||||
'phone_groups' => $phone_groups,
|
||||
'contacts' => $all_contacts,
|
||||
]);
|
||||
}
|
||||
|
@ -238,7 +244,7 @@ namespace controllers\publics;
|
|||
* @param string $_POST['at'] : Date to send message for
|
||||
* @param string $_POST['text'] : Text of the message
|
||||
* @param ?bool $_POST['flash'] : Is the message a flash message (by default false)
|
||||
* @param ?int $_POST['id_phone'] : Id of the phone to send message from, if null use random phone
|
||||
* @param ?int $_POST['id_phone'] : Id of the phone or phone group to send message from. id will be preceed by phone_ of phonegroup_ depending on type of ressource to use, if null use random phone
|
||||
* @param ?array $_POST['numbers'] : Numbers to send the message to
|
||||
* @param ?array $_POST['contacts'] : Numbers to send the message to
|
||||
* @param ?array $_POST['groups'] : Numbers to send the message to
|
||||
|
@ -258,6 +264,7 @@ namespace controllers\publics;
|
|||
$at = $_POST['at'] ?? false;
|
||||
$text = $_POST['text'] ?? false;
|
||||
$flash = (bool) ($_POST['flash'] ?? false);
|
||||
$tag = ($_POST['tag'] ?? null) ?: null;
|
||||
$id_phone = empty($_POST['id_phone']) ? null : $_POST['id_phone'];
|
||||
$numbers = $_POST['numbers'] ?? [];
|
||||
$numbers = is_array($numbers) ? $numbers : [$numbers];
|
||||
|
@ -433,7 +440,12 @@ namespace controllers\publics;
|
|||
|
||||
$mms = (bool) count($media_ids);
|
||||
|
||||
$scheduled_id = $this->internal_scheduled->create($id_user, $at, $text, $id_phone, $flash, $mms, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
// Check if we must send message to a phone or a phone_group based on if id_phone start with 'phone_' or 'phonegroup_'
|
||||
$original_id_phone = $id_phone;
|
||||
$id_phone = str_starts_with($original_id_phone, 'phone_') ? mb_substr($original_id_phone, mb_strlen('phone_')) : null;
|
||||
$id_phone_group = str_starts_with($original_id_phone, 'phonegroup_') ? mb_substr($original_id_phone, mb_strlen('phonegroup_')) : null;
|
||||
|
||||
$scheduled_id = $this->internal_scheduled->create($id_user, $at, $text, $id_phone, $id_phone_group, $flash, $mms, $tag, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
if (!$scheduled_id)
|
||||
{
|
||||
\FlashMessage\FlashMessage::push('danger', 'Impossible de créer le Sms.');
|
||||
|
@ -473,6 +485,7 @@ namespace controllers\publics;
|
|||
$text = $scheduled['text'] ?? false;
|
||||
$id_phone = empty($scheduled['id_phone']) ? null : $scheduled['id_phone'];
|
||||
$flash = (bool) ($scheduled['flash'] ?? false);
|
||||
$tag = ($scheduled['tag'] ?? null) ?: null;
|
||||
$numbers = $scheduled['numbers'] ?? [];
|
||||
$contacts = $scheduled['contacts'] ?? [];
|
||||
$groups = $scheduled['groups'] ?? [];
|
||||
|
@ -650,7 +663,11 @@ namespace controllers\publics;
|
|||
|
||||
$mms = (bool) count($media_ids);
|
||||
|
||||
$this->internal_scheduled->update_for_user($id_user, $id_scheduled, $at, $text, $id_phone, $flash, $mms, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
$original_id_phone = $id_phone;
|
||||
$id_phone = str_starts_with($original_id_phone, 'phone_') ? mb_substr($original_id_phone, mb_strlen('phone_')) : null;
|
||||
$id_phone_group = str_starts_with($original_id_phone, 'phonegroup_') ? mb_substr($original_id_phone, mb_strlen('phonegroup_')) : null;
|
||||
|
||||
$this->internal_scheduled->update_for_user($id_user, $id_scheduled, $at, $text, $id_phone, $id_phone_group, $flash, $mms, $tag, $numbers, $contacts, $groups, $conditional_groups, $media_ids);
|
||||
++$nb_update;
|
||||
}
|
||||
|
||||
|
|
|
@ -59,8 +59,9 @@ namespace controllers\publics;
|
|||
0 => 'phone_name',
|
||||
1 => 'searchable_destination',
|
||||
2 => 'text',
|
||||
3 => 'at',
|
||||
4 => 'status',
|
||||
3 => 'tag',
|
||||
4 => 'at',
|
||||
5 => 'status',
|
||||
];
|
||||
|
||||
$search = $_GET['search']['value'] ?? null;
|
||||
|
|
|
@ -144,7 +144,7 @@ class Phone extends AbstractDaemon
|
|||
//Do message sending
|
||||
$this->logger->info('Try send message : ' . json_encode($message));
|
||||
|
||||
$response = $internal_sended->send($this->adapter, $this->phone['id_user'], $this->phone['id'], $message['text'], $message['destination'], $message['flash'], $message['mms'], $message['medias'], $message['id_scheduled']);
|
||||
$response = $internal_sended->send($this->adapter, $this->phone['id_user'], $this->phone['id'], $message['text'], $message['destination'], $message['flash'], $message['mms'], $message['tag'], $message['medias'], $message['id_scheduled']);
|
||||
if ($response['error'])
|
||||
{
|
||||
$this->logger->error('Failed send message : ' . json_encode($message) . ' with error : ' . $response['error_message']);
|
||||
|
|
|
@ -80,6 +80,7 @@ class Sender extends AbstractDaemon
|
|||
'destination' => $sms['destination'],
|
||||
'flash' => $sms['flash'],
|
||||
'mms' => $sms['mms'],
|
||||
'tag' => $sms['tag'],
|
||||
'medias' => $sms['medias'] ?? [],
|
||||
];
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Db\Adapter\MysqlAdapter;
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class CreatePhoneGroup 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()
|
||||
{
|
||||
$this->table('phone_group')
|
||||
->addColumn('id_user', 'integer', ['null' => false])
|
||||
->addColumn('name', 'string', ['null' => false, 'limit' => 100])
|
||||
->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
|
||||
->addColumn('updated_at', 'timestamp', ['null' => true, 'update' => 'CURRENT_TIMESTAMP'])
|
||||
->addForeignKey('id_user', 'user', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->create();
|
||||
|
||||
$this->table('phone_group_phone')
|
||||
->addColumn('id_phone_group', 'integer', ['null' => false])
|
||||
->addColumn('id_phone', 'integer', ['null' => false])
|
||||
->addColumn('created_at', 'timestamp', ['null' => false, 'default' => 'CURRENT_TIMESTAMP'])
|
||||
->addColumn('updated_at', 'timestamp', ['null' => true, 'update' => 'CURRENT_TIMESTAMP'])
|
||||
->addForeignKey('id_phone_group', 'phone_group', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->addForeignKey('id_phone', 'phone', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->create();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class AddIdPhoneGroupToScheduled 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()
|
||||
{
|
||||
$this->table('scheduled')
|
||||
->addColumn('id_phone_group', 'integer', ['null' => true, 'default' => null, 'after' => 'id_phone'])
|
||||
->addForeignKey('id_phone_group', 'phone_group', 'id', ['delete' => 'CASCADE', 'update' => 'CASCADE'])
|
||||
->update();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Phinx\Migration\AbstractMigration;
|
||||
|
||||
class AddScheduledTag 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('scheduled');
|
||||
$table->addColumn('tag', 'string', ['default' => NULL, 'null' => true, 'limit' => 1000])
|
||||
->update();
|
||||
|
||||
$table = $this->table('sended');
|
||||
$table->addColumn('tag', 'string', ['default' => NULL, 'null' => true, 'limit' => 255])
|
||||
->update();
|
||||
}
|
||||
}
|
|
@ -144,7 +144,7 @@
|
|||
|
||||
/**
|
||||
* Generate IN query params and values
|
||||
* @param string $values : Values to generate in array from
|
||||
* @param array $values : Values to generate in array from
|
||||
* @return array : Array ['QUERY' => string 'IN(...)', 'PARAMS' => [parameters to pass to execute]]
|
||||
*/
|
||||
protected function _generate_in_from_array ($values)
|
||||
|
@ -214,6 +214,11 @@
|
|||
$operator = '>';
|
||||
break;
|
||||
|
||||
case ('%' == $first_char) :
|
||||
$true_fieldname = mb_substr($fieldname, 1);
|
||||
$operator = 'LIKE';
|
||||
break;
|
||||
|
||||
case ('=' == $first_char) :
|
||||
$true_fieldname = mb_substr($fieldname, 1);
|
||||
$operator = '=';
|
||||
|
@ -227,8 +232,11 @@
|
|||
//Protect against injection in fieldname
|
||||
$true_fieldname = preg_replace('#[^a-zA-Z0-9_]#', '', $true_fieldname);
|
||||
|
||||
$query = '`' . $true_fieldname . '` ' . $operator . ' :where_' . $true_fieldname;
|
||||
$param = ['where_' . $true_fieldname => $value];
|
||||
// Add a uid to fieldname so we can combine multiple rules on same field
|
||||
$uid = uniqid();
|
||||
|
||||
$query = '`' . $true_fieldname . '` ' . $operator . ' :where_' . $true_fieldname . '_' . $uid;
|
||||
$param = ['where_' . $true_fieldname . '_' . $uid => $value];
|
||||
|
||||
return ['QUERY' => $query, 'PARAM' => $param];
|
||||
}
|
||||
|
@ -358,7 +366,6 @@
|
|||
}
|
||||
|
||||
$query = "SELECT COUNT(*) as `count` FROM `" . $table . "` WHERE 1 " . (count($wheres) ? 'AND ' : '') . implode(' AND ', $wheres);
|
||||
|
||||
$query = $this->pdo->prepare($query);
|
||||
|
||||
foreach ($params as $label => &$param)
|
||||
|
|
|
@ -83,6 +83,8 @@
|
|||
'alert_quota_limit_close' => 0.9,
|
||||
'hide_menus' => '',
|
||||
'force_gsm_alphabet' => 0,
|
||||
'phone_limit' => 0,
|
||||
'phone_priority' => 0,
|
||||
],
|
||||
];
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -0,0 +1,123 @@
|
|||
<?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 models;
|
||||
|
||||
class PhoneGroup extends StandardModel
|
||||
{
|
||||
/**
|
||||
* Return a list of phone groups for a user.
|
||||
* Add a column nb_phone.
|
||||
*
|
||||
* @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 pg.*, COUNT(pgp.id) as nb_phone
|
||||
FROM `phone_group` as pg
|
||||
LEFT JOIN phone_group_phone as pgp
|
||||
ON pg.id = pgp.id_phone_group
|
||||
WHERE pg.id_user = :id_user
|
||||
GROUP BY pg.id
|
||||
';
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a phone group by his name for a user.
|
||||
*
|
||||
* @param int $id_user : User id
|
||||
* @param string $name : Group name
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_by_name_for_user(int $id_user, string $name)
|
||||
{
|
||||
return $this->_select_one($this->get_table_name(), ['id_user' => $id_user, 'name' => $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete relations between phone group and phone for a group.
|
||||
*
|
||||
* @param int $id_phone_group : Group id
|
||||
*
|
||||
* @return int : Number of deleted rows
|
||||
*/
|
||||
public function delete_phone_group_phone_relations(int $id_phone_group)
|
||||
{
|
||||
return $this->_delete('phone_group_phone', ['id_phone_group' => $id_phone_group]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a relation between a phone group and a phone.
|
||||
*
|
||||
* @param int $id_phone_group : Phone Group id
|
||||
* @param int $id_phone : Phone id
|
||||
*
|
||||
* @return mixed (bool|int) : False on error, new row id else
|
||||
*/
|
||||
public function insert_phone_group_phone_relation(int $id_phone_group, int $id_phone)
|
||||
{
|
||||
$success = (bool) $this->_insert('phone_group_phone', ['id_phone_group' => $id_phone_group, 'id_phone' => $id_phone]);
|
||||
|
||||
return $success ? $this->_last_id() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get phone groups phones.
|
||||
*
|
||||
* @param int $id_phone_group : Phone Group id
|
||||
*
|
||||
* @return array : Phones of the group
|
||||
*/
|
||||
public function get_phones(int $id_phone_group)
|
||||
{
|
||||
$query = '
|
||||
SELECT *
|
||||
FROM `phone`
|
||||
WHERE id IN (SELECT id_phone FROM `phone_group_phone` WHERE id_phone_group = :id_phone_group)
|
||||
';
|
||||
|
||||
$params = ['id_phone_group' => $id_phone_group];
|
||||
|
||||
return $this->_run_query($query, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return table name.
|
||||
*/
|
||||
protected function get_table_name(): string
|
||||
{
|
||||
return 'phone_group';
|
||||
}
|
||||
}
|
|
@ -183,13 +183,35 @@ namespace models;
|
|||
*
|
||||
* @param int $id_user : User id
|
||||
* @param int $id_phone : Phone id we want the number of sended message for
|
||||
* @param \DateTime $since : Date since which we want sended number
|
||||
* @param ?\DateTime $since : Date since which we want sended Number. Default to null.
|
||||
* @param ?\DateTime $before : Date up to which we want sended number. Default to null.
|
||||
* @param ?string $tag_like : Tag to filter sms by, this is not a = but a LIKE operator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, \DateTime $since) : int
|
||||
public function count_since_for_phone_and_user(int $id_user, int $id_phone, ?\DateTime $since = null, ?\DateTime $before = null, ?string $tag_like = null) : int
|
||||
{
|
||||
return $this->_count('sended', ['id_user' => $id_user, 'id_phone' => $id_phone, '>=at' => $since->format('c')]);
|
||||
$data = [
|
||||
'id_user' => $id_user,
|
||||
'id_phone' => $id_phone,
|
||||
];
|
||||
|
||||
if ($since)
|
||||
{
|
||||
$data['>=at'] = $since->format('c');
|
||||
}
|
||||
|
||||
if ($before)
|
||||
{
|
||||
$data['<=at'] = $before->format('c');
|
||||
}
|
||||
|
||||
if ($tag_like)
|
||||
{
|
||||
$data['%tag'] = $tag_like;
|
||||
}
|
||||
|
||||
return $this->_count('sended', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
18
routes.php
18
routes.php
|
@ -164,6 +164,20 @@
|
|||
'delete' => '/phone/delete/{csrf}/',
|
||||
'edit' => '/phone/edit/',
|
||||
'update' => '/phone/update/{csrf}/',
|
||||
'update_status' => '/phone/update_status/{csrf}/',
|
||||
'json_list' => '/phones.json/',
|
||||
],
|
||||
|
||||
'PhoneGroup' => [
|
||||
'list' => '/phone_group/',
|
||||
'list_json' => '/phone_group/json/',
|
||||
'add' => '/phone_group/add/',
|
||||
'create' => '/phone_group/create/{csrf}/',
|
||||
'delete' => '/phone_group/delete/{csrf}/',
|
||||
'edit' => '/phone_group/edit/',
|
||||
'update' => '/phone_group/update/{csrf}/',
|
||||
'preview' => '/phone_group/preview/{id_group}/',
|
||||
'json_list' => '/phone_group.json/',
|
||||
],
|
||||
|
||||
'Call' => [
|
||||
|
@ -194,6 +208,7 @@
|
|||
'/api/list/{entry_type}/',
|
||||
'/api/list/{entry_type}/{page}/',
|
||||
],
|
||||
'get_usage' => '/api/usage/',
|
||||
'post_scheduled' => [
|
||||
'/api/scheduled/',
|
||||
],
|
||||
|
@ -206,6 +221,9 @@
|
|||
'post_update_phone' => [
|
||||
'/api/phone/{id}/',
|
||||
],
|
||||
'post_update_phone_status' => [
|
||||
'/api/phone/{id}/status/',
|
||||
],
|
||||
'delete_phone' => [
|
||||
'/api/phone/{id}/',
|
||||
],
|
||||
|
|
|
@ -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>';
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -145,7 +145,6 @@ jQuery(document).ready(function ()
|
|||
html += ' <div class="preview-contact-number">' + jQuery.fn.dataTable.render.text().display(contact.number) + '</div>'
|
||||
html += ' <code class="preview-contact-data">' + jQuery.fn.dataTable.render.text().display(contact.data) + '</code>'
|
||||
html += '</div>';
|
||||
console.log(contact);
|
||||
}
|
||||
|
||||
jQuery('#preview-text-modal').find('.modal-body').html(html);
|
||||
|
|
|
@ -110,8 +110,16 @@
|
|||
</li>
|
||||
<?php } ?>
|
||||
<?php if (!in_array('phones', json_decode($_SESSION['user']['settings']['hide_menus'], true) ?? [])) { ?>
|
||||
<li <?php echo $page == 'phones' ? 'class="active"' : ''; ?>>
|
||||
<a href="<?php echo \descartes\Router::url('Phone', 'list'); ?>"><i class="fa fa-fw fa-phone"></i> Téléphones</a>
|
||||
<li>
|
||||
<a href="javascript:;" data-toggle="collapse" data-target="#phones"><i class="fa fa-fw fa-phone"></i> Téléphones <i class="fa fa-fw fa-caret-down"></i></a>
|
||||
<ul id="phones" class="collapse <?php echo in_array($page, array('phones', 'phone_groups')) ? 'in' : ''; ?>">
|
||||
<li <?php echo $page == 'phones' ? 'class="active"' : ''; ?>>
|
||||
<a href="<?php echo \descartes\Router::url('Phone', 'list'); ?>"><i class="fa fa-fw fa-phone"></i> Téléphones</a>
|
||||
</li>
|
||||
<li <?php echo $page == 'phone_groups' ? 'class="active"' : ''; ?>>
|
||||
<a href="<?php echo \descartes\Router::url('PhoneGroup', 'list'); ?>"><i class="fa fa-list-alt fa-fw"></i> Groupes de Téléphones</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<?php } ?>
|
||||
<?php if (!in_array('settings', json_decode($_SESSION['user']['settings']['hide_menus'], true) ?? [])) { ?>
|
||||
|
|
|
@ -44,18 +44,22 @@
|
|||
Le nom du téléphone qui enverra et recevra les messages.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="name" class="form-control" placeholder="Nom du téléphone" value="<?php $this->s($_SESSION['previous_http_post']['name'] ?? '') ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="priority" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($_SESSION['previous_http_post']['priority'] ?? 0) ?>">
|
||||
<input required="required" name="name" class="form-control" placeholder="Nom du téléphone" value="<?php $this->s($_SESSION['previous_http_post']['name'] ?? '') ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($_SESSION['user']['settings']['phone_priority']) { ?>
|
||||
<div class="form-group">
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="priority" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($_SESSION['previous_http_post']['priority'] ?? 0) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Type de téléphone</label>
|
||||
<p class="italic small help" id="description-adapter-general">
|
||||
|
@ -87,15 +91,19 @@
|
|||
<div id="adapter-data-fields"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
|
||||
<?php if ($_SESSION['user']['settings']['phone_limit']) { ?>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('Phone', 'list'); ?>">Annuler</a>
|
||||
<input type="submit" class="btn btn-success" value="Enregistrer le téléphone" />
|
||||
</form>
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
<form action="<?php echo \descartes\Router::url('Phone', 'update', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<div class="entry-container" data-entry-id="<?php $this->s($phone['id']); ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Nom du téléphone</label>
|
||||
<p class="italic small help">
|
||||
|
@ -49,15 +50,19 @@
|
|||
<input required="required" name="phones[<?php $this->s($phone['id']); ?>][name]" class="form-control" placeholder="Nom du téléphone" value="<?php $this->s($phone['name']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
|
||||
<?php if ($_SESSION['user']['settings']['phone_priority']) { ?>
|
||||
<div class="form-group">
|
||||
<input required="required" name="phones[<?php $this->s($phone['id']); ?>][priority]" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($phone['priority']) ?>">
|
||||
<label>Priorité d'utilisation du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Lors de l'envoi de SMS sans téléphone spécifié, les téléphones avec la plus haute priorité seront utilisés en premier.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input required="required" name="phones[<?php $this->s($phone['id']); ?>][priority]" class="form-control" type="number" min="0" placeholder="Priorité d'utilisation" value="<?php $this->s($phone['priority']) ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Type de téléphone</label>
|
||||
<p class="italic small help description-adapter-general">
|
||||
|
@ -65,13 +70,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 } ?>
|
||||
>
|
||||
|
@ -92,44 +99,48 @@
|
|||
<div class="adapter-data-fields"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<?php foreach ($phone['limits'] as $limit) { ?>
|
||||
<div class="row phone-limits-group">
|
||||
<div class="col-xs-4">
|
||||
<label>Période</label><br/>
|
||||
<?php $random_id = uniqid(); ?>
|
||||
<select name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][startpoint]" class="form-control" required>
|
||||
<option value="" disabled selected>Période sur laquelle appliquer la limite</option>
|
||||
<option <?= $limit['startpoint'] == 'today' ? 'selected' : ''; ?> value="today">Par jour</option>
|
||||
<option <?= $limit['startpoint'] == '-24 hours' ? 'selected' : ''; ?> value="-24 hours">24 heures glissantes</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight' ? 'selected' : ''; ?> value="this week midnight">Cette semaine</option>
|
||||
<option <?= $limit['startpoint'] == '-7 days' ? 'selected' : ''; ?> value="-7 days">7 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight -1 week' ? 'selected' : ''; ?> value="this week midnight -1 week">Ces deux dernières semaines</option>
|
||||
<option <?= $limit['startpoint'] == '-14 days' ? 'selected' : ''; ?> value="-14 days">14 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this month midnight' ? 'selected' : ''; ?> value="this month midnight">Ce mois</option>
|
||||
<option <?= $limit['startpoint'] == '-1 month' ? 'selected' : ''; ?> value="-1 month">1 mois glissant</option>
|
||||
<option <?= $limit['startpoint'] == '-28 days' ? 'selected' : ''; ?> value="-28 days">28 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-30 days' ? 'selected' : ''; ?> value="-30 days">30 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-31 days' ? 'selected' : ''; ?> value="-31 days">31 jours glissants</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="scheduleds-number-data-container col-xs-8">
|
||||
<label>Volume</label>
|
||||
<div class="form-group">
|
||||
<input name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][volume]" class="form-control" type="number" min="1" value="<?php $this->s($limit['volume']); ?>" placeholder="Nombre de SMS maximum sur la période.">
|
||||
|
||||
<?php if ($_SESSION['user']['settings']['phone_limit']) { ?>
|
||||
<div class="form-group">
|
||||
<label>Limites des volumes d'envoi du téléphone</label>
|
||||
<p class="italic small help">
|
||||
Défini le nombre maximum de SMS qui pourront être envoyés avec ce téléphone sur des périodes de temps données.
|
||||
</p>
|
||||
<div class="form-group phone-limits-container container-fluid">
|
||||
<?php foreach ($phone['limits'] as $limit) { ?>
|
||||
<div class="row phone-limits-group">
|
||||
<div class="col-xs-4">
|
||||
<label>Période</label><br/>
|
||||
<?php $random_id = uniqid(); ?>
|
||||
<select name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][startpoint]" class="form-control" required>
|
||||
<option value="" disabled selected>Période sur laquelle appliquer la limite</option>
|
||||
<option <?= $limit['startpoint'] == 'today' ? 'selected' : ''; ?> value="today">Par jour</option>
|
||||
<option <?= $limit['startpoint'] == '-24 hours' ? 'selected' : ''; ?> value="-24 hours">24 heures glissantes</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight' ? 'selected' : ''; ?> value="this week midnight">Cette semaine</option>
|
||||
<option <?= $limit['startpoint'] == '-7 days' ? 'selected' : ''; ?> value="-7 days">7 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this week midnight -1 week' ? 'selected' : ''; ?> value="this week midnight -1 week">Ces deux dernières semaines</option>
|
||||
<option <?= $limit['startpoint'] == '-14 days' ? 'selected' : ''; ?> value="-14 days">14 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == 'this month midnight' ? 'selected' : ''; ?> value="this month midnight">Ce mois</option>
|
||||
<option <?= $limit['startpoint'] == '-1 month' ? 'selected' : ''; ?> value="-1 month">1 mois glissant</option>
|
||||
<option <?= $limit['startpoint'] == '-28 days' ? 'selected' : ''; ?> value="-28 days">28 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-30 days' ? 'selected' : ''; ?> value="-30 days">30 jours glissants</option>
|
||||
<option <?= $limit['startpoint'] == '-31 days' ? 'selected' : ''; ?> value="-31 days">31 jours glissants</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="scheduleds-number-data-container col-xs-8">
|
||||
<label>Volume</label>
|
||||
<div class="form-group">
|
||||
<input name="phones[<?= $phone['id']; ?>][limits][<?= $random_id; ?>][volume]" class="form-control" type="number" min="1" value="<?php $this->s($limit['volume']); ?>" placeholder="Nombre de SMS maximum sur la période.">
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>
|
||||
</div>
|
||||
<a href="#" class="phone-limits-group-remove"><span class="fa fa-times"></span></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
<?php } ?>
|
||||
<div class="text-center"><div class="add-phone-limit-button fa fa-plus-circle"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
<hr/>
|
||||
<?php } ?>
|
||||
|
|
|
@ -41,10 +41,14 @@
|
|||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Nom</th>
|
||||
<th>Priorité</th>
|
||||
<?php if ($_SESSION['user']['settings']['phone_priority']) { ?>
|
||||
<th>Priorité</th>
|
||||
<?php } ?>
|
||||
<th>Type de téléphone</th>
|
||||
<th>Callbacks</th>
|
||||
<th>Limites</th>
|
||||
<?php if ($_SESSION['user']['settings']['phone_limit']) { ?>
|
||||
<th>Limites</th>
|
||||
<?php } ?>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -58,6 +62,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,8 +95,31 @@ jQuery(document).ready(function ()
|
|||
},
|
||||
"columns" : [
|
||||
{data: 'id', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'name', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'priority', 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
|
||||
},
|
||||
},
|
||||
<?php if ($_SESSION['user']['settings']['phone_priority']) { ?>
|
||||
{data: 'priority', render: jQuery.fn.dataTable.render.text()},
|
||||
<?php } ?>
|
||||
{data: 'adapter', render: jQuery.fn.dataTable.render.text()},
|
||||
{
|
||||
data: '_',
|
||||
|
@ -127,61 +155,63 @@ jQuery(document).ready(function ()
|
|||
return html;
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'limits',
|
||||
render: function (limits) {
|
||||
if (!limits.length)
|
||||
{
|
||||
return 'Pas de limites.';
|
||||
}
|
||||
|
||||
var html = '';
|
||||
for (limit of limits)
|
||||
{
|
||||
switch (limit.startpoint)
|
||||
<?php if ($_SESSION['user']['settings']['phone_limit']) { ?>
|
||||
{
|
||||
data: 'limits',
|
||||
render: function (limits) {
|
||||
if (!limits.length)
|
||||
{
|
||||
case "today" :
|
||||
var startpoint = 'Par jour';
|
||||
break;
|
||||
case "-24 hours" :
|
||||
var startpoint = '24 heures glissantes';
|
||||
break;
|
||||
case "this week midnight" :
|
||||
var startpoint = 'Cette semaine';
|
||||
break;
|
||||
case "-7 days" :
|
||||
var startpoint = '7 jours glissants';
|
||||
break;
|
||||
case "this week midnight -1 week" :
|
||||
var startpoint = 'Ces deux dernières semaines';
|
||||
break;
|
||||
case "-14 days" :
|
||||
var startpoint = '14 jours glissants';
|
||||
break;
|
||||
case "this month midnight" :
|
||||
var startpoint = 'Ce mois';
|
||||
break;
|
||||
case "-1 month" :
|
||||
var startpoint = '1 mois glissant';
|
||||
break;
|
||||
case "-28 days" :
|
||||
var startpoint = '28 jours glissants';
|
||||
break;
|
||||
case "-30 days" :
|
||||
var startpoint = '30 jours glissants';
|
||||
break;
|
||||
case "-31 days" :
|
||||
var startpoint = '31 jours glissants';
|
||||
break;
|
||||
default :
|
||||
var startpoint = 'Inconnu'
|
||||
return 'Pas de limites.';
|
||||
}
|
||||
html += '<div><span class="bold">' + jQuery.fn.dataTable.render.text().display(startpoint) + ' : </span>' + jQuery.fn.dataTable.render.text().display(limit.volume) + '</div>';
|
||||
}
|
||||
|
||||
return html;
|
||||
var html = '';
|
||||
for (limit of limits)
|
||||
{
|
||||
switch (limit.startpoint)
|
||||
{
|
||||
case "today" :
|
||||
var startpoint = 'Par jour';
|
||||
break;
|
||||
case "-24 hours" :
|
||||
var startpoint = '24 heures glissantes';
|
||||
break;
|
||||
case "this week midnight" :
|
||||
var startpoint = 'Cette semaine';
|
||||
break;
|
||||
case "-7 days" :
|
||||
var startpoint = '7 jours glissants';
|
||||
break;
|
||||
case "this week midnight -1 week" :
|
||||
var startpoint = 'Ces deux dernières semaines';
|
||||
break;
|
||||
case "-14 days" :
|
||||
var startpoint = '14 jours glissants';
|
||||
break;
|
||||
case "this month midnight" :
|
||||
var startpoint = 'Ce mois';
|
||||
break;
|
||||
case "-1 month" :
|
||||
var startpoint = '1 mois glissant';
|
||||
break;
|
||||
case "-28 days" :
|
||||
var startpoint = '28 jours glissants';
|
||||
break;
|
||||
case "-30 days" :
|
||||
var startpoint = '30 jours glissants';
|
||||
break;
|
||||
case "-31 days" :
|
||||
var startpoint = '31 jours glissants';
|
||||
break;
|
||||
default :
|
||||
var startpoint = 'Inconnu'
|
||||
}
|
||||
html += '<div><span class="bold">' + jQuery.fn.dataTable.render.text().display(startpoint) + ' : </span>' + jQuery.fn.dataTable.render.text().display(limit.volume) + '</div>';
|
||||
}
|
||||
|
||||
return html;
|
||||
},
|
||||
},
|
||||
},
|
||||
<?php } ?>
|
||||
{
|
||||
data: 'id',
|
||||
render: function (data, type, row, meta) {
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
//Template dashboard
|
||||
|
||||
$this->render('incs/head', ['title' => 'Groupes de Téléphones - Add'])
|
||||
?>
|
||||
<div id="wrapper">
|
||||
<?php
|
||||
$this->render('incs/nav', ['page' => 'phone_groups'])
|
||||
?>
|
||||
<div id="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">
|
||||
Nouveau groupe de téléphones
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li>
|
||||
<i class="fa fa-dashboard"></i> <a href="<?php echo \descartes\Router::url('Dashboard', 'show'); ?>">Dashboard</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-list-alt"></i> <a href="<?php echo \descartes\Router::url('PhoneGroup', 'list'); ?>">Groupes de téléphones</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<i class="fa fa-plus"></i> Nouveau
|
||||
</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-list-alt fa-fw"></i> Ajout d'un groupe de téléphones</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('PhoneGroup', 'create', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Nom du groupe de téléphone</label>
|
||||
<div class="form-group input-group">
|
||||
<span class="input-group-addon"><span class="fa fa-phone"></span></span>
|
||||
<input name="name" class="form-control" type="text" placeholder="Nom du groupe" autofocus required value="<?php $this->s($_SESSION['previous_http_post']['name'] ?? '') ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Téléphones du groupe</label>
|
||||
<input class="add-phones form-control" name="phones[]" value="<?php $this->s(json_encode($_SESSION['previous_http_post']['phones'] ?? [])); ?>"/>
|
||||
</div>
|
||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('PhoneGroup', 'list'); ?>">Annuler</a>
|
||||
<input type="submit" class="btn btn-success" value="Enregistrer le groupe de téléphones" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function()
|
||||
{
|
||||
jQuery('.add-phones').each(function()
|
||||
{
|
||||
jQuery(this).magicSuggest({
|
||||
data: '<?php echo \descartes\Router::url('Phone', 'json_list'); ?>',
|
||||
valueField: 'id',
|
||||
displayField: 'name',
|
||||
name: 'phones[]',
|
||||
maxSelection: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
$this->render('incs/footer');
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
//Template dashboard
|
||||
|
||||
$this->render('incs/head', ['title' => 'Groupes de Téléphones - Edit'])
|
||||
?>
|
||||
<div id="wrapper">
|
||||
<?php
|
||||
$this->render('incs/nav', ['page' => 'phone_groups'])
|
||||
?>
|
||||
<div id="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">
|
||||
Modification groupes de téléphones
|
||||
</h1>
|
||||
<ol class="breadcrumb">
|
||||
<li>
|
||||
<i class="fa fa-dashboard"></i> <a href="<?php echo \descartes\Router::url('Dashboard', 'show'); ?>">Dashboard</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="fa fa-list-alt"></i> <a href="<?php echo \descartes\Router::url('PhoneGroup', 'list'); ?>">Groupes de téléphones</a>
|
||||
</li>
|
||||
<li class="active">
|
||||
<i class="fa fa-edit"></i> Modifier
|
||||
</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-edit fa-fw"></i> Modification des groupes de téléphones</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('PhoneGroup', 'update', ['csrf' => $_SESSION['csrf']]);?>" method="POST">
|
||||
<?php
|
||||
foreach ($phone_groups as $phone_group)
|
||||
{
|
||||
$phones = array();
|
||||
foreach ($phone_group['phones'] as $phone)
|
||||
{
|
||||
$phones[] = (int)$phone['id'];
|
||||
}
|
||||
$phones = json_encode($phones);
|
||||
|
||||
?>
|
||||
<input name="phone_groups[<?php $this->s($phone_group['id']); ?>][phone_group][id]" type="hidden" value="<?php $this->s($phone_group['id']); ?>">
|
||||
<div class="form-group">
|
||||
<label>Nom du groupe de téléphone</label>
|
||||
<div class="form-group input-group">
|
||||
<span class="input-group-addon"><span class="fa fa-user"></span></span>
|
||||
<input name="phone_groups[<?php $this->s($phone_group['id']); ?>][name]" class="form-control" type="text" placeholder="Nom du groupe" autofocus required value="<?php $this->s($phone_group['name']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Téléphones du groupe</label>
|
||||
<input class="add-phones form-control" name="phone_groups[<?php $this->s($phone_group['id']); ?>][phones_ids][]" value="<?php $this->s($phones); ?>"/>
|
||||
</div>
|
||||
<hr/>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<a class="btn btn-danger" href="<?php echo \descartes\Router::url('PhoneGroup', 'list'); ?>">Annuler</a>
|
||||
<input type="submit" class="btn btn-success" value="Enregistrer le groupe de téléphones" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
jQuery(document).ready(function()
|
||||
{
|
||||
jQuery('.add-phones').each(function()
|
||||
{
|
||||
jQuery(this).magicSuggest({
|
||||
data: '<?php echo \descartes\Router::url('Phone', 'json_list'); ?>',
|
||||
valueField: 'id',
|
||||
displayField: 'name',
|
||||
maxSelection: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
$this->render('incs/footer');
|
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
//Template dashboard
|
||||
|
||||
$this->render('incs/head', ['title' => 'Groupes de Téléphones - Show All'])
|
||||
?>
|
||||
<div id="wrapper">
|
||||
<?php
|
||||
$this->render('incs/nav', ['page' => 'phone_groups'])
|
||||
?>
|
||||
<div id="page-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Page Heading -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<h1 class="page-header">
|
||||
Dashboard <small>Groupes de téléphones</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-list-alt"></i> Groupes de téléphones
|
||||
</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-list-alt fa-fw"></i> Liste des groupes de téléphones</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form method="GET">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover table-striped datatable" id="table-groupes">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nom</th>
|
||||
<th>Nombre de téléphones</th>
|
||||
<th>Date de création</th>
|
||||
<th>Dernière modification</th>
|
||||
<th>Preview</th>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-xs-6 no-padding">
|
||||
<a class="btn btn-success" href="<?php echo \descartes\Router::url('PhoneGroup', 'add'); ?>"><span class="fa fa-plus"></span> Ajouter un groupe de téléphones</a>
|
||||
</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('PhoneGroup', 'edit'); ?>"><span class="fa fa-edit"></span> Modifier</button>
|
||||
<button class="btn btn-default btn-confirm" type="submit" formaction="<?php echo \descartes\Router::url('PhoneGroup', 'delete', ['csrf' => $_SESSION['csrf']]); ?>"><span class="fa fa-trash-o"></span> Supprimer</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" tabindex="-1" id="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">×</span></button>
|
||||
<h4 class="modal-title">Prévisualisation des téléphones</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</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 ()
|
||||
{
|
||||
jQuery('.datatable').DataTable({
|
||||
"pageLength": 25,
|
||||
"lengthMenu": [[25, 50, 100, 1000, 10000, -1], [25, 50, 100, 1000, 10000, "All"]],
|
||||
"language": {
|
||||
"url": HTTP_PWD + "/assets/js/datatables/french.json",
|
||||
},
|
||||
"columnDefs": [{
|
||||
'targets': 'checkcolumn',
|
||||
'orderable': false,
|
||||
}],
|
||||
|
||||
"ajax": {
|
||||
'url': '<?php echo \descartes\Router::url('PhoneGroup', 'list_json'); ?>',
|
||||
'dataSrc': 'data',
|
||||
},
|
||||
"columns" : [
|
||||
{data: 'name', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'nb_phone', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'created_at'},
|
||||
{data: 'updated_at'},
|
||||
{
|
||||
data: '_',
|
||||
render: function (data, type, row, meta) {
|
||||
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>';
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'id',
|
||||
render: function (data, type, row, meta) {
|
||||
return '<input name="ids[]" type="checkbox" value="' + data + '">';
|
||||
},
|
||||
},
|
||||
],
|
||||
"deferRender": true
|
||||
});
|
||||
|
||||
jQuery('body').on('click', '.preview-button', function (e)
|
||||
{
|
||||
e.preventDefault();
|
||||
var group_id = jQuery(this).attr('data-id-group');
|
||||
|
||||
jQuery.ajax({
|
||||
type: "GET",
|
||||
url: HTTP_PWD + '/phone_group/preview/' + group_id + '/',
|
||||
success: function (data) {
|
||||
if (!data.success) {
|
||||
jQuery('#preview-text-modal').find('.modal-body').text(data.result);
|
||||
} else {
|
||||
html = '';
|
||||
|
||||
for (phone of data.result)
|
||||
{
|
||||
html += '<div class="preview-phone well">';
|
||||
html += ' <div class="preview-phone-name"><span class="bold">Nom : </span>' + jQuery.fn.dataTable.render.text().display(phone.name) + '</div>'
|
||||
html += ' <div class="preview-phone-adapter"><span class="bold">Type : </span>' + jQuery.fn.dataTable.render.text().display(phone.adapter_name) + '</div>'
|
||||
html += '</div>';
|
||||
}
|
||||
|
||||
jQuery('#preview-text-modal').find('.modal-body').html(html);
|
||||
}
|
||||
jQuery('#preview-text-modal').modal({'keyboard': true});
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
<?php
|
||||
$this->render('incs/footer');
|
|
@ -131,14 +131,32 @@
|
|||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<?php if (count($phones)) { ?>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Tag à associé à la campagne</label>
|
||||
<p class="italic small help">
|
||||
Vous pouvez renseigner une chaine de caractère qui sera associée à tous les SMS envoyés. Utile pour associer un identifiant interne à vos systèmes. Laissez vide si vous ne voulez pas associé de chaine.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input name="tag" class="form-control" type="text" placeholder="Ex: region-001" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if (count($phones) || count($phone_groups)) { ?>
|
||||
<div class="form-group">
|
||||
<label>Numéro à employer : </label>
|
||||
<select name="id_phone" class="form-control">
|
||||
<option value="">N'importe lequel</option>
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<option value="<?php $this->s($phone['id']); ?>" <?= ($_SESSION['previous_http_post']['id_phone'] ?? '') == $phone['id'] ? 'selected' : '' ?>><?php $this->s($phone['name']); ?></option>
|
||||
<?php } ?>
|
||||
<optgroup label="Téléphones">
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<option value="phone_<?php $this->s($phone['id']); ?>" <?= ($_SESSION['previous_http_post']['id_phone'] ?? '') == ('phone_' . $phone['id']) ? 'selected' : '' ?>><?php $this->s($phone['name']); ?></option>
|
||||
<?php } ?>
|
||||
</optgroup>
|
||||
<optgroup label="Groupes de téléphones">
|
||||
<?php foreach ($phone_groups as $phone_group) { ?>
|
||||
<option value="phonegroup_<?php $this->s($phone_group['id']); ?>" <?= ($_SESSION['previous_http_post']['id_phone'] ?? '') == ('phonegroup_' . $phone_group['id']) ? 'selected' : '' ?>><?php $this->s($phone_group['name']); ?></option>
|
||||
<?php } ?>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
|
|
@ -152,13 +152,29 @@
|
|||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="form-group">
|
||||
<label>Tag à associé à la campagne</label>
|
||||
<p class="italic small help">
|
||||
Vous pouvez renseigner une chaine de caractère qui sera associée à tous les SMS envoyés. Utile pour associer un identifiant interne à vos systèmes. Laissez vide si vous ne voulez pas associé de chaine.
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<input name="scheduleds[<?php $this->s($scheduled['id']); ?>][tag]" class="form-control" type="text" placeholder="Ex: region-001" maxlength="255" value="<?php $this->s($scheduled['tag']); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Numéro à employer : </label>
|
||||
<select name="scheduleds[<?php $this->s($scheduled['id']); ?>][id_phone]" class="form-control">
|
||||
<option <?php echo ($scheduled['id_phone'] ? '' : 'selected="selected"'); ?> value="">N'importe lequel</option>
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<option <?php echo ($scheduled['id_phone'] == $phone['id'] ? 'selected="selected"' : '' ); ?> value="<?php $this->s($phone['id']); ?>"><?php $this->s($phone['name']); ?></option>
|
||||
<?php } ?>
|
||||
<optgroup label="Téléphones">
|
||||
<?php foreach ($phones as $phone) { ?>
|
||||
<option <?php echo (($scheduled['id_phone'] && $scheduled['id_phone'] == $phone['id']) ? 'selected="selected"' : '' ); ?> value="phone_<?php $this->s($phone['id']); ?>"><?php $this->s($phone['name']); ?></option>
|
||||
<?php } ?>
|
||||
</optgroup>
|
||||
<optgroup label="Groupes de téléphones">
|
||||
<?php foreach ($phone_groups as $phone_group) { ?>
|
||||
<option <?php echo (($scheduled['id_phone_group'] && $scheduled['id_phone_group'] == $phone_group['id']) ? 'selected="selected"' : '' ); ?> value="phonegroup_<?php $this->s($phone_group['id']); ?>"><?php $this->s($phone_group['name']); ?></option>
|
||||
<?php } ?>
|
||||
</optgroup>
|
||||
</select>
|
||||
</div>
|
||||
<hr/>
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
<th>Expéditeur</th>
|
||||
<th>Destinataire</th>
|
||||
<th>Message</th>
|
||||
<th>Tag</th>
|
||||
<th>Date</th>
|
||||
<th>Statut</th>
|
||||
<th class="checkcolumn"><input type="checkbox" id="check-all"/></th>
|
||||
|
@ -74,7 +75,7 @@ jQuery(document).ready(function ()
|
|||
"url": HTTP_PWD + "/assets/js/datatables/french.json",
|
||||
},
|
||||
"orderMulti": false,
|
||||
"order": [[3, "desc"]],
|
||||
"order": [[4, "desc"]],
|
||||
"columnDefs": [{
|
||||
'targets': 'checkcolumn',
|
||||
'orderable': false,
|
||||
|
@ -111,6 +112,7 @@ jQuery(document).ready(function ()
|
|||
return jQuery.fn.dataTable.render.text().display(data);
|
||||
},
|
||||
},
|
||||
{data: 'tag', render: jQuery.fn.dataTable.render.text()},
|
||||
{data: 'at', render: jQuery.fn.dataTable.render.text()},
|
||||
{
|
||||
data: 'status',
|
||||
|
|
|
@ -34,26 +34,64 @@
|
|||
<h3 class="panel-title"><i class="fa fa-cogs fa-fw"></i> Les réglages de RaspiSMS</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-share fa-fw"></i> Transfert des SMS par e-mail</h4>
|
||||
<h4 class="panel-title"><i class="fa fa-phone fa-fw"></i> Pays par défaut numéros internationaux</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'transfer', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'default_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Transfert activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['transfer'] ? 'selected' : ''; ?>>Oui</option>
|
||||
</select>
|
||||
<label>Code du pays (norme ISO 3166-1 alpha-2) : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['default_phone_country']); ?>" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-phone fa-fw"></i> Pays préférés numéros internationaux</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'preferred_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Code des pays (norme ISO 3166-1 alpha-2) séparés par des virgules : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['preferred_phone_country']); ?>" />
|
||||
</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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-flag fa-fw"></i> Pays autorisés pour l'envoi</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'authorized_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Code des pays (norme ISO 3166-1 alpha-2) séparés par des virgules (laissez vide pour tout autoriser) : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['authorized_phone_country']); ?>" />
|
||||
</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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-font fa-fw"></i> Alphabet SMS optimisé</h4>
|
||||
|
@ -73,7 +111,10 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-picture-o fa-fw"></i> Support des MMS</h4>
|
||||
</div>
|
||||
|
@ -92,17 +133,20 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-link fa-fw"></i> Détection des URL dans les discussions</h4>
|
||||
<h4 class="panel-title"><i class="fa fa-flash fa-fw"></i> Support des SMS Flash</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'detect_url', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'sms_flash', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Détection activé : </label>
|
||||
<label>SMS Flash activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['detect_url'] ? 'selected' : ''; ?>>Oui</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['sms_flash'] ? 'selected' : ''; ?>>Oui</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="text-center">
|
||||
|
@ -111,96 +155,8 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-phone fa-fw"></i> Pays préférés numéros internationaux</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'preferred_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Code des pays (norme ISO 3166-1 alpha-2) séparés par des virgules : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['preferred_phone_country']); ?>" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-flag fa-fw"></i> Pays autorisés pour l'envoi</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'authorized_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Code des pays (norme ISO 3166-1 alpha-2) séparés par des virgules (laissez vide pour tout autoriser) : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['authorized_phone_country']); ?>" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-music fa-fw"></i> Son sur reception d'un SMS</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'sms_reception_sound', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Jouer un son quand vous recevez un SMS : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['sms_reception_sound'] ? '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 class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-exclamation-triangle fa-fw"></i> Alerte limite de SMS atteinte</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'alert_quota_limit_reached', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Recevoir un e-mail quand la limite de SMS est atteinte :</label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['alert_quota_limit_reached'] == 1 ? '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 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>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
|
@ -221,79 +177,9 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-plug fa-fw"></i> Activation de Webhooks</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'webhook', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Webhooks activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['webhook'] ? '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 class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-phone fa-fw"></i> Pays par défaut numéros internationaux</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'default_phone_country', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Code du pays (norme ISO 3166-1 alpha-2) : </label>
|
||||
<input name="setting_value" class="form-control" value="<?php $this->s($_SESSION['user']['settings']['default_phone_country']); ?>" />
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-flash fa-fw"></i> Support des SMS Flash</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'sms_flash', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>SMS Flash activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['sms_flash'] ? '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 class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-bullseye fa-fw"></i> Support des groupes conditionnels</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'conditional_group', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Groupes conditionnels activés : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['conditional_group'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-code fa-fw"></i> Support du templating</h4>
|
||||
|
@ -313,6 +199,141 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-bullseye fa-fw"></i> Support des groupes conditionnels</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'conditional_group', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Groupes conditionnels activés : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['conditional_group'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-thermometer-3 fa-fw"></i> Support des limites d'envoi par téléphones</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'phone_limit', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Limites d'envoi par téléphones activées : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['phone_limit'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-sort-numeric-desc fa-fw"></i> Support des téléphones prioritaires</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'phone_priority', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Téléphones prioritaires activés : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['phone_priority'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-plug fa-fw"></i> Activation de Webhooks</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'webhook', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Webhooks activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['webhook'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-share fa-fw"></i> Transfert des SMS par e-mail</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'transfer', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Transfert activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['transfer'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-exclamation-triangle fa-fw"></i> Alerte limite de SMS atteinte</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'alert_quota_limit_reached', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Recevoir un e-mail quand la limite de SMS est atteinte :</label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['alert_quota_limit_reached'] == 1 ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-exclamation fa-fw"></i> Alerte limite de SMS proche</h4>
|
||||
|
@ -337,6 +358,75 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-music fa-fw"></i> Son sur reception d'un SMS</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'sms_reception_sound', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Jouer un son quand vous recevez un SMS : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['sms_reception_sound'] ? '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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-link fa-fw"></i> Détection des URL dans les discussions</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<form action="<?php echo \descartes\Router::url('Setting', 'update', ['setting_name' => 'detect_url', 'csrf' => $_SESSION['csrf']]); ?>" method="POST">
|
||||
<div class="form-group">
|
||||
<label>Détection activé : </label>
|
||||
<select name="setting_value" class="form-control">
|
||||
<option value="0">Non</option>
|
||||
<option value="1" <?php echo $_SESSION['user']['settings']['detect_url'] ? '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">
|
||||
<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">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title"><i class="fa fa-eye-slash fa-fw"></i> Cacher des menus</h4>
|
||||
|
@ -346,7 +436,7 @@
|
|||
<input type="hidden" name="allow_no_value" value="1" />
|
||||
<div class="form-group">
|
||||
<label>Cacher certains menus à l'utilisateur (ces menus restent accessibles par l'URL) : </label>
|
||||
<input name="setting_value[]" class="add-hide-menus form-control" type="text" placeholder="Menus à cacher" autofocus value="<?php $this->s($_SESSION['user']['settings']['hide_menus']); ?>">
|
||||
<input name="setting_value[]" class="add-hide-menus form-control" type="text" placeholder="Menus à cacher" value="<?php $this->s($_SESSION['user']['settings']['hide_menus']); ?>">
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-success">Mettre à jour les données</button>
|
||||
|
@ -354,7 +444,7 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue