mirror of https://github.com/sipwise/ngcp-csc.git
Change-Id: Ib5bb129553c0433204449f6bf93e14e73069973dchanges/33/11433/18
parent
c6a07c124f
commit
844b0c4a2d
@ -1,13 +1,13 @@
|
||||
Ext.define('NgcpCsc.store.ChatList', {
|
||||
Ext.define('NgcpCsc.store.Contacts', {
|
||||
extend: 'Ext.data.TreeStore',
|
||||
|
||||
alias: 'store.chatlist',
|
||||
alias: 'store.contacts',
|
||||
|
||||
storeId: 'ChatList',
|
||||
storeId: 'Contacts',
|
||||
|
||||
proxy: {
|
||||
type: 'ajax',
|
||||
url: 'resources/data/chatlist.json'
|
||||
url: 'resources/data/contacts.json'
|
||||
},
|
||||
|
||||
sorters: [{
|
@ -0,0 +1,51 @@
|
||||
// Custom rules
|
||||
$border-radius : 50%;
|
||||
.rtc-panel{
|
||||
.x-tool-expand-right:before{
|
||||
content:'\f0d9' !important
|
||||
}
|
||||
}
|
||||
.rtc-container {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.rtc-avatar-container {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.rtc-avatar {
|
||||
border-radius: $border-radius ;
|
||||
width: 100px !important;
|
||||
margin: 0 auto !important;
|
||||
display: block;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.rtc-icons {
|
||||
border-radius: $border-radius ;
|
||||
margin-right: 10px;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
.rtc-icons-big {
|
||||
border-radius: $border-radius ;
|
||||
.x-fa:before{
|
||||
margin-left: -7px;
|
||||
}
|
||||
}
|
||||
|
||||
.rtc-btns-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rtc-chat-tbar {
|
||||
.x-tab-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.rtc-digit {
|
||||
.x-btn-inner-default-small{
|
||||
font-size:16px;
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
// Custom rules
|
||||
|
||||
.webrtc-container {
|
||||
text-align: center;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.webrtc-avatar-container {
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.webrtc-avatar {
|
||||
border-radius: 50%;
|
||||
width: 100px !important;
|
||||
margin: 0 auto !important;
|
||||
display: block;
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.webrtc-icons {
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
width: 35px;
|
||||
}
|
||||
|
||||
.webrtc-btns-container {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.webrtc-chat-tbar {
|
||||
.x-tab-bar {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
.contacts {
|
||||
.x-tool-expand-right:before{
|
||||
content:'\f0d9' !important
|
||||
}
|
||||
.x-tool-collapse-left:before{
|
||||
content:'\f0da' !important
|
||||
}
|
||||
.x-grid-row:hover {
|
||||
.x-phone-display {
|
||||
padding-left: 5px;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f095";
|
||||
}
|
||||
}
|
||||
|
||||
.x-video-display {
|
||||
margin-left: 10px;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f03d";
|
||||
}
|
||||
}
|
||||
|
||||
.x-drop-display {
|
||||
position: relative;
|
||||
right: 15px;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f1f8";
|
||||
}
|
||||
}
|
||||
|
||||
.x-add-user-display {
|
||||
position: relative;
|
||||
right: 20px;
|
||||
|
||||
&:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f234";
|
||||
}
|
||||
}
|
||||
}
|
||||
// @include box-shadow(0px,2px,8px,0px,rgba(0,0,0,.15));
|
||||
@include box-shadow(0, 1px, 2px, 0, rgba(0,0,0,0.2));
|
||||
|
||||
&.x-menu-default {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
.x-menu-header {
|
||||
line-height: 20px;
|
||||
background-color: $lightest-color;
|
||||
padding: 22px 15px;
|
||||
border-bottom: 1px solid #ccc !important;
|
||||
|
||||
.x-title-icon-wrap {
|
||||
width: 40px;
|
||||
padding-right: 28px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.x-title-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.x-menu-item-icon-default {
|
||||
padding-top: 10px;
|
||||
padding-left: 12px;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.x-menu-item {
|
||||
line-height: 50px;
|
||||
|
||||
.x-menu-item-text-default.x-menu-item-indent-no-separator {
|
||||
margin-left: 56px;
|
||||
}
|
||||
|
||||
&.online-user {
|
||||
.x-menu-item-text-default.x-menu-item-indent-no-separator {
|
||||
margin-left: 18px;
|
||||
}
|
||||
|
||||
.x-menu-item-link:after {
|
||||
color: $online-menu-item-color;
|
||||
content: "\f111";
|
||||
@extend .menu-item-common;
|
||||
}
|
||||
|
||||
&.x-menu-item-active {
|
||||
.x-menu-item-link:after {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.offline-user {
|
||||
.x-menu-item-link:after {
|
||||
color: $offline-menu-item-color;
|
||||
content: "\f111";
|
||||
@extend .menu-item-common;
|
||||
}
|
||||
|
||||
.x-menu-item-text-default.x-menu-item-indent-no-separator {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.x-menu-item-link:after {
|
||||
@extend .menu-item-common;
|
||||
color: $default-menu-item-color;
|
||||
content: "\f105";
|
||||
}
|
||||
}
|
||||
|
||||
.x-action-col-icon {
|
||||
color: #919191;
|
||||
font-size: 18px;
|
||||
height: 16px;
|
||||
width: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
Ext.define('NgcpCsc.view.common.rtc.RtcController', {
|
||||
extend: 'Ext.app.ViewController',
|
||||
alias: 'controller.rtc',
|
||||
listen: {
|
||||
controller: {
|
||||
'*': {
|
||||
initrtc: 'showRtcPanel',
|
||||
emulateCall: 'emulateCall',
|
||||
endcall: 'endCall'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
currentStream: null,
|
||||
intervalId: '',
|
||||
|
||||
showRtcPanel: function(record, action, switchVideoOn) {
|
||||
var panel = this.getView();
|
||||
var vm = this.getViewModel();
|
||||
vm.set('numberToCall', '');
|
||||
switch (action) {
|
||||
case 'startCall':
|
||||
case 'startVideoCall':
|
||||
var buddyUser = Ext.getStore('Chat').findRecord('uid', record.get('uid'));
|
||||
var number = (buddyUser) ? buddyUser.get('number') : record.get('caller') || record.get('source_cli') || record.get('mobile');
|
||||
var mainView = Ext.ComponentQuery.query('[name=mainView]')[0];
|
||||
vm.set('title', Ext.String.format('Call with {0}', number));
|
||||
vm.set('thumbnail', (buddyUser) ? buddyUser.get('thumbnail') : this.getViewModel().get('defaultThumbnail'));
|
||||
vm.set('status', Ext.String.format('calling {0} ...', (buddyUser) ? buddyUser.get('name') : ''));
|
||||
vm.set('callEnabled', false);
|
||||
vm.set('micEnabled', false);
|
||||
vm.set('phoneComposerHidden', true);
|
||||
vm.set('faxComposerHidden', true);
|
||||
vm.set('smsComposerHidden', true);
|
||||
vm.set('callPanelHidden', false);
|
||||
vm.set('videoEnabled', switchVideoOn || false);
|
||||
mainView.getViewModel().set('sectionTitle', 'Conversation with ' + number);
|
||||
this.redirectTo('conversation-with');
|
||||
this.emulateCall(true, action == 'startVideoCall');
|
||||
break;
|
||||
case 'phoneComposer':
|
||||
if(vm.get('connected')){
|
||||
this.fireEvent('showmessage', false, Ngcp.csc.locales.rtc.call_in_progress[localStorage.getItem('languageSelected')]);
|
||||
return;
|
||||
}
|
||||
vm.set('title', Ngcp.csc.locales.conversations.btns.new_call[localStorage.getItem('languageSelected')]);
|
||||
vm.set('phoneComposerHidden', false);
|
||||
vm.set('faxComposerHidden', true);
|
||||
vm.set('smsComposerHidden', true);
|
||||
vm.set('callPanelHidden', true);
|
||||
break;
|
||||
case 'faxComposer':
|
||||
if (record) {
|
||||
vm.set('numberToCall', record.get('source_cli'));
|
||||
}
|
||||
vm.set('title', Ngcp.csc.locales.conversations.btns.new_fax[localStorage.getItem('languageSelected')]);
|
||||
vm.set('phoneComposerHidden', true);
|
||||
vm.set('faxComposerHidden', false);
|
||||
vm.set('smsComposerHidden', true);
|
||||
vm.set('callPanelHidden', true);
|
||||
break;
|
||||
case 'smsComposer':
|
||||
if (record) {
|
||||
vm.set('numberToCall', record.get('source_cli'));
|
||||
}
|
||||
vm.set('title', Ngcp.csc.locales.conversations.btns.new_sms[localStorage.getItem('languageSelected')]);
|
||||
vm.set('phoneComposerHidden', true);
|
||||
vm.set('faxComposerHidden', true);
|
||||
vm.set('smsComposerHidden', false);
|
||||
vm.set('callPanelHidden', true);
|
||||
break;
|
||||
}
|
||||
panel.show().expand();
|
||||
},
|
||||
|
||||
toogleChat: function(btn) {
|
||||
this.fireEvent('togglechat', btn.pressed);
|
||||
},
|
||||
|
||||
toggleFullscreen: function() {
|
||||
var video = document.querySelector("video");
|
||||
var videoInProgress = false;
|
||||
Ext.each(this.currentStream.getTracks(), function(mediaTrack) {
|
||||
if (mediaTrack.readyState == 'live' && mediaTrack.kind == "video") {
|
||||
videoInProgress = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (videoInProgress) {
|
||||
if (Ext.isWebKit) {
|
||||
video.webkitEnterFullScreen();
|
||||
} else {
|
||||
video.mozRequestFullScreen();
|
||||
}
|
||||
}
|
||||
},
|
||||
minimizeRtcPanel: function() {
|
||||
this.getView().collapse();
|
||||
},
|
||||
|
||||
onBeforeClose: function() {
|
||||
var vm = this.getViewModel();
|
||||
this.getView().hide();
|
||||
vm.set('status', '');
|
||||
clearInterval(this.intervalId);
|
||||
this.endCall();
|
||||
return false;
|
||||
},
|
||||
emulateCall: function(audioOn, videoOn) {
|
||||
var me = this;
|
||||
var vm = me.getViewModel();
|
||||
var sample = document.getElementById("ring");
|
||||
var ringDuration = 3000;
|
||||
if (this.intervalId !== '') {
|
||||
clearInterval(me.intervalId);
|
||||
}
|
||||
vm.set('status', 'calling...');
|
||||
sample.play();
|
||||
setTimeout(function() {
|
||||
var seconds = minutes = hours = 0;
|
||||
sample.pause();
|
||||
sample.currentTime = 0;
|
||||
vm.set('callEnabled', true);
|
||||
vm.set('micEnabled', true);
|
||||
|
||||
me.startMedia(audioOn, videoOn);
|
||||
|
||||
me.intervalId = setInterval(function() {
|
||||
seconds++;
|
||||
if (seconds == 60) {
|
||||
seconds = 0;
|
||||
minutes++;
|
||||
}
|
||||
if (minutes == 60) {
|
||||
minutes = 0;
|
||||
hours++;
|
||||
}
|
||||
if (hours == 24) {
|
||||
hours = 0;
|
||||
}
|
||||
var duration = ((hours < 10) ? '0' + hours : hours) + ':' +
|
||||
((minutes < 10) ? '0' + minutes : minutes) + ':' +
|
||||
((seconds < 10) ? '0' + seconds : seconds);
|
||||
vm.set('status', 'connected ' + duration);
|
||||
}, 1000);
|
||||
}, ringDuration);
|
||||
},
|
||||
|
||||
toggleAudioVideo: function() {
|
||||
var me = this;
|
||||
var vm = this.getViewModel();
|
||||
var video = document.querySelector("video");
|
||||
Ext.each(this.currentStream.getTracks(), function(mediaTrack) {
|
||||
if (mediaTrack.readyState == 'live') {
|
||||
video.pause();
|
||||
video.src = "";
|
||||
mediaTrack.stop();
|
||||
}
|
||||
});
|
||||
if (vm.get('micEnabled') || vm.get('videoEnabled')) {
|
||||
me.startMedia(vm.get('micEnabled'), vm.get('videoEnabled'));
|
||||
}
|
||||
},
|
||||
toggleCall: function(btn) {
|
||||
if (btn.pressed) { // this can be also checked against vm.get('callEnabled')
|
||||
btn.removeCls('fa-rotate-180');
|
||||
this.emulateCall(true, false);
|
||||
} else {
|
||||
btn.addCls('fa-rotate-180');
|
||||
this.endCall();
|
||||
}
|
||||
},
|
||||
endCall: function() {
|
||||
var vm = this.getViewModel();
|
||||
var videoObj = this.lookupReference('videoObj');
|
||||
var video = document.querySelector("video");
|
||||
var me = this;
|
||||
this.lookupReference('avatar').show();
|
||||
clearInterval(this.intervalId);
|
||||
video.pause();
|
||||
video.src = "";
|
||||
videoObj.hide();
|
||||
if(this.currentStream){
|
||||
Ext.each(this.currentStream.getTracks(), function(mediaTrack) {
|
||||
mediaTrack.stop();
|
||||
});
|
||||
}
|
||||
vm.set('status', 'Call ended.');
|
||||
vm.set('connected', false);
|
||||
},
|
||||
|
||||
startMedia: function(audio, video) {
|
||||
var me = this;
|
||||
var vm = me.getViewModel();
|
||||
//Wrap the getUserMedia function from the different browsers
|
||||
navigator.getUserMedia = navigator.getUserMedia ||
|
||||
navigator.webkitGetUserMedia ||
|
||||
navigator.mozGetUserMedia;
|
||||
|
||||
//Our success callback where we get the media stream object and assign it to a video tag on the page
|
||||
function onSuccess(mediaObj) {
|
||||
me.currentStream = mediaObj;
|
||||
me.lookupReference('avatar').setVisible(!vm.get('videoEnabled'));
|
||||
me.lookupReference('videoObj').setVisible(vm.get('videoEnabled'));
|
||||
vm.set('connected', true);
|
||||
window.stream = mediaObj;
|
||||
var video = document.querySelector("video");
|
||||
video.src = window.URL.createObjectURL(mediaObj);
|
||||
video.play();
|
||||
}
|
||||
|
||||
//Our error callback where we will handle any issues
|
||||
function onError(errorObj) {
|
||||
console.log("There was an error: " + errorObj);
|
||||
}
|
||||
|
||||
//We can select to request audio and video or just one of them
|
||||
var mediaConstraints = {
|
||||
video: video,
|
||||
audio: audio
|
||||
};
|
||||
|
||||
//Call our method to request the media object - this will trigger the browser to prompt a request.
|
||||
navigator.getUserMedia(mediaConstraints, onSuccess, onError);
|
||||
},
|
||||
|
||||
showPhoneComposer: function(btn) {
|
||||
var vm = this.getViewModel();
|
||||
vm.set('phoneKeyboardHidden', !btn.pressed);
|
||||
},
|
||||
digitNumber: function(btn) {
|
||||
var vm = this.getViewModel();
|
||||
var currentNum = vm.get('numberToCall');
|
||||
vm.set('numberToCall', currentNum + btn.getText())
|
||||
},
|
||||
startNewCall: function() {
|
||||
var vm = this.getViewModel();
|
||||
var currentNum = vm.get('numberToCall');
|
||||
var record = Ext.create('NgcpCsc.model.Conversation', {
|
||||
caller: currentNum
|
||||
});
|
||||
this.showRtcPanel(record, 'startCall');
|
||||
},
|
||||
sendFax: function() {
|
||||
var vm = this.getViewModel();
|
||||
var mainView = Ext.ComponentQuery.query('[name=mainView]')[0];
|
||||
var faxForm = this.getView().down('fax-composer');
|
||||
if(faxForm.isValid()){
|
||||
mainView.getViewModel().set('sectionTitle', 'Conversation with ' + vm.get('numberToCall'));
|
||||
this.redirectTo('conversation-with');
|
||||
faxForm.reset();
|
||||
this.fireEvent('showmessage', true, Ngcp.csc.locales.rtc.fax_sent[localStorage.getItem('languageSelected')]);
|
||||
}else{
|
||||
this.fireEvent('showmessage', false, Ngcp.csc.locales.common.invalid_form[localStorage.getItem('languageSelected')]);
|
||||
}
|
||||
|
||||
},
|
||||
sendSms: function() {
|
||||
var vm = this.getViewModel();
|
||||
var mainView = Ext.ComponentQuery.query('[name=mainView]')[0];
|
||||
mainView.getViewModel().set('sectionTitle', 'Conversation with ' + vm.get('numberToCall'));
|
||||
this.redirectTo('conversation-with');
|
||||
this.fireEvent('showmessage', true, Ngcp.csc.locales.rtc.sms_sent[localStorage.getItem('languageSelected')]);
|
||||
}
|
||||
});
|
@ -0,0 +1,44 @@
|
||||
Ext.define('NgcpCsc.view.rtc.RtcModel', {
|
||||
extend: 'Ext.app.ViewModel',
|
||||
|
||||
alias: 'viewmodel.rtc',
|
||||
|
||||
data: {
|
||||
title: 123456789,
|
||||
defaultThumbnail: 'resources/images/icons/phoneicon.png',
|
||||
thumbnail: 'resources/images/icons/phoneicon.png',
|
||||
status: 'calling...',
|
||||
callPanelHidden: false,
|
||||
phoneComposerHidden: false,
|
||||
faxComposerHidden: false,
|
||||
smsComposerHidden: false,
|
||||
phoneKeyboardHidden: true,
|
||||
callEnabled: false,
|
||||
connected: false,
|
||||
micEnabled: false,
|
||||
videoEnabled: false,
|
||||
numberToCall: '',
|
||||
// fax only fields
|
||||
faxPageHeader: '',
|
||||
faxContent: '',
|
||||
faxSelectedQuality: '',
|
||||
faxChosenFile: '',
|
||||
// sms only fields
|
||||
smsText: '',
|
||||
// panel status
|
||||
minimized: false
|
||||
},
|
||||
formulas: {
|
||||
disableSubmit: function(get) {
|
||||
var digitNumber = get('numberToCall');
|
||||
if (digitNumber.length < 1) {
|
||||
return true;
|
||||
} else {
|
||||
return !digitNumber.match(/^[0-9#*+]+$/);
|
||||
};
|
||||
},
|
||||
disableSmsSubmit: function(get) {
|
||||
return get('smsText').length > 140 || get('smsText').length < 1;
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,137 @@
|
||||
Ext.define('NgcpCsc.view.common.rtc.RtcPanel', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
xtype: 'rtc',
|
||||
|
||||
controller: 'rtc',
|
||||
|
||||
viewModel: 'rtc',
|
||||
|
||||
padding: '0 0 0 1',
|
||||
|
||||
width: '30%',
|
||||
|
||||
closable: true,
|
||||
|
||||
collapseDirection:'left',
|
||||
|
||||
cls:'rtc-panel',
|
||||
|
||||
bind: {
|
||||
title: '{title}'
|
||||
},
|
||||
|
||||
tools: [ {
|
||||
glyph: 'xf065@FontAwesome',
|
||||
callback: 'toggleFullscreen',
|
||||
bind:{
|
||||
hidden:'{!videoEnabled}'
|
||||
}
|
||||
},{
|
||||
type: 'minimize',
|
||||
callback: 'minimizeRtcPanel'
|
||||
}],
|
||||
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch'
|
||||
},
|
||||
|
||||
listeners: {
|
||||
beforeclose: 'onBeforeClose'
|
||||
},
|
||||
|
||||
items: [{
|
||||
flex: 4,
|
||||
reference: 'callpanel',
|
||||
bind: {
|
||||
hidden: '{callPanelHidden}'
|
||||
},
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch',
|
||||
pack: 'center'
|
||||
},
|
||||
defaults: {
|
||||
cls: 'rtc-container'
|
||||
},
|
||||
items: [
|
||||
{
|
||||
margin:20,
|
||||
hidden:true,
|
||||
width:'100%',
|
||||
reference:'videoObj',
|
||||
html:"<video width=100% id=videoTag height=240></video>"
|
||||
},{
|
||||
cls: 'rtc-avatar-container',
|
||||
reference:'avatar',
|
||||
items: {
|
||||
xtype: 'image',
|
||||
cls: 'rtc-avatar',
|
||||
bind: {
|
||||
src: '{thumbnail}'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
xtype: 'label',
|
||||
margin: '20 0 20 0',
|
||||
bind: '{status}'
|
||||
}, {
|
||||
xtype: 'container',
|
||||
cls: 'rtc-btns-container',
|
||||
layout: {
|
||||
type: 'hbox',
|
||||
align: 'stretch',
|
||||
pack: 'center'
|
||||
},
|
||||
defaults: {
|
||||
xtype: 'button',
|
||||
cls: 'rtc-icons',
|
||||
enableToggle: true
|
||||
},
|
||||
items: [{
|
||||
iconCls: 'x-fa fa-phone',
|
||||
bind: {
|
||||
pressed: '{callEnabled}'
|
||||
},
|
||||
handler:'toggleCall'
|
||||
}, {
|
||||
iconCls: 'x-fa fa-microphone',
|
||||
bind: {
|
||||
pressed: '{micEnabled}',
|
||||
disabled: '{!connected}',
|
||||
hidden: '{!micEnabled}'
|
||||
},
|
||||
handler:'toggleAudioVideo'
|
||||
},{
|
||||
iconCls: 'x-fa fa-microphone-slash',
|
||||
bind: {
|
||||
pressed: '{micEnabled}',
|
||||
disabled: '{!connected}',
|
||||
hidden: '{micEnabled}'
|
||||
},
|
||||
handler:'toggleAudioVideo'
|
||||
}, {
|
||||
iconCls: 'x-fa fa-video-camera',
|
||||
bind: {
|
||||
pressed: '{videoEnabled}',
|
||||
disabled: '{!connected}'
|
||||
},
|
||||
handler:'toggleAudioVideo'
|
||||
}, {
|
||||
iconCls: 'x-fa fa-comment',
|
||||
bind: {
|
||||
pressed: '{chatEnabled}',
|
||||
disabled: '{!connected}'
|
||||
},
|
||||
handler: 'toogleChat'
|
||||
}]
|
||||
}]
|
||||
}, {
|
||||
xtype: 'phone-composer'
|
||||
}, {
|
||||
xtype: 'sms-composer'
|
||||
}, {
|
||||
xtype: 'fax-composer'
|
||||
}]
|
||||
})
|
@ -0,0 +1,75 @@
|
||||
Ext.define('NgcpCsc.view.common.composer.Fax', {
|
||||
extend: 'Ext.form.Panel',
|
||||
|
||||
alias: 'widget.fax-composer',
|
||||
|
||||
bind: {
|
||||
hidden: '{faxComposerHidden}'
|
||||
},
|
||||
defaults: {
|
||||
width: '90%',
|
||||
margin: 20
|
||||
},
|
||||
|
||||
items: [{
|
||||
layout: 'hbox',
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
emptyText: 'Allowed digits are 0-9, +, # and *.',
|
||||
hideTrigger: true,
|
||||
width: '80%',
|
||||
bind: '{numberToCall}'
|
||||
}, {
|
||||
xtype: 'button',
|
||||
enableToggle: true,
|
||||
iconCls: 'x-fa fa-fax',
|
||||
width: '20%',
|
||||
handler: 'showPhoneComposer'
|
||||
}]
|
||||
}, {
|
||||
xtype: 'phonekeys',
|
||||
bind: {
|
||||
hidden: '{phoneKeyboardHidden}'
|
||||
}
|
||||
}, {
|
||||
xtype: 'combo',
|
||||
store: ['Normal', 'Fine', 'Super'],
|
||||
fieldLabel: 'Quality',
|
||||
allowBlank: false,
|
||||
editable: false,
|
||||
bind: '{faxSelectedQuality}'
|
||||
}, {
|
||||
xtype: 'textfield',
|
||||
allowBlank: false,
|
||||
bind: '{faxSageHeader}',
|
||||
fieldLabel: 'Page header'
|
||||
}, {
|
||||
xtype: 'textarea',
|
||||
allowBlank: false,
|
||||
bind: '{faxContent}',
|
||||
fieldLabel: 'Content'
|
||||
}, {
|
||||
xtype: 'filefield',
|
||||
bind: '{faxContenthosenFile}',
|
||||
fieldLabel: 'File'
|
||||
}, {
|
||||
xtype: 'container',
|
||||
layout: 'center',
|
||||
margin: '40 20 20 20',
|
||||
items: [{
|
||||
xtype: 'button',
|
||||
cls: 'rtc-icons-big',
|
||||
bind: {
|
||||
disabled: '{disableSubmit}'
|
||||
},
|
||||
width: 60,
|
||||
height: 60,
|
||||
margin: '50 0 10 0',
|
||||
iconCls: 'x-fa fa-send fa-2x',
|
||||
cls: 'rtc-icons-big',
|
||||
listeners: {
|
||||
click: 'sendFax'
|
||||
}
|
||||
}]
|
||||
}]
|
||||
})
|
@ -0,0 +1,56 @@
|
||||
Ext.define('NgcpCsc.view.common.composer.Phone', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
alias: 'widget.phone-composer',
|
||||
|
||||
bind: {
|
||||
hidden: '{phoneComposerHidden}'
|
||||
},
|
||||
items: [{
|
||||
layout: 'hbox',
|
||||
margin: 20,
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
emptyText: 'Allowed digits are 0-9, +, # and *.',
|
||||
hideTrigger: true,
|
||||
width: '80%',
|
||||
bind: '{numberToCall}'
|
||||
}, {
|
||||
xtype: 'button',
|
||||
enableToggle: true,
|
||||
iconCls: 'x-fa fa-fax',
|
||||
width: '20%',
|
||||
handler: 'showPhoneComposer'
|
||||
}]
|
||||
}, {
|
||||
xtype: 'phonekeys',
|
||||
bind: {
|
||||
hidden: '{phoneKeyboardHidden}'
|
||||
}
|
||||
}, {
|
||||
xtype: 'container',
|
||||
layout: 'center',
|
||||
margin: '40 20 20 20',
|
||||
items: [{
|
||||
xtype: 'button',
|
||||
cls: 'rtc-icons-big',
|
||||
bind: {
|
||||
disabled: '{disableSubmit}'
|
||||
},
|
||||
width: 60,
|
||||
height: 60,
|
||||
margin: '50 0 10 0',
|
||||
iconCls: 'x-fa fa-phone fa-3x',
|
||||
cls: 'rtc-icons-big',
|
||||
listeners: {
|
||||
click: {
|
||||
fn: 'startNewCall',
|
||||
el: 'element'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
hidden: true,
|
||||
html: '<audio id="ring" src="resources/audio/skype_ring.mp3" preload="auto"></audio>'
|
||||
}]
|
||||
})
|
@ -0,0 +1,66 @@
|
||||
Ext.define('NgcpCsc.view.common.composer.PhoneKeys', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
alias: 'widget.phonekeys',
|
||||
|
||||
hidden: true,
|
||||
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch'
|
||||
},
|
||||
|
||||
height: 300,
|
||||
|
||||
margin: '30 10 10 20',
|
||||
|
||||
defaults: {
|
||||
flex: 1,
|
||||
layout: {
|
||||
type: 'hbox',
|
||||
align: 'stretch',
|
||||
pack:'center'
|
||||
},
|
||||
defaults: {
|
||||
xtype: 'button',
|
||||
flex: 1,
|
||||
margin: '0 10 10 0',
|
||||
handler: 'digitNumber',
|
||||
cls: 'rtc-digit',
|
||||
maxWidth:90
|
||||
}
|
||||
},
|
||||
items: [{
|
||||
items: [{
|
||||
text: '1'
|
||||
}, {
|
||||
text: '2'
|
||||
}, {
|
||||
text: '3'
|
||||
}]
|
||||
}, {
|
||||
items: [{
|
||||
text: '4'
|
||||
}, {
|
||||
text: '5'
|
||||
}, {
|
||||
text: '6'
|
||||
}]
|
||||
}, {
|
||||
items: [{
|
||||
text: '7'
|
||||
}, {
|
||||
text: '8'
|
||||
}, {
|
||||
text: '9'
|
||||
}]
|
||||
}, {
|
||||
items: [{
|
||||
text: '*'
|
||||
}, {
|
||||
text: '0'
|
||||
}, {
|
||||
text: '#'
|
||||
}]
|
||||
}]
|
||||
})
|
@ -0,0 +1,62 @@
|
||||
Ext.define('NgcpCsc.view.common.composer.Sms', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
alias: 'widget.sms-composer',
|
||||
|
||||
bind: {
|
||||
hidden: '{smsComposerHidden}'
|
||||
},
|
||||
defaults: {
|
||||
width: '90%',
|
||||
margin: 20
|
||||
},
|
||||
items: [{
|
||||
layout: 'hbox',
|
||||
items: [{
|
||||
xtype: 'textfield',
|
||||
emptyText: 'Allowed digits are 0-9, +, # and *.',
|
||||
hideTrigger: true,
|
||||
width: '80%',
|
||||
bind: '{numberToCall}'
|
||||
}, {
|
||||
xtype: 'button',
|
||||
enableToggle: true,
|
||||
iconCls: 'x-fa fa-fax',
|
||||
width: '20%',
|
||||
handler: 'showPhoneComposer'
|
||||
}]
|
||||
}, {
|
||||
xtype: 'phonekeys',
|
||||
bind: {
|
||||
hidden: '{phoneKeyboardHidden}'
|
||||
}
|
||||
}, {
|
||||
xtype: 'textarea',
|
||||
allowBlank: false,
|
||||
bind: '{smsText}',
|
||||
fieldLabel: 'Content',
|
||||
emptyText: 'Max 140 digits.'
|
||||
}, {
|
||||
xtype: 'container',
|
||||
layout: 'center',
|
||||
margin: '40 20 20 20',
|
||||
items: [{
|
||||
xtype: 'button',
|
||||
cls: 'rtc-icons-big',
|
||||
bind: {
|
||||
disabled: '{disableSmsSubmit}'
|
||||
},
|
||||
width: 60,
|
||||
height: 60,
|
||||
margin: '50 0 10 0',
|
||||
iconCls: 'x-fa fa-send fa-2x',
|
||||
cls: 'rtc-icons-big',
|
||||
listeners: {
|
||||
click: {
|
||||
fn: 'sendSms',
|
||||
el: 'element'
|
||||
}
|
||||
}
|
||||
}]
|
||||
}]
|
||||
})
|
@ -1,74 +0,0 @@
|
||||
Ext.define('NgcpCsc.view.common.webrtc.WebrtcController', {
|
||||
extend: 'Ext.app.ViewController',
|
||||
alias: 'controller.webrtc',
|
||||
|
||||
listen: {
|
||||
controller: {
|
||||
'*': {
|
||||
initwebrtc: 'showWebrtcPanel',
|
||||
startcall: 'startCall',
|
||||
pausecall: 'pauseCall',
|
||||
endcall: 'endCall',
|
||||
startvideocall: 'startVideoCall',
|
||||
pausevideocall: 'pauseVideoCall',
|
||||
endvideocall: 'endVideoCall'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
showWebrtcPanel: function(record, switchVideoOn, newCall) {
|
||||
var panel = this.getView();
|
||||
if(!newCall){
|
||||
var vm = this.getViewModel();
|
||||
var buddyUser = Ext.getStore('Chat').findRecord('uid', record.get('uid'));
|
||||
var number = (buddyUser) ? buddyUser.get('number') : record.get('caller') || record.get('source_cli') || record.get('mobile');
|
||||
this.getViewModel().set('title', Ext.String.format('{0}', number));
|
||||
vm.set('thumbnail', (buddyUser) ? buddyUser.get('thumbnail') : this.getViewModel().get('defaultThumbnail'));
|
||||
vm.set('status', Ext.String.format('calling {0} ...', (buddyUser) ? buddyUser.get('name') : ''));
|
||||
vm.set('callEnabled', true);
|
||||
vm.set('micEnabled', true);
|
||||
vm.set('videoEnabled', switchVideoOn || false);
|
||||
}
|
||||
panel.show().expand();
|
||||
},
|
||||
|
||||
toogleChat: function(btn) {
|
||||
this.fireEvent('togglechat', btn.pressed);
|
||||
},
|
||||
|
||||
onBeforeClose: function(){
|
||||
this.getView().hide();
|
||||
return false;
|
||||
},
|
||||
|
||||
startCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
pauseCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
endCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
startVideoCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
pauseVideoCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
endVideoCall: function() {
|
||||
//TODO
|
||||
},
|
||||
|
||||
onPressSubmitBtn: function() {
|
||||
// TODO
|
||||
},
|
||||
onPressEnter: function() {
|
||||
// TODO
|
||||
}
|
||||
});
|
@ -1,15 +0,0 @@
|
||||
Ext.define('NgcpCsc.view.webrtc.WebrtcModel', {
|
||||
extend: 'Ext.app.ViewModel',
|
||||
|
||||
alias: 'viewmodel.webrtc',
|
||||
|
||||
data: {
|
||||
title: 123456789,
|
||||
defaultThumbnail: 'resources/images/icons/phoneicon.png',
|
||||
thumbnail: 'resources/images/icons/phoneicon.png',
|
||||
status: 'calling...',
|
||||
callEnabled: false,
|
||||
micEnabled: false,
|
||||
videoEnabled: false
|
||||
}
|
||||
});
|
@ -1,108 +0,0 @@
|
||||
Ext.define('NgcpCsc.view.common.webrtc.WebrtcPanel', {
|
||||
extend: 'Ext.panel.Panel',
|
||||
|
||||
xtype: 'webrtc',
|
||||
|
||||
controller: 'webrtc',
|
||||
|
||||
viewModel: 'webrtc',
|
||||
|
||||
padding: '0 0 0 1',
|
||||
|
||||
width: '30%',
|
||||
|
||||
closable: true,
|
||||
|
||||
bind: {
|
||||
title: '{title}'
|
||||
},
|
||||
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch'
|
||||
},
|
||||
|
||||
listeners:{
|
||||
beforeclose: 'onBeforeClose'
|
||||
},
|
||||
|
||||
initComponent: function() {
|
||||
this.items = [{
|
||||
flex: 4,
|
||||
layout: {
|
||||
type: 'vbox',
|
||||
align: 'stretch',
|
||||
pack: 'center'
|
||||
},
|
||||
defaults: {
|
||||
cls: 'webrtc-container'
|
||||
},
|
||||
items: [{
|
||||
cls: 'webrtc-avatar-container',
|
||||
items: {
|
||||
xtype: 'image',
|
||||
cls: 'webrtc-avatar',
|
||||
bind: {
|
||||
src: '{thumbnail}'
|
||||
}
|
||||
}
|
||||
}, {
|
||||
xtype: 'label',
|
||||
margin: '20 0 20 0',
|
||||
bind: '{status}'
|
||||
}, {
|
||||
xtype: 'container',
|
||||
cls: 'webrtc-btns-container',
|
||||
layout: {
|
||||
type: 'hbox',
|
||||
align: 'stretch',
|
||||
pack: 'center'
|
||||
},
|
||||
defaults: {
|
||||
xtype: 'button',
|
||||
cls: 'webrtc-icons',
|
||||
enableToggle: true
|
||||
},
|
||||
items: [{
|
||||
iconCls: 'x-fa fa-phone',
|
||||
bind: {
|
||||
pressed: '{callEnabled}'
|
||||
}
|
||||
}, {
|
||||
iconCls: 'x-fa fa-microphone',
|
||||
bind: {
|
||||
pressed: '{micEnabled}'
|
||||
}
|
||||
}, {
|
||||
iconCls: 'x-fa fa-video-camera',
|
||||
bind: {
|
||||
pressed: '{videoEnabled}'
|
||||
}
|
||||
}, {
|
||||
iconCls: 'x-fa fa-wechat',
|
||||
bind: {
|
||||
pressed: '{chatEnabled}'
|
||||
},
|
||||
handler: 'toogleChat'
|
||||
}]
|
||||
}]
|
||||
}, Ext.create('NgcpCsc.view.pages.chat.ChatContainer', {
|
||||
flex: 3,
|
||||
cls: 'webrtc-chat-tbar',
|
||||
bind: {
|
||||
hidden: '{!chatEnabled}'
|
||||
},
|
||||
items: [{
|
||||
xtype: 'chat-notifications',
|
||||
closable: false,
|
||||
scrollable: true,
|
||||
cls: 'private-conversation-text',
|
||||
deferEmptyText: false,
|
||||
store: Ext.create('Ext.data.Store', {
|
||||
model: 'NgcpCsc.model.ChatNotification'
|
||||
})
|
||||
}]
|
||||
})];
|
||||
this.callParent();
|
||||
}
|
||||
})
|
@ -1,11 +0,0 @@
|
||||
Ext.define('NgcpCsc.view.pages.chat.ChatListModel', {
|
||||
extend: 'Ext.app.ViewModel',
|
||||
|
||||
alias: 'viewmodel.chatlist',
|
||||
|
||||
stores: {
|
||||
buddyList: {
|
||||
type: 'chatlist'
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,11 @@
|
||||
Ext.define('NgcpCsc.view.pages.contacts.ContactsModel', {
|
||||
extend: 'Ext.app.ViewModel',
|
||||
|
||||
alias: 'viewmodel.contacts',
|
||||
|
||||
stores: {
|
||||
buddyList: {
|
||||
type: 'contacts'
|
||||
}
|
||||
}
|
||||
});
|
Binary file not shown.
Loading…
Reference in new issue