Example #1
0
			templateDevice.find('.action-device').on('click', function() {
				if(monster.ui.valid(templateDevice.find('#device_form'))) {
					var formData = monster.ui.getFormData('device_form'),
						dataDevice = {
							device_type: 'sip_device',
							enabled: true,
							mac_address: formData.mac_address,
							name: formData.name,
							provision: {
								endpoint_brand: selectedBrand,
								endpoint_family: selectedFamily,
								endpoint_model: selectedModel
							},
							sip: {
								password: monster.util.randomString(12),
								realm: monster.apps.auth.currentAccount.realm,
								username: '******' + monster.util.randomString(10)
							},
							suppress_unregister_notifications: false
						},
						callbackAfterSave = function() {
							popup.dialog('close').remove();
						};
						popup.dialog('close').remove();
					callback && callback(dataDevice, callbackAfterSave);
				}
			});
Example #2
0
		groupsCreationMergeData: function(data, template) {
			var formData = form2object('form_group_creation'),
				fixedTimeout = '20',
				fixedDelay = '0',
				settings = {
					timeout: fixedTimeout,
					delay: fixedDelay,
					endpoint_type: 'user'
				},
				listUserRingGroup = [],
				listUserGroup = {};

			template.find('.selected-users li').each(function() {
				var userId = $(this).data('user_id'),
					ringGroupUser = $.extend(true, {}, settings, { id: userId });

				listUserGroup[userId] = { type: 'user' };
				listUserRingGroup.push(ringGroupUser);
			});

			var formattedData = {
				group: {
					name: formData.name,
					endpoints: listUserGroup
				},
				baseCallflow: {
					numbers: [ monster.util.randomString(25) ],
					name: formData.name + ' Base Group',
					flow: {
						module: 'ring_group',
						children: {},
						data: {
							strategy: 'simultaneous',
							timeout: parseInt(fixedTimeout) + parseInt(fixedDelay),
							endpoints: listUserRingGroup
						}
					},
					type: 'baseGroup'
				},
				callflow: {
					numbers: [ formData.extra.extension ],
					name: formData.name + ' Ring Group',
					flow: {
						module: 'callflow',
						children: {},
						data: {
							id: ''
						}
					},
					type: 'userGroup'
				}
			};

			return formattedData;
		},
Example #3
0
			function(err, results){
				var parent = args.parent || $('#monster-content'),
					target = args.target || parent.find('#pbxs_manager_view'),
					_callbacks = args.callbacks || {},
					callbacks = {
						saveSuccess: _callbacks.saveSuccess || function(_data) {
							var savedId = (args.id === 0 || args.id) ? args.id : _data.data.servers.length-1;

							self.renderList(savedId, parent, function() {
								self.renderPbxsManager(_data, $.extend(true, defaults, _data.data.servers[savedId]), target, callbacks);
							}, _data.data.servers);
						},

						saveError: _callbacks.saveError,

						deleteSuccess: _callbacks.deleteSuccess || function() {
							target.empty();

							 self.renderList();
						},

						cancelSuccess: _callbacks.cancelSuccess || function() {
							monster.pub('pbxsManager.edit', {
								id: args.id,
								parent: parent,
								target: target,
								callbacks: callbacks
							});
						},

						deleteError: _callbacks.deleteError,

						afterRender: _callbacks.afterRender
					},
					defaults = $.extend(true, {
						auth: {
							auth_user: '******' + monster.util.randomString(8),
							auth_password: monster.util.randomString(12),
							auth_method: 'IP'
						},
						options: {
							e911_info: {}
						},
						cfg: {
							register_time: '360',
							opening_pings: true,
							caller_id_header: 'p-asserted',
							supported_codecs: 'g722',
							signaling_type: 'rfc_2833',
							allow_refer: true,
							use_t38: true
						},
						extra: {
							support_email: monster.config.support_email || '*****@*****.**',
							pbx_help_link: monster.config.pbx_help_link || 'https://2600hz.atlassian.net/wiki/display/docs/Trunking.io',
							pbx_help_configuration_link: monster.config.pbx_help_configuration_link || 'https://2600hz.atlassian.net/wiki/display/docs/Trunking_config.io',
							configure: 'manually',
							realm: results.realm,
							id: args.id || (args.id === 0 ? 0 : 'new')
						}
					}, args.data_defaults || {});

				if(results.account.data.servers) {
					$.each(results.account.data.servers, function(k, server) {
						$.each(server.DIDs, function(did, v) {
							if(did in results.numbers.data.numbers) {
								var num = results.numbers.data.numbers[did];
								results.account.data.servers[k].DIDs[did].features = num.features;
								if('locality' in num) {
									results.account.data.servers[k].DIDs[did].isoCountry = num.locality.country || '';
								}
							}
						});
					});
				}

				if(typeof args === 'object' && (args.id || args.id === 0)) {
					self.renderPbxsManager(results.account, $.extend(true, defaults, results.account.data.servers[args.id]), target, callbacks);
				}
				else {
					self.renderEndpoint(results.accounts, defaults, target, callbacks, parent);
				}
			});
