FS-8045 [Verto-Communicator] Make the folder structure compliant with AngularJS best practices and adjust build system.
|
@ -1,18 +1,62 @@
|
||||||
{
|
{
|
||||||
"bitwise": true,
|
"bitwise": true,
|
||||||
"browser": true,
|
"camelcase": true,
|
||||||
"curly": true,
|
"curly": true,
|
||||||
"eqeqeq": true,
|
"eqeqeq": true,
|
||||||
"esnext": true,
|
"es3": false,
|
||||||
"latedef": true,
|
"forin": true,
|
||||||
"noarg": true,
|
"freeze": true,
|
||||||
"node": true,
|
"immed": true,
|
||||||
"strict": true,
|
"indent": 4,
|
||||||
"undef": true,
|
"latedef": "nofunc",
|
||||||
"unused": true,
|
"newcap": true,
|
||||||
"globals": {
|
"noarg": true,
|
||||||
"angular": false,
|
"noempty": true,
|
||||||
"jQuery": false,
|
"nonbsp": true,
|
||||||
"$": false
|
"nonew": true,
|
||||||
}
|
"plusplus": false,
|
||||||
|
"quotmark": "single",
|
||||||
|
"undef": true,
|
||||||
|
"unused": false,
|
||||||
|
"strict": false,
|
||||||
|
"maxparams": 10,
|
||||||
|
"maxdepth": 5,
|
||||||
|
"maxstatements": 40,
|
||||||
|
"maxcomplexity": 8,
|
||||||
|
"maxlen": 120,
|
||||||
|
|
||||||
|
"asi": false,
|
||||||
|
"boss": false,
|
||||||
|
"debug": false,
|
||||||
|
"eqnull": true,
|
||||||
|
"esnext": false,
|
||||||
|
"evil": false,
|
||||||
|
"expr": false,
|
||||||
|
"funcscope": false,
|
||||||
|
"globalstrict": false,
|
||||||
|
"iterator": false,
|
||||||
|
"lastsemic": false,
|
||||||
|
"laxbreak": false,
|
||||||
|
"laxcomma": false,
|
||||||
|
"loopfunc": true,
|
||||||
|
"maxerr": false,
|
||||||
|
"moz": false,
|
||||||
|
"multistr": false,
|
||||||
|
"notypeof": false,
|
||||||
|
"proto": false,
|
||||||
|
"scripturl": false,
|
||||||
|
"shadow": false,
|
||||||
|
"sub": true,
|
||||||
|
"supernew": false,
|
||||||
|
"validthis": false,
|
||||||
|
"noyield": false,
|
||||||
|
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
|
||||||
|
"globals": {
|
||||||
|
"angular": false,
|
||||||
|
"$": false,
|
||||||
|
"jQuery": false
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
// Configurable paths
|
// Configurable paths
|
||||||
var config = {
|
var config = {
|
||||||
app: '.',
|
app: './src',
|
||||||
dist: 'dist'
|
dist: 'dist'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,10 +33,6 @@ module.exports = function (grunt) {
|
||||||
files: ['bower.json'],
|
files: ['bower.json'],
|
||||||
tasks: ['wiredep']
|
tasks: ['wiredep']
|
||||||
},
|
},
|
||||||
js: {
|
|
||||||
files: ['js/verto-service.js'],
|
|
||||||
tasks: ['string-replace:dev']
|
|
||||||
},
|
|
||||||
styles: {
|
styles: {
|
||||||
files: ['<%= config.app %>/css/{,*/}*.css'],
|
files: ['<%= config.app %>/css/{,*/}*.css'],
|
||||||
tasks: ['newer:copy:styles', 'postcss']
|
tasks: ['newer:copy:styles', 'postcss']
|
||||||
|
@ -46,25 +42,9 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Replace so we can have it properly passed from dev
|
|
||||||
'string-replace': {
|
|
||||||
dev: {
|
|
||||||
files: {
|
|
||||||
'.tmp/js/verto-service.js': '<%= config.app %>/js/verto-service.js'
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
replacements: [
|
|
||||||
{
|
|
||||||
pattern: /window\.location\.hostname/gi,
|
|
||||||
replacement: ip
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
wiredep: {
|
wiredep: {
|
||||||
app: {
|
app: {
|
||||||
src: ['index.html'],
|
src: ['src/index.html'],
|
||||||
ignorePath: /\.\.\//
|
ignorePath: /\.\.\//
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -94,24 +74,51 @@ module.exports = function (grunt) {
|
||||||
notify: false,
|
notify: false,
|
||||||
background: true,
|
background: true,
|
||||||
https: true,
|
https: true,
|
||||||
open: false
|
open: false,
|
||||||
|
// logLevel: "debug",
|
||||||
|
ghostMode: false,
|
||||||
|
logConnections: true,
|
||||||
|
ui: false
|
||||||
},
|
},
|
||||||
livereload: {
|
livereload: {
|
||||||
options: {
|
options: {
|
||||||
files: [
|
files: [
|
||||||
'<%= config.app %>/{,*/}*.html',
|
'<%= config.app %>/**/*.html',
|
||||||
'.tmp/styles/{,*/}*.css',
|
'.tmp/styles/{,*/}*.css',
|
||||||
'<%= config.app %>/images/{,*/}*',
|
'<%= config.app %>/images/{,*/}*',
|
||||||
'.tmp/js/{,*/}*.js',
|
'.tmp/**/*.js',
|
||||||
'<%= config.app %>/js/**/*.js'
|
'<%= config.app %>/**/*.js'
|
||||||
],
|
],
|
||||||
port: 9001,
|
port: 9001,
|
||||||
server: {
|
server: {
|
||||||
baseDir: ['.tmp', '../js/src/', config.app],
|
baseDir: ['../js/src/', './js', '.'],
|
||||||
watchTask: true,
|
index: 'src/index.html',
|
||||||
|
middleware: [
|
||||||
|
require("connect-logger")(),
|
||||||
|
function(req, res, next) {
|
||||||
|
if (ip) {
|
||||||
|
var parsed = require("url").parse(req.url);
|
||||||
|
if (!parsed.pathname.match(/vertoService\.js$/)) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
grunt.log.writeln('Providing replaced data.');
|
||||||
|
var path = require('path');
|
||||||
|
var theFilePath = path.resolve('./src', 'vertoService', 'services', 'vertoService.js');
|
||||||
|
var f = require('fs').readFileSync(theFilePath).toString();
|
||||||
|
res.setHeader('Content-Type', 'text/javascript');
|
||||||
|
res.end(f.replace(/window\.location\.hostname/gi, ip));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
],
|
||||||
routes: {
|
routes: {
|
||||||
|
'/partials': 'src/partials',
|
||||||
'/bower_components': './bower_components',
|
'/bower_components': './bower_components',
|
||||||
'/js/src': '../js/src'
|
'/js/src': '../js/src',
|
||||||
|
'/js': './js'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,7 +144,7 @@ module.exports = function (grunt) {
|
||||||
all: {
|
all: {
|
||||||
src: [
|
src: [
|
||||||
'Gruntfile.js',
|
'Gruntfile.js',
|
||||||
'js/{,*/}*.js'
|
'src/**/*.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -151,8 +158,7 @@ module.exports = function (grunt) {
|
||||||
'!dist/.git{,*/}*'
|
'!dist/.git{,*/}*'
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
},
|
}
|
||||||
server: '.tmp'
|
|
||||||
},
|
},
|
||||||
// Renames files for browser caching purposes
|
// Renames files for browser caching purposes
|
||||||
filerev: {
|
filerev: {
|
||||||
|
@ -184,7 +190,7 @@ module.exports = function (grunt) {
|
||||||
'<%= config.dist %>/styles'
|
'<%= config.dist %>/styles'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
html: ['<%= config.dist %>/{,*/}*.html'],
|
html: ['<%= config.dist %>/**/*.html'],
|
||||||
css: ['<%= config.dist %>/styles/{,*/}*.css']
|
css: ['<%= config.dist %>/styles/{,*/}*.css']
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -257,14 +263,15 @@ module.exports = function (grunt) {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
dot: true,
|
dot: true,
|
||||||
cwd: '',
|
cwd: '<%= config.app %>',
|
||||||
dest: 'dist',
|
dest: 'dist',
|
||||||
src: [
|
src: [
|
||||||
'*.{ico,png,txt}',
|
'*.{ico,png,txt}',
|
||||||
'*.html',
|
'*.html',
|
||||||
'partials/**/*.html',
|
'partials/**/*.html',
|
||||||
'images/{,*/}*.{webp}',
|
'images/{,*/}*.{webp}',
|
||||||
'css/fonts/{,*/}*.*'
|
'css/fonts/{,*/}*.*',
|
||||||
|
'sounds/*.*'
|
||||||
]
|
]
|
||||||
}, {
|
}, {
|
||||||
expand: true,
|
expand: true,
|
||||||
|
@ -285,7 +292,7 @@ module.exports = function (grunt) {
|
||||||
},
|
},
|
||||||
styles: {
|
styles: {
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: '/css',
|
cwd: '<%= config.app %>/css',
|
||||||
dest: '.tmp/css/',
|
dest: '.tmp/css/',
|
||||||
src: '{,*/}*.css'
|
src: '{,*/}*.css'
|
||||||
}
|
}
|
||||||
|
@ -304,19 +311,14 @@ module.exports = function (grunt) {
|
||||||
});
|
});
|
||||||
|
|
||||||
grunt.registerTask('serve', function (target) {
|
grunt.registerTask('serve', function (target) {
|
||||||
var tasks = ['clean:server',
|
var tasks = [
|
||||||
'wiredep',
|
'wiredep',
|
||||||
'concurrent:server',
|
'concurrent:server',
|
||||||
'postcss'];
|
'postcss'];
|
||||||
|
|
||||||
if (ip) {
|
|
||||||
tasks = tasks.concat(['string-replace:dev',
|
tasks = tasks.concat(['browserSync:livereload',
|
||||||
'browserSync:livereload',
|
'watch']);
|
||||||
'watch']);
|
|
||||||
} else {
|
|
||||||
tasks = tasks.concat(['browserSync:livereload',
|
|
||||||
'watch']);
|
|
||||||
}
|
|
||||||
|
|
||||||
grunt.task.run(tasks);
|
grunt.task.run(tasks);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,102 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* App Module */
|
|
||||||
|
|
||||||
var vertoApp = angular.module('vertoApp', [
|
|
||||||
'timer',
|
|
||||||
'ngRoute',
|
|
||||||
'vertoControllers',
|
|
||||||
'vertoDirectives',
|
|
||||||
'vertoFilters',
|
|
||||||
'ngStorage',
|
|
||||||
'ngAnimate',
|
|
||||||
'toastr',
|
|
||||||
'FBAngular',
|
|
||||||
'cgPrompt',
|
|
||||||
'720kb.tooltips',
|
|
||||||
'ui.gravatar',
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoApp.config(['$routeProvider', 'gravatarServiceProvider', 'toastrConfig',
|
|
||||||
function($routeProvider, gravatarServiceProvider, toastrConfig) {
|
|
||||||
$routeProvider.
|
|
||||||
when('/login', {
|
|
||||||
title: 'Login',
|
|
||||||
templateUrl: 'partials/login.html',
|
|
||||||
controller: 'LoginController'
|
|
||||||
}).
|
|
||||||
when('/dialpad', {
|
|
||||||
title: 'Dialpad',
|
|
||||||
templateUrl: 'partials/dialpad.html',
|
|
||||||
controller: 'DialPadController'
|
|
||||||
}).
|
|
||||||
when('/incall', {
|
|
||||||
title: 'In a Call',
|
|
||||||
templateUrl: 'partials/incall.html',
|
|
||||||
controller: 'InCallController'
|
|
||||||
}).
|
|
||||||
/*when('/contributors', {
|
|
||||||
title: 'Contributors',
|
|
||||||
templateUrl: 'partials/contributors.html',
|
|
||||||
controller: 'ContributorsController',
|
|
||||||
}).*/
|
|
||||||
when('/browser-upgrade', {
|
|
||||||
title: '',
|
|
||||||
templateUrl: 'partials/browser_upgrade.html',
|
|
||||||
controller: 'BrowserUpgradeController'
|
|
||||||
}).
|
|
||||||
otherwise({
|
|
||||||
redirectTo: '/login'
|
|
||||||
});
|
|
||||||
|
|
||||||
gravatarServiceProvider.defaults = {
|
|
||||||
default: 'mm' // Mystery man as default for missing avatars
|
|
||||||
};
|
|
||||||
|
|
||||||
angular.extend(toastrConfig, {
|
|
||||||
maxOpened: 4
|
|
||||||
});
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoApp.run(['$rootScope', '$location', 'toastr', 'prompt',
|
|
||||||
function($rootScope, $location, toastr, prompt) {
|
|
||||||
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
|
|
||||||
$rootScope.title = current.$$route.title;
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.safeProtocol = false;
|
|
||||||
|
|
||||||
if (window.location.protocol == 'https:') {
|
|
||||||
$rootScope.safeProtocol = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$rootScope.checkBrowser = function() {
|
|
||||||
navigator.getUserMedia = navigator.getUserMedia ||
|
|
||||||
navigator.webkitGetUserMedia ||
|
|
||||||
navigator.mozGetUserMedia;
|
|
||||||
|
|
||||||
if (!navigator.getUserMedia) {
|
|
||||||
$location.path('/browser-upgrade');
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$rootScope.promptInput = function(title, message, label, callback) {
|
|
||||||
var ret = prompt({
|
|
||||||
title: title,
|
|
||||||
message: message,
|
|
||||||
input: true,
|
|
||||||
label: label
|
|
||||||
}).then(function(ret) {
|
|
||||||
if (angular.isFunction(callback)) {
|
|
||||||
callback(ret);
|
|
||||||
}
|
|
||||||
}, function() {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
|
@ -1,940 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* Controllers */
|
|
||||||
|
|
||||||
var vertoControllers = angular.module('vertoControllers', ['ui.bootstrap',
|
|
||||||
'vertoService', 'storageService', 'ui.gravatar'
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.filter('gravatar',
|
|
||||||
function() {
|
|
||||||
return function(email, size) {
|
|
||||||
if (angular.isUndefined(size)) {
|
|
||||||
size = 40;
|
|
||||||
}
|
|
||||||
var hash = md5(email);
|
|
||||||
return 'https://secure.gravatar.com/avatar/' + hash + '?s=' + size + '&d=mm';
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('MainController', ['$scope', '$rootScope',
|
|
||||||
'$location', '$modal', '$timeout', 'verto', 'storage', 'toastr',
|
|
||||||
'Fullscreen', 'prompt',
|
|
||||||
function($scope, $rootScope, $location, $modal,
|
|
||||||
$timeout, verto, storage, toastr, Fullscreen, prompt) {
|
|
||||||
console.debug('Executing MainController.');
|
|
||||||
|
|
||||||
var myVideo = document.getElementById("webcam");
|
|
||||||
$scope.verto = verto;
|
|
||||||
$scope.storage = storage;
|
|
||||||
$scope.call_history = angular.element("#call_history").hasClass('active');
|
|
||||||
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* (explanation) scope in another controller extends rootScope (singleton)
|
|
||||||
*/
|
|
||||||
$rootScope.chat_counter = 0;
|
|
||||||
$rootScope.activePane = 'members';
|
|
||||||
/**
|
|
||||||
* The number that will be called.
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
$rootScope.dialpadNumber = '';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* if user data saved, use stored data for logon
|
|
||||||
*/
|
|
||||||
if (storage.data.ui_connected && storage.data.ws_connected) {
|
|
||||||
$scope.verto.data.name = storage.data.name;
|
|
||||||
$scope.verto.data.email = storage.data.email;
|
|
||||||
$scope.verto.data.login = storage.data.login;
|
|
||||||
$scope.verto.data.password = storage.data.password;
|
|
||||||
|
|
||||||
verto.connect(function(v, connected) {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
if (connected) {
|
|
||||||
toastr.success('Nice to see you again.', 'Welcome back');
|
|
||||||
$location.path('/dialpad');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// If verto is not connected, redirects to login page.
|
|
||||||
if (!verto.data.connected) {
|
|
||||||
console.debug('MainController: WebSocket not connected. Redirecting to login.');
|
|
||||||
$location.path('/login');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login the user to verto server and
|
|
||||||
* redirects him to dialpad page.
|
|
||||||
*/
|
|
||||||
$scope.login = function() {
|
|
||||||
var connectCallback = function(v, connected) {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
if (connected) {
|
|
||||||
storage.data.ui_connected = verto.data.connected;
|
|
||||||
storage.data.ws_connected = verto.data.connected;
|
|
||||||
storage.data.name = verto.data.name;
|
|
||||||
storage.data.email = verto.data.email;
|
|
||||||
storage.data.login = verto.data.login;
|
|
||||||
storage.data.password = verto.data.password;
|
|
||||||
|
|
||||||
console.debug('Redirecting to dialpad page.');
|
|
||||||
storage.changeData(verto);
|
|
||||||
toastr.success('Login successful.', 'Welcome');
|
|
||||||
$location.path('/dialpad');
|
|
||||||
} else {
|
|
||||||
toastr.error('There was an error while trying to login. Please try again.', 'Error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
verto.connect(connectCallback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout the user from verto server and
|
|
||||||
* redirects him to login page.
|
|
||||||
*/
|
|
||||||
$scope.logout = function() {
|
|
||||||
var disconnect = function() {
|
|
||||||
var disconnectCallback = function(v, connected) {
|
|
||||||
console.debug('Redirecting to login page.');
|
|
||||||
storage.reset();
|
|
||||||
$location.path('/login');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (verto.data.call) {
|
|
||||||
verto.hangup();
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.closeChat();
|
|
||||||
verto.disconnect(disconnectCallback);
|
|
||||||
|
|
||||||
verto.hangup();
|
|
||||||
};
|
|
||||||
|
|
||||||
if (verto.data.call) {
|
|
||||||
prompt({
|
|
||||||
title: 'Oops, Active Call in Course.',
|
|
||||||
message: 'It seems that you are in a call. Do you want to hang up?'
|
|
||||||
}).then(function() {
|
|
||||||
disconnect();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows a modal with the settings.
|
|
||||||
*/
|
|
||||||
$scope.openModalSettings = function() {
|
|
||||||
var modalInstance = $modal.open({
|
|
||||||
animation: $scope.animationsEnabled,
|
|
||||||
templateUrl: 'partials/modal_settings.html',
|
|
||||||
controller: 'ModalSettingsController',
|
|
||||||
});
|
|
||||||
|
|
||||||
modalInstance.result.then(
|
|
||||||
function(result) {
|
|
||||||
console.log(result);
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
console.info('Modal dismissed at: ' + new Date());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
modalInstance.rendered.then(
|
|
||||||
function() {
|
|
||||||
jQuery.material.init();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.openModal = function(templateUrl, controller) {
|
|
||||||
var modalInstance = $modal.open({
|
|
||||||
animation: $scope.animationsEnabled,
|
|
||||||
templateUrl: templateUrl,
|
|
||||||
controller: controller,
|
|
||||||
});
|
|
||||||
|
|
||||||
modalInstance.result.then(
|
|
||||||
function(result) {
|
|
||||||
console.log(result);
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
console.info('Modal dismissed at: ' + new Date());
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
modalInstance.rendered.then(
|
|
||||||
function() {
|
|
||||||
jQuery.material.init();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.showContributors = function() {
|
|
||||||
$scope.openModal('partials/contributors.html', 'ContributorsController');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the display adding the new number touched.
|
|
||||||
*
|
|
||||||
* @param {String} number - New touched number.
|
|
||||||
*/
|
|
||||||
$rootScope.dtmf = function(number) {
|
|
||||||
$rootScope.dialpadNumber = $scope.dialpadNumber + number;
|
|
||||||
if (verto.data.call) {
|
|
||||||
verto.dtmf(number);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes the last character from the number.
|
|
||||||
*/
|
|
||||||
$rootScope.backspace = function() {
|
|
||||||
var number = $rootScope.dialpadNumber;
|
|
||||||
var len = number.length;
|
|
||||||
$rootScope.dialpadNumber = number.substring(0, len - 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
$scope.toggleCallHistory = function() {
|
|
||||||
if (!$scope.call_history) {
|
|
||||||
angular.element("#call_history").addClass('active');
|
|
||||||
angular.element("#call-history-wrapper").addClass('active');
|
|
||||||
} else {
|
|
||||||
angular.element("#call_history").removeClass('active');
|
|
||||||
angular.element("#call-history-wrapper").removeClass('active');
|
|
||||||
}
|
|
||||||
$scope.call_history = angular.element("#call_history").hasClass('active');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.clearCallHistory = function() {
|
|
||||||
storage.data.call_history = [];
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.toggleChat = function() {
|
|
||||||
if ($scope.chatStatus && $rootScope.activePane === 'chat') {
|
|
||||||
$rootScope.chat_counter = 0;
|
|
||||||
}
|
|
||||||
angular.element('#wrapper').toggleClass('toggled');
|
|
||||||
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.openChat = function() {
|
|
||||||
$scope.chatStatus = false;
|
|
||||||
angular.element('#wrapper').removeClass('toggled');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.closeChat = function() {
|
|
||||||
$scope.chatStatus = true;
|
|
||||||
angular.element('#wrapper').addClass('toggled');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.goFullscreen = function() {
|
|
||||||
if (storage.data.userStatus !== 'connected') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$rootScope.fullscreenEnabled = !Fullscreen.isEnabled();
|
|
||||||
if (Fullscreen.isEnabled()) {
|
|
||||||
Fullscreen.cancel();
|
|
||||||
} else {
|
|
||||||
Fullscreen.enable(document.getElementsByTagName('body')[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$rootScope.$on('call.video', function(event) {
|
|
||||||
storage.data.videoCall = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('call.hangup', function(event, data) {
|
|
||||||
if (Fullscreen.isEnabled()) {
|
|
||||||
Fullscreen.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
console.log($scope.chatStatus);
|
|
||||||
if (!$scope.chatStatus) {
|
|
||||||
angular.element('#wrapper').toggleClass('toggled');
|
|
||||||
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rootScope.dialpadNumber = '';
|
|
||||||
console.debug('Redirecting to dialpad page.');
|
|
||||||
$location.path('/dialpad');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$rootScope.$digest();
|
|
||||||
} catch (e) {
|
|
||||||
console.log('not digest');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('page.incall', function(event, data) {
|
|
||||||
if (storage.data.askRecoverCall) {
|
|
||||||
prompt({
|
|
||||||
title: 'Oops, Active Call in Course.',
|
|
||||||
message: 'It seems you were in a call before leaving the last time. Wanna go back to that?'
|
|
||||||
}).then(function() {
|
|
||||||
verto.changeData(storage);
|
|
||||||
console.log('redirect to incall page');
|
|
||||||
$location.path('/incall');
|
|
||||||
}, function() {
|
|
||||||
storage.data.userStatus = 'connecting';
|
|
||||||
verto.hangup();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
verto.changeData(storage);
|
|
||||||
console.log('redirect to incall page');
|
|
||||||
$location.path('/incall');
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.callActive = function(data) {
|
|
||||||
verto.data.mutedMic = storage.data.mutedMic;
|
|
||||||
verto.data.mutedVideo = storage.data.mutedVideo;
|
|
||||||
|
|
||||||
if (!storage.data.cur_call) {
|
|
||||||
storage.data.call_start = new Date();
|
|
||||||
}
|
|
||||||
storage.data.userStatus = 'connected';
|
|
||||||
var call_start = new Date(storage.data.call_start);
|
|
||||||
$rootScope.start_time = call_start;
|
|
||||||
|
|
||||||
$timeout(function() {
|
|
||||||
$scope.$broadcast('timer-start');
|
|
||||||
});
|
|
||||||
myVideo.play();
|
|
||||||
storage.data.calling = false;
|
|
||||||
|
|
||||||
storage.data.cur_call = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
$rootScope.$on('call.active', function(event, data) {
|
|
||||||
$rootScope.callActive(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('call.calling', function(event, data) {
|
|
||||||
storage.data.calling = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('call.incoming', function(event, data) {
|
|
||||||
console.log('Incoming call from: ' + data);
|
|
||||||
|
|
||||||
storage.data.cur_call = 0;
|
|
||||||
$scope.incomingCall = true;
|
|
||||||
storage.data.videoCall = false;
|
|
||||||
storage.data.mutedVideo = false;
|
|
||||||
storage.data.mutedMic = false;
|
|
||||||
|
|
||||||
prompt({
|
|
||||||
title: 'Incoming Call',
|
|
||||||
message: 'from ' + data
|
|
||||||
}).then(function() {
|
|
||||||
var call_start = new Date(storage.data.call_start);
|
|
||||||
$rootScope.start_time = call_start;
|
|
||||||
console.log($rootScope.start_time);
|
|
||||||
|
|
||||||
$scope.answerCall();
|
|
||||||
storage.data.called_number = data;
|
|
||||||
|
|
||||||
storage.data.call_history.unshift({
|
|
||||||
'number': data,
|
|
||||||
'direction': 'inbound',
|
|
||||||
'status': true,
|
|
||||||
'call_start': Date()
|
|
||||||
});
|
|
||||||
$location.path('/incall');
|
|
||||||
}, function() {
|
|
||||||
$scope.declineCall();
|
|
||||||
storage.data.call_history.unshift({
|
|
||||||
'number': data,
|
|
||||||
'direction': 'inbound',
|
|
||||||
'status': false,
|
|
||||||
'call_start': Date()
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.hold = function() {
|
|
||||||
storage.data.onHold = !storage.data.onHold;
|
|
||||||
verto.data.call.toggleHold();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hangup the current call.
|
|
||||||
*/
|
|
||||||
$scope.hangup = function() {
|
|
||||||
if (!verto.data.call) {
|
|
||||||
toastr.warning('There is no call to hangup.');
|
|
||||||
$location.path('/dialpad');
|
|
||||||
}
|
|
||||||
|
|
||||||
//var hangupCallback = function(v, hangup) {
|
|
||||||
// if (hangup) {
|
|
||||||
// $location.path('/dialpad');
|
|
||||||
// } else {
|
|
||||||
// console.debug('The call could not be hangup.');
|
|
||||||
// }
|
|
||||||
//};
|
|
||||||
//
|
|
||||||
//verto.hangup(hangupCallback);
|
|
||||||
|
|
||||||
verto.hangup();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.answerCall = function() {
|
|
||||||
storage.data.onHold = false;
|
|
||||||
|
|
||||||
verto.data.call.answer({
|
|
||||||
useStereo: verto.data.useStereo,
|
|
||||||
useCamera: verto.data.useCamera,
|
|
||||||
useMic: verto.data.useMic,
|
|
||||||
callee_id_name: verto.data.name,
|
|
||||||
callee_id_number: verto.data.login
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$location.path('/incall');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.declineCall = function() {
|
|
||||||
$scope.hangup();
|
|
||||||
$scope.incomingCall = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.screenshare = function() {
|
|
||||||
if (verto.data.shareCall) {
|
|
||||||
verto.screenshareHangup();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
verto.screenshare(storage.data.called_number);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.play = function() {
|
|
||||||
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
|
||||||
function(file) {
|
|
||||||
verto.data.conf.play(file);
|
|
||||||
console.log('play file :', file);
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.stop = function() {
|
|
||||||
verto.data.conf.stop();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.record = function() {
|
|
||||||
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
|
||||||
function(file) {
|
|
||||||
verto.data.conf.record(file);
|
|
||||||
console.log('recording file :', file);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.stopRecord = function() {
|
|
||||||
verto.data.conf.stopRecord();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.snapshot = function() {
|
|
||||||
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
|
||||||
function(file) {
|
|
||||||
verto.data.conf.snapshot(file);
|
|
||||||
console.log('snapshot file :', file);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('ChatController', ['$scope', '$rootScope', '$http',
|
|
||||||
'$location', '$anchorScroll', '$timeout', 'toastr', 'verto', 'storage', 'prompt',
|
|
||||||
function($scope, $rootScope, $http, $location, $anchorScroll, $timeout,
|
|
||||||
toastr, verto, storage, prompt) {
|
|
||||||
console.debug('Executing ChatController.');
|
|
||||||
|
|
||||||
function scrollToChatBottom() {
|
|
||||||
// Going to the bottom of chat messages.
|
|
||||||
var obj = document.querySelector('.chat-messages');
|
|
||||||
obj.scrollTop = obj.scrollHeight;
|
|
||||||
//var chat_messages_top = jQuery('.chat-messages').scrollTop();
|
|
||||||
//var marker_position = jQuery('#chat-message-bottom').position().top;
|
|
||||||
//jQuery('.chat-messages').scrollTop(chat_messages_top + marker_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
var CLEAN_MESSAGE = '';
|
|
||||||
|
|
||||||
function clearConferenceChat() {
|
|
||||||
$scope.members = [];
|
|
||||||
$scope.messages = [];
|
|
||||||
$scope.message = CLEAN_MESSAGE;
|
|
||||||
}
|
|
||||||
clearConferenceChat();
|
|
||||||
|
|
||||||
$scope.$watch('activePane', function() {
|
|
||||||
if ($scope.activePane == 'chat') {
|
|
||||||
$rootScope.chat_counter = 0;
|
|
||||||
}
|
|
||||||
$rootScope.activePane = $scope.activePane;
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('chat.newMessage', function(event, data) {
|
|
||||||
data.created_at = new Date();
|
|
||||||
console.log('chat.newMessage', data);
|
|
||||||
|
|
||||||
$scope.$apply(function() {
|
|
||||||
$scope.messages.push(data);
|
|
||||||
if(data.from != storage.data.name &&
|
|
||||||
(angular.element('#wrapper').hasClass('toggled') ||
|
|
||||||
$scope.activePane != 'chat')) {
|
|
||||||
toastr.info(data.body, data.from, {onHidden: function(clicked) {
|
|
||||||
if(clicked) {
|
|
||||||
$scope.chatStatus = false;
|
|
||||||
angular.element('#wrapper').removeClass('toggled');
|
|
||||||
$rootScope.activePane = 'chat';
|
|
||||||
$scope.activePane = 'chat';
|
|
||||||
$scope.$apply();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
++$rootScope.chat_counter;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
$timeout(function() {
|
|
||||||
scrollToChatBottom();
|
|
||||||
}, 300);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('call.recovering', function(event){
|
|
||||||
console.log('Our current call is recovering, clear the participant list.');
|
|
||||||
$scope.members = [];
|
|
||||||
});
|
|
||||||
|
|
||||||
function findMemberByUUID(uuid) {
|
|
||||||
var found = false;
|
|
||||||
for (var idx in $scope.members) {
|
|
||||||
var member = $scope.members[idx];
|
|
||||||
if (member.uuid == uuid) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found) {
|
|
||||||
return idx;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function translateMember(member) {
|
|
||||||
return {
|
|
||||||
'uuid': member[0],
|
|
||||||
'id': member[1][0],
|
|
||||||
'number': member[1][1],
|
|
||||||
'name': member[1][2],
|
|
||||||
'codec': member[1][3],
|
|
||||||
'status': JSON.parse(member[1][4]),
|
|
||||||
'email': member[1][5].email
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMember(member) {
|
|
||||||
$scope.members.push(translateMember(member));
|
|
||||||
}
|
|
||||||
|
|
||||||
$rootScope.$on('members.boot', function(event, members) {
|
|
||||||
console.log('members.boot', event, members);
|
|
||||||
$scope.$apply(function() {
|
|
||||||
clearConferenceChat();
|
|
||||||
for (var idx in members) {
|
|
||||||
var member = members[idx];
|
|
||||||
addMember(member);
|
|
||||||
console.log($scope.members);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('members.add', function(event, member) {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
addMember(member);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('members.del', function(event, uuid) {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
var memberIdx = findMemberByUUID(uuid);
|
|
||||||
if (memberIdx != -1) {
|
|
||||||
// Removing the member.
|
|
||||||
$scope.members.splice(memberIdx, 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('members.update', function(event, member) {
|
|
||||||
member = translateMember(member);
|
|
||||||
var memberIdx = findMemberByUUID(member.uuid);
|
|
||||||
if (memberIdx < 0) {
|
|
||||||
console.log('Didn\'t find the member uuid ' + member.uuid);
|
|
||||||
} else {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
console.log('Updating', memberIdx, ' <', $scope.members[memberIdx],
|
|
||||||
'> with <', member, '>');
|
|
||||||
angular.extend($scope.members[memberIdx], member);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$on('members.clear', function(event) {
|
|
||||||
$scope.$apply(function() {
|
|
||||||
clearConferenceChat();
|
|
||||||
$scope.closeChat();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Public methods.
|
|
||||||
*/
|
|
||||||
$scope.send = function() {
|
|
||||||
verto.sendMessage($scope.message, function() {
|
|
||||||
$scope.message = CLEAN_MESSAGE;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Participants moderation.
|
|
||||||
$scope.confKick = function(memberID) {
|
|
||||||
console.log('$scope.confKick');
|
|
||||||
verto.data.conf.kick(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confMuteMic = function(memberID) {
|
|
||||||
console.log('$scope.confMuteMic');
|
|
||||||
verto.data.conf.muteMic(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confMuteVideo = function(memberID) {
|
|
||||||
console.log('$scope.confMuteVideo');
|
|
||||||
verto.data.conf.muteVideo(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confPresenter = function(memberID) {
|
|
||||||
console.log('$scope.confPresenter');
|
|
||||||
verto.data.conf.presenter(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confVideoFloor = function(memberID) {
|
|
||||||
console.log('$scope.confVideoFloor');
|
|
||||||
verto.data.conf.videoFloor(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confBanner = function(memberID) {
|
|
||||||
console.log('$scope.confBanner');
|
|
||||||
prompt({
|
|
||||||
title: 'Participant banner',
|
|
||||||
message: 'What would you like the banner to say?',
|
|
||||||
input: true,
|
|
||||||
label: 'Text',
|
|
||||||
value: 'New text'
|
|
||||||
}).then(function(text){
|
|
||||||
verto.data.conf.banner(memberID, text);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confVolumeDown = function(memberID) {
|
|
||||||
console.log('$scope.confVolumeDown');
|
|
||||||
verto.data.conf.volumeDown(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confVolumeUp = function(memberID) {
|
|
||||||
console.log('$scope.confVolumeUp');
|
|
||||||
verto.data.conf.volumeUp(memberID);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.confTransfer = function(memberID) {
|
|
||||||
console.log('$scope.confTransfer');
|
|
||||||
var exten = '1800';
|
|
||||||
verto.data.conf.transfer(memberID, exten);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('MenuController', ['$scope', '$http', '$location',
|
|
||||||
'verto', 'storage',
|
|
||||||
function($scope, $http, $location, verto, storage) {
|
|
||||||
console.debug('Executing MenuController.');
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('ModalSettingsController', ['$scope', '$http',
|
|
||||||
'$location', '$modalInstance', 'verto', 'storage',
|
|
||||||
function($scope, $http, $location, $modalInstance, verto, storage) {
|
|
||||||
console.debug('Executing ModalSettingsController.');
|
|
||||||
|
|
||||||
verto.changeData(storage);
|
|
||||||
$scope.verto = verto;
|
|
||||||
$scope.storage = storage;
|
|
||||||
|
|
||||||
$scope.ok = function() {
|
|
||||||
storage.changeData(verto);
|
|
||||||
$modalInstance.close('Ok.');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
|
||||||
$modalInstance.dismiss('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.refreshDeviceList = function() {
|
|
||||||
return verto.refreshDevices();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoControllers.controller('ModalLoginInformationController', ['$scope',
|
|
||||||
'$http', '$location', '$modalInstance', 'verto', 'storage',
|
|
||||||
function($scope, $http, $location, $modalInstance, verto, storage) {
|
|
||||||
console.debug('Executing ModalLoginInformationController.');
|
|
||||||
|
|
||||||
$scope.verto = verto;
|
|
||||||
$scope.storage = storage;
|
|
||||||
|
|
||||||
$scope.ok = function() {
|
|
||||||
$modalInstance.close('Ok.');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
|
||||||
$modalInstance.dismiss('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoControllers.controller('LoginController', ['$scope', '$http', '$location',
|
|
||||||
'verto',
|
|
||||||
function($scope, $http, $location, verto) {
|
|
||||||
$scope.checkBrowser();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* using stored data (localStorage) for logon
|
|
||||||
*/
|
|
||||||
verto.data.name = $scope.storage.data.name;
|
|
||||||
verto.data.email = $scope.storage.data.email;
|
|
||||||
if ($scope.storage.data.login != '' && $scope.storage.data.password != '') {
|
|
||||||
verto.data.login = $scope.storage.data.login;
|
|
||||||
verto.data.password = $scope.storage.data.password;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug('Executing LoginController.');
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('DialPadController', ['$rootScope', '$scope',
|
|
||||||
'$http', '$location', 'toastr', 'verto', 'storage',
|
|
||||||
function($rootScope, $scope, $http, $location, toastr, verto, storage) {
|
|
||||||
console.debug('Executing DialPadController.');
|
|
||||||
|
|
||||||
$scope.checkBrowser();
|
|
||||||
storage.data.videoCall = false;
|
|
||||||
storage.data.userStatus = 'connecting';
|
|
||||||
storage.data.calling = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* fill dialpad via querystring [?autocall=\d+]
|
|
||||||
*/
|
|
||||||
if ($location.search().autocall) {
|
|
||||||
$rootScope.dialpadNumber = $location.search().autocall;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* used to bind click on number in call history to fill dialpad
|
|
||||||
* 'cause inside a ng-repeat the angular isnt in ctrl scope
|
|
||||||
*/
|
|
||||||
$scope.fillDialpadNumber = function(number) {
|
|
||||||
$rootScope.dialpadNumber = number;
|
|
||||||
};
|
|
||||||
|
|
||||||
$rootScope.transfer = function() {
|
|
||||||
if (!$rootScope.dialpadNumber) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
verto.data.call.transfer($rootScope.dialpadNumber);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call to the number in the $rootScope.dialpadNumber.
|
|
||||||
*/
|
|
||||||
$rootScope.call = function(extension) {
|
|
||||||
storage.data.onHold = false;
|
|
||||||
storage.data.cur_call = 0;
|
|
||||||
$rootScope.dialpadNumber = extension;
|
|
||||||
if (!$rootScope.dialpadNumber && storage.data.called_number) {
|
|
||||||
$rootScope.dialpadNumber = storage.data.called_number;
|
|
||||||
return false;
|
|
||||||
} else if (!$rootScope.dialpadNumber && !storage.data.called_number) {
|
|
||||||
toastr.warning('Enter an extension, please.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (verto.data.call) {
|
|
||||||
console.debug('A call is already in progress.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
storage.data.mutedVideo = false;
|
|
||||||
storage.data.mutedMic = false;
|
|
||||||
|
|
||||||
storage.data.videoCall = false;
|
|
||||||
verto.call($rootScope.dialpadNumber);
|
|
||||||
|
|
||||||
storage.data.called_number = $rootScope.dialpadNumber;
|
|
||||||
storage.data.call_history.unshift({
|
|
||||||
'number': $rootScope.dialpadNumber,
|
|
||||||
'direction': 'outbound',
|
|
||||||
'call_start': Date()
|
|
||||||
});
|
|
||||||
$location.path('/incall');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
|
||||||
vertoControllers.controller('InCallController', ['$rootScope', '$scope',
|
|
||||||
'$http', '$location', '$modal', '$timeout', 'toastr', 'verto', 'storage', 'prompt', 'Fullscreen',
|
|
||||||
function($rootScope, $scope, $http, $location, $modal, $timeout, toatr,
|
|
||||||
verto, storage, prompt, Fullscreen) {
|
|
||||||
|
|
||||||
console.debug('Executing InCallController.');
|
|
||||||
$scope.layout = null;
|
|
||||||
$scope.checkBrowser();
|
|
||||||
$rootScope.dialpadNumber = '';
|
|
||||||
$scope.callTemplate = 'partials/phone_call.html';
|
|
||||||
$scope.dialpadTemplate = '';
|
|
||||||
$scope.incall = true;
|
|
||||||
|
|
||||||
if (storage.data.videoCall) {
|
|
||||||
$scope.callTemplate = 'partials/video_call.html';
|
|
||||||
}
|
|
||||||
|
|
||||||
$rootScope.$on('call.video', function(event, data) {
|
|
||||||
$timeout(function() {
|
|
||||||
$scope.callTemplate = 'partials/video_call.html';
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* toggle dialpad in incall page
|
|
||||||
*/
|
|
||||||
$scope.toggleDialpad = function() {
|
|
||||||
$scope.openModal('partials/dialpad_widget.html',
|
|
||||||
'ModalDialpadController');
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(!$scope.dialpadTemplate) {
|
|
||||||
$scope.dialpadTemplate = 'partials/dialpad_widget.html';
|
|
||||||
} else {
|
|
||||||
$scope.dialpadTemplate = '';
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: useless?
|
|
||||||
*/
|
|
||||||
$scope.videoCall = function() {
|
|
||||||
prompt({
|
|
||||||
title: 'Would you like to activate video for this call?',
|
|
||||||
message: 'Video will be active during the next calls.'
|
|
||||||
}).then(function() {
|
|
||||||
storage.data.videoCall = true;
|
|
||||||
$scope.callTemplate = 'partials/video_call.html';
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cbMuteVideo = function(event, data) {
|
|
||||||
storage.data.mutedVideo = !storage.data.mutedVideo;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.cbMuteMic = function(event, data) {
|
|
||||||
storage.data.mutedMic = !storage.data.mutedMic;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.confChangeVideoLayout = function(layout) {
|
|
||||||
verto.data.conf.setVideoLayout(layout);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.muteMic = verto.muteMic;
|
|
||||||
$scope.muteVideo = verto.muteVideo;
|
|
||||||
|
|
||||||
$timeout(function() {
|
|
||||||
console.log('broadcast time-start incall');
|
|
||||||
$scope.$broadcast('timer-start');
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoControllers.controller('ModalDialpadController', ['$scope',
|
|
||||||
'$modalInstance',
|
|
||||||
function($scope, $modalInstance) {
|
|
||||||
|
|
||||||
$scope.ok = function() {
|
|
||||||
$modalInstance.close('Ok.');
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
|
||||||
$modalInstance.dismiss('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoControllers.controller('BrowserUpgradeController', ['$scope', '$http',
|
|
||||||
'$location', 'verto', 'storage', 'Fullscreen',
|
|
||||||
function($scope, $http, $location, verto, storage, Fullscreen) {
|
|
||||||
console.debug('Executing BrowserUpgradeController.');
|
|
||||||
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
vertoControllers.controller('ContributorsController', ['$scope', '$http',
|
|
||||||
'toastr',
|
|
||||||
function($scope, $http, toastr) {
|
|
||||||
$http.get(window.location.pathname + '/contributors.txt')
|
|
||||||
.success(function(data) {
|
|
||||||
|
|
||||||
var contributors = [];
|
|
||||||
|
|
||||||
angular.forEach(data, function(value, key) {
|
|
||||||
var re = /(.*) <(.*)>/;
|
|
||||||
var name = value.replace(re, "$1");
|
|
||||||
var email = value.replace(re, "$2");
|
|
||||||
|
|
||||||
this.push({
|
|
||||||
'name': name,
|
|
||||||
'email': email
|
|
||||||
});
|
|
||||||
}, contributors);
|
|
||||||
|
|
||||||
$scope.contributors = contributors;
|
|
||||||
})
|
|
||||||
.error(function() {
|
|
||||||
toastr.error('contributors not found.');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
]);
|
|
|
@ -1,109 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* Directives */
|
|
||||||
|
|
||||||
var vertoDirectives = angular.module('vertoDirectives', []);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* To RTC work properly we need to give a <video> tag as soon as possible
|
|
||||||
* because it needs to attach the video and audio stream to the tag.
|
|
||||||
*
|
|
||||||
* This directive is responsible for moving the video tag from the body to
|
|
||||||
* the right place when a call start and move back to the body when the
|
|
||||||
* call ends. It also hides and display the tag when its convenient.
|
|
||||||
*/
|
|
||||||
vertoDirectives.directive('videoTag',
|
|
||||||
function() {
|
|
||||||
function link(scope, element, attrs) {
|
|
||||||
// Moving the video tag to the new place inside the incall page.
|
|
||||||
console.log('Moving the video to element.');
|
|
||||||
jQuery('video').removeClass('hide').appendTo(element);
|
|
||||||
jQuery('video').css('display', 'block');
|
|
||||||
scope.callActive();
|
|
||||||
|
|
||||||
element.on('$destroy', function() {
|
|
||||||
// Move the video back to the body.
|
|
||||||
console.log('Moving the video back to body.');
|
|
||||||
jQuery('video').addClass('hide').appendTo(jQuery('body'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
link: link
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
vertoDirectives.directive('userStatus',
|
|
||||||
function() {
|
|
||||||
var link = function(scope, element, attrs) {
|
|
||||||
scope.$watch('condition', function(condition) {
|
|
||||||
element.removeClass('connected');
|
|
||||||
element.removeClass('disconnected');
|
|
||||||
element.removeClass('connecting');
|
|
||||||
|
|
||||||
element.addClass(condition);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
scope: {
|
|
||||||
'condition': '='
|
|
||||||
},
|
|
||||||
link: link
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
vertoDirectives.directive('showControls',
|
|
||||||
function(Fullscreen) {
|
|
||||||
var link = function(scope, element, attrs) {
|
|
||||||
var i = null;
|
|
||||||
jQuery('.video-footer').fadeIn('slow');
|
|
||||||
jQuery('.video-hover-buttons').fadeIn('slow');
|
|
||||||
element.parent().bind('mousemove', function() {
|
|
||||||
if (Fullscreen.isEnabled()) {
|
|
||||||
clearTimeout(i);
|
|
||||||
jQuery('.video-footer').fadeIn('slow');
|
|
||||||
jQuery('.video-hover-buttons').fadeIn(500);
|
|
||||||
i = setTimeout(function() {
|
|
||||||
if (Fullscreen.isEnabled()) {
|
|
||||||
jQuery('.video-footer').fadeOut('slow');
|
|
||||||
jQuery('.video-hover-buttons').fadeOut(500);
|
|
||||||
}
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
element.parent().bind('mouseleave', function() {
|
|
||||||
jQuery('.video-footer').fadeIn();
|
|
||||||
jQuery('.video-hover-buttons').fadeIn();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
link: link
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
/*
|
|
||||||
Sometimes autofocus HTML5 directive just isn't enough with SPAs.
|
|
||||||
This directive will force autofocus to work properly under those circumstances.
|
|
||||||
*/
|
|
||||||
(function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
vertoDirectives.directive('autofocus', ['$timeout',
|
|
||||||
function ($timeout) {
|
|
||||||
return {
|
|
||||||
restrict: 'A',
|
|
||||||
link: function ($scope, $element) {
|
|
||||||
$timeout(function () {
|
|
||||||
console.log('Focusing...');
|
|
||||||
$element[0].focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
})();
|
|
|
@ -1,16 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/* Filters */
|
|
||||||
|
|
||||||
var vertoFilters = angular.module('vertoFilters', []);
|
|
||||||
|
|
||||||
vertoFilters.filter('gravatar',
|
|
||||||
function() {
|
|
||||||
return function (email, size) {
|
|
||||||
if (angular.isUndefined(size)) {
|
|
||||||
size = 40;
|
|
||||||
}
|
|
||||||
var hash = md5(email);
|
|
||||||
return 'https://secure.gravatar.com/avatar/' + hash + '?s=' + size + '&d=mm';
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -5,6 +5,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"autoprefixer-core": "^5.2.1",
|
"autoprefixer-core": "^5.2.1",
|
||||||
"browser-sync": "^2.8.2",
|
"browser-sync": "^2.8.2",
|
||||||
|
"connect-logger": "0.0.1",
|
||||||
"grunt": "^0.4.5",
|
"grunt": "^0.4.5",
|
||||||
"grunt-browser-sync": "^2.1.2",
|
"grunt-browser-sync": "^2.1.2",
|
||||||
"grunt-concurrent": "^1.0.0",
|
"grunt-concurrent": "^1.0.0",
|
||||||
|
@ -21,7 +22,6 @@
|
||||||
"grunt-newer": "^1.1.0",
|
"grunt-newer": "^1.1.0",
|
||||||
"grunt-ng-annotate": "^0.9.2",
|
"grunt-ng-annotate": "^0.9.2",
|
||||||
"grunt-postcss": "^0.5.3",
|
"grunt-postcss": "^0.5.3",
|
||||||
"grunt-string-replace": "^1.2.0",
|
|
||||||
"grunt-svgmin": "^2.0.0",
|
"grunt-svgmin": "^2.0.0",
|
||||||
"grunt-usemin": "^3.0.0",
|
"grunt-usemin": "^3.0.0",
|
||||||
"grunt-wiredep": "^2.0.0",
|
"grunt-wiredep": "^2.0.0",
|
||||||
|
|
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
<!-- CSS -->
|
<!-- CSS -->
|
||||||
<!-- build:css(.) css/verto.css -->
|
<!-- build:css(.) css/verto.css -->
|
||||||
<link rel="stylesheet" type="text/css" href="css/verto.css">
|
<link rel="stylesheet" type="text/css" href="src/css/verto.css">
|
||||||
<!-- endbuild -->
|
<!-- endbuild -->
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,17 +86,41 @@
|
||||||
<!-- endbuild -->
|
<!-- endbuild -->
|
||||||
|
|
||||||
<!-- build:js(.) scripts/scripts.js -->
|
<!-- build:js(.) scripts/scripts.js -->
|
||||||
|
|
||||||
<script type="text/javascript" src="../js/src/jquery.jsonrpcclient.js"></script>
|
<script type="text/javascript" src="../js/src/jquery.jsonrpcclient.js"></script>
|
||||||
<script type="text/javascript" src="../js/src/jquery.FSRTC.js"></script>
|
<script type="text/javascript" src="../js/src/jquery.FSRTC.js"></script>
|
||||||
<script type="text/javascript" src="../js/src/jquery.verto.js"></script>
|
<script type="text/javascript" src="../js/src/jquery.verto.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/3rd-party/getScreenId.js"></script>
|
<script type="text/javascript" src="js/3rd-party/getScreenId.js"></script>
|
||||||
<script type="text/javascript" src="js/3rd-party/md5.min.js"></script>
|
<script type="text/javascript" src="js/3rd-party/md5.min.js"></script>
|
||||||
<script type="text/javascript" src="js/filters.js"></script>
|
|
||||||
<script type="text/javascript" src="js/verto-service.js"></script>
|
<script type="text/javascript" src="src/vertoApp/vertoApp.module.js"></script>
|
||||||
<script type="text/javascript" src="js/storage-service.js"></script>
|
|
||||||
<script type="text/javascript" src="js/app.js"></script>
|
<script type="text/javascript" src="src/vertoControllers/vertoControllers.module.js"></script>
|
||||||
<script type="text/javascript" src="js/controllers.js"></script>
|
<script type="text/javascript" src="src/vertoControllers/controllers/BrowserUpgradeController.js"></script>
|
||||||
<script type="text/javascript" src="js/directives.js"></script>
|
<script type="text/javascript" src="src/vertoControllers/controllers/ChatController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/ContributorsController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/DialPadController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/InCallController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/LoginController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/MainController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/MenuController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/ModalDialpadController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/ModalLoginInformationController.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoControllers/controllers/ModalSettingsController.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="src/vertoDirectives/vertoDirectives.module.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoDirectives/directives/autofocus.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoDirectives/directives/showControls.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoDirectives/directives/userStatus.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoDirectives/directives/videoTag.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="src/vertoService/vertoService.module.js"></script>
|
||||||
|
<script type="text/javascript" src="src/vertoService/services/vertoService.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="src/storageService/storageService.module.js"></script>
|
||||||
|
<script type="text/javascript" src="src/storageService/services/storage.js"></script>
|
||||||
|
|
||||||
<!-- endbuild -->
|
<!-- endbuild -->
|
||||||
|
|
||||||
</body>
|
</body>
|
|
@ -1,8 +1,8 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var storageService = angular.module('storageService', ['ngStorage']);
|
angular
|
||||||
|
.module('storageService')
|
||||||
storageService.service('storage', ['$rootScope', '$localStorage',
|
.service('storage', ['$rootScope', '$localStorage',
|
||||||
function($rootScope, $localStorage) {
|
function($rootScope, $localStorage) {
|
||||||
var data = $localStorage;
|
var data = $localStorage;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var vertoService = angular.module('storageService', ['ngStorage']);
|
||||||
|
})();
|
|
@ -0,0 +1,98 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var vertoApp = angular.module('vertoApp', [
|
||||||
|
'timer',
|
||||||
|
'ngRoute',
|
||||||
|
'vertoControllers',
|
||||||
|
'vertoDirectives',
|
||||||
|
'ngStorage',
|
||||||
|
'ngAnimate',
|
||||||
|
'toastr',
|
||||||
|
'FBAngular',
|
||||||
|
'cgPrompt',
|
||||||
|
'720kb.tooltips',
|
||||||
|
'ui.gravatar',
|
||||||
|
]);
|
||||||
|
|
||||||
|
vertoApp.config(['$routeProvider', 'gravatarServiceProvider',
|
||||||
|
function($routeProvider, gravatarServiceProvider) {
|
||||||
|
$routeProvider.
|
||||||
|
when('/login', {
|
||||||
|
title: 'Login',
|
||||||
|
templateUrl: 'partials/login.html',
|
||||||
|
controller: 'LoginController'
|
||||||
|
}).
|
||||||
|
when('/dialpad', {
|
||||||
|
title: 'Dialpad',
|
||||||
|
templateUrl: 'partials/dialpad.html',
|
||||||
|
controller: 'DialPadController'
|
||||||
|
}).
|
||||||
|
when('/incall', {
|
||||||
|
title: 'In a Call',
|
||||||
|
templateUrl: 'partials/incall.html',
|
||||||
|
controller: 'InCallController'
|
||||||
|
}).
|
||||||
|
/*when('/contributors', {
|
||||||
|
title: 'Contributors',
|
||||||
|
templateUrl: 'partials/contributors.html',
|
||||||
|
controller: 'ContributorsController',
|
||||||
|
}).*/
|
||||||
|
when('/browser-upgrade', {
|
||||||
|
title: '',
|
||||||
|
templateUrl: 'partials/browser_upgrade.html',
|
||||||
|
controller: 'BrowserUpgradeController'
|
||||||
|
}).
|
||||||
|
otherwise({
|
||||||
|
redirectTo: '/login'
|
||||||
|
});
|
||||||
|
|
||||||
|
gravatarServiceProvider.defaults = {
|
||||||
|
default: 'mm' // Mystery man as default for missing avatars
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
vertoApp.run(['$rootScope', '$location', 'toastr', 'prompt',
|
||||||
|
function($rootScope, $location, toastr, prompt) {
|
||||||
|
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
|
||||||
|
$rootScope.title = current.$$route.title;
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.safeProtocol = false;
|
||||||
|
|
||||||
|
if (window.location.protocol == 'https:') {
|
||||||
|
$rootScope.safeProtocol = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.checkBrowser = function() {
|
||||||
|
navigator.getUserMedia = navigator.getUserMedia ||
|
||||||
|
navigator.webkitGetUserMedia ||
|
||||||
|
navigator.mozGetUserMedia;
|
||||||
|
|
||||||
|
if (!navigator.getUserMedia) {
|
||||||
|
$location.path('/browser-upgrade');
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$rootScope.promptInput = function(title, message, label, callback) {
|
||||||
|
var ret = prompt({
|
||||||
|
title: title,
|
||||||
|
message: message,
|
||||||
|
input: true,
|
||||||
|
label: label
|
||||||
|
}).then(function(ret) {
|
||||||
|
if (angular.isFunction(callback)) {
|
||||||
|
callback(ret);
|
||||||
|
}
|
||||||
|
}, function() {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,14 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('BrowserUpgradeController', ['$scope', '$http',
|
||||||
|
'$location', 'verto', 'storage', 'Fullscreen',
|
||||||
|
function($scope, $http, $location, verto, storage, Fullscreen) {
|
||||||
|
console.debug('Executing BrowserUpgradeController.');
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,192 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('ChatController', ['$scope', '$rootScope', '$http',
|
||||||
|
'$location', '$anchorScroll', '$timeout', 'verto',
|
||||||
|
function($scope, $rootScope, $http, $location, $anchorScroll, $timeout,
|
||||||
|
verto) {
|
||||||
|
console.debug('Executing ChatController.');
|
||||||
|
|
||||||
|
function scrollToChatBottom() {
|
||||||
|
// Going to the bottom of chat messages.
|
||||||
|
var obj = document.querySelector('.chat-messages');
|
||||||
|
obj.scrollTop = obj.scrollHeight;
|
||||||
|
//var chat_messages_top = jQuery('.chat-messages').scrollTop();
|
||||||
|
//var marker_position = jQuery('#chat-message-bottom').position().top;
|
||||||
|
//jQuery('.chat-messages').scrollTop(chat_messages_top + marker_position);
|
||||||
|
}
|
||||||
|
|
||||||
|
var CLEAN_MESSAGE = '';
|
||||||
|
|
||||||
|
function clearConferenceChat() {
|
||||||
|
$scope.members = [];
|
||||||
|
$scope.messages = [];
|
||||||
|
$scope.message = CLEAN_MESSAGE;
|
||||||
|
}
|
||||||
|
clearConferenceChat();
|
||||||
|
|
||||||
|
$scope.$watch('activePane', function() {
|
||||||
|
if ($scope.activePane == 'chat') {
|
||||||
|
$rootScope.chat_counter = 0;
|
||||||
|
}
|
||||||
|
$rootScope.activePane = $scope.activePane;
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('chat.newMessage', function(event, data) {
|
||||||
|
data.created_at = new Date();
|
||||||
|
console.log('chat.newMessage', data);
|
||||||
|
$scope.$apply(function() {
|
||||||
|
$scope.messages.push(data);
|
||||||
|
if (data.from != verto.data.name && (!$scope.chatStatus ||
|
||||||
|
$scope.activePane != 'chat')) {
|
||||||
|
++$rootScope.chat_counter;
|
||||||
|
}
|
||||||
|
$timeout(function() {
|
||||||
|
scrollToChatBottom();
|
||||||
|
}, 300);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function findMemberByUUID(uuid) {
|
||||||
|
var found = false;
|
||||||
|
for (var idx in $scope.members) {
|
||||||
|
var member = $scope.members[idx];
|
||||||
|
if (member.uuid == uuid) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found) {
|
||||||
|
return idx;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function translateMember(member) {
|
||||||
|
return {
|
||||||
|
'uuid': member[0],
|
||||||
|
'id': member[1][0],
|
||||||
|
'number': member[1][1],
|
||||||
|
'name': member[1][2],
|
||||||
|
'codec': member[1][3],
|
||||||
|
'status': JSON.parse(member[1][4]),
|
||||||
|
'email': member[1][5].email
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMember(member) {
|
||||||
|
$scope.members.push(translateMember(member));
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$on('members.boot', function(event, members) {
|
||||||
|
console.log('members.boot', event, members);
|
||||||
|
$scope.$apply(function() {
|
||||||
|
clearConferenceChat();
|
||||||
|
for (var idx in members) {
|
||||||
|
var member = members[idx];
|
||||||
|
addMember(member);
|
||||||
|
console.log($scope.members);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('members.add', function(event, member) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
addMember(member);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('members.del', function(event, uuid) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
var memberIdx = findMemberByUUID(uuid);
|
||||||
|
if (memberIdx != -1) {
|
||||||
|
// Removing the member.
|
||||||
|
$scope.members.splice(memberIdx, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('members.update', function(event, member) {
|
||||||
|
member = translateMember(member);
|
||||||
|
var memberIdx = findMemberByUUID(member.uuid);
|
||||||
|
if (memberIdx < 0) {
|
||||||
|
console.log('Didn\'t find the member uuid ' + member.uuid);
|
||||||
|
} else {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
console.log('Updating', memberIdx, ' <', $scope.members[memberIdx],
|
||||||
|
'> with <', member, '>');
|
||||||
|
angular.extend($scope.members[memberIdx], member);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('members.clear', function(event) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
clearConferenceChat();
|
||||||
|
$scope.closeChat();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public methods.
|
||||||
|
*/
|
||||||
|
$scope.send = function() {
|
||||||
|
verto.sendMessage($scope.message, function() {
|
||||||
|
$scope.message = CLEAN_MESSAGE;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Participants moderation.
|
||||||
|
$scope.confKick = function(memberID) {
|
||||||
|
console.log('$scope.confKick');
|
||||||
|
verto.data.conf.kick(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confMuteMic = function(memberID) {
|
||||||
|
console.log('$scope.confMuteMic');
|
||||||
|
verto.data.conf.muteMic(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confMuteVideo = function(memberID) {
|
||||||
|
console.log('$scope.confMuteVideo');
|
||||||
|
verto.data.conf.muteVideo(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confPresenter = function(memberID) {
|
||||||
|
console.log('$scope.confPresenter');
|
||||||
|
verto.data.conf.presenter(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confVideoFloor = function(memberID) {
|
||||||
|
console.log('$scope.confVideoFloor');
|
||||||
|
verto.data.conf.videoFloor(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confBanner = function(memberID) {
|
||||||
|
console.log('$scope.confBanner');
|
||||||
|
var text = 'New Banner';
|
||||||
|
verto.data.conf.banner(memberID, text);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confVolumeDown = function(memberID) {
|
||||||
|
console.log('$scope.confVolumeDown');
|
||||||
|
verto.data.conf.volumeDown(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confVolumeUp = function(memberID) {
|
||||||
|
console.log('$scope.confVolumeUp');
|
||||||
|
verto.data.conf.volumeUp(memberID);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.confTransfer = function(memberID) {
|
||||||
|
console.log('$scope.confTransfer');
|
||||||
|
var exten = '1800';
|
||||||
|
verto.data.conf.transfer(memberID, exten);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,32 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('ContributorsController', ['$scope', '$http',
|
||||||
|
'toastr',
|
||||||
|
function($scope, $http, toastr) {
|
||||||
|
$http.get(window.location.pathname + '/contributors.txt')
|
||||||
|
.success(function(data) {
|
||||||
|
|
||||||
|
var contributors = [];
|
||||||
|
|
||||||
|
angular.forEach(data, function(value, key) {
|
||||||
|
var re = /(.*) <(.*)>/;
|
||||||
|
var name = value.replace(re, "$1");
|
||||||
|
var email = value.replace(re, "$2");
|
||||||
|
|
||||||
|
this.push({
|
||||||
|
'name': name,
|
||||||
|
'email': email
|
||||||
|
});
|
||||||
|
}, contributors);
|
||||||
|
|
||||||
|
$scope.contributors = contributors;
|
||||||
|
})
|
||||||
|
.error(function() {
|
||||||
|
toastr.error('contributors not found.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
})();
|
|
@ -0,0 +1,75 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('DialPadController', ['$rootScope', '$scope',
|
||||||
|
'$http', '$location', 'toastr', 'verto', 'storage',
|
||||||
|
function($rootScope, $scope, $http, $location, toastr, verto, storage) {
|
||||||
|
console.debug('Executing DialPadController.');
|
||||||
|
|
||||||
|
$scope.checkBrowser();
|
||||||
|
storage.data.videoCall = false;
|
||||||
|
storage.data.userStatus = 'connecting';
|
||||||
|
storage.data.calling = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fill dialpad via querystring [?autocall=\d+]
|
||||||
|
*/
|
||||||
|
if ($location.search().autocall) {
|
||||||
|
$rootScope.dialpadNumber = $location.search().autocall;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used to bind click on number in call history to fill dialpad
|
||||||
|
* 'cause inside a ng-repeat the angular isnt in ctrl scope
|
||||||
|
*/
|
||||||
|
$scope.fillDialpadNumber = function(number) {
|
||||||
|
$rootScope.dialpadNumber = number;
|
||||||
|
};
|
||||||
|
|
||||||
|
$rootScope.transfer = function() {
|
||||||
|
if (!$rootScope.dialpadNumber) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
verto.data.call.transfer($rootScope.dialpadNumber);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call to the number in the $rootScope.dialpadNumber.
|
||||||
|
*/
|
||||||
|
$rootScope.call = function(extension) {
|
||||||
|
storage.data.onHold = false;
|
||||||
|
storage.data.cur_call = 0;
|
||||||
|
$rootScope.dialpadNumber = extension;
|
||||||
|
if (!$rootScope.dialpadNumber && storage.data.called_number) {
|
||||||
|
$rootScope.dialpadNumber = storage.data.called_number;
|
||||||
|
return false;
|
||||||
|
} else if (!$rootScope.dialpadNumber && !storage.data.called_number) {
|
||||||
|
toastr.warning('Enter an extension, please.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verto.data.call) {
|
||||||
|
console.debug('A call is already in progress.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
storage.data.mutedVideo = false;
|
||||||
|
storage.data.mutedMic = false;
|
||||||
|
|
||||||
|
storage.data.videoCall = false;
|
||||||
|
verto.call($rootScope.dialpadNumber);
|
||||||
|
|
||||||
|
storage.data.called_number = $rootScope.dialpadNumber;
|
||||||
|
storage.data.call_history.unshift({
|
||||||
|
'number': $rootScope.dialpadNumber,
|
||||||
|
'direction': 'outbound',
|
||||||
|
'call_start': Date()
|
||||||
|
});
|
||||||
|
$location.path('/incall');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,81 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('InCallController', ['$rootScope', '$scope',
|
||||||
|
'$http', '$location', '$modal', '$timeout', 'toastr', 'verto', 'storage', 'prompt', 'Fullscreen',
|
||||||
|
function($rootScope, $scope, $http, $location, $modal, $timeout, toatr,
|
||||||
|
verto, storage, prompt, Fullscreen) {
|
||||||
|
|
||||||
|
console.debug('Executing InCallController.');
|
||||||
|
$scope.layout = null;
|
||||||
|
$scope.checkBrowser();
|
||||||
|
$rootScope.dialpadNumber = '';
|
||||||
|
$scope.callTemplate = 'partials/phone_call.html';
|
||||||
|
$scope.dialpadTemplate = '';
|
||||||
|
$scope.incall = true;
|
||||||
|
|
||||||
|
|
||||||
|
if (storage.data.videoCall) {
|
||||||
|
$scope.callTemplate = 'partials/video_call.html';
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$on('call.video', function(event, data) {
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.callTemplate = 'partials/video_call.html';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* toggle dialpad in incall page
|
||||||
|
*/
|
||||||
|
$scope.toggleDialpad = function() {
|
||||||
|
$scope.openModal('partials/dialpad_widget.html',
|
||||||
|
'ModalDialpadController');
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(!$scope.dialpadTemplate) {
|
||||||
|
$scope.dialpadTemplate = 'partials/dialpad_widget.html';
|
||||||
|
} else {
|
||||||
|
$scope.dialpadTemplate = '';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: useless?
|
||||||
|
*/
|
||||||
|
$scope.videoCall = function() {
|
||||||
|
prompt({
|
||||||
|
title: 'Would you like to activate video for this call?',
|
||||||
|
message: 'Video will be active during the next calls.'
|
||||||
|
}).then(function() {
|
||||||
|
storage.data.videoCall = true;
|
||||||
|
$scope.callTemplate = 'partials/video_call.html';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cbMuteVideo = function(event, data) {
|
||||||
|
storage.data.mutedVideo = !storage.data.mutedVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.cbMuteMic = function(event, data) {
|
||||||
|
storage.data.mutedMic = !storage.data.mutedMic;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.confChangeVideoLayout = function(layout) {
|
||||||
|
verto.data.conf.setVideoLayout(layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.muteMic = verto.muteMic;
|
||||||
|
$scope.muteVideo = verto.muteVideo;
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
console.log('broadcast time-start incall');
|
||||||
|
$scope.$broadcast('timer-start');
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
})();
|
|
@ -0,0 +1,25 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('LoginController', ['$scope', '$http', '$location',
|
||||||
|
'verto',
|
||||||
|
function($scope, $http, $location, verto) {
|
||||||
|
$scope.checkBrowser();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* using stored data (localStorage) for logon
|
||||||
|
*/
|
||||||
|
verto.data.name = $scope.storage.data.name;
|
||||||
|
verto.data.email = $scope.storage.data.email;
|
||||||
|
if ($scope.storage.data.login != '' && $scope.storage.data.password != '') {
|
||||||
|
verto.data.login = $scope.storage.data.login;
|
||||||
|
verto.data.password = $scope.storage.data.password;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug('Executing LoginController.');
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,445 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('MainController',
|
||||||
|
function($scope, $rootScope, $location, $modal, $timeout, verto, storage, toastr, Fullscreen, prompt) {
|
||||||
|
|
||||||
|
console.debug('Executing MainController.');
|
||||||
|
|
||||||
|
var myVideo = document.getElementById("webcam");
|
||||||
|
$scope.verto = verto;
|
||||||
|
$scope.storage = storage;
|
||||||
|
$scope.call_history = angular.element("#call_history").hasClass('active');
|
||||||
|
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (explanation) scope in another controller extends rootScope (singleton)
|
||||||
|
*/
|
||||||
|
$rootScope.chat_counter = 0;
|
||||||
|
$rootScope.activePane = 'members';
|
||||||
|
/**
|
||||||
|
* The number that will be called.
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
$rootScope.dialpadNumber = '';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if user data saved, use stored data for logon
|
||||||
|
*/
|
||||||
|
if (storage.data.ui_connected && storage.data.ws_connected) {
|
||||||
|
$scope.verto.data.name = storage.data.name;
|
||||||
|
$scope.verto.data.email = storage.data.email;
|
||||||
|
$scope.verto.data.login = storage.data.login;
|
||||||
|
$scope.verto.data.password = storage.data.password;
|
||||||
|
|
||||||
|
verto.connect(function(v, connected) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
if (connected) {
|
||||||
|
toastr.success('Nice to see you again.', 'Welcome back');
|
||||||
|
$location.path('/dialpad');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If verto is not connected, redirects to login page.
|
||||||
|
if (!verto.data.connected) {
|
||||||
|
console.debug('MainController: WebSocket not connected. Redirecting to login.');
|
||||||
|
$location.path('/login');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login the user to verto server and
|
||||||
|
* redirects him to dialpad page.
|
||||||
|
*/
|
||||||
|
$scope.login = function() {
|
||||||
|
var connectCallback = function(v, connected) {
|
||||||
|
$scope.$apply(function() {
|
||||||
|
if (connected) {
|
||||||
|
storage.data.ui_connected = verto.data.connected;
|
||||||
|
storage.data.ws_connected = verto.data.connected;
|
||||||
|
storage.data.name = verto.data.name;
|
||||||
|
storage.data.email = verto.data.email;
|
||||||
|
storage.data.login = verto.data.login;
|
||||||
|
storage.data.password = verto.data.password;
|
||||||
|
|
||||||
|
console.debug('Redirecting to dialpad page.');
|
||||||
|
storage.changeData(verto);
|
||||||
|
toastr.success('Login successful.', 'Welcome');
|
||||||
|
$location.path('/dialpad');
|
||||||
|
} else {
|
||||||
|
toastr.error('There was an error while trying to login. Please try again.', 'Error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
verto.connect(connectCallback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logout the user from verto server and
|
||||||
|
* redirects him to login page.
|
||||||
|
*/
|
||||||
|
$scope.logout = function() {
|
||||||
|
var disconnect = function() {
|
||||||
|
var disconnectCallback = function(v, connected) {
|
||||||
|
console.debug('Redirecting to login page.');
|
||||||
|
storage.reset();
|
||||||
|
$location.path('/login');
|
||||||
|
};
|
||||||
|
|
||||||
|
if (verto.data.call) {
|
||||||
|
verto.hangup();
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.closeChat();
|
||||||
|
verto.disconnect(disconnectCallback);
|
||||||
|
|
||||||
|
verto.hangup();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (verto.data.call) {
|
||||||
|
prompt({
|
||||||
|
title: 'Oops, Active Call in Course.',
|
||||||
|
message: 'It seems that you are in a call. Do you want to hang up?'
|
||||||
|
}).then(function() {
|
||||||
|
disconnect();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a modal with the settings.
|
||||||
|
*/
|
||||||
|
$scope.openModalSettings = function() {
|
||||||
|
var modalInstance = $modal.open({
|
||||||
|
animation: $scope.animationsEnabled,
|
||||||
|
templateUrl: 'partials/modal_settings.html',
|
||||||
|
controller: 'ModalSettingsController',
|
||||||
|
});
|
||||||
|
|
||||||
|
modalInstance.result.then(
|
||||||
|
function(result) {
|
||||||
|
console.log(result);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
console.info('Modal dismissed at: ' + new Date());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
modalInstance.rendered.then(
|
||||||
|
function() {
|
||||||
|
jQuery.material.init();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.openModal = function(templateUrl, controller) {
|
||||||
|
var modalInstance = $modal.open({
|
||||||
|
animation: $scope.animationsEnabled,
|
||||||
|
templateUrl: templateUrl,
|
||||||
|
controller: controller,
|
||||||
|
});
|
||||||
|
|
||||||
|
modalInstance.result.then(
|
||||||
|
function(result) {
|
||||||
|
console.log(result);
|
||||||
|
},
|
||||||
|
function() {
|
||||||
|
console.info('Modal dismissed at: ' + new Date());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
modalInstance.rendered.then(
|
||||||
|
function() {
|
||||||
|
jQuery.material.init();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.showContributors = function() {
|
||||||
|
$scope.openModal('partials/contributors.html', 'ContributorsController');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the display adding the new number touched.
|
||||||
|
*
|
||||||
|
* @param {String} number - New touched number.
|
||||||
|
*/
|
||||||
|
$rootScope.dtmf = function(number) {
|
||||||
|
$rootScope.dialpadNumber = $scope.dialpadNumber + number;
|
||||||
|
if (verto.data.call) {
|
||||||
|
verto.dtmf(number);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the last character from the number.
|
||||||
|
*/
|
||||||
|
$rootScope.backspace = function() {
|
||||||
|
var number = $rootScope.dialpadNumber;
|
||||||
|
var len = number.length;
|
||||||
|
$rootScope.dialpadNumber = number.substring(0, len - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
$scope.toggleCallHistory = function() {
|
||||||
|
if (!$scope.call_history) {
|
||||||
|
angular.element("#call_history").addClass('active');
|
||||||
|
angular.element("#call-history-wrapper").addClass('active');
|
||||||
|
} else {
|
||||||
|
angular.element("#call_history").removeClass('active');
|
||||||
|
angular.element("#call-history-wrapper").removeClass('active');
|
||||||
|
}
|
||||||
|
$scope.call_history = angular.element("#call_history").hasClass('active');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.clearCallHistory = function() {
|
||||||
|
storage.data.call_history = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.toggleChat = function() {
|
||||||
|
if ($scope.chatStatus && $rootScope.activePane === 'chat') {
|
||||||
|
$rootScope.chat_counter = 0;
|
||||||
|
}
|
||||||
|
angular.element('#wrapper').toggleClass('toggled');
|
||||||
|
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.openChat = function() {
|
||||||
|
$scope.chatStatus = false;
|
||||||
|
angular.element('#wrapper').removeClass('toggled');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.closeChat = function() {
|
||||||
|
$scope.chatStatus = true;
|
||||||
|
angular.element('#wrapper').addClass('toggled');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.goFullscreen = function() {
|
||||||
|
if (storage.data.userStatus !== 'connected') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$rootScope.fullscreenEnabled = !Fullscreen.isEnabled();
|
||||||
|
if (Fullscreen.isEnabled()) {
|
||||||
|
Fullscreen.cancel();
|
||||||
|
} else {
|
||||||
|
Fullscreen.enable(document.getElementsByTagName('body')[0]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$rootScope.$on('call.video', function(event) {
|
||||||
|
storage.data.videoCall = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('call.hangup', function(event, data) {
|
||||||
|
if (Fullscreen.isEnabled()) {
|
||||||
|
Fullscreen.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
console.log($scope.chatStatus);
|
||||||
|
if (!$scope.chatStatus) {
|
||||||
|
angular.element('#wrapper').toggleClass('toggled');
|
||||||
|
$scope.chatStatus = angular.element('#wrapper').hasClass('toggled');
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.dialpadNumber = '';
|
||||||
|
console.debug('Redirecting to dialpad page.');
|
||||||
|
$location.path('/dialpad');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$rootScope.$digest();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('not digest');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('page.incall', function(event, data) {
|
||||||
|
if (storage.data.askRecoverCall) {
|
||||||
|
prompt({
|
||||||
|
title: 'Oops, Active Call in Course.',
|
||||||
|
message: 'It seems you were in a call before leaving the last time. Wanna go back to that?'
|
||||||
|
}).then(function() {
|
||||||
|
verto.changeData(storage);
|
||||||
|
console.log('redirect to incall page');
|
||||||
|
$location.path('/incall');
|
||||||
|
}, function() {
|
||||||
|
storage.data.userStatus = 'connecting';
|
||||||
|
verto.hangup();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
verto.changeData(storage);
|
||||||
|
console.log('redirect to incall page');
|
||||||
|
$location.path('/incall');
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.callActive = function(data) {
|
||||||
|
verto.data.mutedMic = storage.data.mutedMic;
|
||||||
|
verto.data.mutedVideo = storage.data.mutedVideo;
|
||||||
|
|
||||||
|
if (!storage.data.cur_call) {
|
||||||
|
storage.data.call_start = new Date();
|
||||||
|
}
|
||||||
|
storage.data.userStatus = 'connected';
|
||||||
|
var call_start = new Date(storage.data.call_start);
|
||||||
|
$rootScope.start_time = call_start;
|
||||||
|
|
||||||
|
$timeout(function() {
|
||||||
|
$scope.$broadcast('timer-start');
|
||||||
|
});
|
||||||
|
myVideo.play();
|
||||||
|
storage.data.calling = false;
|
||||||
|
|
||||||
|
storage.data.cur_call = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
$rootScope.$on('call.active', function(event, data) {
|
||||||
|
$rootScope.callActive(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('call.calling', function(event, data) {
|
||||||
|
storage.data.calling = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$rootScope.$on('call.incoming', function(event, data) {
|
||||||
|
console.log('Incoming call from: ' + data);
|
||||||
|
|
||||||
|
storage.data.cur_call = 0;
|
||||||
|
$scope.incomingCall = true;
|
||||||
|
storage.data.videoCall = false;
|
||||||
|
storage.data.mutedVideo = false;
|
||||||
|
storage.data.mutedMic = false;
|
||||||
|
|
||||||
|
prompt({
|
||||||
|
title: 'Incoming Call',
|
||||||
|
message: 'from ' + data
|
||||||
|
}).then(function() {
|
||||||
|
var call_start = new Date(storage.data.call_start);
|
||||||
|
$rootScope.start_time = call_start;
|
||||||
|
console.log($rootScope.start_time);
|
||||||
|
|
||||||
|
$scope.answerCall();
|
||||||
|
storage.data.called_number = data;
|
||||||
|
|
||||||
|
storage.data.call_history.unshift({
|
||||||
|
'number': data,
|
||||||
|
'direction': 'inbound',
|
||||||
|
'status': true,
|
||||||
|
'call_start': Date()
|
||||||
|
});
|
||||||
|
$location.path('/incall');
|
||||||
|
}, function() {
|
||||||
|
$scope.declineCall();
|
||||||
|
storage.data.call_history.unshift({
|
||||||
|
'number': data,
|
||||||
|
'direction': 'inbound',
|
||||||
|
'status': false,
|
||||||
|
'call_start': Date()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.hold = function() {
|
||||||
|
storage.data.onHold = !storage.data.onHold;
|
||||||
|
verto.data.call.toggleHold();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hangup the current call.
|
||||||
|
*/
|
||||||
|
$scope.hangup = function() {
|
||||||
|
if (!verto.data.call) {
|
||||||
|
toastr.warning('There is no call to hangup.');
|
||||||
|
$location.path('/dialpad');
|
||||||
|
}
|
||||||
|
|
||||||
|
//var hangupCallback = function(v, hangup) {
|
||||||
|
// if (hangup) {
|
||||||
|
// $location.path('/dialpad');
|
||||||
|
// } else {
|
||||||
|
// console.debug('The call could not be hangup.');
|
||||||
|
// }
|
||||||
|
//};
|
||||||
|
//
|
||||||
|
//verto.hangup(hangupCallback);
|
||||||
|
|
||||||
|
verto.hangup();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.answerCall = function() {
|
||||||
|
storage.data.onHold = false;
|
||||||
|
|
||||||
|
verto.data.call.answer({
|
||||||
|
useStereo: verto.data.useStereo,
|
||||||
|
useCamera: verto.data.useCamera,
|
||||||
|
useMic: verto.data.useMic,
|
||||||
|
callee_id_name: verto.data.name,
|
||||||
|
callee_id_number: verto.data.login
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$location.path('/incall');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.declineCall = function() {
|
||||||
|
$scope.hangup();
|
||||||
|
$scope.incomingCall = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.screenshare = function() {
|
||||||
|
if (verto.data.shareCall) {
|
||||||
|
verto.screenshareHangup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
verto.screenshare(storage.data.called_number);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.play = function() {
|
||||||
|
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
||||||
|
function(file) {
|
||||||
|
verto.data.conf.play(file);
|
||||||
|
console.log('play file :', file);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.stop = function() {
|
||||||
|
verto.data.conf.stop();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.record = function() {
|
||||||
|
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
||||||
|
function(file) {
|
||||||
|
verto.data.conf.record(file);
|
||||||
|
console.log('recording file :', file);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.stopRecord = function() {
|
||||||
|
verto.data.conf.stopRecord();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.snapshot = function() {
|
||||||
|
var file = $scope.promptInput('Please, enter filename', '', 'File',
|
||||||
|
function(file) {
|
||||||
|
verto.data.conf.snapshot(file);
|
||||||
|
console.log('snapshot file :', file);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,13 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('MenuController', ['$scope', '$http', '$location',
|
||||||
|
'verto', 'storage',
|
||||||
|
function($scope, $http, $location, verto, storage) {
|
||||||
|
console.debug('Executing MenuController.');
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,20 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('ModalDialpadController', ['$scope',
|
||||||
|
'$modalInstance',
|
||||||
|
function($scope, $modalInstance) {
|
||||||
|
|
||||||
|
$scope.ok = function() {
|
||||||
|
$modalInstance.close('Ok.');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function() {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
})();
|
|
@ -0,0 +1,25 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('ModalLoginInformationController', ['$scope',
|
||||||
|
'$http', '$location', '$modalInstance', 'verto', 'storage',
|
||||||
|
function($scope, $http, $location, $modalInstance, verto, storage) {
|
||||||
|
console.debug('Executing ModalLoginInformationController.');
|
||||||
|
|
||||||
|
$scope.verto = verto;
|
||||||
|
$scope.storage = storage;
|
||||||
|
|
||||||
|
$scope.ok = function() {
|
||||||
|
$modalInstance.close('Ok.');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function() {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,30 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoControllers')
|
||||||
|
.controller('ModalSettingsController', ['$scope', '$http',
|
||||||
|
'$location', '$modalInstance', 'verto', 'storage',
|
||||||
|
function($scope, $http, $location, $modalInstance, verto, storage) {
|
||||||
|
console.debug('Executing ModalSettingsController.');
|
||||||
|
|
||||||
|
verto.changeData(storage);
|
||||||
|
$scope.verto = verto;
|
||||||
|
$scope.storage = storage;
|
||||||
|
|
||||||
|
$scope.ok = function() {
|
||||||
|
storage.changeData(verto);
|
||||||
|
$modalInstance.close('Ok.');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.cancel = function() {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.refreshDeviceList = function() {
|
||||||
|
return verto.refreshDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,11 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var vertoControllers = angular.module('vertoControllers', [
|
||||||
|
'ui.bootstrap',
|
||||||
|
'vertoService',
|
||||||
|
'storageService',
|
||||||
|
'ui.gravatar'
|
||||||
|
]);
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
Sometimes autofocus HTML5 directive just isn't enough with SPAs.
|
||||||
|
This directive will force autofocus to work properly under those circumstances.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoDirectives')
|
||||||
|
.directive('autofocus', ['$timeout',
|
||||||
|
function ($timeout) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function ($scope, $element) {
|
||||||
|
$timeout(function () {
|
||||||
|
$element[0].focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
})();
|
|
@ -0,0 +1,37 @@
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoDirectives')
|
||||||
|
.directive('showControls',
|
||||||
|
function(Fullscreen) {
|
||||||
|
var link = function(scope, element, attrs) {
|
||||||
|
var i = null;
|
||||||
|
jQuery('.video-footer').fadeIn('slow');
|
||||||
|
jQuery('.video-hover-buttons').fadeIn('slow');
|
||||||
|
element.parent().bind('mousemove', function() {
|
||||||
|
if (Fullscreen.isEnabled()) {
|
||||||
|
clearTimeout(i);
|
||||||
|
jQuery('.video-footer').fadeIn('slow');
|
||||||
|
jQuery('.video-hover-buttons').fadeIn(500);
|
||||||
|
i = setTimeout(function() {
|
||||||
|
if (Fullscreen.isEnabled()) {
|
||||||
|
jQuery('.video-footer').fadeOut('slow');
|
||||||
|
jQuery('.video-hover-buttons').fadeOut(500);
|
||||||
|
}
|
||||||
|
}, 3000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
element.parent().bind('mouseleave', function() {
|
||||||
|
jQuery('.video-footer').fadeIn();
|
||||||
|
jQuery('.video-hover-buttons').fadeIn();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,27 @@
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoDirectives').directive('userStatus',
|
||||||
|
function() {
|
||||||
|
var link = function(scope, element, attrs) {
|
||||||
|
scope.$watch('condition', function(condition) {
|
||||||
|
element.removeClass('connected');
|
||||||
|
element.removeClass('disconnected');
|
||||||
|
element.removeClass('connecting');
|
||||||
|
|
||||||
|
element.addClass(condition);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
scope: {
|
||||||
|
'condition': '='
|
||||||
|
},
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* To RTC work properly we need to give a <video> tag as soon as possible
|
||||||
|
* because it needs to attach the video and audio stream to the tag.
|
||||||
|
*
|
||||||
|
* This directive is responsible for moving the video tag from the body to
|
||||||
|
* the right place when a call start and move back to the body when the
|
||||||
|
* call ends. It also hides and display the tag when its convenient.
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
angular
|
||||||
|
.module('vertoDirectives')
|
||||||
|
.directive('videoTag',
|
||||||
|
function() {
|
||||||
|
function link(scope, element, attrs) {
|
||||||
|
// Moving the video tag to the new place inside the incall page.
|
||||||
|
console.log('Moving the video to element.');
|
||||||
|
jQuery('video').removeClass('hide').appendTo(element);
|
||||||
|
jQuery('video').css('display', 'block');
|
||||||
|
scope.callActive();
|
||||||
|
|
||||||
|
element.on('$destroy', function() {
|
||||||
|
// Move the video back to the body.
|
||||||
|
console.log('Moving the video back to body.');
|
||||||
|
jQuery('video').addClass('hide').appendTo(jQuery('body'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
link: link
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
|
@ -0,0 +1,4 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var vertoDirectives = angular.module('vertoDirectives', []);
|
||||||
|
})();
|
|
@ -170,10 +170,6 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
|
||||||
$rootScope.$emit('call.incoming', number);
|
$rootScope.$emit('call.incoming', number);
|
||||||
}
|
}
|
||||||
|
|
||||||
function recoveringCall() {
|
|
||||||
$rootScope.$emit('call.recovering');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getVideoParams() {
|
function getVideoParams() {
|
||||||
var maxWidth, maxHeight;
|
var maxWidth, maxHeight;
|
||||||
|
|
||||||
|
@ -348,7 +344,7 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
|
||||||
|
|
||||||
videoQuality.length = videoQuality.length - removed;
|
videoQuality.length = videoQuality.length - removed;
|
||||||
this.videoQuality = videoQuality;
|
this.videoQuality = videoQuality;
|
||||||
this.data.vidQual = videoQuality[videoQuality.length - 1].id;
|
this.data.vidQual = (videoQuality.length > 0) ? videoQuality[videoQuality.length - 1].id : null;
|
||||||
|
|
||||||
return videoQuality;
|
return videoQuality;
|
||||||
},
|
},
|
||||||
|
@ -504,10 +500,6 @@ vertoService.service('verto', ['$rootScope', '$cookieStore', '$location', 'stora
|
||||||
data.callState = 'active';
|
data.callState = 'active';
|
||||||
calling();
|
calling();
|
||||||
break;
|
break;
|
||||||
case "recovering":
|
|
||||||
console.debug('We are recovering a call!');
|
|
||||||
recoveringCall();
|
|
||||||
break;
|
|
||||||
case "active":
|
case "active":
|
||||||
console.debug('Talking to:', d.cidString());
|
console.debug('Talking to:', d.cidString());
|
||||||
data.callState = 'active';
|
data.callState = 'active';
|
|
@ -0,0 +1,4 @@
|
||||||
|
(function() {
|
||||||
|
'use strict';
|
||||||
|
var vertoService = angular.module('vertoService', []);
|
||||||
|
})();
|