From 331d8a44057847a3aa249432ddf7625ae86650cc Mon Sep 17 00:00:00 2001 From: Robert Axelsen Date: Thu, 1 Jun 2017 16:31:56 +0200 Subject: [PATCH] TT#16853 Csc pbx changes and fixes What has been done: 1. Rename button in groups module to "ADD NEW GROUP" 2. Investigate Alignment issue on Andreas' laptop. Not able to reproduce 3. Change extension number to have no upper limit 4. When clicking "ADD NEW GROUP" and new card is outside view, it doesn't show it/scroll to it. Works for Robert. Try and solve with scrollTo - window.scrollTo(0,document.body.scrollHeight); 5. Cancel button shows delete box. Remove 6. When editing a card, and switching module, shows "All fields required". Use a VM model to set last edited card id, and a onRouteChange event and controller to hide fields on that card 7. Implement check for whether a new pbx card already is in progress to not allow multiple new cards being created at same time 8. Toggle icons at bottom of card back to editCard and no cancel 9. Add more fine-grained error messages for validation in call blocking module 10. Fix typo in DevicseController name at top of DevicesController.js Change-Id: I3dec8301b39dacec36d7e140246e5d51b6ca1b52 --- app/utils/locales.js | 35 ++++++ classic/src/view/main/Main.js | 3 +- classic/src/view/main/MainController.js | 2 +- .../callblocking/CallBlockingController.js | 25 +++- classic/src/view/pages/pbxconfig/PbxConfig.js | 3 +- .../pages/pbxconfig/PbxConfigController.js | 109 +++++++++++++++--- .../view/pages/pbxconfig/PbxConfigModel.js | 4 +- .../pbxconfig/devices/DevicesController.js | 17 ++- .../view/pages/pbxconfig/groups/GroupsGrid.js | 3 +- .../view/pages/pbxconfig/seats/SeatsGrid.js | 3 +- 10 files changed, 170 insertions(+), 34 deletions(-) diff --git a/app/utils/locales.js b/app/utils/locales.js index 25a96e8c..5f4bcc62 100644 --- a/app/utils/locales.js +++ b/app/utils/locales.js @@ -598,6 +598,34 @@ Ext.define('Ngcp.csc.locales', { fr: 'Mode', sp: 'Mode' }, + save_unsuccess_duplicate_anonymous: { + en: 'An anonymous entry already exists.', + it: 'An anonymous entry already exists.', + de: 'An anonymous entry already exists.', + fr: 'An anonymous entry already exists.', + sp: 'An anonymous entry already exists.' + }, + save_unsuccess_number_empty: { + en: 'Number field can not be empty.', + it: 'Number field can not be empty.', + de: 'Number field can not be empty.', + fr: 'Number field can not be empty.', + sp: 'Number field can not be empty.' + }, + save_unsuccess_duplicate_number: { + en: 'An entry with the same value already exists.', + it: 'An entry with the same value already exists.', + de: 'An entry with the same value already exists.', + fr: 'An entry with the same value already exists.', + sp: 'An entry with the same value already exists.' + }, + save_unsuccess_invalid_number: { + en: 'Invalid number entry.', + it: 'Invalid number entry.', + de: 'Invalid number entry.', + fr: 'Invalid number entry.', + sp: 'Invalid number entry.' + }, submodules: { incoming: { header: { @@ -1970,6 +1998,13 @@ Ext.define('Ngcp.csc.locales', { fr: 'Must be a 3 digit extension number', sp: 'Must be a 3 digit extension number' }, + not_add_new_while_another: { + en: 'Can not create new card while another is active.', + it: 'Can not create new card while another is active.', + de: 'Can not create new card while another is active.', + fr: 'Can not create new card while another is active.', + sp: 'Can not create new card while another is active.' + }, autoattendant: { title: { en: 'Your auto attendants.', diff --git a/classic/src/view/main/Main.js b/classic/src/view/main/Main.js index 75e2efbe..01f9d635 100644 --- a/classic/src/view/main/Main.js +++ b/classic/src/view/main/Main.js @@ -21,7 +21,8 @@ Ext.define('NgcpCsc.view.main.Main', { listeners: { render: 'onMainViewRender', - resize: 'setItemsSize' + resize: 'setItemsSize', + click: 'clickMain' }, name: 'mainView', diff --git a/classic/src/view/main/MainController.js b/classic/src/view/main/MainController.js index f0c08350..b3d86e87 100644 --- a/classic/src/view/main/MainController.js +++ b/classic/src/view/main/MainController.js @@ -86,7 +86,7 @@ Ext.define('NgcpCsc.view.main.MainController', { onNavigationTreeSelectionChange: function(tree, node) { var to = node && (node.get('routeId') || node.get('viewType')); - + this.fireEvent('navSelectionChange'); if (to) { if (node.parentNode) { node.parentNode.expand(); diff --git a/classic/src/view/pages/callblocking/CallBlockingController.js b/classic/src/view/pages/callblocking/CallBlockingController.js index 9e163d65..139b1b87 100644 --- a/classic/src/view/pages/callblocking/CallBlockingController.js +++ b/classic/src/view/pages/callblocking/CallBlockingController.js @@ -38,8 +38,21 @@ Ext.define('NgcpCsc.view.pages.callblocking.CallBlockingController', { } }, - addUnsuccessful: function() { - this.fireEvent('showmessage', false, Ngcp.csc.locales.common.save_unsuccess[localStorage.getItem('languageSelected')]); + addUnsuccessful: function(unsuccessType) { + switch (unsuccessType) { + case 'duplicateAnonymous': + this.fireEvent('showmessage', false, Ngcp.csc.locales.callblocking.save_unsuccess_duplicate_anonymous[localStorage.getItem('languageSelected')]); + break; + case 'numberEmpty': + this.fireEvent('showmessage', false, Ngcp.csc.locales.callblocking.save_unsuccess_number_empty[localStorage.getItem('languageSelected')]); + break; + case 'duplicateNumber': + this.fireEvent('showmessage', false, Ngcp.csc.locales.callblocking.save_unsuccess_duplicate_number[localStorage.getItem('languageSelected')]); + break; + case 'invalidNumber': + this.fireEvent('showmessage', false, Ngcp.csc.locales.callblocking.save_unsuccess_invalid_number[localStorage.getItem('languageSelected')]); + break; + }; }, addToStore: function(newNumber, newId, store) { @@ -88,12 +101,12 @@ Ext.define('NgcpCsc.view.pages.callblocking.CallBlockingController', { me.addToStore('anonymous', newId, store); break; default: - me.addUnsuccessful(); + me.addUnsuccessful('duplicateAnonymous'); break; } break; case ('CallBlockingOutgoing'): - me.addUnsuccessful(); + me.addUnsuccessful('numberEmpty'); break; } break; @@ -106,12 +119,12 @@ Ext.define('NgcpCsc.view.pages.callblocking.CallBlockingController', { me.addToStore(newNumber, newId, store); break; default: - me.addUnsuccessful(); + me.addUnsuccessful('duplicateNumber'); break; }; break; case (1): - me.addUnsuccessful(); + me.addUnsuccessful('invalidNumber'); break; } break; diff --git a/classic/src/view/pages/pbxconfig/PbxConfig.js b/classic/src/view/pages/pbxconfig/PbxConfig.js index 537d892c..ea9e9a58 100644 --- a/classic/src/view/pages/pbxconfig/PbxConfig.js +++ b/classic/src/view/pages/pbxconfig/PbxConfig.js @@ -25,7 +25,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfig', { xtype: 'button', reference: 'addNewBtn', bind: { - text: '{add_new_button}' + text: '{add_new_button}', + disabled: '{add_pbx_active}' }, handler: 'addPbx' }] diff --git a/classic/src/view/pages/pbxconfig/PbxConfigController.js b/classic/src/view/pages/pbxconfig/PbxConfigController.js index 35976fb2..64151e93 100644 --- a/classic/src/view/pages/pbxconfig/PbxConfigController.js +++ b/classic/src/view/pages/pbxconfig/PbxConfigController.js @@ -7,7 +7,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { controller: { '*': { unmatchedroute: 'onRouteChange', - confirmPbxCardRemoval: 'confirmPbxCardRemoval' + confirmPbxCardRemoval: 'confirmPbxCardRemoval', + navSelectionChange: 'abortEdit' } } }, @@ -55,6 +56,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { } } // eval is never the best option + // true value passed as argument in [el, true] is for keeping track + // of toggleFields value Ext.Function.defer(eval('this.' + el.dataset.callback), 1, this, [el, true]); if (fieldToKeepFocused) { fieldToKeepFocused.suspendEvent('blur'); @@ -197,6 +200,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { saveCard: function(el, toggleFields) { var me = this; + var vm = this.getViewModel(); var elClassList = el.firstChild.classList; var currentRoute = window.location.hash; var storeName = this.getStoreFromRoute(currentRoute); @@ -237,6 +241,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { me.showMsgSwitchIconHideFields(storeName, el, toggleFieldsValue, false); break; }; + vm.set('add_pbx_active', false); } else if (emptyCheck > 0) { me.fireEvent('showmessage', false, Ngcp.csc.locales.common.fields_required[localStorage.getItem('languageSelected')]); } else if (invalidCheck > 0) { @@ -275,26 +280,38 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { addPbx: function() { var me = this; + var vm = this.getViewModel(); var currentRoute = window.location.hash; var storeName = me.getStoreFromRoute(currentRoute); var store = Ext.getStore(storeName); var newId = Ext.id().replace('ext-', ''); var grid = this.lookupReference(storeName.toLowerCase() + 'Grid'); var plugin = grid.getPlugin('rowwidget' + storeName); - me.addNewEmptyRowToGrid(store, storeName, newId); - var rec = store.findRecord('id', newId); - plugin.toggleRow(store.indexOf(rec), rec); - Ext.defer(function() { - me.showHideFocusFieldsById(newId, storeName, 'show'); - var el = document.getElementById('edit' + storeName.slice(0, -1) + '-' + newId); - var elClassList = el.firstChild.classList; - elClassList.remove(Ngcp.csc.icons.edit.split(' ')[1]) - elClassList.add(Ngcp.csc.icons.floppy.split(' ')[1]); - el.dataset.callback = 'saveCard'; - el.dataset.qtip = Ngcp.csc.locales.filters.tooltips.save_entry[localStorage.getItem('languageSelected')]; - me.toggleCancelCard(el, 'on'); - grid.updateLayout(); - }, 50); + var addPbxActive = vm.get('add_pbx_active'); + switch (addPbxActive) { + case false: + me.addNewEmptyRowToGrid(store, storeName, newId); + var rec = store.findRecord('id', newId); + plugin.toggleRow(store.indexOf(rec), rec); + Ext.defer(function() { + me.showHideFocusFieldsById(newId, storeName, 'show'); + var el = document.getElementById('edit' + storeName.slice(0, -1) + '-' + newId); + var elClassList = el.firstChild.classList; + elClassList.remove(Ngcp.csc.icons.edit.split(' ')[1]) + elClassList.add(Ngcp.csc.icons.floppy.split(' ')[1]); + el.dataset.callback = 'saveCard'; + el.dataset.qtip = Ngcp.csc.locales.filters.tooltips.save_entry[localStorage.getItem('languageSelected')]; + me.toggleCancelCard(el, 'on'); + grid.updateLayout(); + window.scrollTo(0, document.body.scrollHeight); + vm.set('last_edited_row', storeName.toLowerCase() + '-' + newId); + vm.set('add_pbx_active', true); + }, 50); + break; + case true: + me.fireEvent('showmessage', false, Ngcp.csc.locales.pbxconfig.not_add_new_while_another[localStorage.getItem('languageSelected')]); + break; + }; }, setFieldValue: function(cmp) { @@ -337,6 +354,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { var deviceLabel = Ext.ComponentQuery.query('#' + viewName + '-label-device-' + id) || ''; var macLabel = Ext.ComponentQuery.query('#' + viewName + '-label-mac-' + id) || ''; var statusLabel = Ext.ComponentQuery.query('#' + viewName + '-label-status-' + id) || ''; + // To break out of this function if we switched to module outside pbxconfig + if (mainNameLabel.length === 0) { return; }; // To make sure we always hide name label and field when not editing mainNameLabel[0].setHidden(hideOrShow == 'hide'); nameField[0].setHidden(hideOrShow == 'hide'); @@ -402,10 +421,12 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { editCard: function(el) { var me = this; + var vm = this.getViewModel(); var currentRoute = window.location.hash; var storeName = this.getStoreFromRoute(currentRoute); var recId = el.id.split("-")[1]; var elClassList = el.firstChild.classList; + vm.set('last_edited_row', storeName.toLowerCase() + '-' + recId); this.toggleCancelCard(el, 'on'); // Workaround with split(), since classList.add() does not allow strings // with spaces (https://developer.mozilla.org/en/docs/Web/API/Element/classList) @@ -418,7 +439,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { }, 50); }, - removeCard: function(el) { + removeCard: function(el, evalValue, cancelCheck) { var me = this; var currentRoute = window.location.hash; var storeName = this.getStoreFromRoute(currentRoute); @@ -428,13 +449,19 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { var title = Ngcp.csc.locales.common.delete[localStorage.getItem('languageSelected')]; var question = Ngcp.csc.locales.common.remove_confirm[localStorage.getItem('languageSelected')]; var sucessMsg = Ngcp.csc.locales.common.remove_success[localStorage.getItem('languageSelected')]; + if (cancelCheck === true) { + this.confirmPbxCardRemoval(selectedRow); + return; + }; me.fireEvent('showconfirmbox', title, question, sucessMsg, 'confirmPbxCardRemoval', selectedRow); }, confirmPbxCardRemoval: function(card) { + var vm = this.getViewModel(); var view = this.getView(); var store = card.store; store.remove(card); + vm.set('add_pbx_active', false); Ext.Function.defer(function() { view.fireEvent('cardContainerResized', view); }, 1); @@ -454,7 +481,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { }; }, - cancelCard: function(el, abortAdd) { + cancelCard: function(el) { var me = this; var currentRoute = window.location.hash; var storeName = this.getStoreFromRoute(currentRoute); @@ -466,7 +493,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { var nameRecord = selectedRow.get('name'); switch (nameRecord === '') { case true: - me.removeCard(el); + me.removeCard(el, null, true); break; case false: me.showHideFocusFieldsById(recId, storeName, 'hide'); @@ -480,8 +507,10 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { fieldBlurred: function(event) { var me = this; + var vm = this.getViewModel(); var fields = this.getView().query('textfield'); var anyFieldHasFocus = false; + if (vm.get('add_pbx_active')) { return; }; Ext.defer(function() { for (i = 0; i < fields.length; i++) { if (fields[i].hasFocus) { @@ -491,11 +520,53 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigController', { if (!anyFieldHasFocus) { var currentRoute = window.location.hash; var storeName = me.getStoreFromRoute(currentRoute); - var recId = event.id.split("-")[3]; + var recId = event.id.split('-')[3]; var iconDivId = 'edit' + storeName.slice(0, -1) + '-' + recId; var iconDiv = document.getElementById(iconDivId); me.saveCard(iconDiv, false); } }, 1); + }, + + abortEdit: function () { + var me = this; + var vm = this.getViewModel(); + var currentRoute = window.location.hash; + var storeName = this.getStoreFromRoute(currentRoute); + var store = Ext.getStore(storeName); + var lastEditedCard = vm.get('last_edited_row'); + var recId = lastEditedCard.split('-')[1]; + var addPbxActive = vm.get('add_pbx_active'); + var elClassList; + switch (storeName) { + case 'Groups': + case 'Seats': + case 'Devices': + switch (addPbxActive) { + case true: + var selectedRow = store.findRecord('id', recId); + me.confirmPbxCardRemoval(selectedRow); + break; + case false: + var el = document.getElementById('edit' + storeName.slice(0, -1) + '-' + recId); + if (!el) { + return; + } else { + elClassList = el.firstChild.classList; + }; + if (lastEditedCard.length > 0) { + me.showHideFocusFieldsById(recId, storeName, 'hide'); + }; + elClassList.remove(Ngcp.csc.icons.floppy.split(' ')[1]); + elClassList.add(Ngcp.csc.icons.edit.split(' ')[1]); + el.dataset.callback = 'editCard'; + el.dataset.qtip = Ngcp.csc.locales.filters.tooltips.edit_entry[localStorage.getItem('languageSelected')]; + me.toggleCancelCard(el, 'off'); + vm.set('add_pbx_active', false); + break; + }; + break; + }; } + }); diff --git a/classic/src/view/pages/pbxconfig/PbxConfigModel.js b/classic/src/view/pages/pbxconfig/PbxConfigModel.js index bf6c1dea..1cbb3048 100644 --- a/classic/src/view/pages/pbxconfig/PbxConfigModel.js +++ b/classic/src/view/pages/pbxconfig/PbxConfigModel.js @@ -3,7 +3,9 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.PbxConfigModel', { alias: 'viewmodel.pbxconfig', // non-API data data: { - add_new_button: 'ADD NEW SEAT' + add_new_button: 'ADD NEW GROUP', + last_edited_row: '', + add_pbx_active: false } }); diff --git a/classic/src/view/pages/pbxconfig/devices/DevicesController.js b/classic/src/view/pages/pbxconfig/devices/DevicesController.js index ecbd6483..cfc8340e 100644 --- a/classic/src/view/pages/pbxconfig/devices/DevicesController.js +++ b/classic/src/view/pages/pbxconfig/devices/DevicesController.js @@ -1,6 +1,7 @@ -Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { +Ext.define('NgcpCsc.view.pages.pbxconfig.DevicesController', { extend: 'NgcpCsc.view.pages.pbxconfig.PbxConfigController', alias: 'controller.devices', + listen: { controller: { '*': { @@ -8,6 +9,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { } } }, + onIconClicked: function(event, el) { // overrides onIconClicked of PbxConfigController if (el.dataset.onseatclick) { @@ -33,6 +35,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { } }; }, + onMouseEntered: function(event, el) { var selectedRec = this.getSelectedRec(); var editPanel = Ext.ComponentQuery.query('#seat-edit-panel-' + selectedRec.get('id'))[0]; @@ -40,14 +43,17 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { Ext.Function.defer(eval('this.' + el.dataset.onseathovered), 1, this, [el]); } }, + onMouseLeave: function() { var selectedRec = this.getSelectedRec(); var showPanel = Ext.ComponentQuery.query('#seat-show-panel-' + selectedRec.get('id'))[0]; showPanel.hide(); }, + seatHovered: function(el) { this.setShowEditPanelFields(el); }, + setShowEditPanelFields: function(el) { var selectedRec = this.getSelectedRec(); var showPanel = Ext.ComponentQuery.query('#seat-show-panel-' + selectedRec.get('id'))[0]; @@ -72,6 +78,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { showPanel.getEl().setLeft(parseInt(labelPositioning.left.split('px')[0]) + offset); showPanel.getEl().setTop(parseInt(labelPositioning.top.split('px')[0]) + 20); }, + deviceSelected: function(combo, rec) { var grid = this.lookupReference('devicesGrid'); var devicesListStore = Ext.getStore('DevicesList'); @@ -93,6 +100,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { nameField.focus(); }, 50) }, + editSeat: function(el) { var selectedRec = this.getSelectedRec(); var showPanel = Ext.ComponentQuery.query('#seat-show-panel-' + selectedRec.get('id'))[0]; @@ -124,6 +132,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { editPanel.getEl().setLeft(parseInt(labelPositioning.left.split('px')[0]) + offset); editPanel.getEl().setTop(parseInt(labelPositioning.top.split('px')[0]) + 20); }, + deleteSeat: function() { var me = this; var selectedRec = me.getSelectedRec(); @@ -138,6 +147,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { }); }, + seatRemoveConfirmed: function(seat) { var me = this; var grid = me.lookupReference('devicesGrid'); @@ -150,6 +160,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { grid.focus(); }, + saveSeat: function() { var me = this; var grid = this.lookupReference('devicesGrid'); @@ -177,6 +188,7 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { me.commitUnsavedChanges(); editPanel.hide(); }, + commitUnsavedChanges: function() { var grid = this.lookupReference('devicesGrid'); var selectedRec = this.getSelectedRec(); @@ -190,13 +202,16 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.DevicseController', { grid.getView().refresh(); }, 50); }, + discardChanges: function() { var editPanel = Ext.ComponentQuery.query('#seat-edit-panel-' + this.getSelectedRec().get('id'))[0]; editPanel.hide(); }, + getSelectedRec: function() { var grid = this.lookupReference('devicesGrid'); var selectedRec = grid.getSelectionModel().getSelection()[0]; return selectedRec; } + }); diff --git a/classic/src/view/pages/pbxconfig/groups/GroupsGrid.js b/classic/src/view/pages/pbxconfig/groups/GroupsGrid.js index 40eb6dea..3624d916 100644 --- a/classic/src/view/pages/pbxconfig/groups/GroupsGrid.js +++ b/classic/src/view/pages/pbxconfig/groups/GroupsGrid.js @@ -109,9 +109,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.seats.GroupsGrid', { id: 'groups-textfield-extension-{record.id}' }, msgTarget: 'side', - maxLength: 3, enforceMaxLength: true, - regex: /^[0-9]{3}$/, + regex: /^[1-9][0-9]*$/, regexText: Ngcp.csc.locales.pbxconfig.digit_extension_number[localStorage.getItem('languageSelected')], listeners: { focus: { diff --git a/classic/src/view/pages/pbxconfig/seats/SeatsGrid.js b/classic/src/view/pages/pbxconfig/seats/SeatsGrid.js index 5764cfe1..c3351953 100644 --- a/classic/src/view/pages/pbxconfig/seats/SeatsGrid.js +++ b/classic/src/view/pages/pbxconfig/seats/SeatsGrid.js @@ -112,9 +112,8 @@ Ext.define('NgcpCsc.view.pages.pbxconfig.seats.SeatsGrid', { id: 'seats-textfield-extension-{record.id}' }, msgTarget: 'side', - maxLength: 3, enforceMaxLength: true, - regex: /^[0-9]{3}$/, + regex: /^[1-9][0-9]*$/, regexText: Ngcp.csc.locales.pbxconfig.digit_extension_number[localStorage.getItem('languageSelected')], listeners: { focus: {