Example #4
0
		devicesFormatData: function(data) {
			var self = this,
				codecsAudioI18n = self.i18n.active().devices.popupSettings.audio.codecs,
				codecsVideoI18n = self.i18n.active().devices.popupSettings.video.codecs,
				defaults = {
					extra: {
						hasE911Numbers: data.e911Numbers.length > 0,
						e911Numbers: data.e911Numbers,
						restrictions: data.listClassifiers,
						rtpMethod: data.device.media && data.device.media.encryption && data.device.media.encryption.enforce_security ? data.device.media.encryption.methods[0] : '',
						selectedCodecs: {
							audio: [],
							video: []
						},
						availableCodecs: {
							audio: [],
							video: []
						},
						listCodecs: {
							audio: {
								'OPUS': codecsAudioI18n['OPUS'],
								'CELT@32000h': codecsAudioI18n['CELT@32000h'],
								'G7221@32000h': codecsAudioI18n['G7221@32000h'],
								'G7221@16000h': codecsAudioI18n['G7221@16000h'],
								'G722': codecsAudioI18n['G722'],
								'speex@32000h':codecsAudioI18n['speex@32000h'],
								'speex@16000h': codecsAudioI18n['speex@16000h'],
								'speex': codecsAudioI18n['speex'],
								'PCMU': codecsAudioI18n['PCMU'],
								'PCMA': codecsAudioI18n['PCMA'],
								'G729':codecsAudioI18n['G729'],
								'GSM': codecsAudioI18n['GSM'],
								'CELT@48000h': codecsAudioI18n['CELT@48000h'],
								'CELT@64000h': codecsAudioI18n['CELT@64000h']
							},
							video: {
								'VP8': codecsVideoI18n['VP8'],
								'H264': codecsVideoI18n['H264'],
								'H263': codecsVideoI18n['H263'],
								'H261': codecsVideoI18n['H261']
							}
						}
					},
					call_restriction: {},
					device_type: 'sip_device',
					enabled: true,
					media: {
						encryption: {
							enforce_security: false,
						},
						audio: {
							codecs: ['PCMU', 'PCMA']
						},
						video: {
							codecs: []
						}
					},
					suppress_unregister_notifications: false
				},
				typedDefaults = {
					sip_device: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					landline: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						}
					},
					cellphone: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						},
					},
					ata: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					fax: {
						media: {
							fax_option: 'false'
						},
						outbound_flags: ['fax'],
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					softphone: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					mobile: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					smartphone: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						},
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps['auth'].currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					sip_uri: {
						sip: {
							password: monster.util.randomString(12),
							username: '******' + monster.util.randomString(10),
							expire_seconds: 360,
							invite_format: 'route',
							method: 'password'
						}
					}
				};
			
			_.each(data.listClassifiers, function(restriction, name) {
				if(name in self.i18n.active().devices.classifiers) {
					defaults.extra.restrictions[name].friendly_name = self.i18n.active().devices.classifiers[name].name;

					if('help' in self.i18n.active().devices.classifiers[name]) {
						defaults.extra.restrictions[name].help = self.i18n.active().devices.classifiers[name].help;
					}
				}

				if('call_restriction' in data.accountLimits 
				&& name in data.accountLimits.call_restriction
				&& data.accountLimits.call_restriction[name].action === 'deny') {
					defaults.extra.restrictions[name].disabled = true;
					defaults.extra.hasDisabledRestrictions = true;
				}

				if('call_restriction' in data.device && name in data.device.call_restriction) {
					defaults.extra.restrictions[name].action = data.device.call_restriction[name].action;
				}
				else {
					defaults.extra.restrictions[name].action = 'inherit';
				}
			});

			var formattedData = $.extend(true, {}, typedDefaults[data.device.device_type], defaults, data.device);

			/* Audio Codecs*/
			/* extend doesn't replace the array so we need to do it manually */
			if(data.device.media && data.device.media.audio && data.device.media.audio.codecs) {
				var mapMigrateCodec = {
						'Speex': 'speex@16000h',
						'G722_16': 'G7221@16000h',
						'G722_32': 'G7221@32000h',
						'CELT_48': 'CELT@48000h',
						'CELT_64': 'CELT@64000h'
					},
					newCodecList = [];

				_.each(data.device.media.audio.codecs, function(codec) {
					mapMigrateCodec.hasOwnProperty(codec) ? newCodecList.push(mapMigrateCodec[codec]) : newCodecList.push(codec);
				});

				formattedData.media.audio.codecs = newCodecList;
			}

			_.each(formattedData.media.audio.codecs, function(codec) {
				formattedData.extra.selectedCodecs.audio.push({ codec: codec, description: defaults.extra.listCodecs.audio[codec] });
			});

			_.each(defaults.extra.listCodecs.audio, function(description, codec) {
				if(formattedData.media.audio.codecs.indexOf(codec) === -1) {
					formattedData.extra.availableCodecs.audio.push({ codec: codec, description: description });
				}
			});

			/* Video codecs */
			if(data.device.media && data.device.media.video && data.device.media.video.codecs) {
				formattedData.media.video.codecs = data.device.media.video.codecs;
			}

			_.each(formattedData.media.video.codecs, function(codec) {
				formattedData.extra.selectedCodecs.video.push({ codec: codec, description: defaults.extra.listCodecs.video[codec] });
			});

			_.each(defaults.extra.listCodecs.video, function(description, codec) {
				if(formattedData.media.video.codecs.indexOf(codec) === -1) {
					formattedData.extra.availableCodecs.video.push({ codec: codec, description: description });
				}
			});

			return formattedData;
		},
		deviceEdit: function(data, _parent, _target, _callbacks, data_defaults) {
			var self = this,
				parent = _parent || $('#device-content'),
				target = _target || $('#device-view', parent),
				_callbacks = _callbacks || {},
				callbacks = {
					save_success: _callbacks.save_success,
					save_error: _callbacks.save_error || function(_data, status, type) {
						if(status == 200 && type == 'mac_address') {
							monster.ui.alert(self.i18n.active().callflows.device.this_mac_address_is_already_in_use);
						}
					},
					delete_success: _callbacks.delete_success,
					delete_error: _callbacks.delete_error,
					after_render: _callbacks.after_render
				},
				defaults = {
					data: $.extend(true, {
						enabled: true,
						caller_id: {
							external: {},
							internal: {},
							emergency: {}
						},
						ringtones: {},
						call_restriction: { closed_groups: 'inherit' },
						media: {
							secure_rtp: 'none',
							peer_to_peer: 'auto',
							audio: {
								codecs: ['PCMU', 'PCMA']
							},
							video: {
								codecs: []
							},
							fax: {
								option: 'false'
							},
							fax_option: false
						},
						sip: {
							method: 'password',
							invite_format: 'username',
							username: '******' + monster.util.randomString(6),
							password: monster.util.randomString(12),
							expire_seconds: '360'
						},
						contact_list: {
							exclude: false
						},
						call_forward: {},
						music_on_hold: {}
					}, data_defaults || {}),

					field_data: {
						users: [],
						call_restriction: {},
						sip: {
							methods: {
								'password': self.i18n.active().callflows.device.password,
								'ip': 'IP'
							},
							invite_formats: {
								'username': '******',
								'npan': 'NPA NXX XXXX',
								'e164': 'E. 164'
							}
						},
						media: {
							secure_rtp: {
								value: 'none',
								options: {
									'none': self.i18n.active().callflows.device.none,
									'srtp': self.i18n.active().callflows.device.srtp,
									'zrtp': self.i18n.active().callflows.device.zrtp
								}
							},
							peer_to_peer_options: {
								'auto': self.i18n.active().callflows.device.automatic,
								'true': self.i18n.active().callflows.device.always,
								'false': self.i18n.active().callflows.device.never
							},
							fax: {
								options: {
									'auto': self.i18n.active().callflows.device.auto_detect,
									'true': self.i18n.active().callflows.device.always_force,
									'false': self.i18n.active().callflows.device.disabled
								}
							},
							audio: {
								codecs: {
									'OPUS': 'OPUS',
									'CELT@32000h': 'Siren @ 32Khz',
									'G7221@32000h': 'G722.1 @ 32khz',
									'G7221@16000h': 'G722.1 @ 16khz',
									'G722': 'G722',
									'speex@32000h': 'Speex @ 32khz',
									'speex@16000h': 'Speex @ 16khz',
									'PCMU': 'G711u / PCMU - 64kbps (North America)',
									'PCMA': 'G711a / PCMA - 64kbps (Elsewhere)',
									'G729':'G729 - 8kbps (Requires License)',
									'GSM':'GSM',
									'CELT@48000h': 'Siren (HD) @ 48kHz',
									'CELT@64000h': 'Siren (HD) @ 64kHz'
								}
							},
							video: {
								codecs: {
									'VP8': 'VP8',
									'H264': 'H264',
									'H263': 'H263',
									'H261': 'H261'
								}
							}
						},
						hide_owner: data.hide_owner || false,
						outbound_flags: data.outbound_flags ? data.outbound_flags.join(", ") : data.outbound_flags
					},
					functions: {
						inArray: function(value, array) {
							if(array) {
								return ($.inArray(value, array) == -1) ? false : true;
							}
							else return false;
						}
					}
				},
				parallelRequests = function (deviceData) {
					monster.parallel({
						list_classifier: function(callback){
							self.callApi({
								resource: 'numbers.listClassifiers',
								data: {
									accountId: self.accountId,
									filters: { paginate:false }
								},
								success: function(_data_classifiers) {
									if('data' in _data_classifiers) {
										$.each(_data_classifiers.data, function(k, v) {
											defaults.field_data.call_restriction[k] = {
												friendly_name: v.friendly_name
											};

											defaults.data.call_restriction[k] = { action: 'inherit' };
										});
									}
									callback(null, _data_classifiers);
								}
							});
						},
						account: function(callback){
							self.callApi({
								resource: 'account.get',
								data: {
									accountId: self.accountId
								},
								success: function(_data, status) {
									$.extend(defaults.field_data.sip, {
										realm: _data.data.realm,
									});

									callback(null, _data);
								}
							});
						},
						user_list: function(callback) {
							self.callApi({
								resource: 'user.list',
								data: {
									accountId: self.accountId,
									filters: { paginate:false }
								},
								success: function(_data, status) {
									_data.data.sort(function(a, b) {
										return (a.first_name + a.last_name).toLowerCase() < (b.first_name + b.last_name).toLowerCase() ? -1 : 1;
									});

									_data.data.unshift({
										id: '',
										first_name: '- No',
										last_name: 'owner -',
									});

									if (deviceData.hasOwnProperty('device_type') && deviceData.device_type === 'mobile') {
										var userData = _.find(_data.data, function(user, idx) { return user.id === deviceData.owner_id; });

										if (userData) {
											defaults.field_data.users = userData;
										}
										else {
											defaults.field_data.users = {
												first_name: '- No',
												last_name: 'owner -'
											};
										}
									}
									else {
										defaults.field_data.users = _data.data;
									}

									callback(null, _data);
								}
							});
						},
						media_list: function(callback) {
							self.callApi({
								resource: 'media.list',
								data: {
									accountId: self.accountId,
									filters: { paginate:false }
								},
								success: function(_data, status) {
									_data.data.unshift(
										{
											id: '',
											name: self.i18n.active().callflows.device.default_music
										},
										{
											id: 'silence_stream://300000',
											name: self.i18n.active().callflows.device.silence
										}
									);

									defaults.field_data.music_on_hold = _data.data;

									callback(null, _data);
								}
							});
						},
						provisionerData: function(callback) {
							if(monster.config.api.hasOwnProperty('provisioner') && monster.config.api.provisioner) {
								self.deviceGetDataProvisoner(function(data) {
									callback(null, data);
								});
							}
							else {
								callback(null, {});
							}
						}
					},
					function(err, results){
						var render_data = self.devicePrepareDataForTemplate(data, defaults, $.extend(true, results, {
								get_device: deviceData
							}));

						self.deviceRender(render_data, target, callbacks);

						if(typeof callbacks.after_render == 'function') {
							callbacks.after_render();
						}
					});
				};

			if(typeof data == 'object' && data.id) {
				self.deviceGet(data.id, function(_data, status) {
					defaults.data.device_type = 'sip_device';

					if('media' in _data && 'encryption' in _data.media) {
						defaults.field_data.media.secure_rtp.value = _data.media.encryption.enforce_security ? _data.media.encryption.methods[0] : 'none';
					}

					if('sip' in _data && 'realm' in _data.sip) {
						defaults.field_data.sip.realm = _data.sip.realm;
					}

					self.deviceMigrateData(_data);

					parallelRequests(_data);
				});
			}
			else {
				parallelRequests(defaults);
			}
		},
