Rediseño de interfaz
This commit is contained in:
parent
b802418546
commit
0eb3f30b6f
15
router.js
15
router.js
|
@ -6,4 +6,19 @@ router.get('/', function(request, response) {
|
||||||
view.render('home', {id: request.user.id}, response);
|
view.render('home', {id: request.user.id}, response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/history', function(request, response) {
|
||||||
|
let number = request.query.number;
|
||||||
|
view.render('history', {id: request.user.id, call: number}, response);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/dialpad', function(request, response) {
|
||||||
|
let number = request.query.number;
|
||||||
|
view.render('dialpad', {id: request.user.id, call: number}, response);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/call', function(request, response) {
|
||||||
|
let number = request.query.number;
|
||||||
|
view.render('call', {id: request.user.id, call: number}, response);
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
|
@ -1,206 +1,221 @@
|
||||||
body {
|
body {
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: Arial, Verdana, Helvetica, sans-serif;
|
||||||
background-color: #292929;
|
background-color: #292929;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 65.5px 0 0 0;
|
padding: 0;
|
||||||
margin: 0
|
margin: 0;
|
||||||
}
|
|
||||||
|
}
|
||||||
html, body {
|
|
||||||
min-height: 100%;
|
html, body {
|
||||||
height: 100%
|
min-height: 100%;
|
||||||
}
|
height: 100%
|
||||||
|
}
|
||||||
* {
|
|
||||||
-webkit-box-sizing: border-box;
|
* {
|
||||||
-moz-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box
|
-moz-box-sizing: border-box;
|
||||||
}
|
box-sizing: border-box
|
||||||
|
}
|
||||||
a {
|
|
||||||
color: #FFF
|
a {
|
||||||
}
|
color: #FFF;
|
||||||
|
font-family: inherit;
|
||||||
.container {
|
}
|
||||||
min-height: 100%;
|
|
||||||
height: 100%
|
.navigation {
|
||||||
}
|
background-color: #3C393B;
|
||||||
|
position: fixed;
|
||||||
.quickbar {
|
padding: 15px;
|
||||||
background-color: #3C393B;
|
width: 100%;
|
||||||
position: absolute;
|
z-index: 2;
|
||||||
padding: 15px;
|
top: 0
|
||||||
width: 100%;
|
}
|
||||||
top: 0
|
|
||||||
}
|
.navigation a {
|
||||||
|
text-decoration: none;
|
||||||
.quickbar a {
|
margin-left: 10px;
|
||||||
text-decoration: none;
|
color: #FFF
|
||||||
margin-left: 10px;
|
}
|
||||||
color: #FFF
|
|
||||||
}
|
.navigation a:hover {
|
||||||
|
color: #ff6e40
|
||||||
.quickbar a:hover {
|
}
|
||||||
color: #ff6e40
|
|
||||||
}
|
.navigation .pull-right a i {
|
||||||
|
font-size: 32px;
|
||||||
.quickbar .pull-right a i {
|
}
|
||||||
font-size: 32px;
|
|
||||||
}
|
#container {
|
||||||
|
position: fixed;
|
||||||
.side {
|
padding-left: 80px;
|
||||||
background: #2C2C2C;
|
top: 65.5px;
|
||||||
height: 100%;
|
bottom: 0;
|
||||||
width: 15%;
|
width: 100%;
|
||||||
float: left
|
float: left
|
||||||
}
|
}
|
||||||
|
|
||||||
.side .user {
|
#container.side-display {
|
||||||
padding: 15px;
|
padding-left: 335px
|
||||||
color: #FFF
|
}
|
||||||
}
|
|
||||||
|
.quickbar {
|
||||||
.side .user .extension {
|
background: #232323;
|
||||||
font-size: 12px
|
position: fixed;
|
||||||
}
|
width: 80px;
|
||||||
|
top: 65.5px;
|
||||||
.side .user:after {
|
bottom: 0;
|
||||||
display: block;
|
left: 0
|
||||||
content: ' ';
|
}
|
||||||
clear: both
|
|
||||||
}
|
.quickbar ul {
|
||||||
|
padding: 0;
|
||||||
.side .user .name {
|
margin: 0
|
||||||
font-weight: bold;
|
}
|
||||||
color: #FFF
|
|
||||||
}
|
.quickbar ul li {
|
||||||
|
position: relative;
|
||||||
.side .title {
|
list-style: none
|
||||||
background-color: #333333;
|
}
|
||||||
text-transform: uppercase;
|
|
||||||
padding: 15px 10px;
|
.quickbar ul li a {
|
||||||
font-weight: bold;
|
padding: 20px 0;
|
||||||
color: #111111
|
text-align: center;
|
||||||
|
display: block
|
||||||
}
|
}
|
||||||
|
|
||||||
.side .navigation a {
|
.quickbar ul li a i {
|
||||||
background-color: #ff9e00;
|
font-size: 32px
|
||||||
text-decoration: none;
|
}
|
||||||
transition: 0.2s all;
|
|
||||||
text-align: center;
|
.quickbar ul li a:hover {
|
||||||
font-size: 24px;
|
background-color: #383838
|
||||||
display: block;
|
}
|
||||||
padding: 15px;
|
|
||||||
color: #FFF
|
.quickbar ul li a.active {
|
||||||
}
|
background-color: #2C2C2C
|
||||||
|
}
|
||||||
.side .navigation a.active, .side .navigation a.active:hover {
|
|
||||||
background-color: #FFF;
|
.quickbar .audioControls {
|
||||||
color: #FFA410
|
position:absolute;
|
||||||
}
|
bottom: 0;
|
||||||
|
color: #FFF
|
||||||
.side .navigation a:hover {
|
}
|
||||||
background-color: #ffb030;
|
|
||||||
}
|
.profile .status {
|
||||||
|
position:absolute;
|
||||||
.side .navigation a i {
|
width: 10px;
|
||||||
margin-right: 10px
|
height: 10px;
|
||||||
}
|
top: 15px;
|
||||||
|
left: 15px;
|
||||||
.side .audioControls {
|
border-radius: 50%
|
||||||
position:absolute;
|
}
|
||||||
bottom: 0;
|
|
||||||
padding: 15px;
|
.profile .status.offline {
|
||||||
color: #FFF
|
background-color: #CCC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.profile .status.online {
|
||||||
|
background-color: #95D600
|
||||||
.chatbox .search {
|
}
|
||||||
margin-bottom: 15px
|
|
||||||
}
|
.profile .status.error {
|
||||||
|
background-color: #d81212
|
||||||
.chatbox .search .control {
|
}
|
||||||
-webkit-border-radius: 15px;
|
|
||||||
-moz-border-radius: 15px;
|
#side {
|
||||||
border-radius: 15px;
|
background-color: #2C2C2C;
|
||||||
background: #232323;
|
position: fixed;
|
||||||
padding: 10px
|
padding: 15px;
|
||||||
}
|
display: none;
|
||||||
|
height: 100%;
|
||||||
.chatbox .search input[type=text] {
|
width: 255px;
|
||||||
background-color: transparent;
|
left: 80px
|
||||||
font-family: inherit;
|
}
|
||||||
font-size: 18px;
|
|
||||||
color: #FFF;
|
#content {
|
||||||
border: 0px;
|
position:relative;
|
||||||
|
width: 100%;
|
||||||
width:100%
|
height: 100%;
|
||||||
}
|
float:left
|
||||||
|
}
|
||||||
.chatbox .callTimer {
|
|
||||||
text-align: center;
|
.call {
|
||||||
padding: 15px
|
background-color: #111;
|
||||||
}
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
.chatbox .callTimer span {
|
float: left
|
||||||
font-size: 18px;
|
}
|
||||||
color: #FFF
|
|
||||||
}
|
.chatbox {
|
||||||
|
position: relative
|
||||||
.chatbox {
|
}
|
||||||
background-color: #292929;
|
|
||||||
height: 100%;
|
.chatbox {
|
||||||
width: 85%;
|
background-color: #292929;
|
||||||
float: left
|
height: 100%;
|
||||||
}
|
width: 100%;
|
||||||
|
margin-left: 80px;
|
||||||
.chatbox .navigation {
|
float: left
|
||||||
padding: 15px;
|
}
|
||||||
color: #FFF
|
|
||||||
}
|
#notifications {
|
||||||
|
position: fixed;
|
||||||
#notifications {
|
overflow: hidden;
|
||||||
position: fixed;
|
left: 50%;
|
||||||
overflow: hidden;
|
max-height: 200px;
|
||||||
left: 50%;
|
width: 500px;
|
||||||
max-height: 200px;
|
margin-left: -250px;
|
||||||
width: 500px;
|
top: 80px
|
||||||
margin-left: -250px;
|
}
|
||||||
top: 80px
|
|
||||||
}
|
#notifications .dialog {
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
#notifications .dialog {
|
text-align:center;
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
-moz-border-radius:3px;
|
||||||
text-align:center;
|
-webkit-border-radius:3px;
|
||||||
-moz-border-radius:3px;
|
border-radius:3px;
|
||||||
-webkit-border-radius:3px;
|
margin-bottom: 15px;
|
||||||
border-radius:3px;
|
padding: 10px;
|
||||||
margin-bottom: 15px;
|
color: #FFF
|
||||||
padding: 10px;
|
}
|
||||||
color: #FFF
|
|
||||||
}
|
.dial .search {
|
||||||
|
margin-bottom: 15px
|
||||||
.dial {
|
}
|
||||||
width: 500px;
|
|
||||||
margin: 100px auto
|
.dial .search .control {
|
||||||
}
|
-webkit-border-radius: 15px;
|
||||||
|
-moz-border-radius: 15px;
|
||||||
.dial .callStatus {
|
border-radius: 15px;
|
||||||
font-size: 18px;
|
background: #232323;
|
||||||
text-align: center;
|
padding: 10px
|
||||||
color: #FFF
|
}
|
||||||
}
|
|
||||||
|
.dial .search input[type=text] {
|
||||||
.dial .btn {
|
background-color: transparent;
|
||||||
margin-bottom: 10px
|
font-family: inherit;
|
||||||
}
|
font-size: 18px;
|
||||||
|
color: #FFF;
|
||||||
.dial .columns .column {
|
border: 0px;
|
||||||
padding-right: 10px
|
|
||||||
}
|
width:100%
|
||||||
|
}
|
||||||
.dial .columns .column:last-child {
|
|
||||||
padding-right: 0
|
.dial .callStatus {
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
color: #FFF
|
||||||
|
}
|
||||||
|
|
||||||
|
.dial .btn {
|
||||||
|
margin-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.dial .columns .column {
|
||||||
|
padding-right: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.dial .columns .column:last-child {
|
||||||
|
padding-right: 0
|
||||||
}
|
}
|
|
@ -1,76 +1,76 @@
|
||||||
let audio = {
|
let audio = {
|
||||||
|
|
||||||
audioLoop: null,
|
audioLoop: null,
|
||||||
|
|
||||||
init: function() {
|
init: function() {
|
||||||
if (ua.audioInstance)
|
if (ua.audioInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ua.audioInstance = document.createElement('audio');
|
ua.audioInstance = document.createElement('audio');
|
||||||
},
|
},
|
||||||
|
|
||||||
addTrack: function(track) {
|
addTrack: function(track) {
|
||||||
if (ua.audioInstance)
|
if (ua.audioInstance)
|
||||||
this.stop();
|
this.stop();
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
ua.audioInstance.src = this.getTrackPath(track);
|
ua.audioInstance.src = this.getTrackPath(track);
|
||||||
},
|
},
|
||||||
|
|
||||||
addStream: function(stream) {
|
addStream: function(stream) {
|
||||||
if (ua.audioInstance)
|
if (ua.audioInstance)
|
||||||
this.stop();
|
this.stop();
|
||||||
|
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
ua.audioInstance.srcObject = stream;
|
ua.audioInstance.srcObject = stream;
|
||||||
},
|
},
|
||||||
|
|
||||||
play: function(loop = false) {
|
play: function(loop = false) {
|
||||||
if (!ua.audioInstance)
|
if (!ua.audioInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ua.audioInstance.volume = Softphone.getVolume();
|
ua.audioInstance.volume = Softphone.getVolume();
|
||||||
|
|
||||||
ua.audioInstance.play();
|
ua.audioInstance.play();
|
||||||
|
|
||||||
if (loop) {
|
if (loop) {
|
||||||
this.audioLoop = setInterval(function() {
|
this.audioLoop = setInterval(function() {
|
||||||
ua.audioInstance.play();
|
ua.audioInstance.play();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
stop: function() {
|
stop: function() {
|
||||||
if (!ua.audioInstance)
|
if (!ua.audioInstance)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this.audioLoop)
|
if (this.audioLoop)
|
||||||
clearInterval(this.audioLoop);
|
clearInterval(this.audioLoop);
|
||||||
|
|
||||||
ua.audioInstance.pause();
|
ua.audioInstance.pause();
|
||||||
ua.audioInstance = null;
|
ua.audioInstance = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
isPlaying: function() {
|
isPlaying: function() {
|
||||||
if (!ua.audioInstance.paused)
|
if (!ua.audioInstance.paused)
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
getTrackPath: function(track) {
|
getTrackPath: function(track) {
|
||||||
return `/static/audio/${track}.wav`;
|
return `/static/audio/${track}.wav`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,168 +1,65 @@
|
||||||
window.addEventListener('load', function() {
|
$(window).on('load', function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Incoming/Outgoint calls
|
||||||
|
*/
|
||||||
|
/* if (!Softphone.isOnCall()) {
|
||||||
|
let number = Util.query('number');
|
||||||
|
Softphone.call(number);
|
||||||
|
} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make new call
|
* Make new call
|
||||||
*/
|
*/
|
||||||
$('call').addEventListener('click', function(event) {
|
$(document).on('click', '#call', function() {
|
||||||
if (ua.sessionInstance && ua.sessionInstance.direction === 'incoming')
|
let number = $('#callNumber').val();
|
||||||
ua.sessionInstance.answer(options);
|
|
||||||
|
|
||||||
let number = $('callNumber').value;
|
if (number)
|
||||||
$('callNumber').value = '';
|
Softphone.call(number, options);
|
||||||
|
|
||||||
if (number != '') {
|
return false;
|
||||||
Softphone.call(number);
|
|
||||||
} else {
|
|
||||||
notify('Introduce un destinatario para realizar la llamada');
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset call number field
|
* Insert key on call field
|
||||||
*/
|
*/
|
||||||
$('clear').addEventListener('click', function(event) {
|
$(document).on('click', '#zero, #one, #two, #three, #four, '
|
||||||
$('callNumber').value = '';
|
+ '#five, #six, #seven, #eight, #nine, #asterisk, #pad', padKey);
|
||||||
|
|
||||||
audio.addTrack('reset');
|
/**
|
||||||
audio.play();
|
* History
|
||||||
event.preventDefault();
|
*/
|
||||||
|
$(document).on('click', '#history', function() {
|
||||||
|
Util.navigate('#content', '/history');
|
||||||
|
|
||||||
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End a call
|
* Show/Hide dialpad
|
||||||
*/
|
*/
|
||||||
$('callHangup').addEventListener('click', function(event) {
|
$(document).on('click', '#dial', function() {
|
||||||
|
Util.navigate('#side', '/dialpad');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept incoming call
|
||||||
|
*/
|
||||||
|
$(document).on('click', '#accept', function() {
|
||||||
|
Softphone.answer(options);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decline incoming call
|
||||||
|
*/
|
||||||
|
$(document).on('click', '#decline', function() {
|
||||||
Softphone.hangup();
|
Softphone.hangup();
|
||||||
|
|
||||||
audio.addTrack('hangup');
|
return false;
|
||||||
audio.play();
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
/* *
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('zero').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('one').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('two').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('three').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('four').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('five').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('six').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('seven').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('eight').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('nine').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('asterisk').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Insert key on call field
|
|
||||||
*/
|
|
||||||
$('pad').addEventListener('click', padKey);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Transfer current call
|
|
||||||
*/
|
|
||||||
$('callTransfer').addEventListener('click', function(event) {
|
|
||||||
let number = document.getElementById('callNumber').value;
|
|
||||||
|
|
||||||
if (number != '') {
|
|
||||||
Softphone.transfer(number);
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hold current call
|
|
||||||
*/
|
|
||||||
$('callPause').addEventListener('click', function(event) {
|
|
||||||
if (Softphone.isOnHold()) {
|
|
||||||
Softphone.unhold();
|
|
||||||
} else {
|
|
||||||
Softphone.hold();
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do not disturb
|
|
||||||
*/
|
|
||||||
$('doNotDisturb').addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call settings
|
|
||||||
*/
|
|
||||||
$('callConfig').addEventListener('click', function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change volume action
|
|
||||||
*/
|
|
||||||
$('volume').addEventListener('change', function(event) {
|
|
||||||
if (!ua.callInstance)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ua.audioInstance.volume = this.value;
|
|
||||||
});
|
|
||||||
|
|
||||||
$('mic').addEventListener('click', function(event) {
|
|
||||||
if(Softphone.isMuted()) {
|
|
||||||
Softphone.unmute();
|
|
||||||
} else {
|
|
||||||
Softphone.mute();
|
|
||||||
}
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,7 +70,7 @@ window.addEventListener('load', function() {
|
||||||
let key = event.target.innerHTML;
|
let key = event.target.innerHTML;
|
||||||
let keyName = event.target.id;
|
let keyName = event.target.id;
|
||||||
|
|
||||||
$('callNumber').value += key;
|
document.getElementById('callNumber').value += key;
|
||||||
|
|
||||||
audio.addTrack(keyName);
|
audio.addTrack(keyName);
|
||||||
audio.play();
|
audio.play();
|
||||||
|
@ -184,6 +81,6 @@ window.addEventListener('load', function() {
|
||||||
/**
|
/**
|
||||||
* Prevent page reload without confirmation
|
* Prevent page reload without confirmation
|
||||||
*/
|
*/
|
||||||
window.addEventListener("beforeunload", function (event) {
|
window.addEventListener("beforeunload", function (event) {
|
||||||
event.returnValue = "\o/";
|
event.returnValue = "\o/";
|
||||||
});
|
});
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,20 @@
|
||||||
let Softphone = {
|
let Softphone = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if has a call session
|
||||||
|
*/
|
||||||
|
isOnCall: function() {
|
||||||
|
if (ua.sessionInstance)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a new call
|
* Make a new call
|
||||||
*/
|
*/
|
||||||
call: function(number) {
|
call: function(number) {
|
||||||
if (ua.sessionInstance)
|
if (this.isOnCall())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ua.sessionInstance = ua.call(`sip:${number}@${uriHost}`, options);
|
ua.sessionInstance = ua.call(`sip:${number}@${uriHost}`, options);
|
||||||
|
@ -13,17 +24,27 @@ let Softphone = {
|
||||||
* Hang up current call
|
* Hang up current call
|
||||||
*/
|
*/
|
||||||
hangup: function() {
|
hangup: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ua.sessionInstance.terminate();
|
ua.sessionInstance.terminate();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answer incoming call
|
||||||
|
*/
|
||||||
|
answer: function() {
|
||||||
|
if (!this.isOnCall())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ua.sessionInstance.answer(options);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mute current call
|
* Mute current call
|
||||||
*/
|
*/
|
||||||
mute: function() {
|
mute: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
ua.sessionInstance.mute();
|
ua.sessionInstance.mute();
|
||||||
|
@ -33,7 +54,7 @@ let Softphone = {
|
||||||
* Unmute current call
|
* Unmute current call
|
||||||
*/
|
*/
|
||||||
unmute: function() {
|
unmute: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
ua.sessionInstance.unmute();
|
ua.sessionInstance.unmute();
|
||||||
|
@ -43,7 +64,7 @@ let Softphone = {
|
||||||
* Get if current call is muted
|
* Get if current call is muted
|
||||||
*/
|
*/
|
||||||
isMuted: function() {
|
isMuted: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
return ua.sessionInstance.isMuted();
|
return ua.sessionInstance.isMuted();
|
||||||
|
@ -53,7 +74,7 @@ let Softphone = {
|
||||||
* Hold current call
|
* Hold current call
|
||||||
*/
|
*/
|
||||||
hold: function() {
|
hold: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
ua.sessionInstance.hold();
|
ua.sessionInstance.hold();
|
||||||
|
@ -73,7 +94,7 @@ let Softphone = {
|
||||||
* Get if current call is on hold
|
* Get if current call is on hold
|
||||||
*/
|
*/
|
||||||
isOnHold: function() {
|
isOnHold: function() {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
return ua.sessionInstance.isOnHold().local;
|
return ua.sessionInstance.isOnHold().local;
|
||||||
|
@ -83,7 +104,7 @@ let Softphone = {
|
||||||
* Transfer current call
|
* Transfer current call
|
||||||
*/
|
*/
|
||||||
transfer: function(number) {
|
transfer: function(number) {
|
||||||
if (!ua.sessionInstance)
|
if (!this.isOnCall())
|
||||||
return
|
return
|
||||||
|
|
||||||
ua.sessionInstance.refer(`sip:${number}@${uriHost}`);
|
ua.sessionInstance.refer(`sip:${number}@${uriHost}`);
|
||||||
|
@ -107,5 +128,25 @@ let Softphone = {
|
||||||
|
|
||||||
setStatus: function() {
|
setStatus: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a number from incoming calls
|
||||||
|
*/
|
||||||
|
getRemoteIdentity: function() {
|
||||||
|
if (!this.isOnCall())
|
||||||
|
return;
|
||||||
|
|
||||||
|
return ua.sessionInstance._remote_identity._uri._user;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns call direction
|
||||||
|
*/
|
||||||
|
getDirection: function() {
|
||||||
|
if (!this.isOnCall())
|
||||||
|
return;
|
||||||
|
|
||||||
|
return ua.sessionInstance.direction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
341
static/js/ua.js
341
static/js/ua.js
|
@ -1,171 +1,172 @@
|
||||||
const socketHost = 'ws://pbx.dyn.verdnatura.es:8088/asterisk/ws';
|
const socketHost = 'ws://pbx.dyn.verdnatura.es:8088/asterisk/ws';
|
||||||
const uriHost = 'pbx.dyn.verdnatura.es';
|
const uriHost = 'pbx.dyn.verdnatura.es';
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
mediaConstraints: {
|
mediaConstraints: {
|
||||||
audio: true,
|
audio: true,
|
||||||
video: false
|
video: false
|
||||||
},
|
},
|
||||||
session_timers: false,
|
session_timers: false,
|
||||||
volume: 0.5,
|
volume: 0.5,
|
||||||
microphone: true
|
microphone: true
|
||||||
};
|
};
|
||||||
|
|
||||||
let socket = new JsSIP.WebSocketInterface(socketHost);
|
let socket = new JsSIP.WebSocketInterface(socketHost);
|
||||||
let configuration = {
|
let configuration = {
|
||||||
sockets : [ socket ],
|
sockets : [ socket ],
|
||||||
uri : 'sip:8000@pbx.dyn.verdnatura.es',
|
uri : 'sip:8000@pbx.dyn.verdnatura.es',
|
||||||
password : '123456',
|
password : '123456',
|
||||||
authorizationUser: '8000',
|
authorizationUser: '8000',
|
||||||
hackIpInContact: true,
|
hackIpInContact: true,
|
||||||
rtcpMuxPolicy: 'negotiate',
|
rtcpMuxPolicy: 'negotiate',
|
||||||
hackWssInTransport: true
|
hackWssInTransport: true
|
||||||
};
|
};
|
||||||
|
|
||||||
let ua = new JsSIP.UA(configuration);
|
let ua = new JsSIP.UA(configuration);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show event message
|
* Show event message
|
||||||
* @param {Object} event
|
* @param {Object} event
|
||||||
*/
|
*/
|
||||||
function eventStatus(event) {
|
function eventStatus(event) {
|
||||||
if (event.cause === JsSIP.C.causes.CONNECTION_ERROR)
|
if (event.cause === JsSIP.C.causes.CONNECTION_ERROR)
|
||||||
return notify('Ha ocurrido un error de conexión');
|
return Util.notify('Ha ocurrido un error de conexión');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.INTERNAL_ERROR)
|
if (event.cause === JsSIP.C.causes.INTERNAL_ERROR)
|
||||||
return notify('Ha ocurrido un error inesperado');
|
return Util.notify('Ha ocurrido un error inesperado');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.AUTHENTICATION_ERROR)
|
if (event.cause === JsSIP.C.causes.AUTHENTICATION_ERROR)
|
||||||
return notify('No se ha podido autenticar la sesión');
|
return Util.notify('No se ha podido autenticar la sesión');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.UNAVAILABLE)
|
if (event.cause === JsSIP.C.causes.UNAVAILABLE)
|
||||||
return notify('El destinatario no está disponible');
|
return Util.notify('El destinatario no está disponible');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.BUSY)
|
if (event.cause === JsSIP.C.causes.BUSY)
|
||||||
return notify('El destinatario está ocupado');
|
return Util.notify('El destinatario está ocupado');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.REJECTED)
|
if (event.cause === JsSIP.C.causes.REJECTED)
|
||||||
return notify('La conexión ha sido rechazada')
|
return Util.notify('La llamada ha sido rechazada')
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.NOT_FOUND)
|
if (event.cause === JsSIP.C.causes.NOT_FOUND)
|
||||||
return notify('No se ha podido encontrar el destinatario');
|
return Util.notify('No se ha podido encontrar el destinatario');
|
||||||
|
|
||||||
if (event.cause === JsSIP.C.causes.REQUEST_TIMEOUT)
|
if (event.cause === JsSIP.C.causes.REQUEST_TIMEOUT)
|
||||||
return notify('El destinatario no ha respondido la llamada');
|
return Util.notify('El destinatario no ha respondido la llamada');
|
||||||
|
|
||||||
if (event.cause === JsSIP.USER_DENIED_MEDIA_ACCESS)
|
if (event.cause === JsSIP.USER_DENIED_MEDIA_ACCESS)
|
||||||
return notify('Es necesario permitir el acceso al micrófono');
|
return Util.notify('Es necesario permitir el acceso al micrófono');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UA register
|
* UA register
|
||||||
*/
|
*/
|
||||||
ua.on('registered', function(event) {
|
ua.on('registered', function(event) {
|
||||||
$('callStatus').innerHTML = 'Conectado';
|
$('.profile .status').removeClass('offline').addClass('online');
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client disconnection
|
* Client disconnection
|
||||||
*/
|
*/
|
||||||
ua.on('disconnected', function(event) {
|
ua.on('disconnected', function(event) {
|
||||||
$('callStatus').innerHTML = 'Desconectado';
|
$('.profile .status').removeClass('online').addClass('offline');
|
||||||
});
|
eventStatus(event);
|
||||||
|
});
|
||||||
ua.on('registrationFailed', function(event) {
|
|
||||||
|
ua.on('registrationFailed', function(event) {
|
||||||
Softphone.notifyStatus(event);
|
$('.profile .status').removeClass('offline').addClass('error');
|
||||||
|
eventStatus(event);
|
||||||
$('callStatus').innerHTML = 'Desconectado';
|
});
|
||||||
});
|
|
||||||
|
/**
|
||||||
/**
|
* Call session
|
||||||
* Call session
|
*/
|
||||||
*/
|
ua.on('newRTCSession', function(event) {
|
||||||
ua.on('newRTCSession', function(event) {
|
let session = event.session;
|
||||||
let session = event.session;
|
ua.sessionInstance = session;
|
||||||
ua.sessionInstance = session;
|
|
||||||
|
session.on('confirmed', function() {
|
||||||
console.log(session);
|
console.log('confirmed');
|
||||||
|
});
|
||||||
session.on('confirmed', function() {
|
|
||||||
console.log('confirmed');
|
session.on('reinvite', function() {
|
||||||
})
|
console.log('reinvite');
|
||||||
|
});
|
||||||
session.on('reinvite', function() {
|
|
||||||
console.log('reinvite');
|
session.on('update', function() {
|
||||||
})
|
console.log('update');
|
||||||
|
});
|
||||||
session.on('update', function() {
|
|
||||||
console.log('update');
|
/**
|
||||||
})
|
* Call in progress
|
||||||
/**
|
*/
|
||||||
* Call in progress
|
session.on('progress', function(event) {
|
||||||
*/
|
if (session.direction === 'incoming') {
|
||||||
session.on('progress', function(event) {
|
Util.load('#content', '/call', function() {
|
||||||
console.log('progress');
|
audio.addTrack('incoming');
|
||||||
if (session.direction === 'incoming') {
|
audio.play(true);
|
||||||
audio.addTrack('incoming');
|
});
|
||||||
audio.play(true);
|
} else {
|
||||||
$('callStatus').innerHTML = 'Llamada entrante...';
|
Util.load('#content', '/call', function() {
|
||||||
} else {
|
audio.addTrack('outgoing');
|
||||||
audio.addTrack('outgoing');
|
audio.play(true);
|
||||||
audio.play(true);
|
});
|
||||||
$('callStatus').innerHTML = 'Llamando...';
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
/**
|
||||||
/**
|
* Call accepted
|
||||||
* Call accepted
|
*/
|
||||||
*/
|
session.on('accepted', function(event) {
|
||||||
session.on('accepted', function(event) {
|
console.log('accepted');
|
||||||
console.log('accepted');
|
document.getElementById('callStatus').innerHTML = 'Llamada conectada';
|
||||||
$('callStatus').innerHTML = 'Llamada conectada';
|
if (session.connection.getRemoteStreams().length > 0) {
|
||||||
if (session.connection.getRemoteStreams().length > 0) {
|
let stream = session.connection.getRemoteStreams()[0];
|
||||||
let stream = session.connection.getRemoteStreams()[0];
|
|
||||||
|
audio.addStream(stream);
|
||||||
audio.addStream(stream);
|
audio.play();
|
||||||
audio.play();
|
}
|
||||||
}
|
Util.startTimer();
|
||||||
startTimer();
|
});
|
||||||
});
|
|
||||||
|
session.on('hold', function(event) {
|
||||||
session.on('hold', function(event) {
|
$('callStatus').innerHTML = 'Llamada en espera';
|
||||||
$('callStatus').innerHTML = 'Llamada en espera';
|
});
|
||||||
});
|
|
||||||
|
session.on('unhold', function(event) {
|
||||||
session.on('unhold', function(event) {
|
$('callStatus').innerHTML = 'Llamada conectada';
|
||||||
$('callStatus').innerHTML = 'Llamada conectada';
|
});
|
||||||
});
|
|
||||||
|
session.on('refer', function() {
|
||||||
session.on('refer', function() {
|
$('callStatus').innerHTML = 'Llamada transferida';
|
||||||
$('callStatus').innerHTML = 'Llamada transferida';
|
});
|
||||||
});
|
|
||||||
|
/**
|
||||||
/**
|
* Call ended
|
||||||
* Call ended
|
*/
|
||||||
*/
|
session.on('ended', function(event) {
|
||||||
session.on('ended', function(event) {
|
audio.addTrack('hangup');
|
||||||
audio.addTrack('hangup');
|
audio.play();
|
||||||
audio.play();
|
|
||||||
|
Util.load('#content', '/', function() {
|
||||||
stopTimer();
|
|
||||||
|
});
|
||||||
$('callStatus').innerHTML = 'Conectado';
|
|
||||||
ua.sessionInstance = null;
|
Util.stopTimer();
|
||||||
eventStatus(event);
|
|
||||||
});
|
ua.sessionInstance = null;
|
||||||
|
eventStatus(event);
|
||||||
/**
|
});
|
||||||
* Call failed
|
|
||||||
*/
|
/**
|
||||||
session.on('failed', function(event) {
|
* Call failed
|
||||||
audio.addTrack('hangup');
|
*/
|
||||||
audio.play();
|
session.on('failed', function(event) {
|
||||||
|
audio.addTrack('hangup');
|
||||||
$('callStatus').innerHTML = 'Conectado';
|
audio.play();
|
||||||
ua.sessionInstance = null;
|
|
||||||
eventStatus(event);
|
ua.sessionInstance = null;
|
||||||
});
|
eventStatus(event);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ua.start();
|
ua.start();
|
|
@ -1,57 +1,105 @@
|
||||||
let timer;
|
let Util = {
|
||||||
let timerSeconds = 1;
|
timerSeconds: 1,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object selector
|
* Get URL query
|
||||||
*/
|
*/
|
||||||
function $(object) {
|
query: function(name) {
|
||||||
return document.getElementById(object);
|
let queries = window.location.search.replace('?', '').split('&');
|
||||||
}
|
|
||||||
|
for(let i = 0; i < queries.length; i++) {
|
||||||
|
let query = queries[i].split('=');
|
||||||
|
let keyName = query[0];
|
||||||
|
let value = query[1];
|
||||||
|
|
||||||
|
if (keyName == name)
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify
|
||||||
|
*/
|
||||||
|
notify: function(message) {
|
||||||
|
if (!document.getElementById('notifications')) {
|
||||||
|
let container = document.createElement('div');
|
||||||
|
container.setAttribute('id', 'notifications');
|
||||||
|
document.body.appendChild(container);
|
||||||
|
}
|
||||||
|
|
||||||
|
let dialog = document.createElement('div');
|
||||||
|
let text = document.createTextNode(message);
|
||||||
|
dialog.appendChild(text);
|
||||||
|
dialog.setAttribute('class', 'dialog');
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
dialog.remove();
|
||||||
|
}, 8000);
|
||||||
|
|
||||||
|
|
||||||
|
document.getElementById('notifications').insertBefore(dialog, document.getElementById('notifications').firstChild);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start call timer
|
* Start call timer
|
||||||
*/
|
*/
|
||||||
function startTimer() {
|
startTimer: function() {
|
||||||
timer = setInterval(function() {
|
this.timer = setInterval(() => {
|
||||||
let date = new Date(null);
|
let date = new Date(null);
|
||||||
date.setSeconds(timerSeconds);
|
console.log(this.timerSeconds);
|
||||||
|
date.setSeconds(this.timerSeconds);
|
||||||
|
|
||||||
$('timer').innerHTML = date.toISOString().substr(11, 8);
|
document.getElementById('timer').innerHTML = date.toISOString().substr(11, 8);
|
||||||
timerSeconds++;
|
this.timerSeconds++;
|
||||||
}, 1000)
|
}, 1000);
|
||||||
}
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop call timer
|
* Stop call timer
|
||||||
*/
|
*/
|
||||||
function stopTimer() {
|
stopTimer: function() {
|
||||||
clearInterval(timer);
|
clearInterval(this.timer);
|
||||||
timer = null;
|
this.timer = null;
|
||||||
timerSeconds = 0;
|
this.timerSeconds = 0;
|
||||||
$('timer').innerHTML = '00:00:00';
|
document.getElementById('timer').innerHTML = '00:00:00';
|
||||||
}
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page navigation
|
||||||
|
*/
|
||||||
|
navigate: function(container, path) {
|
||||||
|
this.load(container, path, function() {
|
||||||
|
if ($('#side').css('display') == 'block') {
|
||||||
|
$('#side').css('display', 'none');
|
||||||
|
$('#container').removeClass('side-display');
|
||||||
|
} else {
|
||||||
|
$('#side').css('display', 'block');
|
||||||
|
$('#container').addClass('side-display');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load view
|
||||||
|
* @param {String} container Container element
|
||||||
|
* @param {String} path Path to view
|
||||||
|
*/
|
||||||
|
load: function(container, path, cb) {
|
||||||
|
$(container).load(path + '/?token=' + this.query('token'), function(response, status) {
|
||||||
|
if (status == 'error')
|
||||||
|
alert(response);
|
||||||
|
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
showSpinner: function() {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
hideSpinner: function() {
|
||||||
|
|
||||||
function notify(message) {
|
|
||||||
if (!$('notifications')) {
|
|
||||||
let container = document.createElement('div');
|
|
||||||
container.setAttribute('id', 'notifications');
|
|
||||||
document.body.appendChild(container);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
let dialog = document.createElement('div');
|
|
||||||
let text = document.createTextNode(message);
|
|
||||||
dialog.appendChild(text);
|
|
||||||
dialog.setAttribute('class', 'dialog');
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
dialog.remove();
|
|
||||||
}, 8000);
|
|
||||||
|
|
||||||
|
|
||||||
$('notifications').insertBefore(dialog, $('notifications').firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
function showStatus(status) {
|
|
||||||
$('callStatus').innerHTML = 'Desconectado';
|
|
||||||
}
|
|
3
view.js
3
view.js
|
@ -8,6 +8,9 @@ module.exports = {
|
||||||
render: function(view, args, response) {
|
render: function(view, args, response) {
|
||||||
let instance = require(`./views/${view}/index.js`);
|
let instance = require(`./views/${view}/index.js`);
|
||||||
|
|
||||||
|
if (!instance.partials)
|
||||||
|
return response.render(`${view}/index`, instance);
|
||||||
|
|
||||||
instance.init(args, () => {
|
instance.init(args, () => {
|
||||||
this.getPartials(instance, args, (instance) => {
|
this.getPartials(instance, args, (instance) => {
|
||||||
response.render(`${view}/index`, instance);
|
response.render(`${view}/index`, instance);
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
<div class="call">
|
||||||
|
<div style="width:300px;margin: 50px auto 0 auto">
|
||||||
|
<div class="photo" style="background-color:#333;width:200px;height:200px;text-align:center;padding: 25px 0;margin:0 auto">
|
||||||
|
<i class="material-icons" style="font-size: 120px">person</i>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div>Nombre:</div>
|
||||||
|
<div>dd:</div>
|
||||||
|
</div>
|
||||||
|
<div class="dial">
|
||||||
|
<div class="callStatus" id="callStatus"></div>
|
||||||
|
<div class="callTimer">
|
||||||
|
<span id="timer">00:00:00</span>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon green" id="accept" title="Aceptar llamada">
|
||||||
|
<i class="material-icons">call</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon red" id="decline" title="Colgar">
|
||||||
|
<i class="material-icons">call_end</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon white" id="transfer" title="Transferir llamada">
|
||||||
|
<i class="material-icons">phone_forwarded</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon white" id="hold" title="Pausar llamada">
|
||||||
|
<i class="material-icons">phone_paused</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- <div style="width:300px;margin: 50px auto 0 auto">
|
||||||
|
<div class="photo" style="background-color:#333;width:200px;height:200px;text-align:center;padding: 25px 0;margin:0 auto">
|
||||||
|
<i class="material-icons" style="font-size: 120px">person</i>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div>Nombre:</div>
|
||||||
|
<div>dd:</div>
|
||||||
|
</div>
|
||||||
|
<div class="dial">
|
||||||
|
<div class="callStatus" id="callStatus"></div>
|
||||||
|
<div class="callTimer">
|
||||||
|
<span id="timer">00:00:00</span>
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon green" id="accept" title="Aceptar llamada">
|
||||||
|
<i class="material-icons">call</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon red" id="hangup" title="Colgar">
|
||||||
|
<i class="material-icons">call_end</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon white" id="transfer" title="Transferir llamada">
|
||||||
|
<i class="material-icons">phone_forwarded</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x25">
|
||||||
|
<a href="" class="btn big icon white" id="pause" title="Pausar llamada">
|
||||||
|
<i class="material-icons">phone_paused</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
init: function(args, cb) {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<div class="dial">
|
||||||
|
<div class="search">
|
||||||
|
<div class="control">
|
||||||
|
<input type="text" placeholder="Introduce un número..." id="callNumber"/> <i class="material-icons" id="clear">close</i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Controls block start -->
|
||||||
|
<div class="controls">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column x50">
|
||||||
|
<a href="" class="btn normal icon green" id="call" title="LLamar">
|
||||||
|
<i class="material-icons">call</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="column x50">
|
||||||
|
<a href="" class="btn normal icon white" id="clear" title="Vaciar campo de llamada">
|
||||||
|
<i class="material-icons">DND</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column x33">
|
||||||
|
<a href="" class="btn normal white pad" id="one">1</a>
|
||||||
|
<a href="" class="btn normal white pad" id="four">4</a>
|
||||||
|
<a href="" class="btn normal white" id="seven">7</a>
|
||||||
|
<a href="" class="btn normal white" id="asterisk">*</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column x33">
|
||||||
|
<a href="" class="btn normal white pad" id="two">2</a>
|
||||||
|
<a href="" class="btn normal white pad" id="five">5</a>
|
||||||
|
<a href="" class="btn normal white pad" id="eight">8</a>
|
||||||
|
<a href="" class="btn normal white pad" id="zero">0</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column x33">
|
||||||
|
<a href="" class="btn normal white pad" id="three">3</a>
|
||||||
|
<a href="" class="btn normal white pad" id="six">6</a>
|
||||||
|
<a href="" class="btn normal white pad" id="nine">9</a>
|
||||||
|
<a href="" class="btn normal white pad" id="pad">#</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Controls block end -->
|
||||||
|
|
||||||
|
</div>
|
|
@ -1,33 +1,17 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="es">
|
<html lang="es">
|
||||||
<head>
|
<head>
|
||||||
<title>Softphone</title>
|
<title>Softphone</title>
|
||||||
<meta charset="utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/css/app.css"/>
|
<link rel="stylesheet" type="text/css" href="/static/css/app.css"/>
|
||||||
<link rel="stylesheet" type="text/css" href="/static/css/components.css"/>
|
<link rel="stylesheet" type="text/css" href="/static/css/components.css"/>
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
<script type="text/javascript" src="/static/js/jssip.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/ua.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/jssip.js?v=1"></script>
|
||||||
<script type="text/javascript" src="/static/js/audio.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/ua.js?v=1"></script>
|
||||||
<script type="text/javascript" src="/static/js/softphone.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/audio.js?v=1"></script>
|
||||||
<script type="text/javascript" src="/static/js/util.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/softphone.js?v=1"></script>
|
||||||
<script type="text/javascript" src="/static/js/event.js?v=1"></script>
|
<script type="text/javascript" src="/static/js/util.js?v=1"></script>
|
||||||
</head>
|
<script type="text/javascript" src="/static/js/event.js?v=1"></script>
|
||||||
<body>
|
</head>
|
||||||
<!-- Quickbar block start -->
|
<body>
|
||||||
<div class="quickbar">
|
|
||||||
<img src="http://salix.verdnatura.es/static/34777fb85a1496d64469bd8092a53ef6.svg"/>
|
|
||||||
|
|
||||||
<div class="pull-right">
|
|
||||||
<a href="">
|
|
||||||
<i class="material-icons">settings</i>
|
|
||||||
</a>
|
|
||||||
<a href="">
|
|
||||||
<i class="material-icons">language</i>
|
|
||||||
</a>
|
|
||||||
<a href="">
|
|
||||||
<i class="material-icons">exit_to_app</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Quickbar block end -->
|
|
|
@ -0,0 +1 @@
|
||||||
|
Contactos
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
|
||||||
|
init: function(args, cb) {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,83 +1,3 @@
|
||||||
{{> header}}
|
{{> header}}
|
||||||
{{> side}}
|
{{> navigation}}
|
||||||
|
{{> quickbar}}
|
||||||
<!-- Chatbox block start -->
|
|
||||||
<div class="chatbox">
|
|
||||||
<div class="dial">
|
|
||||||
<div class="search">
|
|
||||||
<div class="control">
|
|
||||||
<input type="text" placeholder="Introduce un número..." id="callNumber"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="callStatus" id="callStatus"></div>
|
|
||||||
<div class="callTimer">
|
|
||||||
<span id="timer">00:00:00</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Controls block start -->
|
|
||||||
<div class="controls">
|
|
||||||
<div class="columns">
|
|
||||||
<div class="column x33">
|
|
||||||
<a href="" class="btn big icon green" id="call" title="LLamar">
|
|
||||||
<i class="material-icons">call</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="column x33">
|
|
||||||
<a href="" class="btn big icon white" id="clear" title="Vaciar campo de llamada">
|
|
||||||
<i class="material-icons">clear_all</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="column x33">
|
|
||||||
<a href="" class="btn big icon red" id="callHangup" title="Colgar">
|
|
||||||
<i class="material-icons">call_end</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="columns">
|
|
||||||
<div class="column x25">
|
|
||||||
<a href="" class="btn big white pad" id="one">1</a>
|
|
||||||
<a href="" class="btn big white pad" id="four">4</a>
|
|
||||||
<a href="" class="btn big white" id="seven">7</a>
|
|
||||||
<a href="" class="btn big white" id="asterisk">*</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column x25">
|
|
||||||
<a href="" class="btn big white pad" id="two">2</a>
|
|
||||||
<a href="" class="btn big white pad" id="five">5</a>
|
|
||||||
<a href="" class="btn big white pad" id="eight">8</a>
|
|
||||||
<a href="" class="btn big white pad" id="zero">0</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column x25">
|
|
||||||
<a href="" class="btn big white pad" id="three">3</a>
|
|
||||||
<a href="" class="btn big white pad" id="six">6</a>
|
|
||||||
<a href="" class="btn big white pad" id="nine">9</a>
|
|
||||||
<a href="" class="btn big white pad" id="pad">#</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="column x25">
|
|
||||||
<a href="" class="btn big icon white" id="callTransfer" title="Transferir llamada">
|
|
||||||
<i class="material-icons">phone_forwarded</i>
|
|
||||||
</a>
|
|
||||||
<a href="" class="btn big icon white" id="callPause" title="Pausar llamada">
|
|
||||||
<i class="material-icons">phone_paused</i>
|
|
||||||
</a>
|
|
||||||
<a href="" class="btn big icon white" id="doNotDisturb" title="No molestar">
|
|
||||||
<i class="material-icons">phone_locked</i>
|
|
||||||
</a>
|
|
||||||
<a href="" class="btn big icon white" id="callConfig" title="Configuración">
|
|
||||||
<i class="material-icons">settings_phone</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<a href="" class="btn normal yellow">
|
|
||||||
<i class="material-icons">add</i> Nuevo contacto</a>
|
|
||||||
<a href="" class="btn normal yellow">
|
|
||||||
<i class="material-icons">search</i>Buscar contacto</a>
|
|
||||||
<a href="" class="btn normal yellow">Ver historial</a>
|
|
||||||
</div>
|
|
||||||
<!-- Controls block end -->
|
|
||||||
</div>
|
|
||||||
<!-- Chatbox block end -->
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ module.exports = {
|
||||||
|
|
||||||
partials: {
|
partials: {
|
||||||
header: 'header',
|
header: 'header',
|
||||||
side: 'side'
|
navigation: 'navigation',
|
||||||
|
quickbar: 'quickbar'
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!-- Navigation block start -->
|
||||||
|
<div class="navigation">
|
||||||
|
<img src="http://salix.verdnatura.es/static/34777fb85a1496d64469bd8092a53ef6.svg"/>
|
||||||
|
|
||||||
|
<div class="pull-right">
|
||||||
|
<a href="">
|
||||||
|
<i class="material-icons">settings</i>
|
||||||
|
</a>
|
||||||
|
<a href="">
|
||||||
|
<i class="material-icons">language</i>
|
||||||
|
</a>
|
||||||
|
<a href="">
|
||||||
|
<i class="material-icons">exit_to_app</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Navigation block end -->
|
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
init: function(args, cb) {
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
<!-- Container block start -->
|
||||||
|
<div id="container">
|
||||||
|
<!-- Quickbar block start -->
|
||||||
|
<div class="quickbar">
|
||||||
|
<!-- Profile block start -->
|
||||||
|
<div class="profile">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="" title="{{name}} - SIP {{extension}}">
|
||||||
|
<span class="status offline" title="Estado"></span>
|
||||||
|
<i class="material-icons">account_circle</i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<!-- Profile block end -->
|
||||||
|
|
||||||
|
<!-- Navigation block start -->
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="" id="history">
|
||||||
|
<i class="material-icons">phone</i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="" id="dial" class="active" title="Mostrar teclado">
|
||||||
|
<i class="material-icons">dialpad</i>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<!-- <li>
|
||||||
|
<a href="" title="Añadir llamada"><i class="material-icons">phone_in_talk</i></a>
|
||||||
|
</li>-->
|
||||||
|
</ul>
|
||||||
|
<!-- Navigation block end -->
|
||||||
|
|
||||||
|
<div class="audioControls">
|
||||||
|
<div>
|
||||||
|
<a href="" id="muteVolume" title="Silenciar volumen">
|
||||||
|
<i class="material-icons">volume_down</i>
|
||||||
|
</a>
|
||||||
|
<!--<input type="range" id="volume" min="0" max="1" step="0.1" value="0.5"/>-->
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="" id="muteMic" title="Silenciar micrófono"><i class="material-icons">mic</i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Quickbar block end -->
|
||||||
|
|
||||||
|
<!-- Side block start -->
|
||||||
|
<div id="side"></div>
|
||||||
|
<!-- Side block end -->
|
||||||
|
|
||||||
|
<div id="content"></div>
|
||||||
|
</div>
|
||||||
|
<!-- Container block end -->
|
|
@ -1,45 +0,0 @@
|
||||||
<!-- Side block start -->
|
|
||||||
<div class="side">
|
|
||||||
<!-- User block start -->
|
|
||||||
<div class="user">
|
|
||||||
<div class="pull-left">
|
|
||||||
<div class="name">{{name}}</div>
|
|
||||||
<spa class="extension">SIP {{extension}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="pull-right">
|
|
||||||
<a href="">
|
|
||||||
<i class="material-icons">menu</i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- User block end -->
|
|
||||||
|
|
||||||
<!-- Navigation block start -->
|
|
||||||
<div class="navigation">
|
|
||||||
<a href="" class="active"><i class="material-icons">home</i></a>
|
|
||||||
<a href=""><i class="material-icons">contacts</i></a>
|
|
||||||
</div>
|
|
||||||
<!-- Navigation block end -->
|
|
||||||
|
|
||||||
<div class="title">
|
|
||||||
Historial de llamadas
|
|
||||||
</div>
|
|
||||||
<div class="callHistory">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="audioControls">
|
|
||||||
<div>
|
|
||||||
<i class="material-icons">volume_down</i>
|
|
||||||
<input type="range" id="volume" min="0" max="1" step="0.1" value="0.5"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<a href="" id="mic"><i class="material-icons">mic</i></a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="contacts">
|
|
||||||
<i class="material-icons">load</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- Side block end -->
|
|
Reference in New Issue