Browse Source

Merge remote-tracking branch 'origin/master'

4.3
Jean-Roch Maitre 9 years ago
parent
commit
7c5b94e7e9
20 changed files with 523 additions and 755 deletions
  1. +14
    -4
      i18n/en-US.json
  2. +126
    -76
      submodules/devices/devices.js
  3. +0
    -8
      submodules/groups/groups.css
  4. +64
    -132
      submodules/groups/groups.js
  5. +0
    -18
      submodules/myOffice/myOffice.css
  6. +45
    -17
      submodules/myOffice/myOffice.js
  7. +0
    -3
      submodules/strategy/strategy.css
  8. +16
    -109
      submodules/strategy/strategy.js
  9. +0
    -2
      submodules/users/fixtures/resendInstructions.json
  10. +0
    -2
      submodules/users/fixtures/resetPassword.json
  11. +0
    -8
      submodules/users/users.css
  12. +151
    -172
      submodules/users/users.js
  13. +41
    -29
      views/devices-sip_device.html
  14. +5
    -28
      views/groups-numbers.html
  15. +5
    -27
      views/groups-numbersItemRow.html
  16. +3
    -9
      views/myOffice-layout.html
  17. +34
    -54
      views/strategy-numbers.html
  18. +7
    -0
      views/users-deleteDialog.html
  19. +7
    -30
      views/users-numbers.html
  20. +5
    -27
      views/users-numbersItemRow.html

+ 14
- 4
i18n/en-US.json View File

@ -254,9 +254,15 @@
},
"__comment": "UI-1351: Add ability to configure feature keys for SIP devices in SmartPBX",
"__version": "v3.20_s4",
"featureKeys": {
"menuTitle": "Feature Keys",
"description": "Feature key",
"keys": {
"featureKeys": {
"title": "Feature Keys",
"label": "Feature key"
},
"comboKeys": {
"title": "Combo Keys",
"label": "Combo key"
},
"labels": {
"user": "User",
"parkingSpot": "Parking Spot",
@ -689,7 +695,11 @@
"deleteUserName": "Delete \"{{variable}}\"",
"proceed": "Proceed",
"deleteDevices": "Also remove this user's devices from the system",
"deleteDevicesHelp": "If you leave this option unchecked, we'll just unassign these devices and they will show up in the list of Spare Devices"
"deleteDevicesHelp": "If you leave this option unchecked, we'll just unassign these devices and they will show up in the list of Spare Devices",
"__comment": "UI-2467: also remove conferences when deleting a user from smartpbx",
"__version": "4.0",
"deleteConferences": "Also remove this user's conferences from the system",
"deleteConferencesHelp": "If you leave this option unchecked, you won't be able to use the user's conference number anywhere else, as it will still be used by that conference."
}
},


+ 126
- 76
submodules/devices/devices.js View File

@ -155,6 +155,20 @@ define(function(require){
});
},
getKeyTypes: function(data) {
var types = [];
if (data.hasOwnProperty('feature_keys') && data.feature_keys.iterate > 0) {
types.push('feature_keys');
}
if (data.hasOwnProperty('combo_keys') && data.combo_keys.iterate > 0) {
types.push('combo_keys');
}
return _.isEmpty(types) ? null : types;
},
devicesRenderEdit: function(args) {
var self = this,
data = args.data,
@ -166,28 +180,32 @@ define(function(require){
self.devicesGetEditData(data, function(dataDevice) {
if (dataDevice.hasOwnProperty('provision')) {
self.devicesGetIterator(dataDevice.provision, function(template) {
if (template.hasOwnProperty('feature_keys') && template.feature_keys.iterate > 0) {
if (!dataDevice.provision.hasOwnProperty('feature_keys')) {
dataDevice.provision.feature_keys = {};
}
var keyTypes = self.getKeyTypes(template);
if (keyTypes) {
self.devicesListUsers({
success: function(users) {
_.each(keyTypes, function(type, idx) {
if (!dataDevice.provision.hasOwnProperty(type)) {
dataDevice.provision[type] = {};
}
for (var i = 0, len = template.feature_keys.iterate; i < len; i++) {
if (!dataDevice.provision.feature_keys.hasOwnProperty(i)) {
dataDevice.provision.feature_keys[i] = { type: 'none' };
}
}
var i = 0,
len = template[type].iterate;
for (; i < len; i++) {
if (!dataDevice.provision[type].hasOwnProperty(i)) {
dataDevice.provision[type][i] = {
type: 'none'
}
}
}
});
self.callApi({
resource: 'user.list',
data: {
accountId: self.accountId
},
success: function(data, status) {
var keyTypes = [ 'none', 'presence', 'parking', 'personal_parking', 'speed_dial' ],
var actions = [ 'none', 'presence', 'parking', 'personal_parking', 'speed_dial' ],
parkingSpots = [],
extra;
data.data.sort(function(a, b) {
users.sort(function(a, b) {
return a.last_name.toLowerCase() > b.last_name.toLowerCase() ? 1 : -1;
});
@ -195,22 +213,38 @@ define(function(require){
parkingSpots[i] = i + 1;
}
keyTypes.forEach(function(val, idx, arr) {
arr[idx] = { id: val, text: self.i18n.active().devices.popupSettings.featureKeys.types[val] };
_.each(actions, function(action, idx, list) {
list[idx] = {
id: action,
text: self.i18n.active().devices.popupSettings.keys.types[action]
};
if (val !== 'none') {
arr[idx].info = self.i18n.active().devices.popupSettings.featureKeys.info.types[val];
if (action !== 'none') {
list[idx].info = self.i18n.active().devices.popupSettings.keys.info.types[action];
}
});
extra = {
users: data.data,
featureKeys:{
provision: {
users: users,
parkingSpots: parkingSpots,
types: keyTypes
keyActions: actions,
keys: []
}
};
_.each(keyTypes, function(key, idx) {
var camelCaseKey = self.devicesSnakeToCamel(key);
extra.provision.keys.push({
id: key,
type: camelCaseKey,
title: self.i18n.active().devices.popupSettings.keys[camelCaseKey].title,
label: self.i18n.active().devices.popupSettings.keys[camelCaseKey].label,
data: dataDevice.provision[key]
});
});
dataDevice.extra = dataDevice.hasOwnProperty('extra') ? $.extend(true, {}, dataDevice.extra, extra) : extra;
self.devicesRenderDevice(dataDevice, callbackSave, callbackDelete);
@ -279,23 +313,28 @@ define(function(require){
}))),
deviceForm = templateDevice.find('#form_device');
if (data.hasOwnProperty('provision') && data.provision.hasOwnProperty('feature_keys')) {
var section = '.tabs-section[data-section="featureKeys"] ';
if (data.extra.hasOwnProperty('provision') && data.extra.provision.hasOwnProperty('keys')) {
_.each(data.extra.provision.keys, function(value, idx) {
var section = '.tabs-section[data-section="' + value.type + '"] ';
_.each(data.provision.feature_keys, function(val, key){
var group = '.control-group[data-id="' + key + '"] ',
value = '.feature-key-value[data-type="' + val.type + '"]';
_.each(value.data, function(val, key) {
var group = '.control-group[data-id="' + key + '"] ',
value = '.feature-key-value[data-type="' + val.type + '"]';
templateDevice
.find(section.concat(group, value))
.addClass('active')
.find('[name="provision.feature_keys[' + key + '].value"]')
.val(val.value);
templateDevice
.find(section.concat(group, value))
.addClass('active')
.find('[name="provision.feature_keys[' + key + '].value"]')
.val(val.value);
});
});
$.each(templateDevice.find('.feature-key-index'), function(idx, val) {
$(val).text(parseInt($(val).text(), 10) + 1);
});
templateDevice
.find('.feature-key-index')
.each(function(idx, el) {
$(el)
.text(parseInt($(el).text(), 10) + 1);
});
}
if ( data.extra.hasE911Numbers ) {
@ -515,7 +554,7 @@ define(function(require){
setTimeout(function() {
var action = ($this.hasClass('collapsed') ? 'show' : 'hide').concat('Info');
$this.find('.text').text(self.i18n.active().devices.popupSettings.featureKeys.info.link[action]);
$this.find('.text').text(self.i18n.active().devices.popupSettings.keys.info.link[action]);
});
});
@ -613,18 +652,29 @@ define(function(require){
});
}
/**
* form2object sends feature_keys back as an array even if the first key is 1
* feature_key needs to be coerced into an object to match the datatype in originalData
*/
if (formData.hasOwnProperty('provision') && formData.provision.hasOwnProperty('feature_keys')) {
var featureKeys = {};
if (formData.hasOwnProperty('provision') && formData.provision.hasOwnProperty('keys')) {
/**
* form2object sends keys back as arrays even if the first key is 1
* they needs to be coerced into an object to match the datatype in originalData
*/
_.each(formData.provision.keys, function(value, key, list) {
var keys = {};
list[key].forEach(function(val, idx) {
if (val.type !== 'none') {
keys[idx] = val;
}
});
formData.provision.feature_keys.forEach(function(val, idx) {
featureKeys[idx] = val;
if (_.isEmpty(keys)) {
delete originalData.provision[key];
}
else {
originalData.provision[key] = keys;
}
});
formData.provision.feature_keys = featureKeys;
delete formData.provision.keys;
}
var mergedData = $.extend(true, {}, originalData, formData);
@ -662,19 +712,6 @@ define(function(require){
delete mergedData.media.fax.option;
}
// Remove feature keys that are not defined
if (mergedData.hasOwnProperty('provision') && mergedData.provision.hasOwnProperty('feature_keys')) {
for (var key in mergedData.provision.feature_keys) {
if (mergedData.provision.feature_keys[key].type === 'none') {
delete mergedData.provision.feature_keys[key];
}
}
if (_.isEmpty(mergedData.provision.feature_keys)) {
delete mergedData.provision.feature_keys;
}
}
if(mergedData.hasOwnProperty('caller_id') && mergedData.caller_id.hasOwnProperty('emergency') && mergedData.caller_id.emergency.hasOwnProperty('number') && mergedData.caller_id.emergency.number === '') {
delete mergedData.caller_id.emergency.number;
@ -947,6 +984,10 @@ define(function(require){
return formattedData;
},
devicesSnakeToCamel: function(string) {
return string.replace(/(\_\w)/g, function (match) { return match[1].toUpperCase(); });
},
/* Utils */
devicesDeleteDevice: function(deviceId, callback) {
var self = this;
@ -990,35 +1031,27 @@ define(function(require){
}
},
success: function(data) {
monster.pub('common.numbers.getListFeatures', function(viewFeatures) {
var e911Numbers = {};
_.each(data.data.numbers, function(val, key) {
if(val.features.indexOf('e911') >= 0) {
e911Numbers[key] = self.devicesFormatNumber(val, viewFeatures);
}
});
var e911Numbers = {};
callback(e911Numbers);
_.each(data.data.numbers, function(val, key) {
if(val.features.indexOf('e911') >= 0) {
e911Numbers[key] = self.devicesFormatNumber(val);
}
});
callback(e911Numbers);
}
});
},
devicesFormatNumber: function(value, viewFeatures) {
devicesFormatNumber: function(value) {
var self = this;
value.viewFeatures = $.extend(true, {}, viewFeatures);
if('locality' in value) {
value.isoCountry = value.locality.country || '';
value.friendlyLocality = 'city' in value.locality ? value.locality.city + ('state' in value.locality ? ', ' + value.locality.state : '') : '';
}
_.each(value.features, function(feature) {
if(feature in value.viewFeatures) {
value.viewFeatures[feature].active = 'active';
}
});
return value;
},
@ -1228,6 +1261,23 @@ define(function(require){
else {
callbackError && callbackError();
}
},
devicesListUsers: function(args) {
var self = this;
self.callApi({
resource: 'user.list',
data: {
accountId: self.accountId
},
success: function(data, status) {
args.hasOwnProperty('success') && args.success(data.data);
},
error: function(data, status) {
args.hasOwnProperty('error') && args.error();
}
});
}
};


+ 0
- 8
submodules/groups/groups.css View File

@ -370,14 +370,6 @@
white-space:pre-wrap;
}
#groups_container .list-wrapper .item-row .features > i {
display: none;
}
#groups_container .list-wrapper .item-row .features > i.active {
display: inline-block;
}
#groups_container .list-wrapper .item-row .locality {
display: none;
border-left: 1px solid #CCC;


+ 64
- 132
submodules/groups/groups.js View File

@ -445,10 +445,22 @@ define(function(require){
self.groupsGetNumbersData(groupId, function(data) {
self.groupsFormatNumbersData(data, function(data) {
template = $(monster.template(self, 'groups-numbers', $.extend(true, {}, data, {
isCnamEnabled: monster.util.isNumberFeatureEnabled('cnam'),
isE911Enabled: monster.util.isNumberFeatureEnabled('e911')
})));
template = $(monster.template(self, 'groups-numbers', data));
_.each(data.assignedNumbers, function(numberData, numberId) {
numberData.phoneNumber = numberId;
var numberDiv = template.find('[data-id="' + numberId + '"]'),
argsFeatures = {
target: numberDiv.find('.edit-features'),
numberData: numberData,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, numberDiv.find('.features'));
}
};
monster.pub('common.numberFeaturesMenu.render', argsFeatures);
});
self.groupsBindNumbers(template, data);
@ -1063,83 +1075,6 @@ define(function(require){
}
});
if (monster.util.isNumberFeatureEnabled('e911')) {
template.on('click', '.e911-number', function() {
var e911Cell = $(this).parents('.item-row').first(),
phoneNumber = e911Cell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if(!($.isEmptyObject(data.data.e911))) {
e911Cell.find('.features i.feature-e911').addClass('active');
}
else {
e911Cell.find('.features i.feature-e911').removeClass('active');
}
}
}
};
monster.pub('common.e911.renderPopup', args);
}
});
}
if (monster.util.isNumberFeatureEnabled('cnam')) {
template.on('click', '.callerId-number', function() {
var cnamCell = $(this).parents('.item-row').first(),
phoneNumber = cnamCell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('cnam' in data.data && data.data.cnam.display_name) {
cnamCell.find('.features i.feature-outbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-outbound_cnam').removeClass('active');
}
if('cnam' in data.data && data.data.cnam.inbound_lookup) {
cnamCell.find('.features i.feature-inbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-inbound_cnam').removeClass('active');
}
}
}
};
monster.pub('common.callerId.renderPopup', args);
}
});
}
template.on('click', '.prepend-number', function() {
var prependCell = $(this).parents('.item-row').first(),
phoneNumber = prependCell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('prepend' in data.data && data.data.prepend.enabled) {
prependCell.find('.features i.feature-prepend').addClass('active');
} else {
prependCell.find('.features i.feature-prepend').removeClass('active');
}
}
}
};
monster.pub('common.numberPrepend.renderPopup', args);
}
});
template.on('click', '.actions .spare-link:not(.disabled)', function(e) {
e.preventDefault();
@ -1155,16 +1090,23 @@ define(function(require){
template.find('.empty-row').hide();
_.each(numberList, function(val, idx) {
val.isLocal = val.features.indexOf('local') > -1;
template
.find('.list-assigned-items')
.append($(monster.template(self, 'groups-numbersItemRow', {
isCnamEnabled: monster.util.isNumberFeatureEnabled('cnam'),
isE911Enabled: monster.util.isNumberFeatureEnabled('e911'),
number: val
})));
var numberDiv = template.find('[data-id="'+val.phoneNumber+'"]'),
args = {
target: numberDiv.find('.edit-features'),
numberData: val,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, numberDiv.find('.features'));
}
};
monster.pub('common.numberFeaturesMenu.render', args);
extraSpareNumbers = _.without(extraSpareNumbers, val.phoneNumber);
});
@ -1186,23 +1128,26 @@ define(function(require){
searchType: $(this).data('type'),
callbacks: {
success: function(numbers) {
monster.pub('common.numbers.getListFeatures', function(features) {
_.each(numbers, function(number, k) {
number.viewFeatures = $.extend(true, {}, features);
number.phoneNumber = number.id;
monster.util.populateBooleansNumberFeatures(number);
number.extra.hasFeatures = number.extra.hasE911 || number.extra.hasPrepend || number.extra.hasCnam;
_.each(numbers, function(number, k) {
number.phoneNumber = number.id;
var rowTemplate = $(monster.template(self, 'groups-numbersItemRow', {
var rowTemplate = $(monster.template(self, 'groups-numbersItemRow', {
number: number
}));
})),
argsFeatures = {
target: rowTemplate.find('.edit-features'),
numberData: number,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, rowTemplate.find('.features'));
}
};
monster.ui.tooltips(rowTemplate);
monster.pub('common.numberFeaturesMenu.render', argsFeatures);
template.find('.list-unassigned-items .empty-row').hide();
template.find('.list-unassigned-items').append(rowTemplate);
});
monster.ui.tooltips(rowTemplate);
template.find('.list-unassigned-items .empty-row').hide();
template.find('.list-unassigned-items').append(rowTemplate);
});
}
}
@ -1481,45 +1426,32 @@ define(function(require){
unassignedNumbers: {}
};
monster.pub('common.numbers.getListFeatures', function(features) {
_.each(data.numbers.numbers, function(number, id) {
/* Formating number */
number.viewFeatures = $.extend(true, {}, features);
/* TODO: Once locality is enabled, we need to remove it */
number.localityEnabled = 'locality' in number ? true : false;
_.each(number.features, function(feature) {
if(feature in number.viewFeatures) {
number.viewFeatures[feature].active = 'active';
}
});
_.each(data.numbers.numbers, function(number, id) {
/* TODO: Once locality is enabled, we need to remove it */
number.localityEnabled = 'locality' in number ? true : false;
monster.util.populateBooleansNumberFeatures(number);
number.extra.hasFeatures = number.extra.hasE911 || number.extra.hasPrepend || number.extra.hasCnam;
if(!number.hasOwnProperty('used_by') || number.used_by === '') {
response.unassignedNumbers[id] = number;
response.countSpare++;
}
});
if(!number.hasOwnProperty('used_by') || number.used_by === '') {
response.unassignedNumbers[id] = number;
response.countSpare++;
if('groupCallflow' in data.callflow && 'numbers' in data.callflow.groupCallflow) {
_.each(data.callflow.groupCallflow.numbers, function(number) {
if(!(number in data.numbers.numbers)) {
response.extensions.push(number);
}
else {
data.numbers.numbers[number].isLocal = data.numbers.numbers[number].features.indexOf('local') > -1;
response.assignedNumbers[number] = data.numbers.numbers[number];
}
});
}
response.emptyExtensions = _.isEmpty(response.extensions);
response.emptyAssigned = _.isEmpty(response.assignedNumbers);
response.emptySpare = _.isEmpty(response.unassignedNumbers);
if('groupCallflow' in data.callflow && 'numbers' in data.callflow.groupCallflow) {
_.each(data.callflow.groupCallflow.numbers, function(number) {
if(!(number in data.numbers.numbers)) {
response.extensions.push(number);
}
else {
data.numbers.numbers[number].isLocal = data.numbers.numbers[number].features.indexOf('local') > -1;
response.assignedNumbers[number] = data.numbers.numbers[number];
}
});
}
response.emptyExtensions = _.isEmpty(response.extensions);
response.emptyAssigned = _.isEmpty(response.assignedNumbers);
response.emptySpare = _.isEmpty(response.unassignedNumbers);
callback && callback(response);
});
callback && callback(response);
},
groupsGetNumbersData: function(groupId, callback) {


+ 0
- 18
submodules/myOffice/myOffice.css View File

@ -246,31 +246,13 @@
color: #22a5ff;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row .row-content .number-list .features > i {
display: none;
cursor: inherit;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row .row-content .number-list .features > i.active {
display: inline-block;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row .row-content .number-list .number-div {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/*#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row.e911-row > div {
line-height: 20px;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row.e911-row .row-title .line1 {
font-size: 24px;
line-height: 24px;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row.e911-row .row-title .line2 {
line-height: 16px;
}
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row.e911-row .row-content {
text-transform: uppercase;
font-size: 12px;
}*/
#myoffice_container .dashboard-right-content .dashboard-box .dashboard-box-row.account-info-box > div {
height: 20px;
line-height: 20px;


+ 45
- 17
submodules/myOffice/myOffice.js View File

@ -6,7 +6,19 @@ define(function(require){
var app = {
requests: {},
requests: {
'google.geocode.address': {
apiRoot: '//maps.googleapis.com/',
url: 'maps/api/geocode/json?address={zipCode}',
verb: 'GET',
generateError: false,
removeHeaders: [
'X-Kazoo-Cluster-ID',
'X-Auth-Token',
'Content-Type'
]
}
},
subscribe: {
'voip.myOffice.render': 'myOfficeRender',
@ -283,11 +295,6 @@ define(function(require){
}
});
},
numberFeatures: function(callback) {
monster.pub('common.numbers.getListFeatures', function(features) {
callback(null, features);
});
},
channels: function(parallelCallback) {
self.callApi({
resource: 'channel.list',
@ -534,13 +541,10 @@ define(function(require){
_.each(val.numbers, function(num) {
if(num !== '0' && num !== 'undefined' && num !== 'undefinedconf' && num !== 'undefinedfaxing') {
var number = {
number: num,
features: $.extend(true, {}, data.numberFeatures)
number: num
};
if(num in data.numbers) {
_.each(data.numbers[num].features, function(feature) {
number.features[feature] = $.extend(true, number.features[feature], { active : 'active'});
});
number.features = data.numbers[num].features;
}
data[numberArrayName].push(number);
}
@ -916,12 +920,21 @@ define(function(require){
});
emergencyZipcodeInput.on('blur', function() {
$.getJSON('http://www.geonames.org/postalCodeLookupJSON?&country=US&callback=?', { postalcode: $(this).val() }, function(response) {
if (response && response.postalcodes.length && response.postalcodes[0].placeName) {
emergencyCityInput.val(response.postalcodes[0].placeName);
emergencyStateInput.val(response.postalcodes[0].adminName1);
}
});
var zipCode = $(this).val();
if (zipCode) {
self.myOfficeGetAddessFromZipCode({
data: {
zipCode: zipCode
},
success: function(results) {
if (!_.isEmpty(results)) {
emergencyCityInput.val(results[0].address_components[1].long_name);
emergencyStateInput.val(results[0].address_components[3].short_name);
}
}
});
}
});
popupTemplate.find('.save').on('click', function() {
@ -1149,6 +1162,21 @@ define(function(require){
callback && callback(savedUser.data);
}
});
},
myOfficeGetAddessFromZipCode: function(args) {
var self = this;
monster.request({
resource: 'google.geocode.address',
data: args.data,
success: function(data, status) {
args.hasOwnProperty('success') && args.success(data.results);
},
error: function(errorPayload, data, globalHandler) {
args.hasOwnProperty('error') ? args.error() : globalHandler(data, { generateError: true });
}
});
}
};


+ 0
- 3
submodules/strategy/strategy.css View File

@ -134,9 +134,6 @@
#strategy_container .element-container .number-element .features-block .features {
margin-right: 45px;
}
#strategy_container .element-container .number-element .features-block .features > i {
display: none;
}
#strategy_container .element-container .number-element .features-block .features > i.active {
display: inline-block;


+ 16
- 109
submodules/strategy/strategy.js View File

@ -181,11 +181,6 @@ define(function(require){
callback(null, voicemailBoxes);
});
},
numberFeatures: function(callback) {
monster.pub('common.numbers.getListFeatures', function(features) {
callback(null, features);
});
},
directories: function (callback) {
self.strategyListDirectories(function (directories) {
callback(null, directories);
@ -396,20 +391,13 @@ define(function(require){
var ret = {
number: {
id: val
},
features: $.extend(true, {}, strategyData.numberFeatures)
}
};
if(accountNumbers.hasOwnProperty(val)) {
_.each(accountNumbers[val].features, function(feature) {
ret.features[feature].active = 'active';
});
ret.number = $.extend(true, accountNumbers[val], ret.number);
}
monster.util.populateBooleansNumberFeatures(ret.number);
ret.number.extra.hasFeatures = ret.number.extra.hasE911 || ret.number.extra.hasPrepend || ret.number.extra.hasCnam;
return ret;
}
}),
@ -417,6 +405,21 @@ define(function(require){
},
template = $(monster.template(self, 'strategy-'+templateName, templateData));
_.each(templateData.numbers, function(data) {
data.number.phoneNumber = data.number.id;
var numberDiv = template.find('[data-phonenumber="'+data.number.id+'"]'),
args = {
target: numberDiv.find('.edit-features'),
numberData: data.number,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, numberDiv.find('.features'));
}
};
monster.pub('common.numberFeaturesMenu.render', args);
});
monster.ui.tooltips(template);
container.find('.element-content').empty()
@ -869,83 +872,6 @@ define(function(require){
});
}
});
if (monster.util.isNumberFeatureEnabled('cnam')) {
container.on('click', '.number-element .callerId-number', function() {
var cnamCell = $(this).parents('.number-element').first(),
phoneNumber = cnamCell.find('.remove-number').data('number');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('cnam' in data.data && data.data.cnam.display_name) {
cnamCell.find('.features i.feature-outbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-outbound_cnam').removeClass('active');
}
if('cnam' in data.data && data.data.cnam.inbound_lookup) {
cnamCell.find('.features i.feature-inbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-inbound_cnam').removeClass('active');
}
}
}
};
monster.pub('common.callerId.renderPopup', args);
}
});
}
if (monster.util.isNumberFeatureEnabled('e911')) {
container.on('click', '.number-element .e911-number', function() {
var e911Cell = $(this).parents('.number-element').first(),
phoneNumber = e911Cell.find('.remove-number').data('number');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if(!($.isEmptyObject(data.data.e911))) {
e911Cell.find('.features i.feature-e911').addClass('active');
}
else {
e911Cell.find('.features i.feature-e911').removeClass('active');
}
}
}
};
monster.pub('common.e911.renderPopup', args);
}
});
}
container.on('click', '.number-element .prepend-number', function() {
var prependCell = $(this).parents('.number-element').first(),
phoneNumber = prependCell.find('.remove-number').data('number');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('prepend' in data.data && data.data.prepend.enabled) {
prependCell.find('.features i.feature-prepend').addClass('active');
} else {
prependCell.find('.features i.feature-prepend').removeClass('active');
}
}
}
};
monster.pub('common.numberPrepend.renderPopup', args);
}
});
},
strategyConfNumBindEvents: function(container, strategyData) {
@ -2277,25 +2203,6 @@ define(function(require){
}
});
// container.on('click', '.number-text', function(e) {
// var $this = $(this);
// $this.parents('.menu-line').addClass('editing');
// $this.siblings('.number-input').focus();
// });
// container.on('blur', '.number-input', function(e) {
// var $this = $(this);
// $this.parents('.menu-line').removeClass('editing');
// $this.siblings('.number-text').text($this.val() || "?");
// });
// container.on('keyup', '.number-input', function(e) {
// var $this = $(this);
// if(!/^[0-9#*]*$/.test($this.val())) {
// $this.val($this.val().replace(/[^0-9#*]/g, ""));
// }
// });
container.on('change', '.target-select', function(e) {
var $this = $(this),
iconElem = $this.parents('.target-input').find('.target-icon'),


+ 0
- 2
submodules/users/fixtures/resendInstructions.json View File

@ -1,2 +0,0 @@
{
}

+ 0
- 2
submodules/users/fixtures/resetPassword.json View File

@ -1,2 +0,0 @@
{
}

+ 0
- 8
submodules/users/users.css View File

@ -443,14 +443,6 @@
white-space:pre-wrap;
}
#users_container .detail-numbers .list-wrapper .item-row .features > i {
display: none;
}
#users_container .detail-numbers .list-wrapper .item-row .features > i.active {
display: inline-block;
}
#users_container .detail-numbers .list-wrapper .item-row .locality {
display: none;
border-left: 1px solid #CCC;


+ 151
- 172
submodules/users/users.js View File

@ -428,9 +428,10 @@ define(function(require){
monster.ui.tooltips(dialogTemplate);
dialogTemplate.find('#confirm_button').on('click', function() {
var removeDevices = dialogTemplate.find('#delete_devices').is(':checked');
var removeDevices = dialogTemplate.find('#delete_devices').is(':checked'),
removeConferences = dialogTemplate.find('#delete_conferences').is(':checked');
self.usersDelete(user.id, removeDevices, function(data) {
self.usersDelete(user.id, removeDevices, removeConferences, function(data) {
popup.dialog('close').remove();
callback && callback(data);
@ -649,6 +650,9 @@ define(function(require){
var dataForm = monster.ui.getFormData('form_user_creation'),
formattedData = self.usersFormatCreationData(dataForm);
$(this)
.prop({ disabled: 'true' });
self.usersCreate(formattedData, function(data) {
popup.dialog('close').remove();
@ -1116,14 +1120,23 @@ define(function(require){
template.find('.empty-row').hide();
_.each(numberList, function(val, idx) {
val.isLocal = val.features.indexOf('local') > -1;
template
.find('.list-assigned-items')
.append($(monster.template(self, 'users-numbersItemRow', {
number: val
})));
var numberDiv = template.find('[data-id="'+val.phoneNumber+'"]'),
args = {
target: numberDiv.find('.edit-features'),
numberData: val,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, numberDiv.find('.features'));
}
};
monster.pub('common.numberFeaturesMenu.render', args);
extraSpareNumbers = _.without(extraSpareNumbers, val.phoneNumber);
});
@ -1145,23 +1158,26 @@ define(function(require){
searchType: $(this).data('type'),
callbacks: {
success: function(numbers) {
monster.pub('common.numbers.getListFeatures', function(features) {
_.each(numbers, function(number, k) {
number.viewFeatures = $.extend(true, {}, features);
number.phoneNumber = number.id;
monster.util.populateBooleansNumberFeatures(number);
number.extra.hasFeatures = number.extra.hasE911 || number.extra.hasPrepend || number.extra.hasCnam;
_.each(numbers, function(number, k) {
number.phoneNumber = number.id;
var rowTemplate = $(monster.template(self, 'users-numbersItemRow', {
var rowTemplate = $(monster.template(self, 'users-numbersItemRow', {
number: number
}));
})),
argsFeatures = {
target: rowTemplate.find('.edit-features'),
numberData: number,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, rowTemplate.find('.features'));
}
};
monster.ui.tooltips(rowTemplate);
monster.pub('common.numberFeaturesMenu.render', argsFeatures);
template.find('.list-assigned-items .empty-row').hide();
template.find('.list-assigned-items').append(rowTemplate);
});
monster.ui.tooltips(rowTemplate);
template.find('.list-assigned-items .empty-row').hide();
template.find('.list-assigned-items').append(rowTemplate);
});
}
}
@ -1214,83 +1230,6 @@ define(function(require){
}
});
if (monster.util.isNumberFeatureEnabled('cnam')) {
template.on('click', '.callerId-number', function() {
var cnamCell = $(this).parents('.item-row').first(),
phoneNumber = cnamCell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('cnam' in data.data && data.data.cnam.display_name) {
cnamCell.find('.features i.feature-outbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-outbound_cnam').removeClass('active');
}
if('cnam' in data.data && data.data.cnam.inbound_lookup) {
cnamCell.find('.features i.feature-inbound_cnam').addClass('active');
} else {
cnamCell.find('.features i.feature-inbound_cnam').removeClass('active');
}
}
}
};
monster.pub('common.callerId.renderPopup', args);
}
});
}
if (monster.util.isNumberFeatureEnabled('e911')) {
template.on('click', '.e911-number', function() {
var e911Cell = $(this).parents('.item-row').first(),
phoneNumber = e911Cell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if(!($.isEmptyObject(data.data.e911))) {
e911Cell.find('.features i.feature-e911').addClass('active');
}
else {
e911Cell.find('.features i.feature-e911').removeClass('active');
}
}
}
};
monster.pub('common.e911.renderPopup', args);
}
});
}
template.on('click', '.prepend-number', function() {
var prependCell = $(this).parents('.item-row').first(),
phoneNumber = prependCell.data('id');
if(phoneNumber) {
var args = {
phoneNumber: phoneNumber,
callbacks: {
success: function(data) {
if('prepend' in data.data && data.data.prepend.enabled) {
prependCell.find('.features i.feature-prepend').addClass('active');
} else {
prependCell.find('.features i.feature-prepend').removeClass('active');
}
}
}
};
monster.pub('common.numberPrepend.renderPopup', args);
}
});
template.on('click', '.feature[data-feature="caller_id"]', function() {
self.usersRenderCallerId(currentUser);
});
@ -2730,6 +2669,19 @@ define(function(require){
self.usersFormatNumbersData(userId, results, function(results) {
template = $(monster.template(self, 'users-numbers', results));
_.each(results.assignedNumbers, function(number) {
var numberDiv = template.find('[data-id="' + number.phoneNumber + '"]'),
argsFeatures = {
target: numberDiv.find('.edit-features'),
numberData: number,
afterUpdate: function(features) {
monster.ui.paintNumberFeaturesIcon(features, numberDiv.find('.features'));
}
};
monster.pub('common.numberFeaturesMenu.render', argsFeatures);
});
callback && callback(template, results);
});
}, true);
@ -2808,83 +2760,70 @@ define(function(require){
});
}
monster.pub('common.numbers.getListFeatures', function(features) {
if('numbers' in data.numbers) {
_.each(data.numbers.numbers, function(number, k) {
/* Formating number */
number.viewFeatures = $.extend(true, {}, features);
/* TODO: Once locality is enabled, we need to remove it */
number.localityEnabled = 'locality' in number ? true : false;
_.each(number.features, function(feature) {
if(feature in number.viewFeatures) {
number.viewFeatures[feature].active = 'active';
}
});
monster.util.populateBooleansNumberFeatures(number);
number.extra.hasFeatures = number.extra.hasE911 || number.extra.hasPrepend || number.extra.hasCnam;
if('numbers' in data.numbers) {
_.each(data.numbers.numbers, function(number, k) {
/* TODO: Once locality is enabled, we need to remove it */
number.localityEnabled = 'locality' in number ? true : false;
/* Adding to spare numbers */
if(!number.hasOwnProperty('used_by') || number.used_by === '') {
response.countSpare++;
response.unassignedNumbers[k] = number;
}
else if (number.used_by === 'mobile') {
response.assignedNumbers.push(number);
}
});
}
/* Adding to spare numbers */
if(!number.hasOwnProperty('used_by') || number.used_by === '') {
response.countSpare++;
response.unassignedNumbers[k] = number;
}
else if (number.used_by === 'mobile') {
response.assignedNumbers.push(number);
}
});
}
if(response.callflow) {
/* If a number is in a callflow and is returned by the phone_numbers, add it to the assigned numbers */
_.each(response.callflow.numbers, function(number) {
if(number in data.numbers.numbers) {
var numberElement = data.numbers.numbers[number];
numberElement.phoneNumber = number;
numberElement.isLocal = numberElement.features.indexOf('local') > -1;
if(response.callflow) {
/* If a number is in a callflow and is returned by the phone_numbers, add it to the assigned numbers */
_.each(response.callflow.numbers, function(number) {
if(number in data.numbers.numbers) {
var numberElement = data.numbers.numbers[number];
numberElement.phoneNumber = number;
numberElement.isLocal = numberElement.features.indexOf('local') > -1;
response.assignedNumbers.push(numberElement);
}
else {
response.extensions.push(number);
}
});
}
response.assignedNumbers.push(numberElement);
}
else {
response.extensions.push(number);
}
});
}
response.assignedNumbers = monster.util.sort(response.assignedNumbers, 'phoneNumber');
response.assignedNumbers = monster.util.sort(response.assignedNumbers, 'phoneNumber');
/* List of extensions */
response.allExtensions = [];
/* List of extensions */
response.allExtensions = [];
_.each(data.callflow.list, function(callflow) {
_.each(callflow.numbers, function(number) {
/* If it's a valid extension number (ie: a number that's not in the number database) */
if(!(number in data.numbers.numbers) && !(_.isNaN(parseInt(number)))) {
response.allExtensions.push(number);
}
});
_.each(data.callflow.list, function(callflow) {
_.each(callflow.numbers, function(number) {
/* If it's a valid extension number (ie: a number that's not in the number database) */
if(!(number in data.numbers.numbers) && !(_.isNaN(parseInt(number)))) {
response.allExtensions.push(number);
}
});
});
/* Sort extensions so that we can recommend an available extension to a user whom would add a new one */
response.allExtensions.sort(function(a, b) {
var parsedA = parseInt(a),
parsedB = parseInt(b),
result = -1;
/* Sort extensions so that we can recommend an available extension to a user whom would add a new one */
response.allExtensions.sort(function(a, b) {
var parsedA = parseInt(a),
parsedB = parseInt(b),
result = -1;
if(parsedA > 0 && parsedB > 0) {
result = parsedA > parsedB;
}
if(parsedA > 0 && parsedB > 0) {
result = parsedA > parsedB;
}
return result;
});
return result;
});
response.emptyAssigned = _.isEmpty(response.assignedNumbers);
response.emptySpare = _.isEmpty(response.unassignedNumbers);
response.emptyExtensions = _.isEmpty(response.extensions);
response.emptyAssigned = _.isEmpty(response.assignedNumbers);
response.emptySpare = _.isEmpty(response.unassignedNumbers);
response.emptyExtensions = _.isEmpty(response.extensions);
callback && callback(response);
});
callback && callback(response);
},
usersFormatCreationData: function(data, callback) {
@ -2935,7 +2874,7 @@ define(function(require){
},
/* Utils */
usersDelete: function(userId, removeDevices, callback) {
usersDelete: function(userId, removeDevices, removeConferences, callback) {
var self = this;
monster.parallel({
@ -2953,6 +2892,11 @@ define(function(require){
self.usersListCallflowsUser(userId, function(data) {
callback(null, data);
});
},
conferences: function(callback) {
self.usersListConferences(userId, function(data) {
callback(null, data);
});
}
},
function(error, results) {
@ -2973,6 +2917,12 @@ define(function(require){
});
});
listFnDelete.push(function(callback) {
self.usersRemoveBulkConferences(results.conferences, removeConferences, function() {
callback(null, '');
});
});
_.each(results.callflows, function(callflow) {
/*
@ -3758,6 +3708,19 @@ define(function(require){
});
},
usersUnassignConference: function(conferenceId, callback) {
var self = this;
self.usersGetConference(conferenceId, function(conference) {
conference.name = 'Unassigned ' + conference.name;
delete conference.owner_id;
self.usersUpdateConference(conference, function(conference) {
callback && callback(conference);
});
});
},
usersUpdateConference: function(conference, callback) {
var self = this;
@ -4209,6 +4172,8 @@ define(function(require){
conference_numbers: []
};
monster.util.dataFlags.add({ source: 'smartpbx'}, baseConference);
baseConference = $.extend(true, {}, baseConference, data.conference);
self.usersListConferences(data.user.id, function(conferences) {
@ -4360,24 +4325,38 @@ define(function(require){
}
},
usersRemoveBulkConferences: function(conferences, forceDelete, callback) {
var self = this,
listRequests = [];
_.each(conferences, function(conference) {
listRequests.push(function(subCallback) {
if(forceDelete) {
self.usersDeleteConference(conference.id, function(data) {
subCallback(null, data);
});
}
else {
self.usersUnassignConference(conference.id, function(data) {
subCallback(null, data);
});
}
});
});
monster.parallel(listRequests, function(err, results) {
callback && callback(results);
});
},
usersDeleteConferencing: function(userId, globalCallback) {
var self = this;
monster.parallel({
conferences: function(callback) {
self.usersListConferences(userId, function(conferences) {
var listRequests = [];
_.each(conferences, function(conference) {
listRequests.push(function(subCallback) {
self.usersDeleteConference(conference.id, function(data) {
subCallback(null, data);
});
});
});
monster.parallel(listRequests, function(err, results) {
callback && callback(results);
self.usersRemoveBulkConferences(conferences, true, function(results) {
callback && callback(null, results);
});
});
},


+ 41
- 29
views/devices-sip_device.html View File

@ -36,9 +36,9 @@
<li><a class="tabs-selector change-section" data-section="callerId" href="javascript:void(0)"><i class="fa fa-ambulance"></i>{{ i18n.devices.popupSettings.callerId.menuTitle }}</a></li>
{{/if}}
<li><a class="tabs-selector change-section" data-section="miscellaneous" href="javascript:void(0)"><i class="fa fa-cogs"></i>{{ i18n.devices.popupSettings.miscellaneous.menuTitle }}</a></li>
{{#if provision.feature_keys}}
<li><a class="tabs-selector change-section" data-section="featureKeys" href="javascript:void(0);"><i class="fa fa-lightbulb-o"></i>{{ i18n.devices.popupSettings.featureKeys.menuTitle }}</a></li>
{{/if}}
{{#each extra.provision.keys}}
<li><a class="tabs-selector change-section" data-section="{{type}}" href="javascript:void(0);"><i class="fa fa-lightbulb-o"></i>{{title}}</a></li>
{{/each}}
</ul>
</li>
</ul>
@ -263,65 +263,77 @@
{{/if}}
</div>
{{#if provision.feature_keys}}
<div class="tabs-section clearfix" data-section="featureKeys">
{{#each extra.provision.keys}}
<div class="tabs-section clearfix keys" data-section="{{type}}">
<div class="title">
{{ i18n.devices.popupSettings.featureKeys.menuTitle }}
{{{title}}}
</div>
<div class="type-info helper">
<a href="javascript:void(0);" data-toggle="collapse" data-target="#info_content"><i class="fa fa-question-circle"></i><span class="text">{{ i18n.devices.popupSettings.featureKeys.info.link.showInfo }}</span></a>
<div id="info_content" class="collapse">
{{#each extra.featureKeys.types}}
<p>{{#if info}}<strong>{{text}}</strong>: {{info}}{{/if}}</p>
{{/each}}
<a href="javascript:void(0);" data-toggle="collapse" data-target="#info_content_{{type}}">
<i class="fa fa-question-circle"></i>
<span class="text">
{{ @root.i18n.devices.popupSettings.keys.info.link.showInfo }}
</span>
</a>
<div id="info_content_{{type}}" class="collapse">
{{#each @root.extra.provision.keyActions}}
{{#if info}}
<p>
<strong>
{{text}}
</strong>
: {{info}}
</p>
{{/if}}
{{/each}}
</div>
</div>
{{#each provision.feature_keys}}
{{#each data}}
<div class="control-group" data-id="{{@key}}">
<label for="provision.feature_keys[{{@key}}].type" class="control-label">
{{ @root.i18n.devices.popupSettings.featureKeys.description }} <span class="feature-key-index">{{@key}}</span>
<label for="provision.keys.{{../id}}[{{@key}}].type" class="control-label">
{{ ../label }} <span class="feature-key-index">{{@key}}</span>
</label>
<div class="controls">
<select name="provision.feature_keys[{{@key}}].type" class="feature-key-type span2">
<select name="provision.keys.{{../id}}[{{@key}}].type" class="feature-key-type span2">
{{#select type}}
{{#each ../extra.featureKeys.types}}
{{#each @root.extra.provision.keyActions}}
<option value="{{id}}">{{text}}</option>
{{/each}}
{{/select}}
</select>
<div class="feature-key-value" data-type="presence">
<label for="provision.feature_keys[{{@key}}].value">{{ @root.i18n.devices.popupSettings.featureKeys.labels.user }}</label>
<select name="provision.feature_keys[{{@key}}].value" class="chosen-feature-key-user">
{{#each ../extra.users}}
<label for="provision.keys.{{../id}}[{{@key}}].value">{{ @root.i18n.devices.popupSettings.keys.labels.user }}</label>
<select name="provision.keys.{{../id}}[{{@key}}].value" class="chosen-feature-key-user">
{{#each @root.extra.provision.users}}
<option value="{{id}}">{{first_name}} {{last_name}}</option>
{{/each}}
</select>
</div>
<div class="feature-key-value" data-type="parking">
<label for="provision.feature_keys[{{@key}}].value">{{ @root.i18n.devices.popupSettings.featureKeys.labels.parkingSpot }}</label>
<select class="span1" name="provision.feature_keys[{{@key}}].value">
{{#each ../extra.featureKeys.parkingSpots}}
<label for="provision.keys.{{../id}}[{{@key}}].value">{{ @root.i18n.devices.popupSettings.keys.labels.parkingSpot }}</label>
<select class="span1" name="provision.keys.{{../id}}[{{@key}}].value">
{{#each @root.extra.provision.parkingSpots}}
<option value="{{this}}">{{this}}</option>
{{/each}}
</select>
</div>
<div class="feature-key-value" data-type="personal_parking">
<label for="provision.feature_keys[{{@key}}].value">{{ @root.i18n.devices.popupSettings.featureKeys.labels.user }}</label>
<select name="provision.feature_keys[{{@key}}].value" class="chosen-feature-key-user">
{{#each ../extra.users}}
<label for="provision.keys.{{../id}}[{{@key}}].value">{{ @root.i18n.devices.popupSettings.keys.labels.user }}</label>
<select name="provision.keys.{{../id}}[{{@key}}].value" class="chosen-feature-key-user">
{{#each @root.extra.provision.users}}
<option value="{{id}}">{{first_name}} {{last_name}}</option>
{{/each}}
</select>
</div>
<div class="feature-key-value" data-type="speed_dial">
<label for="provision.feature_keys[{{@key}}].value">{{ @root.i18n.devices.popupSettings.featureKeys.labels.value }}</label>
<input type="text" value="" name="provision.feature_keys[{{@key}}].value">
<label for="provision.keys.{{../id}}[{{@key}}].value">{{ @root.i18n.devices.popupSettings.keys.labels.value }}</label>
<input type="text" value="" name="provision.keys.{{../id}}[{{@key}}].value">
</div>
</div>
</div>
{{/each}}
{{/each}}
</div>
{{/if}}
{{/each}}
</form>
</div>


+ 5
- 28
views/groups-numbers.html View File

@ -7,35 +7,12 @@
{{#each assignedNumbers}}
<div class="item-row" data-id="{{@key}}" data-search="{{formatPhoneNumber @key}} {{@key}} {{locality.city}} {{locality.country}}">
<div class="features-block pull-right">
<div class="edit-features">
{{#if this.extra.hasFeatures}}
<div class="navbar">
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
{{#if this.extra.hasCnam}}
<li><a class="callerId-number" href="#"><i class="fa fa-user"></i>{{ @root.i18n.callerId }}</a></li>
{{/if}}
{{#if this.extra.hasE911}}
<li><a class="e911-number" href="#"><i class="fa fa-ambulance"></i>{{ @root.i18n.e911 }}</a></li>
{{/if}}
{{#if this.extra.hasPrepend}}
<li><a class="prepend-number" href="#"><i class="fa fa-file-text-o"></i>{{ @root.i18n.numberPrepend }}</a></li>
{{/if}}
</ul>
</li>
</ul>
</div>
{{/if}}
</div>
<div class="edit-features"></div>
<div class="features">
{{#compare this.state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
{{#each viewFeatures}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{#numberFeatures this.features}}{{/numberFeatures}}
{{#compare state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
</div>
</div>
<div class="number">


+ 5
- 27
views/groups-numbersItemRow.html View File

@ -1,34 +1,12 @@
<div class="item-row" data-id="{{number.phoneNumber}}">
<div class="features-block pull-right">
<div class="edit-features">
{{#if number.extra.hasFeatures}}
<div class="navbar">
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
{{#if number.extra.hasCnam}}
<li><a class="callerId-number" href="#"><i class="fa fa-user"></i>{{ @root.i18n.callerId }}</a></li>
{{/if}}
{{#if number.extra.hasE911}}
<li><a class="e911-number" href="#"><i class="fa fa-ambulance"></i>{{ @root.i18n.e911 }}</a></li>
{{/if}}
{{#if number.extra.hasPrepend}}
<li><a class="prepend-number" href="#"><i class="fa fa-file-text-o"></i>{{ @root.i18n.numberPrepend }}</a></li>
{{/if}}
</ul>
</li>
</ul>
</div>
{{/if}}
</div>
<div class="edit-features"></div>
<div class="features">
{{#compare number.state '===' 'port_in'}}
{{#numberFeatures number.features}}{{/numberFeatures}}
{{#compare number.state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
{{#each number.viewFeatures}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{/compare}}
</div>
</div>
<div class="number">


+ 3
- 9
views/myOffice-layout.html View File

@ -87,9 +87,7 @@
{{#each mainNumbers}}
<li{{#compare this.number '===' ../account.caller_id.external.number}} class="caller-id"{{/compare}}>
<div class="features pull-right">
{{#each this.features}}
<i class="icon-small {{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{#numberFeatures this.features}}{{/numberFeatures}}
</div>
<div class="number-div">{{formatPhoneNumber this.number}}</div>
</li>
@ -113,9 +111,7 @@
{{#each confNumbers}}
<li>
<div class="features pull-right">
{{#each this.features}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{#numberFeatures this.features}}{{/numberFeatures}}
</div>
<div class="number-div">{{formatPhoneNumber number}}</div>
</li>
@ -134,9 +130,7 @@
{{#each faxingNumbers}}
<li>
<div class="features pull-right">
{{#each this.features}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{#numberFeatures this.features}}{{/numberFeatures}}
</div>
<div class="number-div">{{formatPhoneNumber number}}</div>
</li>


+ 34
- 54
views/strategy-numbers.html View File

@ -1,59 +1,39 @@
{{#each numbers}}
<div class="number-element">
<div class="number">
<button type="button" class="monster-button monster-button-danger remove-number" data-number="{{this.number.id}}" data-e911="{{this.features.e911.active}}">
{{ @root.i18n.unassign }}
</button>
<span>{{formatPhoneNumber this.number.id}}</span>
</div>
<div class="features-block pull-right">
<div class="edit-features">
{{#if this.number.extra.hasFeatures}}
<div class="navbar">
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
{{#if this.number.extra.hasCnam}}
<li><a class="callerId-number" href="#"><i class="fa fa-user"></i>{{ @root.i18n.callerId }}</a></li>
{{/if}}
{{#if this.number.extra.hasE911}}
<li><a class="e911-number" href="#"><i class="fa fa-ambulance"></i>{{ @root.i18n.e911 }}</a></li>
{{/if}}
{{#if this.number.extra.hasPrepend}}
<li><a class="prepend-number" href="#"><i class="fa fa-file-text-o"></i>{{ @root.i18n.numberPrepend }}</a></li>
{{/if}}
</ul>
</li>
</ul>
<div class="strategy-numbers-wrapper">
{{#each numbers}}
<div class="number-element" data-phoneNumber="{{number.id}}">
<div class="number">
<button type="button" class="monster-button monster-button-danger remove-number" data-number="{{number.id}}" data-e911="{{#ifInArray 'e911' number.features}}active{{/ifInArray}}">
{{ @root.i18n.unassign }}
</button>
<span>{{formatPhoneNumber number.id}}</span>
</div>
<div class="features-block pull-right">
<div class="edit-features"></div>
<div class="features">
{{#numberFeatures number.features}}{{/numberFeatures}}
</div>
{{/if}}
</div>
</div>
<div class="features">
{{#each this.features}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{else}}
<div class="number-element">
<div class="no-number-error">{{ i18n.strategy.noNumberMessage }}</div>
</div>
{{/each}}
<div class="number-actions">
<a href="#" class="cancel-link pull-right monster-link blue">{{ i18n.close }}</a>
<div class="action-links nav-bar clearfix">
<a href="#" class="spare-link monster-link pull-left{{#unless spareLinkEnabled}} disabled{{/unless}}"><i class="fa fa-file-text-o monster-orange fa-lg"></i>{{ i18n.strategy.numberLinks.spare }}</a>
<ul class="nav pull-left">
<li class="dropdown">
<a href="#" class="dropdown-toggle buy-dropdown monster-link" data-toggle="dropdown" data-target="#"><i class="fa fa-shopping-cart monster-green fa-lg"></i>{{ i18n.strategy.numberLinks.buy.link }}</a>
<ul class="dropdown-menu" role="menu">
<li><a class="buy-link" data-type="regular" href="#">{{i18n.strategy.numberLinks.buy.regular}}</a></li>
<li><a class="buy-link" data-type="tollfree" href="#">{{i18n.strategy.numberLinks.buy.tollfree}}</a></li>
<!-- <li><a class="buy-link" data-type="vanity" href="#">{{i18n.strategy.numberLinks.buy.vanity}}</a></li> -->
</ul>
</li>
</ul>
</div>
</div>
</div>
{{else}}
<div class="number-element">
<div class="no-number-error">{{ i18n.strategy.noNumberMessage }}</div>
</div>
{{/each}}
<div class="number-actions">
<a href="#" class="cancel-link pull-right monster-link blue">{{ i18n.close }}</a>
<div class="action-links nav-bar clearfix">
<a href="#" class="spare-link monster-link pull-left{{#unless spareLinkEnabled}} disabled{{/unless}}"><i class="fa fa-file-text-o monster-orange fa-lg"></i>{{ i18n.strategy.numberLinks.spare }}</a>
<ul class="nav pull-left">
<li class="dropdown">
<a href="#" class="dropdown-toggle buy-dropdown monster-link" data-toggle="dropdown" data-target="#"><i class="fa fa-shopping-cart monster-green fa-lg"></i>{{ i18n.strategy.numberLinks.buy.link }}</a>
<ul class="dropdown-menu" role="menu">
<li><a class="buy-link" data-type="regular" href="#">{{i18n.strategy.numberLinks.buy.regular}}</a></li>
<li><a class="buy-link" data-type="tollfree" href="#">{{i18n.strategy.numberLinks.buy.tollfree}}</a></li>
<!-- <li><a class="buy-link" data-type="vanity" href="#">{{i18n.strategy.numberLinks.buy.vanity}}</a></li> -->
</ul>
</li>
</ul>
</div>
</div>

+ 7
- 0
views/users-deleteDialog.html View File

@ -10,6 +10,13 @@
<i class="help-popover fa fa-question-circle fa-lg" data-original-title="{{ i18n.users.deleteDialog.deleteDevicesHelp }}" data-placement="left" data-toggle="tooltip"></i>
</div>
<div>
{{#monsterCheckbox i18n.users.deleteDialog.deleteConferences }}
<input id="delete_conferences" type="checkbox"></input>
{{/monsterCheckbox}}
<i class="help-popover fa fa-question-circle fa-lg" data-original-title="{{ i18n.users.deleteDialog.deleteConferencesHelp }}" data-placement="left" data-toggle="tooltip"></i>
</div>
<div class="dialog-text">
{{#compare user.priv_level "===" "admin"}}
{{ i18n.users.deleteDialog.headerAdmin }}


+ 7
- 30
views/users-numbers.html View File

@ -7,39 +7,16 @@
{{#each assignedNumbers}}
<div class="item-row" data-id="{{this.phoneNumber}}" data-type="{{this.used_by}}" data-search="{{formatPhoneNumber this.phoneNumber}} {{this.phoneNumber}} {{this.locality.city}} {{this.locality.country}}">
<div class="features-block pull-right">
{{#compare this.used_by "!==" "mobile"}}
<div class="edit-features">
{{#if this.extra.hasFeatures}}
<div class="navbar">
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
{{#if this.extra.hasCnam}}
<li><a class="callerId-number" href="#"><i class="fa fa-user"></i>{{ @root.i18n.callerId }}</a></li>
{{/if}}
{{#if this.extra.hasE911}}
<li><a class="e911-number" href="#"><i class="fa fa-ambulance"></i>{{ @root.i18n.e911 }}</a></li>
{{/if}}
{{#if this.extra.hasPrepend}}
<li><a class="prepend-number" href="#"><i class="fa fa-file-text-o"></i>{{ @root.i18n.numberPrepend }}</a></li>
{{/if}}
</ul>
</li>
</ul>
</div>
{{/if}}
</div>
{{/compare}}
<div class="edit-features"></div>
<div class="features">
{{#compare this.state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
{{#each this.viewFeatures}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{#numberFeatures features}}{{/numberFeatures}}
{{#compare state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
</div>
</div>
<div class="number-container">
<button type="button" class="monster-button monster-button-danger remove-number{{#compare this.used_by "===" "mobile"}} disabled" disabled{{else}}"{{/compare}}>{{ @root.i18n.unassign }}</button>
<span class="number">


+ 5
- 27
views/users-numbersItemRow.html View File

@ -1,34 +1,12 @@
<div class="item-row" data-id="{{number.phoneNumber}}">
<div class="features-block pull-right">
<div class="edit-features">
{{#if number.extra.hasFeatures}}
<div class="navbar">
<ul class="nav pull-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-cog"></i></a>
<ul class="dropdown-menu">
{{#if number.extra.hasCnam}}
<li><a class="callerId-number" href="#"><i class="fa fa-user"></i>{{ @root.i18n.callerId }}</a></li>
{{/if}}
{{#if number.extra.hasE911}}
<li><a class="e911-number" href="#"><i class="fa fa-ambulance"></i>{{ @root.i18n.e911 }}</a></li>
{{/if}}
{{#if number.extra.hasPrepend}}
<li><a class="prepend-number" href="#"><i class="fa fa-file-text-o"></i>{{ @root.i18n.numberPrepend }}</a></li>
{{/if}}
</ul>
</li>
</ul>
</div>
{{/if}}
</div>
<div class="edit-features"></div>
<div class="features">
{{#compare number.state '===' 'port_in'}}
{{#numberFeatures number.features}}{{/numberFeatures}}
{{#compare number.state '===' 'port_in'}}
<i class="fa fa-exclamation-triangle monster-red active help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{@root.i18n.portIconHelp}}"></i>
{{/compare}}
{{#each number.viewFeatures}}
<i class="{{icon}} {{active}} help-popover" data-toggle="tooltip" data-placement="top" data-original-title="{{ help }}"></i>
{{/each}}
{{/compare}}
</div>
</div>
<div class="number">


Loading…
Cancel
Save