Example #6
0
		devicesFormatData: function(data, dataList) {
			var self = this,
				defaults = {
					extra: {
						hasE911Numbers: !_.isEmpty(data.e911Numbers),
						e911Numbers: data.e911Numbers,
						restrictions: data.listClassifiers,
						rtpMethod: data.device.media && data.device.media.encryption && data.device.media.encryption.enforce_security ? data.device.media.encryption.methods[0] : '',
						selectedCodecs: {
							audio: [],
							video: []
						},
						availableCodecs: {
							audio: [],
							video: []
						}
					},
					call_restriction: {},
					device_type: 'sip_device',
					enabled: true,
					media: {
						encryption: {
							enforce_security: false,
						},
						audio: {
							codecs: ['G722', 'PCMU', 'GSM'],
							tx_volume: "0",
							rx_volume: "0"
						},
						video: {
							codecs: []
						}
					},
					suppress_unregister_notifications: true
				},
				typedDefaults = {
					sip_device: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						}
					},
					landline: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						}
					},
					cellphone: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						},
					},
					ata: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						},
						codecs: ['PCMU']
					},
					fax: {
						media: {
							fax_option: 'false'
						},
						outbound_flags: ['fax'],
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						},
						codecs: ['PCMU']
					},
					softphone: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						},
						codecs: ['GSM'],
						suppress_unregister_notifications: true
					},
					mobile: {
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						},
						codecs: ['GSM'],
						suppress_unregister_notifications: true
					},
					smartphone: {
						call_forward: {
							require_keypress: true,
							keep_caller_id: true
						},
						contact_list: {
							exclude: true
						},
						sip: {
							password: monster.util.randomString(12),
							realm: monster.apps.auth.currentAccount.realm,
							username: '******' + monster.util.randomString(10)
						},
						codecs: ['GSM'],
						suppress_unregister_notifications: true
					},
					sip_uri: {
						sip: {
							password: monster.util.randomString(12),
							username: '******' + monster.util.randomString(10),
							expire_seconds: 360,
							invite_format: 'route',
							method: 'password'
						},
						codecs: ['PCMU'],
						suppress_unregister_notifications: true
					}
				};
			

			_.each(data.listClassifiers, function(restriction, name) {
				if(name in self.i18n.active().devices.classifiers) {
					defaults.extra.restrictions[name].friendly_name = self.i18n.active().devices.classifiers[name].name;

					if('help' in self.i18n.active().devices.classifiers[name]) {
						defaults.extra.restrictions[name].help = self.i18n.active().devices.classifiers[name].help;
					}
				}

				if('call_restriction' in data.accountLimits && name in data.accountLimits.call_restriction && data.accountLimits.call_restriction[name].action === 'deny') {
					defaults.extra.restrictions[name].disabled = true;
					defaults.extra.hasDisabledRestrictions = true;
				}

				if('call_restriction' in data.device && name in data.device.call_restriction) {
					if(typeof data.device.call_restriction[name].action !== 'undefined')
					    defaults.extra.restrictions[name].action = data.device.call_restriction[name].action;
				}
				else {
					defaults.extra.restrictions[name].action = 'deny';
				}
			});

			var formattedData = $.extend(true, {}, typedDefaults[data.device.device_type], defaults, data.device);

			/* Audio Codecs*/
			/* extend doesn't replace the array so we need to do it manually */
			if(data.device.media && data.device.media.audio && data.device.media.audio.codecs) {
				formattedData.media.audio.codecs = data.device.media.audio.codecs;
			}

			/* Video codecs */
			if(data.device.media && data.device.media.video && data.device.media.video.codecs) {
				formattedData.media.video.codecs = data.device.media.video.codecs;
			}

			formattedData.extra.isRegistered = dataList.isRegistered;

			return formattedData;
		},