-
+ {{#each usersList}}
+ {{#if label}}
+
- + + {{label}} + {{count}} + + {{/if}} + {{/each}} +
diff --git a/app.js b/app.js index 657842e..6f5d568 100644 --- a/app.js +++ b/app.js @@ -29,6 +29,9 @@ define(function(require) { requests: {}, subscribe: {}, + appFlags: { + global: {} + }, subModules: ['devices', 'groups', 'numbers', 'strategy', 'callLogs', 'users', 'myOffice', 'featureCodes', 'vmboxes'], @@ -54,9 +57,11 @@ define(function(require) { parent = container || $('#monster_content'), template = $(monster.template(self, 'app')); - /* On first Load, load my office */ - template.find('.category#myOffice').addClass('active'); - monster.pub('voip.myOffice.render', { parent: template.find('.right-content') }); + self.loadGlobalData(function() { + /* On first Load, load my office */ + template.find('.category#myOffice').addClass('active'); + monster.pub('voip.myOffice.render', { parent: template.find('.right-content') }); + }); self.bindEvents(template); @@ -69,6 +74,38 @@ define(function(require) { var self = this; }, + loadGlobalData: function(callback) { + var self = this; + + monster.parallel({ + servicePlansRole: 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) { + var formattedData = _.keyBy(data.data, 'id'); + + callback(null, formattedData); + } + }); + } else { + callback(null, {}); + } + } + }, function(err, results) { + self.appFlags.global = results; + + callback && callback(self.appFlags.global); + }); + }, + bindEvents: function(parent) { var self = this, container = parent.find('.right-content'); diff --git a/i18n/en-US.json b/i18n/en-US.json index da906be..f53311e 100644 --- a/i18n/en-US.json +++ b/i18n/en-US.json @@ -1130,7 +1130,11 @@ "__version": "3.23", "missingCnamE911Message": "Please setup your Company Caller ID and e911 on a Main Number.", "missingCnamMessage": "Please setup your Company Caller ID on a Main Number.", - "missingE911Message": "Please setup your e911 on a Main Number." + "missingE911Message": "Please setup your e911 on a Main Number.", + + "userChartLegend": { + "none": "No Role" + } }, "__comment": "UI-299, v3.19_s2: Added the Feature Codes tab to SmartPBX.", diff --git a/submodules/myOffice/myOffice.css b/submodules/myOffice/myOffice.css index 5367aa0..858372c 100644 --- a/submodules/myOffice/myOffice.css +++ b/submodules/myOffice/myOffice.css @@ -78,6 +78,9 @@ -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } +#myoffice_container .dashboard-left-section { + margin-bottom: 20px; +} #myoffice_container .dashboard-content-div.dashboard-left-content { padding-right: 10px; } @@ -108,9 +111,6 @@ color: #22a5ff; float: right; } -#myoffice_container .dashboard-left-content .left-section-content { - margin-bottom: 20px; -} #myoffice_container .dashboard-left-content .users-section-content .users-element { display: inline-block; padding: 5px; @@ -132,6 +132,38 @@ float: left; } +#myoffice_container .users-section-content { + display: block; +} + +#myoffice_container .users-section-content .users-canvas-wrapper { + width: 130px; + height: 130px; +} + +#myoffice_container .users-section-content .users-chart-legend { + margin-left: 150px; + margin-right: 10px; +} +#myoffice_container .users-section-content .users-chart-legend ul { + list-style: none; + margin: 0px; +} +#myoffice_container .users-section-content .users-chart-legend .legend-element { + font-size: 12px; + line-height: 18px; +} +#myoffice_container .users-section-content .users-chart-legend .legend-element.no-user { + opacity: 0.5; +} +#myoffice_container .users-section-content .users-chart-legend .legend-number { + float: right; +} +#myoffice_container .users-section-content .users-chart-legend .legend-color { + margin-right: 10px; + font-size: 14px; +} + #myoffice_container .devices-section-content .devices-chart-legend { margin-left: 150px; margin-right: 10px; diff --git a/submodules/myOffice/myOffice.js b/submodules/myOffice/myOffice.js index d7ad8a3..f0afee4 100644 --- a/submodules/myOffice/myOffice.js +++ b/submodules/myOffice/myOffice.js @@ -60,11 +60,13 @@ define(function(require) { faxNumbers: myOfficeData.faxNumbers || [], topMessage: myOfficeData.topMessage, devicesList: _.toArray(myOfficeData.devicesData).sort(function(a, b) { return b.count - a.count; }), + usersList: _.toArray(myOfficeData.usersData).sort(function(a, b) { return b.count - a.count ; }), assignedNumbersList: _.toArray(myOfficeData.assignedNumbersData).sort(function(a, b) { return b.count - a.count; }), // numberTypesList: _.toArray(myOfficeData.numberTypesData).sort(function(a, b) { return b.count - a.count ; }), classifiedNumbers: myOfficeData.classifiedNumbers, directoryUsers: myOfficeData.directory.users && myOfficeData.directory.users.length || 0, - directoryLink: myOfficeData.directoryLink + directoryLink: myOfficeData.directoryLink, + showUserTypes: _.size(self.appFlags.global.servicePlansRole) > 0 }, template = $(monster.template(self, 'myOffice-layout', dataTemplate)), $devicesCanvas = template.find('#dashboard_devices_chart'), @@ -77,6 +79,7 @@ define(function(require) { } ], devicesDataSet = _.chain(myOfficeData.devicesData).omit('totalCount').sortBy('count').value(), + usersDataSet = _.chain(myOfficeData.usersData).omit('totalCount').sortBy('count').value(), assignedNumbersDataSet = _.chain(myOfficeData.assignedNumbersData).omit('totalCount').sortBy('count').value(), classifiedNumbersDataSet = _.chain(myOfficeData.classifiedNumbers).sortBy('count').value(), createDoughnutCanvas = function createDoughnutCanvas($target) { @@ -110,6 +113,7 @@ define(function(require) { }; devicesDataSet = _.isEmpty(devicesDataSet) ? emptyDataSet : devicesDataSet; + usersDataSet = _.isEmpty(usersDataSet) ? emptyDataSet : usersDataSet; assignedNumbersDataSet = _.isEmpty(assignedNumbersDataSet) ? emptyDataSet : assignedNumbersDataSet; classifiedNumbersDataSet = _.isEmpty(classifiedNumbersDataSet) ? emptyDataSet : classifiedNumbersDataSet; @@ -146,6 +150,16 @@ define(function(require) { borderWidth: 0 }); + if (dataTemplate.showUserTypes) { + var $usersCanvas = template.find('#dashboard_user_type_chart'); + + createDoughnutCanvas($usersCanvas, { + data: _.map(usersDataSet, 'count'), + backgroundColor: _.map(usersDataSet, 'color'), + borderWidth: 0 + }); + } + self.myOfficeCheckWalkthrough(); callback && callback(); @@ -451,6 +465,13 @@ define(function(require) { }, totalCount: 0 }, + users = { + "_unassigned": { + label: self.i18n.active().myOffice.userChartLegend.none, + count: 0, + color: self.chartColors[8] + } + }, // numberTypes = { // local: { // label: self.i18n.active().myOffice.numberChartLegend.local, @@ -475,6 +496,17 @@ define(function(require) { registeredDevices = _.map(data.devicesStatus, function(device) { return device.device_id; }), unregisteredDevices = 0; + if (_.size(self.appFlags.global.servicePlansRole) > 0) { + var i = 7; // start from the end of chart colors so all the charts don't look the same + _.each(self.appFlags.global.servicePlansRole, function(role, id) { + users[id] = { + label: role.name, + count: 0, + color: self.chartColors[i >= 1 ? i-- : 8] + }; + }); + } + _.each(data.numbers, function(numData, num) { _.find(data.classifiers, function(classifier, classifierKey) { if (!(classifierKey in classifierRegexes)) { @@ -540,7 +572,22 @@ define(function(require) { }); _.each(data.users, function(val) { - if (val.features.indexOf('conferencing') >= 0) { + if (val.hasOwnProperty('service') && val.service.hasOwnProperty('plans') && !_.isEmpty(val.service.plans)) { + var planId; + + for (var key in val.service.plans) { + if (val.service.plans.hasOwnProperty(key)) { + planId = key; + break; + } + } + + users[planId].count++; + } else { + users._unassigned.count++; + } + + if (val.features.indexOf("conferencing") >= 0) { totalConferences++; } }); @@ -601,6 +648,7 @@ define(function(require) { data.totalChannels = channelsArray.length; data.devicesData = devices; + data.usersData = users; data.assignedNumbersData = assignedNumbers; // data.numberTypesData = numberTypes; data.totalConferences = totalConferences; diff --git a/submodules/users/users.js b/submodules/users/users.js index bf57c0a..37c5321 100644 --- a/submodules/users/users.js +++ b/submodules/users/users.js @@ -17,8 +17,7 @@ define(function(require) { users: { smartPBXCallflowString: ' SmartPBX\'s Callflow', smartPBXConferenceString: ' SmartPBX Conference', - smartPBXVMBoxString: '\'s VMBox', - servicePlansRole: {} + smartPBXVMBoxString: '\'s VMBox' } }, @@ -175,7 +174,7 @@ define(function(require) { extension: dataUser.hasOwnProperty('presence_id') ? dataUser.presence_id : '', hasFeatures: false, isAdmin: dataUser.priv_level === 'admin', - showLicensedUserRoles: _.size(self.appFlags.users.servicePlansRole) > 0, + showLicensedUserRoles: _.size(self.appFlags.global.servicePlansRole) > 0, licensedUserRole: self.i18n.active().users.licensedUserRoles.none, listCallerId: [], listExtensions: [], @@ -251,8 +250,8 @@ define(function(require) { } } - if (self.appFlags.users.servicePlansRole.hasOwnProperty(planId)) { - dataUser.extra.licensedUserRole = self.appFlags.users.servicePlansRole[planId].name; + if (self.appFlags.global.servicePlansRole.hasOwnProperty(planId)) { + dataUser.extra.licensedUserRole = self.appFlags.global.servicePlansRole[planId].name; } } @@ -357,7 +356,7 @@ define(function(require) { mapUsers = {}, registeredDevices = _.map(data.deviceStatus, function(device) { return device.device_id; }); - if (_.size(self.appFlags.users.servicePlansRole) > 0) { + if (_.size(self.appFlags.global.servicePlansRole) > 0) { dataTemplate.showLicensedUserRoles = true; } @@ -1674,8 +1673,8 @@ define(function(require) { arrayVMBoxes = [], allNumbers = []; - if (_.size(self.appFlags.users.servicePlansRole) > 0) { - formattedData.licensedUserRoles = self.appFlags.users.servicePlansRole; + if (_.size(self.appFlags.global.servicePlansRole) > 0) { + formattedData.licensedUserRoles = self.appFlags.global.servicePlansRole; } _.each(data.callflows, function(callflow) { @@ -3117,7 +3116,7 @@ define(function(require) { var self = this, formattedData = { selectedRole: undefined, - availableRoles: self.appFlags.users.servicePlansRole + availableRoles: self.appFlags.global.servicePlansRole }; if (user.hasOwnProperty('service') && user.service.hasOwnProperty('plans') && _.size(user.service.plans) > 0) { @@ -4287,27 +4286,6 @@ define(function(require) { 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) { callback && callback(results); diff --git a/views/myOffice-layout.html b/views/myOffice-layout.html index 9b7842f..f785073 100644 --- a/views/myOffice-layout.html +++ b/views/myOffice-layout.html @@ -34,9 +34,30 @@ {{totalUsers}}