Commit 5f502f73 authored by okhin's avatar okhin

Merge branch '4-connect-to-the-sip-backend' into 'master'

Resolve "Connect to the sip-backend"

Closes #4

See merge request !7
parents b9ade59b 1ac1f950
Pipeline #111 passed with stage
in 1 second
app/config.php app/config.php
tests/tmp tests/tmp
*~ *~
vendor vendor/
composer.lock composer.lock
tmp/
<?php <?php
use GuzzleHttp\Client;
/* /*
* Static class for REST API communication * Static class for REST API communication
*/ */
class Api { class Api {
// Generic get function for REST API // Generic get function for REST API
static function get($url) { static function get($url) {
$curl = curl_init(); $client = new Client(['base_uri' => API_BASE, 'defaults' => [ 'headers' => [ 'Content-type' => 'applications/json']]]);
$url = API_BASE . $url . "/?format=json"; $url = API_BASE . $url . "/?format=json";
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-type: application/json')); $result = $client->request('GET', $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); return $result->getBody();
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
$result = curl_exec($curl);
curl_close($curl);
return $result;
} }
// Generic post function for REST API // Generic post function for REST API
static function post($url, $data) { static function post($url, $data) {
$curl = curl_init(); $client = new Client(['base_uri' => API_BASE, 'defaults' => [ 'headers' => [ 'Content-type' => 'applications/json']]]);
$url = API_BASE . $url; $url = API_BASE . $url . "/?format=json";
curl_setopt($curl, CURLOPT_URL, $url); $result = $client->request('POST', $url, array(), $data);
curl_setopt($curl, CURLOPT_POST, true); return $result->getBody();
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($curl);
curl_close($curl);
return $result;
} }
// Asking for campaign informations // Asking for campaign informations
...@@ -42,6 +35,12 @@ class Api { ...@@ -42,6 +35,12 @@ class Api {
return json_decode($json, true); return json_decode($json, true);
} }
// Asking for a single contact
static function get_contact($id) {
$json = Api::get("campaigns/" . CAMPAIGN_ID . "/contacts/" . $id);
return json_decode($json, true);
}
// Asking for complete list of groups // Asking for complete list of groups
static function get_groups() { static function get_groups() {
$json = Api::get("campaigns/" . CAMPAIGN_ID . "/groups"); $json = Api::get("campaigns/" . CAMPAIGN_ID . "/groups");
......
<?php <?php
use \Firebase\JWT\JWT;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7;
use GuzzleHttp\Exception\RequestException;
class Main extends Controller { class Main extends Controller {
/* /*
* Home page * Home page
...@@ -12,7 +18,7 @@ class Main extends Controller { ...@@ -12,7 +18,7 @@ class Main extends Controller {
$contacts = $f3->get('contacts'); $contacts = $f3->get('contacts');
$f3->set('contact', $contacts[$rand_id]); $f3->set('contact', $contacts[$rand_id]);
$f3->set('random', rand(0, 2)); $f3->set('random', rand(0, 2));
$f3->set('block_content','home.html'); $f3->set('block_content', 'home.html');
} }
/* /*
...@@ -30,9 +36,6 @@ class Main extends Controller { ...@@ -30,9 +36,6 @@ class Main extends Controller {
$contact_id = $f3->get('POST.contact_id'); $contact_id = $f3->get('POST.contact_id');
$f3->set("contact_id", $contact_id); $f3->set("contact_id", $contact_id);
//TODO: create call
//TODO: start call
$f3->set('block_content', 'feedbackform.html'); $f3->set('block_content', 'feedbackform.html');
} }
//POST //POST
...@@ -63,16 +66,37 @@ class Main extends Controller { ...@@ -63,16 +66,37 @@ class Main extends Controller {
function call($f3, $args) { function call($f3, $args) {
//GET //GET
if ($f3->get('VERB') == 'GET') { if ($f3->get('VERB') == 'GET') {
$f3->set('contact', Api::get_contact()); //$args['id'] $f3->set('contact', Api::get_contact($args['id']));
$f3->set('block_content', 'call.html'); $f3->set('block_content', 'call.html');
} }
//POST //POST
elseif ($f3->get('VERB') == 'POST'){ elseif ($f3->get('VERB') == 'POST'){
//GET feedbackform // Create the call
$f3->set('VERB', 'GET'); // Generate a jwt token
$this->feedbackform($f3, $args); $token = JWT::encode(array('api' => JWT_TOKEN), JWT_KEY);
} // To get the callee, we have the callee_id in the form. Using that
// to load the callee and retrieve its number.
$contact = Api::get_contact($args['id']);
$f3->set('contact', $contact);
$data = array('api' => 'piphone', 'caller' => $f3->get('POST.phone'), 'callee' => $contact['phone'], 'token' => $token);
// We want to generate a UNIQUE-ID (doesn't need to be cryptogaphically unique though
$call_id = uniqid();
$f3->set('CALL_ID', $call_id);
// Create the call
$client = new GuzzleHttp\Client(['base_uri' => SIP_API]);
try {
$res = $client->post("calls/$call_id", ['query' => $data]);
$f3->set('call', json_decode($res->getBody()));
$f3->set('VERB', 'GET');
$this->feedbackform($f3, $args);
} catch (RequestException $e) {
echo Psr7\str($e->getRequest());
if ($e->hasResponse()) {
echo Psr7\str($e->getResponse());
}
}
}
} }
function contactslist($f3, $args) { function contactslist($f3, $args) {
......
...@@ -21,6 +21,16 @@ class RestApi { ...@@ -21,6 +21,16 @@ class RestApi {
echo $this->return_datas('app/datas/contacts.json'); echo $this->return_datas('app/datas/contacts.json');
} }
function contact($f3,$args) {
$contacts = json_decode($this->return_datas('app/datas/contacts.json', true));
foreach($contacts as $contact) {
if ( $contact->id == $args['cid'] ) {
echo json_encode($contact);
return;
}
};
}
function categories($f3,$args) { function categories($f3,$args) {
// List of feedback categories // List of feedback categories
echo'{"categories": [ echo'{"categories": [
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
define("CAMPAIGN_ID","1"); define("CAMPAIGN_ID","1");
define("API_BASE","http://localhost/restapi/"); define("API_BASE","http://localhost/restapi/");
define("API_TIMEOUT","1"); define("API_TIMEOUT","1");
define("JWT_KEY", "YOUR_KEY");
define("JWT_TOKEN", "YOUR_TOKEN");
define("SIP_API", "http://backendsip/api");
/* TODO : remove this in production ;) */ /* TODO : remove this in production ;) */
error_reporting(E_ALL|E_WARNING); error_reporting(E_ALL|E_WARNING);
......
...@@ -10,6 +10,7 @@ GET @argumentation:/argumentation=Main->argumentation ...@@ -10,6 +10,7 @@ GET @argumentation:/argumentation=Main->argumentation
; Fake REST API ; Fake REST API
GET /restapi/campaigns/@id=RestApi->campaign GET /restapi/campaigns/@id=RestApi->campaign
GET /restapi/campaigns/@id/contacts=RestApi->contacts GET /restapi/campaigns/@id/contacts=RestApi->contacts
GET /restapi/campaigns/@id/contacts/@cid=RestApi->contact
GET /restapi/campaigns/@id/feedback/categories=RestApi->categories GET /restapi/campaigns/@id/feedback/categories=RestApi->categories
POST /restapi/campaigns/@id/feedback/add=RestApi->feedback_add POST /restapi/campaigns/@id/feedback/add=RestApi->feedback_add
GET /restapi/campaigns/@id/arguments/@lang=RestApi->arguments GET /restapi/campaigns/@id/arguments/@lang=RestApi->arguments
......
...@@ -26,4 +26,4 @@ else ...@@ -26,4 +26,4 @@ else
cd $CI_PROJECT_NAME cd $CI_PROJECT_NAME
fi fi
composer install composer install || composer update
...@@ -96,6 +96,25 @@ background-color: #ccc; ...@@ -96,6 +96,25 @@ background-color: #ccc;
padding: .5em 1em; padding: .5em 1em;
} }
#callModal {
visibility:hidden;
}
#callModal:target {
visibility:visible;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
}
.cmodal .panel{
margin: auto;
background: rgba(255, 255, 255, 1);
max-width: 80%;
min-width: 50%;
}
<include href="header.html" /> <include href="header.html" />
<include href="{{ @block_content }}" /> <include href="{{ @block_content }}" />
<include href="call.html" />
<include href="footer.html" /> <include href="footer.html" />
<h2>{{ _("Call for free") }}</h2> <div class="overlay" id="callModal">
<div class="cmodal container-fluid panel panel-default">
<div class="panel-heading">
<h2>{{ _("Reach out to ");}} {{ @contact.first_name }}&nbsp;{{ @contact.last_name }}
<a type="button" class="btn close" href="#" aria-label="Close"><span aria-hidden="true">&times;</span></a></h2>
</div>
<div class="row panel-body">
<div class="col-sm-6">
<h2>{{ _("Call for free") }}</h2>
<form method="post" action="/call/{{ @contact.id }}">
<input type="text" id="contact_id" name="contact_id" hidden="hidden" value="{{ @contact.id }}">
<p>{{ _("If you want to call for free, you must provide us with your phone number (the PiPhone will call that number to initiate the communication).") }}</p>
<form method="post" action="/call/{{ @contact.id }}"> <p>
<input type="text" id="contact_id" name="contact_id" hidden="hidden" value="{{ @contact.id }}"> <label for="phone">{{_("Your phone number:") }}</label>
<p>{{ _("If you want to call for free, you must provide us with your phone number (the PiPhone will call that number to initiate the communication).") }}</p> <input type="text" name="phone" id="phone" placeholder="+33123456789001" />
</p>
<p>
{{ _('Starting with your <a href="https://en.wikipedia.org/wiki/List_of_country_calling_codes#Zones_3-4:_Europe">country code</a>, without the initial 0') }}
</p>
<input class="btn btn-default" type="submit" value="{{ _("I'm ready, call me") }}" />
</form>
</div>
<div class="col-sm-6">
<h2>{{ _("Call at your expense") }}</h2>
<p>{{ _("If you don't want to call for free, here is the number of the current MEP (you can either dial it from your phone or push the button if any VoIP client is installed on your device.") }}</p>
<a class="btn btn-default" href="tel:{{ @contact.phone }}" target="_blank">☎ {{ @contact.phone }}</a>
<p> </div>
<label for="phone">{{_("Your phone number:") }}</label> </div>
<input type="text" name="phone" id="phone" placeholder="+33123456789001" /> </div>
</p> </div>
<p>
{{ _('Starting with your <a href="https://en.wikipedia.org/wiki/List_of_country_calling_codes#Zones_3-4:_Europe">country code</a>, without the initial 0') }}
</p>
<input type="submit" value="{{ _("I'm ready, call me") }}" />
</form>
<h2>{{ _("Call at your expense") }}</h2>
<p>{{ _("If you don't want to call for free, here is the number of the current MEP (you can either dial it from your phone or push the button if any VoIP client is installed on your device.") }}</p>
<a href="tel:{{ @contact.tel }}" target="_blank">☎ {{ @contact.tel }}</a>
<p><a href="/">{{ _("Cancel the call") }}</a></p>
...@@ -22,14 +22,14 @@ ...@@ -22,14 +22,14 @@
<div class="col-md-8"> <div class="col-md-8">
<!-- titre --> <!-- titre -->
<div> <div>
<h1 class="text-center" id="name">{{ @contact.first_name }} <br class="visible-xs-block">{{ @contact.last_name }}</h2> <h1 class="text-center" id="name">{{ @contact.first_name }} <br class="visible-xs-block">{{ @contact.last_name }}</h1>
<!-- actions --> <!-- actions -->
<div class="text-center row"> <div class="text-center row">
<p class="lead text-center"> <p class="lead text-center">
<abbr title="{{ _("Phone number") }}">{{ _("Phone number") }}:</abbr> <a href="tel: {{ @contact.phone }}">{{ @contact.phone }}</a> <abbr title="{{ _("Phone number") }}">{{ _("Phone number") }}:</abbr> <a href="tel: {{ @contact.phone }}">{{ @contact.phone }}</a>
<br class="visible-xs-block"> <br class="visible-xs-block">
<button type="button" class="btn btn-default" title="{{ _("Call now") }}" data-toggle="modal" data-target="#CallModal"><span class="glyphicon glyphicon-earphone"></span></button> <a type="button" class="btn btn-default" title="{{ _("Call now") }}" href="#callModal"><span class="glyphicon glyphicon-earphone"></span></button>
<a type="button" class="btn btn-info" title="{{ _("Get more info...") }}" href="#"><span class="glyphicon glyphicon-info-sign"></span></a> <a type="button" class="btn btn-info" title="{{ _("Get more info...") }}" href="#"><span class="glyphicon glyphicon-info-sign"></span></a>
<a type="button" class="btn btn-default visible-xs-inline-block" title="{{ _("Choose someone else") }}" href="#"><span class="glyphicon glyphicon-refresh"></span></a> <a type="button" class="btn btn-default visible-xs-inline-block" title="{{ _("Choose someone else") }}" href="#"><span class="glyphicon glyphicon-refresh"></span></a>
</p> </p>
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
</div> </div>
<!-- /committees --> <!-- /committees -->
</div> </div>
<!-- /-- gauche --> <!-- /gauche -->
<!-- droite --> <!-- droite -->
<div class="col-md-4"> <div class="col-md-4">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment