Browse Source

UI-2994: adding licensed service plan roles to smart pbx

Conflicts:
	i18n/en-US.json
4.3
Jean-Roch Maitre 8 years ago
parent
commit
d2db190375
7 changed files with 207 additions and 4 deletions
  1. +13
    -2
      i18n/en-US.json
  2. +21
    -0
      submodules/users/users.css
  3. +125
    -1
      submodules/users/users.js
  4. +14
    -0
      views/users-creation.html
  5. +4
    -1
      views/users-layout.html
  6. +24
    -0
      views/users-licensed-roles.html
  7. +6
    -0
      views/users-row.html

+ 13
- 2
i18n/en-US.json View File

@ -532,7 +532,10 @@
"extensions": "Extensions", "extensions": "Extensions",
"phoneNumbers": "Phone Numbers", "phoneNumbers": "Phone Numbers",
"devices": "Devices", "devices": "Devices",
"features": "User Features"
"features": "User Features",
"__comment": "UI-2994: add licensed user service plans as a listing category",
"__version": "4.1",
"userLicensedRoles": "User Type"
}, },
"toastrMessages": { "toastrMessages": {
"devicesUpdated": "You successfully updated the devices assigned to {{ name }}.", "devicesUpdated": "You successfully updated the devices assigned to {{ name }}.",
@ -746,7 +749,15 @@
"__comment": "UI-2921: Delete User new Dialog", "__comment": "UI-2921: Delete User new Dialog",
"__version": "4.2", "__version": "4.2",
"impersonate": "Impersonate"
"impersonate": "Impersonate",
"__comment": "UI-2994: adding licensed user roles",
"__version": "4.1",
"licensedUserRoles": {
"none": "- Not Set -",
"label": "User Type",
"selectPlaceholder": "Select a User Type"
}
}, },
"strategy": { "strategy": {


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

@ -192,6 +192,21 @@
width: 15%; width: 15%;
} }
/* With 6 columns, shorter width on all other columns */
#users_container .users-grid.additional-column .grid-row .grid-cell.phone-number {
width: 18%;
}
#users_container .users-grid.additional-column .grid-row .grid-cell.devices,
#users_container .users-grid.additional-column .grid-row .grid-cell.extension {
width: 12%;
}
#users_container .users-grid.additional-column .grid-row .grid-cell.licensed-user-role {
width: 13%;
}
/* end 6th columns mode */
#users_container .user-rows .grid-row { #users_container .user-rows .grid-row {
margin-bottom: 10px; margin-bottom: 10px;
border-radius: 2px; border-radius: 2px;
@ -269,6 +284,12 @@
margin-top: 2px; margin-top: 2px;
} }
/* Detail User */
#users_container .detail-user-role .user-role-wrapper {
display: inline-block;
margin-top: 15px;
}
/* Detail User */ /* Detail User */
#users_container .detail-user .user-fields { #users_container .detail-user .user-fields {
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;


+ 125
- 1
submodules/users/users.js View File

@ -17,7 +17,8 @@ define(function(require) {
users: { users: {
smartPBXCallflowString: ' SmartPBX\'s Callflow', smartPBXCallflowString: ' SmartPBX\'s Callflow',
smartPBXConferenceString: ' SmartPBX Conference', smartPBXConferenceString: ' SmartPBX Conference',
smartPBXVMBoxString: '\'s VMBox'
smartPBXVMBoxString: '\'s VMBox',
servicePlansRole: {}
} }
}, },
@ -174,6 +175,8 @@ define(function(require) {
extension: dataUser.hasOwnProperty('presence_id') ? dataUser.presence_id : '', extension: dataUser.hasOwnProperty('presence_id') ? dataUser.presence_id : '',
hasFeatures: false, hasFeatures: false,
isAdmin: dataUser.priv_level === 'admin', isAdmin: dataUser.priv_level === 'admin',
showLicensedUserRoles: _.size(self.appFlags.users.servicePlansRole) > 0,
licensedUserRole: self.i18n.active().users.licensedUserRoles.none,
listCallerId: [], listCallerId: [],
listExtensions: [], listExtensions: [],
listNumbers: [], listNumbers: [],
@ -238,6 +241,21 @@ define(function(require) {
dataUser.extra = formattedUser; dataUser.extra = formattedUser;
} }
if (dataUser.hasOwnProperty('service') && dataUser.service.hasOwnProperty('plans') && _.size(dataUser.service.plans) > 0) {
var planId;
for (var key in dataUser.service.plans) {
if (dataUser.service.plans.hasOwnProperty(key)) {
planId = key;
break;
}
}
if (self.appFlags.users.servicePlansRole.hasOwnProperty(planId)) {
dataUser.extra.licensedUserRole = self.appFlags.users.servicePlansRole[planId].name;
}
}
dataUser.extra.countFeatures = 0; dataUser.extra.countFeatures = 0;
_.each(dataUser.features, function(v) { _.each(dataUser.features, function(v) {
if (v in dataUser.extra.mapFeatures) { if (v in dataUser.extra.mapFeatures) {
@ -332,12 +350,17 @@ define(function(require) {
usersFormatListData: function(data, _sortBy) { usersFormatListData: function(data, _sortBy) {
var self = this, var self = this,
dataTemplate = { dataTemplate = {
showLicensedUserRoles: false,
existingExtensions: [], existingExtensions: [],
countUsers: data.users.length countUsers: data.users.length
}, },
mapUsers = {}, mapUsers = {},
registeredDevices = _.map(data.deviceStatus, function(device) { return device.device_id; }); registeredDevices = _.map(data.deviceStatus, function(device) { return device.device_id; });
if (_.size(self.appFlags.users.servicePlansRole) > 0) {
dataTemplate.showLicensedUserRoles = true;
}
_.each(data.users, function(user) { _.each(data.users, function(user) {
mapUsers[user.id] = self.usersFormatUserData(user); mapUsers[user.id] = self.usersFormatUserData(user);
}); });
@ -612,6 +635,8 @@ define(function(require) {
setTimeout(function() { template.find('.search-query').focus(); }); setTimeout(function() { template.find('.search-query').focus(); });
currentUser = userId; currentUser = userId;
unassignedDevices = {}; unassignedDevices = {};
} else if (type === 'licensed-user-role') {
currentUser = data;
} }
row.find('.edit-user').append(template).slideDown(400, function() { row.find('.edit-user').append(template).slideDown(400, function() {
@ -657,6 +682,8 @@ define(function(require) {
monster.ui.mask(userTemplate.find('#extension'), 'extension'); monster.ui.mask(userTemplate.find('#extension'), 'extension');
userTemplate.find('#licensed_role').chosen({search_contains: true, width: '220px'});
monster.ui.validate(userTemplate.find('#form_user_creation'), { monster.ui.validate(userTemplate.find('#form_user_creation'), {
rules: { rules: {
'callflow.extension': { 'callflow.extension': {
@ -1070,6 +1097,24 @@ define(function(require) {
$(this).blur(); $(this).blur();
}); });
/* Events for License Roles */
template.on('click', '.save-user-role', function() {
var planId = template.find('#licensed_role').val();
/*currentUser.service = currentUser.service || {};
currentUser.service.plans = {};
currentUser.service.plans[planId] = {
account_id: monster.config.resellerId,
overrides: {}
};*/
currentUser.extra = currentUser.extra || {};
currentUser.extra.licensedRole = planId;
self.usersUpdateUser(currentUser, function(userData) {
toastr.success(monster.template(self, '!' + toastrMessages.userUpdated, { name: userData.data.first_name + ' ' + userData.data.last_name }));
self.usersRender({ userId: userData.data.id });
});
});
/* Events for Devices in Users */ /* Events for Devices in Users */
template.on('click', '.create-device', function() { template.on('click', '.create-device', function() {
var $this = $(this), var $this = $(this),
@ -1629,6 +1674,10 @@ define(function(require) {
arrayVMBoxes = [], arrayVMBoxes = [],
allNumbers = []; allNumbers = [];
if (_.size(self.appFlags.users.servicePlansRole) > 0) {
formattedData.licensedUserRoles = self.appFlags.users.servicePlansRole;
}
_.each(data.callflows, function(callflow) { _.each(data.callflows, function(callflow) {
_.each(callflow.numbers, function(number) { _.each(callflow.numbers, function(number) {
if (number.length < 7) { if (number.length < 7) {
@ -2760,6 +2809,15 @@ define(function(require) {
delete userData.language; delete userData.language;
} }
} }
if (userData.extra.hasOwnProperty('licensedRole')) {
userData.service = userData.service || {};
userData.service.plans = {};
userData.service.plans[userData.extra.licensedRole] = {
account_id: monster.config.resellerId,
overrides: {}
};
}
} }
if (userData.hasOwnProperty('call_forward')) { if (userData.hasOwnProperty('call_forward')) {
@ -2805,6 +2863,8 @@ define(function(require) {
self.usersGetFeaturesTemplate(userId, listUsers, callbackAfterData); self.usersGetFeaturesTemplate(userId, listUsers, callbackAfterData);
} else if (type === 'devices') { } else if (type === 'devices') {
self.usersGetDevicesTemplate(userId, callbackAfterData); self.usersGetDevicesTemplate(userId, callbackAfterData);
} else if (type === 'licensed-user-role') {
self.usersGetLicensedRoleTemplate(userId, callbackAfterData);
} }
}, },
@ -3041,6 +3101,36 @@ define(function(require) {
}); });
}); });
}, },
usersGetLicensedRoleTemplate: function(userId, callback) {
var self = this;
self.usersGetUser(userId, function(user) {
var formattedData = self.usersFormatLicensedRolesData(user),
template = $(monster.template(self, 'users-licensed-roles', formattedData));
template.find('#licensed_role').chosen({search_contains: true, width: '220px'});
callback && callback(template, user);
});
},
usersFormatLicensedRolesData: function(user) {
var self = this,
formattedData = {
selectedRole: undefined,
availableRoles: self.appFlags.users.servicePlansRole
};
if (user.hasOwnProperty('service') && user.service.hasOwnProperty('plans') && _.size(user.service.plans) > 0) {
for (var key in user.service.plans) {
if (user.service.plans.hasOwnProperty(key)) {
formattedData.selectedRole = key;
break;
}
}
}
return formattedData;
},
usersFormatDevicesData: function(userId, data) { usersFormatDevicesData: function(userId, data) {
var self = this, var self = this,
formattedData = { formattedData = {
@ -3198,6 +3288,19 @@ define(function(require) {
extra: data.extra extra: data.extra
}; };
if (formattedData.user.extra) {
if (formattedData.user.extra.hasOwnProperty('licensedRole')) {
formattedData.user.service = formattedData.user.service || {};
formattedData.user.service.plans = {};
formattedData.user.service.plans[formattedData.user.extra.licensedRole] = {
account_id: monster.config.resellerId,
overrides: {}
};
}
}
delete formattedData.user.extra;
return formattedData; return formattedData;
}, },
@ -4184,6 +4287,27 @@ define(function(require) {
callback(null, data.data); callback(null, data.data);
} }
}); });
},
availableLicensedUserRoles: function(callback) {
if (monster.config.hasOwnProperty('resellerId') && monster.config.resellerId.length) {
self.callApi({
resource: 'servicePlan.list',
data: {
accountId: self.accountId,
filters: {
paginate: false,
'filter_merge.strategy': 'cumulative'
}
},
success: function(data, status) {
self.appFlags.users.servicePlansRole = _.keyBy(data.data, 'id');
callback(null, self.appFlags.users.servicePlansRole);
}
});
} else {
callback(null, {});
}
} }
}, function(err, results) { }, function(err, results) {
callback && callback(results); callback && callback(results);


+ 14
- 0
views/users-creation.html View File

@ -24,6 +24,20 @@
</div> </div>
</div> </div>
{{/unless}} {{/unless}}
{{#if licensedUserRoles}}
<div class="control-group">
<label for="licensed_role" class="control-label"><i class="fa fa-user"></i></label>
<div class="controls">
<select id="licensed_role" name="user.extra.licensedRole" data-placeholder="{{ i18n.users.licensedUserRoles.selectPlaceholder }}">
<option value></option>
{{#each licensedUserRoles}}
<option value="{{id}}">{{name}}</option>
{{/each}}
</select>
</div>
</div>
{{/if}}
</div> </div>
<div> <div>


+ 4
- 1
views/users-layout.html View File

@ -16,9 +16,12 @@
</span> </span>
</div> </div>
<div class="users-grid">
<div class="users-grid{{#if showLicensedUserRoles}} additional-column{{/if}}">
<div class="grid-row title"> <div class="grid-row title">
<div class="grid-cell name">{{ i18n.users.titleGrid.users }}</div> <div class="grid-cell name">{{ i18n.users.titleGrid.users }}</div>
{{#if showLicensedUserRoles}}
<div class="grid-cell licensed-user-role">{{ i18n.users.titleGrid.userLicensedRoles }}</div>
{{/if}}
<div class="grid-cell extension">{{ i18n.users.titleGrid.extensions }}</div> <div class="grid-cell extension">{{ i18n.users.titleGrid.extensions }}</div>
<div class="grid-cell phone-number">{{ i18n.users.titleGrid.phoneNumbers }}</div> <div class="grid-cell phone-number">{{ i18n.users.titleGrid.phoneNumbers }}</div>
<div class="grid-cell devices">{{ i18n.users.titleGrid.devices }}</div> <div class="grid-cell devices">{{ i18n.users.titleGrid.devices }}</div>


+ 24
- 0
views/users-licensed-roles.html View File

@ -0,0 +1,24 @@
<div class="detail-user-role">
<form class="form form-horizontal user-fields" id="form_update_license_role">
<div class="user-role-wrapper">
<label for="new_password" class="control-label">{{ i18n.users.licensedUserRoles.label }}</label>
<div class="controls">
<select id="licensed_role" name="extra.licensedRole" data-placeholder="{{ i18n.users.licensedUserRoles.selectPlaceholder }}">
<option value></option>
{{#select selectedRole}}
{{#each availableRoles}}
<option value="{{id}}">{{name}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
</form>
<div class="actions">
<div class="pull-right">
<a class="cancel-link monster-link blue" href="javascript:void(0);">{{ i18n.cancel }}</a>
<button type="button" class="monster-button monster-button-success save-user-role">{{ i18n.saveChanges }}</button>
</div>
</div>
</div>

+ 6
- 0
views/users-row.html View File

@ -1,6 +1,12 @@
<div class="grid-row" data-id="{{id}}" data-priv_level="{{priv_level}}" data-name="{{first_name}} {{last_name}}" data-search="{{first_name}} {{last_name}}{{#each extra.listCallerId}} {{formatPhoneNumber this}} {{this}}{{/each}}"> <div class="grid-row" data-id="{{id}}" data-priv_level="{{priv_level}}" data-name="{{first_name}} {{last_name}}" data-search="{{first_name}} {{last_name}}{{#each extra.listCallerId}} {{formatPhoneNumber this}} {{this}}{{/each}}">
<div class="user-cells"> <div class="user-cells">
<div class="name grid-cell" data-type="name"><i class="{{#if extra.isAdmin}}icon-telicon-moderator monster-primary-color{{else}}icon-telicon-user monster-lightgrey{{/if}}"></i> {{ first_name }} {{ last_name }}</div> <div class="name grid-cell" data-type="name"><i class="{{#if extra.isAdmin}}icon-telicon-moderator monster-primary-color{{else}}icon-telicon-user monster-lightgrey{{/if}}"></i> {{ first_name }} {{ last_name }}</div>
{{#if extra.showLicensedUserRoles}}
<div class="licensed-user-role grid-cell" data-type="licensed-user-role">
{{ extra.licensedUserRole }}
</div>
{{/if}}
<div class="extension grid-cell" data-type="extensions"> <div class="extension grid-cell" data-type="extensions">
{{#if extra.extension}} {{#if extra.extension}}
{{ extra.extension }} {{ extra.extension }}


Loading…
Cancel
Save