diff --git a/app.json b/app.json index 8e8f9834..c3ddfa99 100644 --- a/app.json +++ b/app.json @@ -198,7 +198,7 @@ "js": [ // // Remove this entry to individually load sources from the framework. // { -// "path": "${framework.dir}/build/ext-all-rtl-debug.js" +// "path": "${framework.dir}/build/ext-all-debug.js" // } ] }, @@ -549,17 +549,22 @@ "classic": { "toolkit": "classic", "theme": "theme-triton" - }, + } + + // we gonna activate modern later on + /*, "modern": { "toolkit": "modern", "theme": "theme-triton" - } + }*/ }, /** * Uniquely generated id for this application, used as prefix for localStorage keys. * Normally you should never change this value. */ - "id": "39acbe74-575a-4e77-8062-a62324a1e58f" + "id": "39acbe74-575a-4e77-8062-a62324a1e58f", + + "locale": "en" } diff --git a/app/data/addressbook.json b/app/data/addressbook.json index db81315a..49f8afe6 100644 --- a/app/data/addressbook.json +++ b/app/data/addressbook.json @@ -1,59 +1,53 @@ { - "data": [ - { - "firstname": "John", - "lastname": "Doe", - "company": "Acme Inc", - "home": "4311111", - "office": "4311112", - "mobile": "4311113", - "fax": "4311114", - "e-mail": "john@acmetest4.inc", - "homepage": "http://acmetest4.inc" - }, - { - "firstname": "Jane", - "lastname": "Doe", - "company": "Acme Inc", - "home": "4322222", - "office": "4322223", - "mobile": "4322224", - "fax": "4322225", - "e-mail": "jane@acmetest4.inc", - "homepage": "http://acmetest4.inc" - }, - { - "firstname": "Frank", - "lastname": "Costello", - "company": "Acme Inc", - "home": "4333333", - "office": "4333334", - "mobile": "4333335", - "fax": "4333336", - "e-mail": "frank@acmetest4.inc", - "homepage": "http://acmetest4.inc" - }, - { - "firstname": "Bonny", - "lastname": "Johnson", - "company": "Acme Inc", - "home": "4344444", - "office": "4344445", - "mobile": "4344446", - "fax": "4344447", - "e-mail": "bonny@acmetest4.inc", - "homepage": "http://acmetest4.inc" - }, - { - "firstname": "Peter", - "lastname": "Wallet", - "company": "Acme Inc", - "home": "4355555", - "office": "4355556", - "mobile": "4355557", - "fax": "4355558", - "e-mail": "peter@acmetest4.inc", - "homepage": "http://acmetest4.inc" - } - ] + "data": [{ + "firstname": "John", + "lastname": "Doe", + "company": "Acme Inc", + "home": "4311111", + "office": "4311112", + "mobile": "4311113", + "fax": "4311114", + "e_mail": "john@acmetest4.inc", + "homepage": "http://acmetest4.inc" + }, { + "firstname": "Jane", + "lastname": "Doe", + "company": "Acme Inc", + "home": "4322222", + "office": "4322223", + "mobile": "4322224", + "fax": "4322225", + "e_mail": "jane@acmetest4.inc", + "homepage": "http://acmetest4.inc" + }, { + "firstname": "Frank", + "lastname": "Costello", + "company": "Acme Inc", + "home": "4333333", + "office": "4333334", + "mobile": "4333335", + "fax": "4333336", + "e_mail": "frank@acmetest4.inc", + "homepage": "http://acmetest4.inc" + }, { + "firstname": "Bonny", + "lastname": "Johnson", + "company": "Acme Inc", + "home": "4344444", + "office": "4344445", + "mobile": "4344446", + "fax": "4344447", + "e_mail": "bonny@acmetest4.inc", + "homepage": "http://acmetest4.inc" + }, { + "firstname": "Peter", + "lastname": "Wallet", + "company": "Acme Inc", + "home": "4355555", + "office": "4355556", + "mobile": "4355557", + "fax": "4355558", + "e_mail": "peter@acmetest4.inc", + "homepage": "http://acmetest4.inc" + }] } diff --git a/app/data/calls.json b/app/data/calls.json index 27d7e977..452ce688 100644 --- a/app/data/calls.json +++ b/app/data/calls.json @@ -1,40 +1,93 @@ { - "data": [ - { - "source-cli": "43991001", - "duration": 19.488, - "charges": 40.112, - "start_time": "2016-10-07T14:05:33.384000000+02:00" - }, - { - "source-cli": "Reminder", - "duration": 2.000, - "charges": 0.000, - "start_time": "2016-10-07T15:00:53.284000000+02:00" - }, - { - "source-cli": "43991001", - "duration": 84.332, - "charges": 15.014, - "start_time": "2016-10-07T15:05:35.384000000+02:00" - }, - { - "source-cli": "Voicebox", - "duration": 11.342, - "charges": 0.000, - "start_time": "2016-10-07T15:45:16.184000000+02:00" - }, - { - "source-cli": "43991007", - "duration": 1.023, - "charges": 123.040, - "start_time": "2016-10-07T16:01:33.384000000+02:00" - }, - { - "source-cli": "43996601", - "duration": 125.987, - "charges": 23.010, - "start_time": "2016-10-07T16:05:53.584000000+02:00" - } - ] + "data": [{ + "call_type": "call", //('call'|'cfu'|'cfb'|'cft'|'cfna') + "source_cli": "43991001", + "duration": 19.488, + "charges": 40.112, + "start_time": "2016-10-18T14:05:33.384000000+02:00" + }, { + "call_type": "cfu", + "source_cli": "Reminder", + "duration": 2.000, + "charges": 0.000, + "start_time": "2016-10-13T15:00:53.284000000+02:00" + }, { + "call_type": "cfb", + "source_cli": "43991001", + "duration": 84.332, + "charges": 15.014, + "start_time": "2016-10-07T15:05:35.384000000+02:00" + }, { + "call_type": "cft", + "source_cli": "Voicebox", + "duration": 11.342, + "charges": 0.000, + "start_time": "2016-10-07T15:45:16.184000000+02:00" + }, { + "call_type": "cfna", + "source_cli": "43991007", + "duration": 1.023, + "charges": 123.040, + "start_time": "2016-10-07T16:01:33.384000000+02:00" + }, { + "call_type": "call", + "source_cli": "43991001", + "duration": 19.488, + "charges": 40.112, + "start_time": "2016-10-07T14:05:33.384000000+02:00" + }, { + "call_type": "cfu", + "source_cli": "Reminder", + "duration": 2.000, + "charges": 0.000, + "start_time": "2016-10-07T15:00:53.284000000+02:00" + }, { + "call_type": "cfb", + "source_cli": "43991001", + "duration": 84.332, + "charges": 15.014, + "start_time": "2016-10-07T15:05:35.384000000+02:00" + }, { + "call_type": "cft", + "source_cli": "Voicebox", + "duration": 11.342, + "charges": 0.000, + "start_time": "2016-10-07T15:45:16.184000000+02:00" + }, { + "call_type": "cfna", + "source_cli": "43991007", + "duration": 1.023, + "charges": 123.040, + "start_time": "2016-10-07T16:01:33.384000000+02:00" + }, { + "call_type": "call", + "source_cli": "43991001", + "duration": 19.488, + "charges": 40.112, + "start_time": "2016-10-07T14:05:33.384000000+02:00" + }, { + "call_type": "cfu", + "source_cli": "Reminder", + "duration": 2.000, + "charges": 0.000, + "start_time": "2016-10-07T15:00:53.284000000+02:00" + }, { + "call_type": "cfb", + "source_cli": "43991001", + "duration": 84.332, + "charges": 15.014, + "start_time": "2016-10-07T15:05:35.384000000+02:00" + }, { + "call_type": "cft", + "source_cli": "Voicebox", + "duration": 11.342, + "charges": 0.000, + "start_time": "2016-10-07T15:45:16.184000000+02:00" + }, { + "call_type": "cfna", + "source_cli": "43991007", + "duration": 1.023, + "charges": 123.040, + "start_time": "2016-10-01T16:01:33.384000000+02:00" + }] } diff --git a/app/locales.js b/app/locales.js new file mode 100644 index 00000000..3d5ff013 --- /dev/null +++ b/app/locales.js @@ -0,0 +1,102 @@ +Ext.define('Ngcp.csc.locales', { + statics: { + summary: { + title: { + en: 'Welcome to your personal desktop.' + }, + account_balance: { + en: 'ACCOUNT BALANCE' + }, + clients: { + en: 'CLIENTS' + }, + clients_label: { + en: 'client devices registered' + }, + new_voicemails: { + en: 'NEW VOICEMAILS' + }, + call_forwards: { + en: 'CALL FORWARDS' + }, + all_voicemails: { + en: 'all voicemails' + }, + reminder: { + en: 'view settings' + } + }, + calls: { + section_title: { + en: 'Incoming and outgoing calls.' + }, + recent_calls: { + en: 'RECENT CALLS' + }, + columns: { + number: { + en: 'number' + }, + duration: { + en: 'duration' + }, + charges: { + en: 'charges' + }, + date: { + en: 'date' + } + }, + call_type: { + incoming: { + en: 'incoming' + }, + outgoing: { + en: 'outgoing' + }, + forwarded: { + en: 'forwarded' + } + }, + all_calls: { + en: 'all calls' + } + }, + + filters: { + search: { + en: 'SEARCH' + }, + from: { + en: 'time range (DD.MM.YYYY)' + }, + to: { + en: 'to' + }, + search_term: { + en: 'search term' + }, + apply: { + en: 'apply filter' + }, + reset: { + en: 'reset filter' + } + }, + common: { + today: { + en: 'Today' + }, + + last_week: { + en: 'Last week' + }, + past: { + en: 'Past' + }, + no: { + en: 'no' + } + } + } +}) diff --git a/app/model/Call.js b/app/model/Call.js new file mode 100644 index 00000000..c742b6d6 --- /dev/null +++ b/app/model/Call.js @@ -0,0 +1,24 @@ +Ext.define('NgcpCsc.model.Call', { + extend: 'Ext.data.Model', + + fields: [{ + name: 'call-type', + type: 'string' + }, { + name: 'source-cli', + type: 'string' + }, { + name: 'duration', + type: 'string' + }, { + name: 'charges', + type: 'string' + }, { + name: 'start_time', + type: 'string' + }, { + name: 'timeGroup', + type: 'string', + persist: false + }] +}); diff --git a/app/store/Calls.js b/app/store/Calls.js new file mode 100644 index 00000000..46e807a5 --- /dev/null +++ b/app/store/Calls.js @@ -0,0 +1,45 @@ +Ext.define('NgcpCsc.store.Calls', { + extend: 'Ext.data.Store', + + storeId: 'Calls', + + model: 'NgcpCsc.model.Call', + + autoLoad: true, + + groupField: 'timeGroup', + + proxy: { + type: 'ajax', + url: '/app/data/calls.json', + reader: { + type: 'json', + rootProperty: 'data' + } + }, + + listeners: { + load: function(store, recs) { + + var callStartTime, + today = new Date(), + oneWeekAgo = new Date(); + + today.setDate(today.getDate()); + oneWeekAgo.setDate(oneWeekAgo.getDate() - 7); + + Ext.each(recs, function(rec) { + callStartTime = new Date(rec.get('start_time')).getTime(); + if (callStartTime >= today.getTime()) { + rec.set('timeGroup', '1.' + Ngcp.csc.locales.common.today[Ext.manifest.locale]) + } else if (callStartTime < today.getTime() && callStartTime > oneWeekAgo.getTime()) { + rec.set('timeGroup', '2.' + Ngcp.csc.locales.common.last_week[Ext.manifest.locale]) + } else { + rec.set('timeGroup', '3.' + Ngcp.csc.locales.common.past[Ext.manifest.locale]) + } + }); + this.group(); + } + } + +}); diff --git a/app/store/NavigationTree.js b/app/store/NavigationTree.js index e1927eea..73777fbf 100644 --- a/app/store/NavigationTree.js +++ b/app/store/NavigationTree.js @@ -9,87 +9,73 @@ Ext.define('NgcpCsc.store.NavigationTree', { root: { expanded: true, - children: [ - { - text: 'Desktop', - iconCls: 'x-fa fa-desktop', - // rowCls: 'nav-tree-badge nav-tree-badge-hot', + children: [{ + text: 'Desktop', + iconCls: 'x-fa fa-desktop', + viewType: 'summary', + routeId: 'desktop', + leaf: true + }, { + text: 'Calls', + iconCls: 'x-fa fa-phone', + viewType: 'calls', + routeId: 'callist', + leaf: true + }, { + text: 'Voicemails', + iconCls: 'x-fa fa-envelope', + viewType: 'pageblank', + routeId: 'voicebox', + leaf: true + }, { + text: 'Address book', + iconCls: 'x-fa fa-book', + viewType: 'pageblank', + routeId: 'addressbook', + leaf: true + }, { + text: 'Call forward', + iconCls: 'x-fa fa-mail-forward', + expanded: false, + selectable: false, + children: [{ + text: 'Mapping', + iconCls: 'x-fa fa-sitemap', viewType: 'pageblank', - routeId: 'desktop', + routeId: 'callforward/mapping', leaf: true - }, - { - text: 'Calls', - iconCls: 'x-fa fa-phone', + }, { + text: 'Destinations sets', + iconCls: 'x-fa fa-plane', viewType: 'pageblank', - routeId: 'callist', + routeId: '/callforward/destination', leaf: true - }, - { - text: 'Voicemails', - iconCls: 'x-fa fa-envelope', + }, { + text: 'Time sets', + iconCls: 'x-fa fa-clock-o', viewType: 'pageblank', - routeId: 'voicebox', + routeId: '/callforward/time', leaf: true - }, - { - text: 'Address book', - iconCls: 'x-fa fa-book', - viewType: 'pageblank', - routeId: 'addressbook', - leaf: true - }, - { - text: 'Call forward', - iconCls: 'x-fa fa-mail-forward', - expanded: false, - selectable: false, - children: [ - { - text: 'Mapping', - iconCls: 'x-fa fa-sitemap', - viewType: 'pageblank', - routeId: 'callforward/mapping', - leaf: true - }, - { - text: 'Destinations sets', - iconCls: 'x-fa fa-plane', - viewType: 'pageblank', - routeId: '/callforward/destination', - leaf: true - }, - { - text: 'Time sets', - iconCls: 'x-fa fa-clock-o', - viewType: 'pageblank', - routeId: '/callforward/time', - leaf: true - } - ] - }, - { - text: 'Call barring', - iconCls: 'x-fa fa-ban', - routeId:'callblock', - viewType: 'pageblank', - leaf: 'true' + }] + }, { + text: 'Call barring', + iconCls: 'x-fa fa-ban', + routeId: 'callblock', + viewType: 'pageblank', + leaf: 'true' - }, - { - text: 'Reminder', - iconCls: 'x-fa fa-sticky-note', - viewType: 'pageblank', - routeId: 'reminder', - leaf: true - }, - { - text: 'Account', - iconCls: 'x-fa fa-user', - viewType: 'pageblank', - routeId:'account', - leaf: true - } - ] + }, { + text: 'Reminder', + iconCls: 'x-fa fa-sticky-note', + viewType: 'pageblank', + routeId: 'reminder', + leaf: true + }, { + text: 'Account', + iconCls: 'x-fa fa-user', + viewType: 'pageblank', + routeId: 'account', + leaf: true + }] } }); diff --git a/classic/sass/src/view/pages/calls/Calls.scss b/classic/sass/src/view/pages/calls/Calls.scss new file mode 100644 index 00000000..f228f3a2 --- /dev/null +++ b/classic/sass/src/view/pages/calls/Calls.scss @@ -0,0 +1,8 @@ +// mixins + + +// custom rules +.calls-icon { + padding-left: 10px; + padding-right: 10px; +} diff --git a/classic/sass/src/view/pages/summary/Desktop.scss b/classic/sass/src/view/pages/summary/Desktop.scss new file mode 100644 index 00000000..3974686c --- /dev/null +++ b/classic/sass/src/view/pages/summary/Desktop.scss @@ -0,0 +1,9 @@ +// mixins + + +// custom rules +.fa-rotate-left:before, +.fa-exclamation:before { + color:$base-color; + padding: 0px 10px 0px 0px; +} diff --git a/classic/sass/src/view/pages/summary/Summary.scss b/classic/sass/src/view/pages/summary/Summary.scss new file mode 100644 index 00000000..3974686c --- /dev/null +++ b/classic/sass/src/view/pages/summary/Summary.scss @@ -0,0 +1,9 @@ +// mixins + + +// custom rules +.fa-rotate-left:before, +.fa-exclamation:before { + color:$base-color; + padding: 0px 10px 0px 0px; +} diff --git a/classic/src/Application.js b/classic/src/Application.js index d1055411..49be8dee 100644 --- a/classic/src/Application.js +++ b/classic/src/Application.js @@ -17,6 +17,7 @@ Ext.define('NgcpCsc.Application', { stores: [ 'NavigationTree', + 'Calls', 'Languages' ], diff --git a/classic/src/view/common/gridfilters/GridFilters.js b/classic/src/view/common/gridfilters/GridFilters.js new file mode 100644 index 00000000..7b7fd1f7 --- /dev/null +++ b/classic/src/view/common/gridfilters/GridFilters.js @@ -0,0 +1,48 @@ +Ext.define('NgcpCsc.view.common.gridfilters.GridFilters.js', { + extend: 'Ext.form.Panel', + + xtype: 'gridfilters', + + controller: 'gridfilters', + + margin: '0 10 0 0', + + items: [{ + html: Ngcp.csc.locales.filters.search[Ext.manifest.locale], + padding: '10 0 10 0' + }, { + xtype: 'datefield', + format: 'd.m.Y', + labelAlign: 'top', + width: '100%', + fieldLabel: Ngcp.csc.locales.filters.from[Ext.manifest.locale], + name: 'from_date' + }, { + xtype: 'datefield', + format: 'd.m.Y', + width: '100%', + name: 'to_date', + maxValue: new Date() // limited to the current date or prior + }, { + xtype: 'textfield', + labelAlign: 'top', + width: '100%', + fieldLabel: Ngcp.csc.locales.filters.search_term[Ext.manifest.locale] + }, { + layout: 'hbox', + margin: '10 0 0 0', + defaults: { + xtype: 'button', + flex: 1 + }, + items: [{ + text: Ngcp.csc.locales.filters.apply[Ext.manifest.locale], + margin: '0 5 0 0', + handler: 'submitFilters' + }, { + text: Ngcp.csc.locales.filters.reset[Ext.manifest.locale], + handler: 'resetFilters' + }] + }] + +}) diff --git a/classic/src/view/common/gridfilters/GridFiltersController.js b/classic/src/view/common/gridfilters/GridFiltersController.js new file mode 100644 index 00000000..4a113471 --- /dev/null +++ b/classic/src/view/common/gridfilters/GridFiltersController.js @@ -0,0 +1,12 @@ +Ext.define('NgcpCsc.view.common.gridfilters.GridFiltersController', { + extend: 'Ext.app.ViewController', + alias: 'controller.gridfilters', + + submitFilters: function() { + this.getView()._attachedCmp.getStore().load(); + }, + + resetFilters: function() { + this.getView().getForm().reset(); + } +}); diff --git a/classic/src/view/main/Main.js b/classic/src/view/main/Main.js index 8ef79847..9b29f48a 100644 --- a/classic/src/view/main/Main.js +++ b/classic/src/view/main/Main.js @@ -23,81 +23,70 @@ Ext.define('NgcpCsc.view.main.Main', { render: 'onMainViewRender' }, - items: [ - { - xtype: 'toolbar', - cls: 'sencha-dash-dash-headerbar shadow', - height: 64, - itemId: 'headerBar', - items: [ - { - xtype: 'component', - reference: 'logo', - cls: 'logo', - html: '', - width: 250 - }, - { - margin: '0 0 0 8', - ui: 'header', - iconCls:'x-fa fa-navicon', - id: 'main-navigation-btn', - handler: 'onToggleNavigationSize' - }, - '->', - { - iconCls:'x-fa fa-th-large', - ui: 'header', - href: '#account', - hrefTarget: '_self', - tooltip: 'See your profile' - }, - { - xtype: 'tbtext', - text: 'Logged in as TestUser', - cls: 'top-user-name' - }, - { - xtype: 'image', - cls: 'header-right-profile-image', - height: 35, - width: 35, - alt:'current user image', - src: 'resources/images/user-profile/2.png' - } - ] - }, - { - xtype: 'maincontainerwrap', - id: 'main-view-detail-wrap', - reference: 'mainContainerWrap', + items: [{ + xtype: 'toolbar', + cls: 'sencha-dash-dash-headerbar shadow', + height: 64, + itemId: 'headerBar', + items: [{ + xtype: 'component', + reference: 'logo', + cls: 'logo', + html: '', + width: 250 + }, { + margin: '0 0 0 8', + ui: 'header', + iconCls: 'x-fa fa-navicon', + id: 'main-navigation-btn', + handler: 'onToggleNavigationSize' + }, + '->', { + iconCls: 'x-fa fa-th-large', + ui: 'header', + href: '#account', + hrefTarget: '_self', + tooltip: 'See your profile' + }, { + xtype: 'tbtext', + text: 'Logged in as TestUser', + cls: 'top-user-name' + }, { + xtype: 'image', + cls: 'header-right-profile-image', + height: 35, + width: 35, + alt: 'current user image', + src: 'resources/images/user-profile/2.png' + } + ] + }, { + xtype: 'maincontainerwrap', + id: 'main-view-detail-wrap', + reference: 'mainContainerWrap', + flex: 1, + items: [{ + xtype: 'treelist', + reference: 'navigationTreeList', + itemId: 'navigationTreeList', + ui: 'navigation', + store: 'NavigationTree', + width: 250, + expanderFirst: false, + expanderOnly: false, + listeners: { + selectionchange: 'onNavigationTreeSelectionChange' + } + }, { + xtype: 'container', flex: 1, - items: [ - { - xtype: 'treelist', - reference: 'navigationTreeList', - itemId: 'navigationTreeList', - ui: 'navigation', - store: 'NavigationTree', - width: 250, - expanderFirst: false, - expanderOnly: false, - listeners: { - selectionchange: 'onNavigationTreeSelectionChange' - } - }, - { - xtype: 'container', - flex: 1, - reference: 'mainCardPanel', - cls: 'sencha-dash-right-main-container', - itemId: 'contentPanel', - layout: { - type: 'card', - anchor: '100%' - } - } - ] - } - ] + reference: 'mainCardPanel', + cls: 'sencha-dash-right-main-container', + itemId: 'contentPanel', + layout: { + type: 'card', + anchor: '100%' + } + }] + }] }); diff --git a/classic/src/view/main/MainContainerWrap.js b/classic/src/view/main/MainContainerWrap.js index bf8db58c..eece7e5d 100644 --- a/classic/src/view/main/MainContainerWrap.js +++ b/classic/src/view/main/MainContainerWrap.js @@ -2,7 +2,7 @@ Ext.define('NgcpCsc.view.main.MainContainerWrap', { extend: 'Ext.container.Container', xtype: 'maincontainerwrap', - requires : [ + requires: [ 'Ext.layout.container.HBox' ], @@ -20,12 +20,12 @@ Ext.define('NgcpCsc.view.main.MainContainerWrap', { } }, - beforeLayout : function() { + beforeLayout: function() { // We setup some minHeights dynamically to ensure we stretch to fill the height // of the viewport minus the top toolbar var me = this, - height = Ext.Element.getViewportHeight() - 64, // offset by topmost toolbar height + height = Ext.Element.getViewportHeight() - 64, // offset by topmost toolbar height // We use itemId/getComponent instead of "reference" because the initial // layout occurs too early for the reference to be resolved navTree = me.getComponent('navigationTreeList'); diff --git a/classic/src/view/main/MainController.js b/classic/src/view/main/MainController.js index ce4659aa..89aaa256 100644 --- a/classic/src/view/main/MainController.js +++ b/classic/src/view/main/MainController.js @@ -2,10 +2,10 @@ Ext.define('NgcpCsc.view.main.MainController', { extend: 'Ext.app.ViewController', alias: 'controller.main', - listen : { - controller : { - '#' : { - unmatchedroute : 'onRouteChange' + listen: { + controller: { + '#': { + unmatchedroute: 'onRouteChange' } } }, @@ -26,7 +26,7 @@ Ext.define('NgcpCsc.view.main.MainController', { navigationList = refs.navigationTreeList, store = navigationList.getStore(), node = store.findNode('routeId', hashTag) || - store.findNode('viewType', hashTag) || 'desktop', + store.findNode('viewType', hashTag) || 'desktop', view = (node && node.get('viewType')) || 'page404', lastView = me.lastView, existingItem = mainCard.child('component[routeId=' + hashTag + ']'), @@ -42,7 +42,7 @@ Ext.define('NgcpCsc.view.main.MainController', { if (!existingItem) { newView = Ext.create({ xtype: view, - routeId: hashTag, // for existingItem search later + routeId: hashTag, // for existingItem search later hideMode: 'offsets' }); } @@ -56,8 +56,7 @@ Ext.define('NgcpCsc.view.main.MainController', { mainLayout.setActiveItem(existingItem); } newView = existingItem; - } - else { + } else { // newView is set (did not exist already), so add it and make it the // activeItem. Ext.suspendLayouts(); @@ -75,15 +74,18 @@ Ext.define('NgcpCsc.view.main.MainController', { me.lastView = newView; }, - onNavigationTreeSelectionChange: function (tree, node) { + onNavigationTreeSelectionChange: function(tree, node) { var to = node && (node.get('routeId') || node.get('viewType')); if (to) { + if(node.parentNode){ + node.parentNode.expand(); + } this.redirectTo(to); } }, - onToggleNavigationSize: function () { + onToggleNavigationSize: function() { var me = this, refs = me.getReferences(), navigationList = refs.navigationTreeList, @@ -103,9 +105,8 @@ Ext.define('NgcpCsc.view.main.MainController', { // No animation for IE9 or lower... wrapContainer.layout.animatePolicy = wrapContainer.layout.animate = null; - wrapContainer.updateLayout(); // ... since this will flush them - } - else { + wrapContainer.updateLayout(); // ... since this will flush them + } else { if (!collapsing) { // If we are leaving micro mode (expanding), we do that first so that the // text of the items in the navlist will be revealed by the animation. @@ -113,13 +114,20 @@ Ext.define('NgcpCsc.view.main.MainController', { } // Start this layout first since it does not require a layout - refs.logo.animate({dynamic: true, to: {width: new_width}}); + refs.logo.animate({ + dynamic: true, + to: { + width: new_width + } + }); // Directly adjust the width config and then run the main wrap container layout // as the root layout (it and its chidren). This will cause the adjusted size to // be flushed to the element and animate to that new size. navigationList.width = new_width; - wrapContainer.updateLayout({isRoot: true}); + wrapContainer.updateLayout({ + isRoot: true + }); navigationList.el.addCls('nav-tree-animating'); // We need to switch to micro mode on the navlist *after* the animation (this @@ -127,7 +135,7 @@ Ext.define('NgcpCsc.view.main.MainController', { // visible. if (collapsing) { navigationList.on({ - afterlayoutanimation: function () { + afterlayoutanimation: function() { navigationList.setMicro(true); navigationList.el.removeCls('nav-tree-animating'); }, @@ -137,13 +145,13 @@ Ext.define('NgcpCsc.view.main.MainController', { } }, - onMainViewRender:function() { + onMainViewRender: function() { if (!window.location.hash) { this.redirectTo("desktop"); } }, - onRouteChange:function(id){ + onRouteChange: function(id) { this.setCurrentView(id); } }); diff --git a/classic/src/view/pages/calls/Calls.js b/classic/src/view/pages/calls/Calls.js new file mode 100644 index 00000000..f5210ccc --- /dev/null +++ b/classic/src/view/pages/calls/Calls.js @@ -0,0 +1,67 @@ +Ext.define('NgcpCsc.view.pages.calls.Calls', { + extend: 'Ext.panel.Panel', + + xtype: 'calls', + + controller: 'calls', + + layout: { + type: 'hbox', + align: 'stretch' + }, + + initComponent: function() { + var callsGrid = Ext.create('NgcpCsc.view.pages.calls.CallsGrid'); + if (!this._isDesktopSection) { + this.setTitle(Ngcp.csc.locales.calls.section_title[Ext.manifest.locale]); + } + this.items = [{ + flex: 4, + defaults: { + padding: 20 + }, + items: [{ + html: Ngcp.csc.locales.calls.recent_calls[Ext.manifest.locale], + }, { + xtype: 'container', + anchor: '100%', + height: 40, + padding: 10, + layout: 'hbox', + defaults: { + xtype: 'container', + width: 120, + height: 20 + }, + items: [{ + html: Ext.String.format('{0}', Ngcp.csc.locales.calls.call_type.incoming[Ext.manifest.locale]) + }, { + html: Ext.String.format('{0}', Ngcp.csc.locales.calls.call_type.outgoing[Ext.manifest.locale]) + }, { + html: Ext.String.format('{0}', Ngcp.csc.locales.calls.call_type.forwarded[Ext.manifest.locale]) + }] + }, + callsGrid, { + xtype: 'container', + anchor: '100%', + height: 40, + padding: 10, + hidden: !this._isDesktopSection, + html: Ext.String.format('', Ngcp.csc.locales.calls.all_calls[Ext.manifest.locale]), + listeners: { + click: { + element: 'el', + fn: 'showAllCalls' + } + } + } + ] + }, { + flex: 1, + xtype: 'gridfilters', + hidden: this._isDesktopSection, + _attachedCmp: callsGrid + }]; + this.callParent(); + } +}) diff --git a/classic/src/view/pages/calls/CallsController.js b/classic/src/view/pages/calls/CallsController.js new file mode 100644 index 00000000..d3632962 --- /dev/null +++ b/classic/src/view/pages/calls/CallsController.js @@ -0,0 +1,32 @@ +Ext.define('NgcpCsc.view.pages.calls.CallsController', { + extend: 'NgcpCsc.view.pages.summary.SummaryController', + + alias: 'controller.calls', + + renderPhoneIcon: function(value, metaData) { + return '
'; + }, + + renderCallTypeIcons: function(value) { + var icon; + + switch (value) { + case 'call': + icon = 'fa fa-arrow-circle-down'; + break; + case 'cfu': + icon = 'fa fa-arrow-circle-up'; + break; + case 'cfb': + icon = 'fa fa-arrow-circle-left'; + break; + case 'cft': + icon = 'fa fa-arrow-circle-right'; + break; + case 'cfna': + icon = 'fa fa-arrow-circle-down'; + break; + }; + return Ext.String.format('
', icon); + } +}); diff --git a/classic/src/view/pages/calls/CallsGrid.js b/classic/src/view/pages/calls/CallsGrid.js new file mode 100644 index 00000000..abca1761 --- /dev/null +++ b/classic/src/view/pages/calls/CallsGrid.js @@ -0,0 +1,63 @@ +Ext.define('NgcpCsc.view.pages.calls.CallsGrid', { + extend: 'Ext.grid.Panel', + + xtype: 'calls-grid', + + layout: 'fit', + + store: 'Calls', + + // used to toggle grid columns headers visibility + _showColHeaders: true, + + features: [{ + ftype: 'grouping', + groupHeaderTpl: [ + '
{name:this.formatName}
', { + formatName: function(name) { + return name.split('.')[1]; + } + } + ], + }], + + padding: 10, + + initComponent: function() { + var summaryView = (window.location.hash.substr(1) == 'desktop'); + this.columns = { + defaults: { + menuDisabled: true, + resizable: false + }, + items: [{ + dataIndex: 'call_type', + renderer: 'renderCallTypeIcons', + width: 30 + }, { + text: (!summaryView) ? Ngcp.csc.locales.calls.columns.number[Ext.manifest.locale] : '', + flex: 1, + dataIndex: 'source_cli' + }, { + renderer: 'renderPhoneIcon', + width: 30 + }, { + text: (!summaryView) ? Ngcp.csc.locales.calls.columns.duration[Ext.manifest.locale] : '', + flex: 1, + dataIndex: 'duration' + }, { + text: (!summaryView) ? Ngcp.csc.locales.calls.columns.charges[Ext.manifest.locale] : '', + flex: 1, + dataIndex: 'charges' + }, { + xtype: 'datecolumn', + text: (!summaryView) ? Ngcp.csc.locales.calls.columns.date[Ext.manifest.locale] : '', + flex: 1, + dataIndex: 'start_time', + format: 'd-m-Y h:i:s' + }] + }; + + this.callParent(); + } +}) diff --git a/classic/src/view/pages/summary/Summary.js b/classic/src/view/pages/summary/Summary.js new file mode 100644 index 00000000..532faf0b --- /dev/null +++ b/classic/src/view/pages/summary/Summary.js @@ -0,0 +1,106 @@ +Ext.define('NgcpCsc.view.pages.summary.Summary', { + extend: 'Ext.panel.Panel', + + xtype: 'summary', + + viewModel: 'summary', + + controller: 'summary', + + layout: 'fit', + + title: Ngcp.csc.locales.summary.title[Ext.manifest.locale], + + layout: 'hbox', + + defaults: { + flex: 1, + padding: 10 + }, + + items: [{ + flex: 3, + padding: 0, + items: [{ + layout: 'fit', + xtype: 'calls', + _isDesktopSection: true + }] + }, { + defaults: { + editable: false, + xtype: 'textfield', + labelAlign: 'top', + padding: '0 20 0 20', + width: '90%' + }, + items: [{ + fieldLabel: Ngcp.csc.locales.summary.account_balance[Ext.manifest.locale], + bind: { + value: '{initial_balance}', + hidden: '{checkInitialBalance}', + } + }, { + fieldLabel: Ngcp.csc.locales.summary.clients[Ext.manifest.locale], + bind: { + value: '{clients_total_count} ' + Ngcp.csc.locales.summary.clients_label[Ext.manifest.locale] + } + }, { + fieldLabel: Ngcp.csc.locales.summary.new_voicemails[Ext.manifest.locale], + bind: { + value: '{checkVoiceMails}' + } + }, { + xtype: 'container', + height: 40, + padding: 10, + html: Ext.String.format('', Ngcp.csc.locales.summary.all_voicemails[Ext.manifest.locale]), + listeners: { + click: { + element: 'el', + fn: 'showAllVoicemails' + } + } + }] + }, { + padding: 20, + items: [{ + html: Ngcp.csc.locales.summary.call_forwards[Ext.manifest.locale] + }, { + padding: 5, + bind: { + html: '{checkCallFwd}' + } + }, { + xtype: 'container', + height: 40, + padding: 10, + html: Ext.String.format('', Ngcp.csc.locales.summary.reminder[Ext.manifest.locale]), + listeners: { + click: { + element: 'el', + fn: 'showCallForward' + } + } + }, { + html: Ngcp.csc.locales.summary.clients[Ext.manifest.locale] + }, { + + padding: 5, + bind: { + html: '{checkReminder}' + } + }, { + xtype: 'container', + height: 40, + padding: 10, + html: Ext.String.format('', Ngcp.csc.locales.summary.reminder[Ext.manifest.locale]), + listeners: { + click: { + element: 'el', + fn: 'showSettings' + } + } + }] + }] +}); diff --git a/classic/src/view/pages/summary/SummaryController.js b/classic/src/view/pages/summary/SummaryController.js new file mode 100644 index 00000000..acc0c215 --- /dev/null +++ b/classic/src/view/pages/summary/SummaryController.js @@ -0,0 +1,21 @@ +Ext.define('NgcpCsc.view.pages.summary.SummaryController', { + extend: 'Ext.app.ViewController', + + alias: 'controller.summary', + + showAllCalls: function() { + this.redirectTo('#callist'); + }, + + showAllVoicemails: function() { + this.redirectTo('#voicebox'); + }, + + showSettings: function() { + this.redirectTo('#reminder'); + }, + + showCallForward: function() { + this.redirectTo('#callforward/mapping'); + } +}); diff --git a/classic/src/view/pages/summary/SummaryModel.js b/classic/src/view/pages/summary/SummaryModel.js new file mode 100644 index 00000000..56dca6a8 --- /dev/null +++ b/classic/src/view/pages/summary/SummaryModel.js @@ -0,0 +1,30 @@ +Ext.define('NgcpCsc.view.pages.summary.SummaryModel', { + extend: 'Ext.app.ViewModel', + alias: 'viewmodel.summary', + + data: { + initial_balance: 1.123, + clients_total_count: 1, + voicemails_total_count: 3, + call_forward_active: true, + reminder: true + }, + + formulas: { + checkInitialBalance: function(get) { + return get('initial_balance') == 0; + }, + checkVoiceMails: function(get) { + var count; + count = (get('voicemails_total_count') == 0) ? Ngcp.csc.locales.common.no[Ext.manifest.locale] : get('voicemails_total_count'); + return Ext.String.format('{0} {1}', count, Ngcp.csc.locales.summary.new_voicemails[Ext.manifest.locale].toLowerCase()); + }, + checkCallFwd: function(get) { + var active = get('call_forward_active') ? 'active' : 'inactive'; + return Ext.String.format('{0} {1}', Ngcp.csc.locales.summary.call_forwards[Ext.manifest.locale].toLowerCase(), active); + }, + checkReminder: function() { + return Ext.String.format('{0}', Ngcp.csc.locales.calls.call_type.forwarded[Ext.manifest.locale]); + } + } +}); diff --git a/sass/var/all.scss b/sass/var/all.scss index f0dc8434..c406df1b 100644 --- a/sass/var/all.scss +++ b/sass/var/all.scss @@ -43,3 +43,11 @@ $wizard-two-button-background-color: #925e8b; $wizard-three-primary-background-color: #9cc96b; $wizard-three-button-background-color: #9cc96b; +//------------------------------------------------ +// global custom classes + +.link { + cursor: pointer; + color: $base-color; + text-decoration: underline; +}