TT#17452 Csc implement call forward api write

What has been done:
 1. Implement successful write of destinations on store.sync(), using
 beforesync event and custom ajax requests based on id of
 destinationsets
 B. Investigate PATCH method for updating items with use of curl
 (will use this to base building of model in options["update"] on)
 A. Make sure we are able to fire beforesync event
 D. Add all necessary values to store for "add new destination"
 button controller logic ("announcement_id", "destination",
 "priority":, "simple_destination": "timeout" at least)
 D1. If store.last is undefined, create a new destinationset
 D2. Else if store.last is undefined, use store.last to get values for
  new model
 E. Create the "meat" for this cfStoreBeforeSync function
 1G. Make sure removing destination works with the API properly
 3A. Sourceset grid write data to API
 3B. Sourceset write after adding source to empty grid
 6. Disable ability to change titleset name for now, as we don't
 have specs for how to handle this. Currently, changing the name of
 the sourceset would mean that it would disappear in next reload,
 and as we can't rely on localStorage for persistence of
 sourceset_1 (List A), for example, we have no way of handling this
 unless we change the logic here. I've proposed to handle this as
 part of #17651, documented my concerns in ticket, and will discuss
 in next sync-up
 7. Cleanup and last changes and testing

Change-Id: Ic5eed663c032f38b5cf5c34effd86af32550ddde
changes/03/14203/6
Robert Axelsen 8 years ago
parent 395b2cb0ac
commit e84e334855

@ -13,6 +13,9 @@ Ext.define('NgcpCsc.model.CallForwardSourceset', {
}, {
name: 'source',
type: 'auto'
}, {
name: 'edit',
type: 'boolean'
}]
});

@ -75,7 +75,7 @@ Ext.define('NgcpCsc.model.Reminder', {
proxy: {
type: 'ngcp-api',
route: 'reminders',
params: 'subscriber_id=' + localStorage.getItem('subscriber_id')
params: 'subscriber_id=' + localStorage.getItem('subscriber_id') // this must exist in /api/subscribers/ response
}
});

@ -44,6 +44,9 @@ Ext.define('NgcpCsc.proxy.NgcpApi', {
};
records = request._records;
if (me.api && me.api.update) {
me.route = me.api.update;
};
url = Ext.String.format('{0}{1}/{2}', me.baseApiUrl, me.route, me.addSubscriber ? localStorage.getItem('subscriber_id') : records[0].get('id'));
break;
}

@ -5,9 +5,6 @@ Ext.define('NgcpCsc.store.CallForward', {
model: 'NgcpCsc.model.CallForward',
// TODO: (For PUT/PATCH ticket)
// autoSync: true,
proxy: {
type: 'ngcp-api',
route: 'cfmappings',
@ -16,13 +13,12 @@ Ext.define('NgcpCsc.store.CallForward', {
read: 'GET',
update: 'PATCH'
}
}
},
// TODO: (For PUT/PATCH ticket)
// ,listeners: {
// beforesync: function(options) {
// this.fireEvent('cfStoreBeforeSync', this, options);
// }
// }
listeners: {
beforesync: function(options) {
this.fireEvent('cfStoreBeforeSync', this, options);
}
}
});

@ -1,9 +1,6 @@
Ext.define('NgcpCsc.store.CallForwardLocalStorage', {
extend: 'Ext.data.Store',
// TODO: Can be removed as we only have a single model, but is currently
// used with Ext.getStore() references in CallForward modules
storeId: 'CallForwardLocalStorage',
model: 'NgcpCsc.model.CallForwardLocalStorage',

@ -17,10 +17,10 @@ Ext.define('NgcpCsc.store.CallForwardSourceset', {
listeners: {
load: function(store, recs) {
if (recs[0] && recs[0].data && recs[0].data._embedded) {
this.fireEvent('cfSourcesetStoreLoaded', this, recs[0].data._embedded['ngcp:cfsourcesets']);
}
this.fireEvent('cfSourcesetStoreLoaded', this, recs[0]);
},
beforesync: function(options) {
this.fireEvent('cfSourcesetBeforeSync', this, options);
}
}

@ -19,7 +19,10 @@ Ext.define('NgcpCsc.store.CallForwardTimeset', {
listeners: {
load: function(store, recs) {
this.fireEvent('cfTimesetStoreLoaded', this, recs[0].data._embedded['ngcp:cftimesets']);
this.fireEvent('cfTimesetStoreLoaded', this, recs[0]);
},
beforesync: function(options) {
this.fireEvent('cfTimesetBeforeSync', this, options);
}
}

@ -1036,6 +1036,34 @@ Ext.define('Ngcp.csc.locales', {
en: 'From ',
it: 'From '
},
no_after_hours_set: {
de: 'You have not set your after hours calendar yet.',
fr: 'You have not set your after hours calendar yet.',
sp: 'You have not set your after hours calendar yet.',
en: 'You have not set your after hours calendar yet.',
it: 'You have not set your after hours calendar yet.'
},
no_company_hours_set: {
de: 'You have not set your company hours calendar yet.',
fr: 'You have not set your company hours calendar yet.',
sp: 'You have not set your company hours calendar yet.',
en: 'You have not set your company hours calendar yet.',
it: 'You have not set your company hours calendar yet.'
},
number_is_required: {
de: 'Number is required. Please retry.',
fr: 'Number is required. Please retry.',
sp: 'Number is required. Please retry.',
en: 'Number is required. Please retry.',
it: 'Number is required. Please retry.'
},
only_numbers_allowed: {
de: 'Only numbers allowed. Please retry.',
fr: 'Only numbers allowed. Please retry.',
sp: 'Only numbers allowed. Please retry.',
en: 'Only numbers allowed. Please retry.',
it: 'Only numbers allowed. Please retry.'
},
tooltips: {
change_time_from: {
en: 'Change time from',

@ -50,6 +50,20 @@ Ext.define('NgcpCsc.view.login.LoginController', {
}
},
loadSubscriberDomain: function () {
Ext.Ajax.request({
url: window.location.origin + '/api/subscribers/' + localStorage.getItem('subscriber_id'),
success: function(response, opts) {
var decodedResponse = Ext.decode(response.responseText);
var domain = decodedResponse.domain;
localStorage.setItem('domain', domain);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
},
unsuccessLogin: function(response) {
localStorage.removeItem('jwt');
Ext.Msg.alert('Error', 'Username or Password not valid!');

@ -42,7 +42,6 @@ Ext.define('NgcpCsc.view.pages.callblocking.CallBlockingController', {
var vm = this.getViewModel();
var block_in_list = [],
block_out_list = [],
data = [],
storeType = store._type;
delete options['destroy'];
delete options['create'];

@ -13,33 +13,49 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
'*': {
cfStoreLoaded: 'cfStoreLoaded',
cfTimesetStoreLoaded: 'cfTimesetStoreLoaded',
cfSourcesetStoreLoaded: 'cfSourcesetStoreLoaded'
cfSourcesetStoreLoaded: 'cfSourcesetStoreLoaded',
cfStoreBeforeSync: 'cfStoreBeforeSync',
cfSourcesetBeforeSync: 'cfSourcesetBeforeSync',
cfTimesetBeforeSync: 'cfTimesetBeforeSync'
}
}
},
destinationDropped: function (node, data, overModel, dropPosition, eOpts) {
// TODO: Leaving uncommented code here for upcoming task #17654
// var store = Ext.getStore('everybody-always-CallForwardBusy');
// Ext.each(store.getRange(), function(record) {
// console.log(record.get('destination_cleaned'));
// })
},
cfTimesetStoreLoaded: function(store, data) {
var me = this;
var arrayOfModels = [];
var timesets;
if (data.getData()._embedded == undefined) {
return;
} else {
timesets = data.getData()._embedded['ngcp:cftimesets'];
}
store.removeAll();
Ext.each(data, function (timeset) {
Ext.each(timesets, function (timeset) {
var timesetName = timeset.name;
var timesetId = timeset.id;
if (timesetName == 'After Hours' || timesetName == 'Company Hours') {
me.setVmToTrue(timesetName);
if (/(After|Company)\s(Hours)/.test(timesetName)) {
var times = me.getModelValuesFromTimesData(timeset.times[0]);
Ext.each(times.days, function (weekday) {
var cbModel = Ext.create('NgcpCsc.model.CallForward', {
var cfModel = Ext.create('NgcpCsc.model.CallForward', {
id: Ext.id(),
timeset_name: timesetName,
timeset_id: timesetId,
time_from: times.timeFrom,
time_to: times.timeTo,
day: weekday,
closed: false // TODO: (For PUT/PATCH ticket) decide
// if we should keep this, or solve this
// differently, or not at all
closed: false
});
arrayOfModels.push(cbModel);
arrayOfModels.push(cfModel);
});
};
});
@ -47,26 +63,52 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
me.populateTimesetStores(arrayOfModels);
};
},
setVmToTrue: function (name) {
var vm = this.getViewModel();
switch (name) {
case 'After Hours':
vm.set('after_hours_exists_in_api', true);
break;
case 'Company Hours':
vm.set('company_hours_exists_in_api', true);
break;
case 'List A':
vm.set('list_a_exists_in_api', true);
break;
case 'List B':
vm.set('list_b_exists_in_api', true);
break;
};
},
cfSourcesetStoreLoaded: function(store, data) {
var me = this;
var arrayOfModels = [];
store.removeAll();
Ext.each(data, function (sourceset) {
var sourcesetName = sourceset.name;
var sourcesetId = sourceset.id;
Ext.each(sourceset.sources, function (sourceEntry) {
var cbModel = Ext.create('NgcpCsc.model.CallForward', {
id: Ext.id(),
sourceset_name: sourcesetName,
sourceset_id: sourcesetId,
source: sourceEntry.source
if (data.getData()._embedded == undefined) {
return;
} else {
var sourcesets = data.getData()._embedded['ngcp:cfsourcesets'];
store.removeAll();
Ext.each(sourcesets, function (sourceset) {
var sourcesetName = sourceset.name;
var sourcesetId = sourceset.id;
me.setVmToTrue(sourcesetName);
Ext.each(sourceset.sources, function (sourceEntry) {
var cfModel = Ext.create('NgcpCsc.model.CallForward', {
id: Ext.id(),
sourceset_name: sourcesetName,
sourceset_id: sourcesetId,
source: sourceEntry.source
});
arrayOfModels.push(cfModel);
});
arrayOfModels.push(cbModel);
});
});
if (arrayOfModels.length > 0) {
me.populateSourcesetStores(arrayOfModels);
};
if (arrayOfModels.length > 0) {
me.populateSourcesetStores(arrayOfModels);
};
}
},
getTimesetFromRoute: function (route) {
@ -82,6 +124,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
break;
};
},
cfStoreLoaded: function(store, data) {
var me = this;
var cfTypeArrayOfObjects = [data.get('cfu'), data.get('cft'), data.get('cfb'), data.get('cfna')];
@ -90,59 +133,59 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
var arrayOfModels = [];
var currentRoute = window.location.hash;
var routeTimeset = this.getTimesetFromRoute(currentRoute);
if(me.getView()._preventReLoad){
return;
}
if (me.getView()._preventReLoad) return;
store.removeAll();
// TODO optimize, too many nested loops affects performance.
// Ex. Where possible use break Ext.each by return false;
Ext.Ajax.request({
url: window.location.origin + '/api/cfdestinationsets/?subscriber_id=' + localStorage.getItem('subscriber_id'),
url: '/api/cfdestinationsets/?subscriber_id=' + localStorage.getItem('subscriber_id'),
success: function(response, opts) {
var decodedResponse = Ext.decode(response.responseText);
var destinationsets = decodedResponse._embedded['ngcp:cfdestinationsets'];
me.getView()._preventReLoad = true; // assumes there is no need to reload the store
Ext.each(cfTypeArrayOfObjects, function (cfTypeObjects, index) {
var cfType = cfTypes[index];
Ext.each(cfTypeObjects, function(cfTypeObject) {
var destinationsetName = cfTypeObject.destinationset;
var sourcesetName = cfTypeObject.sourceset;
var timesetName = cfTypeObject.timeset;
if (timesetName == routeTimeset) {
Ext.each(destinationsets, function(destinationset) {
if (destinationset.name == destinationsetName) {
for (item in destinationset.destinations) {
var destinationToUse = me.getDestinationFromSipId(destinationset.destinations[item].destination);
var destinationAnnouncementId = destinationset.announcement_id;
var destination = destinationset.destinations[item].destination;
var priority = destinationset.destinations[item].priority;
var simpleDestination = destinationset.destinations[item].simple_destination;
var destinationId = destinationset.id;
var destinationName = destinationset.name;
var ringFor = destinationToUse == 'Voicemail' ? '' : destinationset.destinations[item].timeout;
var cbModel = Ext.create('NgcpCsc.model.CallForward', {
type: cfType,
destination_cleaned: destinationToUse,
destination_announcement_id: destinationAnnouncementId,
destination: destination,
priority: priority,
simple_destination: simpleDestination,
ring_for: ringFor,
sourceset: sourcesetName,
timeset: timesetName,
destinationset_id: destinationId,
destinationset_name: destinationName
});
arrayOfModels.push(cbModel);
if (decodedResponse._embedded) {
var destinationsets = decodedResponse._embedded['ngcp:cfdestinationsets'];
me.getView()._preventReLoad = true; // assumes there is no need to reload the store
Ext.each(cfTypeArrayOfObjects, function (cfTypeObjects, index) {
var cfType = cfTypes[index];
Ext.each(cfTypeObjects, function(cfTypeObject) {
var destinationsetName = cfTypeObject.destinationset;
var sourcesetName = cfTypeObject.sourceset;
var timesetName = cfTypeObject.timeset;
if (timesetName == routeTimeset) {
Ext.each(destinationsets, function(destinationset) {
if (destinationset.name == destinationsetName) {
for (item in destinationset.destinations) {
var destinationToUse = me.getDestinationFromSipId(destinationset.destinations[item].destination);
var destinationAnnouncementId = destinationset.announcement_id;
var destination = destinationset.destinations[item].destination;
var priority = destinationset.destinations[item].priority;
var simpleDestination = destinationset.destinations[item].simple_destination;
var destinationId = destinationset.id;
var destinationName = destinationset.name;
var ringFor = destinationToUse == 'Voicemail' ? '' : destinationset.destinations[item].timeout;
var cbModel = Ext.create('NgcpCsc.model.CallForward', {
type: cfType,
destination_cleaned: destinationToUse,
destination_announcement_id: destinationAnnouncementId,
destination: destination,
priority: priority,
simple_destination: simpleDestination,
ring_for: ringFor,
sourceset: sourcesetName,
timeset: timesetName,
destinationset_id: destinationId,
destinationset_name: destinationName
});
arrayOfModels.push(cbModel);
}
}
}
});
};
});
};
});
});
});
if (arrayOfModels.length > 0) {
me.populateDestinationStores(arrayOfModels);
}
if (arrayOfModels.length > 0) {
me.populateDestinationStores(arrayOfModels);
};
};
},
failure: function(response, opts) {
@ -152,9 +195,124 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
},
destinationIdExistsInArray: function (arr, id) {
return arr.some(function(arrObj) {
return id == arrObj.id;
});
},
cfStoreBeforeSync: function(store, options) {
console.log('cfStoreBeforeSync');
// TODO: (For PUT/PATCH ticket) Base on on CB module implementation
// TODO: #17654 Ensure we also have ability to display and write all
// required destination types, like voicemail, fax, conference, etc
var me = this;
var recordsToSend = [];
delete options['destroy'];
delete options['create'];
Ext.each(store.getRange(), function(record) {
var data = record.getData();
switch (recordsToSend.length === 0 || !me.destinationIdExistsInArray(recordsToSend, data.destinationset_id)) {
case true:
recordsToSend.push({id: data.destinationset_id, records: [{ "announcement_id": null, "destination": data.simple_destination, "priority": data.priority, "timeout": data.ring_for }]});
break;
case false:
recordsToSend.forEach(function (obj, index) {
if (obj.id == data.destinationset_id) {
recordsToSend[index].records.push({ "announcement_id": null, "destination": data.simple_destination, "priority": data.priority, "timeout": data.ring_for });
}
})
};
});
Ext.each(recordsToSend, function (obj) {
Ext.Ajax.request({
url: '/api/cfdestinationsets/' + obj.id,
method: 'PATCH',
headers: { 'Content-Type': 'application/json-patch+json' },
jsonData: [{
"op": "add",
"path": "/destinations",
"value": obj.records
}],
success: function(response, opts) {
store.commitChanges();
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
});
return false;
},
cfSourcesetBeforeSync: function (store, options) {
// Using Ajax request here as we are using different url
// params for PATCH compared to GET
delete options['destroy'];
delete options['create'];
delete options['update'];
var sourcesetId = store.last().get('sourceset_id');
var recordsToSend = [];
Ext.each(store.getRange(), function (record) {
var data = record.getData();
recordsToSend.push({ "source": data.source });
});
Ext.Ajax.request({
url: '/api/cfsourcesets/' + sourcesetId,
method: 'PATCH',
headers: { 'Content-Type': 'application/json-patch+json' },
jsonData: [{
"op": "add",
"path": "/sources",
"value": recordsToSend
}],
success: function(response, opts) {
store.commitChanges();
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
return false;
},
timesBasedOnRecords: function (store) {
// TODO: Started this, but then discovered the issue leading to creation
// of #18401. Leaving the code in place for upcoming task #18401
var recordsToSend = [];
Ext.each(store.getRange(), function(record) {
var data = record.getData();
// console.log(data.time_from);
// console.log(data.time_to);
// For fields of data that have been changed in the grid, data is in
// this format:
// Tue Jan 01 2008 13:00:00 GMT+0100 (CET)
});
return recordsToSend;
},
cfTimesetBeforeSync: function (store, options) {
delete options['destroy'];
delete options['create'];
delete options['update'];
var timesetId = store.last().get('timeset_id');
// var recordsToSend = this.timesBasedOnRecords(store);
// TODO: Example ajax request for #18401
// Ext.Ajax.request({
// url: '/api/cftimesets/' + timesetId,
// method: 'PATCH',
// headers: { 'Content-Type': 'application/json-patch+json' },
// jsonData: [{
// "op": "add",
// "path": "/times",
// "value": recordsToSend
// }],
// success: function(response, opts) {
// console.log('server-side success with status code ' + response.status);
// },
// failure: function(response, opts) {
// console.log('server-side failure with status code ' + response.status);
// }
// });
return false;
},
getDestinationFromSipId: function (destination) {
@ -181,6 +339,20 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
}
},
getTypeFromTypeName: function (type) {
switch (type) {
case 'Online':
return 'cfu';
break;
case 'Busy':
return 'cfb';
break;
case 'Offline':
return 'cfna';
break;
}
},
getSourceNameFromSourceSet: function (sourceset) {
switch (sourceset) {
case 'List A':
@ -195,6 +367,20 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
}
},
getSourceSetFromSourceName: function (sourceset) {
switch (sourceset) {
case 'listA':
return 'List A';
break;
case 'listB':
return 'List B';
break;
case null:
return null;
break;
}
},
getTimeNameFromTimeSet: function (timeset) {
switch (timeset) {
case 'After Hours':
@ -209,6 +395,19 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
}
},
getTimeSetFromTimeSource: function (timeset) {
switch (timeset) {
case 'afterHours':
return 'After Hours';
break;
case 'companyHours':
return 'Company Hours';
break;
case null:
return null;
break;
}
},
getModuleFromRoute: function(currentRoute) {
switch (currentRoute) {
@ -266,26 +465,12 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
};
},
populateSourcesetStores: function (models) {
var storeListAAlways = Ext.getStore('CallForwardListA');
var storeListBAlways = Ext.getStore('CallForwardListB');
storeListAAlways.removeAll();
storeListBAlways.removeAll();
Ext.each(models, function (model) {
if (model.get('sourceset_name') == 'List A') {
storeListAAlways.add(model);
} else if (model.get('sourceset_name') == 'List B') {
storeListBAlways.add(model);
};
});
storeListAAlways.commitChanges();
storeListBAlways.commitChanges();
},
populateDestinationStores: function (models) {
var me = this;
var gridName = this.getGridCategoryFromType(models[0].get('type'));
var store;
// TODO: #17654 New grid logic and styling with conditions for cft/cfu,
// and remove first ring section
Ext.each(models, function (model) {
var sourcename = me.getSourceNameFromSourceSet(model.get('sourceset'));
var timename = me.getTimeNameFromTimeSet(model.get('timeset'));
@ -301,23 +486,29 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
}
},
cfdestinationsetsClick: function () {
console.log('cfdestinationsetsClick');
},
cfsourcesetsClick: function () {
console.log('cfsourcesetsClick');
},
cftimesetsClick: function () {
console.log('cftimesetsClick');
populateSourcesetStores: function (models) {
var storeListAAlways = Ext.getStore('CallForwardListA');
var storeListBAlways = Ext.getStore('CallForwardListB');
storeListAAlways.removeAll();
storeListBAlways.removeAll();
Ext.each(models, function (model) {
if (model.get('sourceset_name') == 'List A') {
storeListAAlways.add(model);
} else if (model.get('sourceset_name') == 'List B') {
storeListBAlways.add(model);
};
});
storeListAAlways.commitChanges();
storeListBAlways.commitChanges();
},
editingPhoneDone: function(editor, context) {
var record = context.record;
var grid = context.grid;
var store = grid.getStore();
record.set("edit", false);
grid.getView().refresh();
store.sync();
},
beforePhoneEdit: function (editor, context) {
@ -405,25 +596,104 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
return target.indexOf(string) > -1;
},
saveEmptyRowToStore: function(grid) {
writeNewSourceToStore: function(grid) {
var vm = this.getViewModel();
var store = grid.getStore();
var plugin = grid.getPlugin('celleditingSource');
var newRowIndex = store.getCount() + 1;
var record = store.getAt(store.getCount() - 1);
if (record == null || (record.data.phone !== ' ' && record.data.phone !== '')) {
// Need to add whitespace in record when using widgetcolumn
store.add({
"phone": " ",
"edit": true
});
};
plugin.startEditByPosition({
row: newRowIndex,
column: 0
var record = store.last();
var sourcesetName = grid.id.split('-')[0] == 'listA' ? 'List A' : 'List B';
var listAId = null;
var listBId = null;
var listExistsInApi = false;
Ext.Ajax.request({
url: '/api/cfsourcesets/?subscriber_id=' + localStorage.getItem('subscriber_id'),
success: function(response, opts) {
var decodedResponse = Ext.decode(response.responseText);
if (decodedResponse._embedded) {
var sourcesets = decodedResponse._embedded['ngcp:cfsourcesets'];
Ext.each(sourcesets, function (destinationset, index) {
if (destinationset.name == 'List A') {
listAId = destinationset.id;
} else if (destinationset.name == 'List B') {
listBId = destinationset.id;
}
if (sourcesetName == 'List A' && listAId !== null) {
listExistsInApi = true;
} else if (sourcesetName == 'List B' && listBId !== null) {
listExistsInApi = true;
}
});
};
switch (!store.last()) {
case false:
if (record == null || (record.data.source !== ' ' && record.data.source !== '')) {
var cfSourcesetModel = Ext.create('NgcpCsc.model.CallForwardSourceset', {
id: Ext.id(),
source: " ",
sourceset_name: record.get('sourceset_name'),
sourceset_id: record.get('sourceset_id'),
edit: true
});
store.add(cfSourcesetModel);
};
break;
case true: // if store empty we need to create new sourceset
switch (listExistsInApi) {
case true:
var cfSourcesetModel = Ext.create('NgcpCsc.model.CallForwardSourceset', {
id: Ext.id(),
source: " ",
sourceset_name: sourcesetName,
sourceset_id: listAId || listBId,
edit: true
});
store.add(cfSourcesetModel);
break;
case false:
var subscriberId = localStorage.getItem('subscriber_id');
Ext.Ajax.request({
url: '/api/cfsourcesets/',
method: 'POST',
jsonData: {
name: sourcesetName,
subscriber_id: subscriberId
},
success: function(response, opts) {
var sourcesetId = response.getResponseHeader('Location').split('/')[3];
var cfSourcesetModel = Ext.create('NgcpCsc.model.CallForward', {
id: Ext.id(),
source: " ",
sourceset_name: sourcesetName,
sourceset_id: sourcesetId,
edit: true
});
store.add(cfSourcesetModel);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
break;
}
break;
}
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
},
callback: function () {
plugin.startEditByPosition({
row: newRowIndex,
column: 0
});
}
});
},
addEmptyRow: function(button) {
addEmptySourcesetRow: function(button) {
var buttonIdSplit = button.id.split('-');
var buttonPrefixOne = buttonIdSplit[0];
var buttonPrefixTwo = buttonIdSplit[1];
@ -431,11 +701,11 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
switch (buttonSuffix) {
case 'addListAButton':
var grid = Ext.getCmp(buttonPrefixOne + '-' + buttonPrefixTwo + '-cf-sourceset-list-a-grid');
this.saveEmptyRowToStore(grid);
this.writeNewSourceToStore(grid);
break;
case 'addListBButton':
var grid = Ext.getCmp(buttonPrefixOne + '-' + buttonPrefixTwo + '-cf-sourceset-list-b-grid');
this.saveEmptyRowToStore(grid);
this.writeNewSourceToStore(grid);
break;
};
},
@ -453,6 +723,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
var store = record.store;
if(store){
store.remove(record);
store.sync();
}
},
@ -596,13 +867,10 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
case true:
switch (Ext.isEmpty(newNumber) && newDest === 'Number') {
case true:
me.fireEvent('showmessage', false, 'Number is required. Please retry.');
me.fireEvent('showmessage', false, Ngcp.csc.locales.callforward.number_is_required[localStorage.getItem('languageSelected')]);
break;
case false:
targetStore.add({
"phone": newDest,
"ring_for": ""
});
me.writeNewDestinationToStore(targetStore, newDest, "");
me.hideThenFieldsByStoreName(vm, storeNameStripped);
break;
};
@ -611,16 +879,13 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
case false:
switch (Ext.isNumber(parseInt(newNumber))) {
case false:
me.fireEvent('showmessage', false, 'Only numbers allowed. Please retry.');
me.fireEvent('showmessage', false, Ngcp.csc.locales.callforward.only_numbers_allowed[localStorage.getItem('languageSelected')]);
vm.set(storeNameCategory + '_then_number', '');
break;
case true:
var newTimeout = newDest === 'Number' ? vm.get(storeNameCategory + '_then_timeout') : '';
var newPhone = newDest === 'Number' ? newNumber : newDest;
targetStore.add({
"phone": newPhone,
"ring_for": newTimeout
});
me.writeNewDestinationToStore(targetStore, newPhone, parseInt(newTimeout));
vm.set(storeNameCategory + '_then_number', '');
me.hideThenFieldsByStoreName(vm, storeNameStripped);
break;
@ -629,6 +894,126 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
};
},
createNewStandardSet: function (url, name, subscriberId) {
var vm = this.getViewModel();
Ext.Ajax.request({
url: url,
method: 'POST',
jsonData: {
name: name,
subscriber_id: subscriberId
},
success: function(response, opts) {
switch (name) {
case 'List A':
vm.set('list_a_exists_in_api', true);
break;
case 'List B':
vm.set('list_b_exists_in_api', true);
break;
case 'After Hours':
vm.set('after_hours_exists_in_api', true);
break;
case 'Company Hours':
vm.set('company_hours_exists_in_api', true);
break;
}
}
});
},
createNewMapping: function (subscriberId, newType, newDestinationsetName, newSourceset, newTimeset) {
Ext.Ajax.request({
url: '/api/cfmappings/' + subscriberId,
method: 'PATCH',
headers: { 'Content-Type': 'application/json-patch+json' },
jsonData: [{
"op": "add",
"path": "/" + newType,
"value": [{ "destinationset": newDestinationsetName, "sourceset": newSourceset, "timeset": newTimeset }]
}]
});
},
writeNewDestinationToStore: function (store, destination, timeout) {
var me = this;
var vm = this.getViewModel();
var simpleDestination = destination;
var priority = 1;
var storeCount = store.getCount();
var ringFor = destination == 'Voicemail' ? '' : timeout;
var destinationCleaned = destination;
var storeIdSplit = store.storeId.split('-');
var newSourcesetName = storeIdSplit[0] == 'everybody' ? null : storeIdSplit[0];
var newTimesetName = storeIdSplit[1] == 'always' ? null : storeIdSplit[1];
var newTypeName = storeIdSplit[2].slice(11);
var newSourceset = this.getSourceSetFromSourceName(newSourcesetName);
var newTimeset = this.getTimeSetFromTimeSource(newTimesetName);
var newType = this.getTypeFromTypeName(newTypeName);
var newDomain = localStorage.getItem('domain');
// TODO: #17654 Consider the fact that one destinationset can be in
// several grids, so if you write one, update all other grids with
// that same destinationset id
if (!store.last()) { // if store empty we need to create new destset
var newDestinationsetName = 'csc_defined_' + newType;
var subscriberId = localStorage.getItem('subscriber_id');
Ext.Ajax.request({
url: '/api/cfdestinationsets/',
method: 'POST',
defaultHeaders: 'Prefer: return=representation',
jsonData: {
name: newDestinationsetName,
subscriber_id: subscriberId
},
success: function(response, opts) {
var destinationsetId = response.getResponseHeader('Location').split('/')[3];
var cfModel = Ext.create('NgcpCsc.model.CallForward', {
type: newType,
destination_cleaned: destinationCleaned,
destination_announcement_id: null,
destination: 'sip:' + destination + '@' + newDomain,
// Keeping priority 1 as default for now, as we'll handle priotity
// with grid "drag-and-drop" widget plugin in upcoming task
priority: 1,
simple_destination: destination,
ring_for: ringFor,
sourceset: newSourceset,
timeset: newTimeset,
destinationset_id: destinationsetId,
destinationset_name: newDestinationsetName
});
store.add(cfModel);
store.sync();
// Creates new sourceset/timeset if variable is not set to null
newSourceset && me.createNewStandardSet('/api/cfsourcesets/', newSourceset, subscriberId);
newTimeset && me.createNewStandardSet('/api/cftimesets/', newTimeset, subscriberId);
me.createNewMapping(subscriberId, newType, newDestinationsetName, newSourceset, newTimeset);
},
failure: function(response, opts) {
console.log('server-side failure with status code ' + response.status);
}
});
} else {
var lastRecordInStore = store.last();
var cfModel = Ext.create('NgcpCsc.model.CallForward', {
type: lastRecordInStore.get('type'),
destination_cleaned: destinationCleaned,
destination_announcement_id: null,
destination: 'sip:' + destination + '@' + newDomain,
priority: 1,
simple_destination: destination,
ring_for: ringFor,
sourceset: lastRecordInStore.get('sourceset'),
timeset: lastRecordInStore.get('timeset'),
destinationset_id: lastRecordInStore.get('destinationset_id'),
destinationset_name: lastRecordInStore.get('destinationset_name')
});
store.add(cfModel);
store.sync();
}
},
addNewDestination: function(element) {
var me = this;
var vm = this.getViewModel();
@ -649,8 +1034,15 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
};
},
saveGrid: function(el) {
this.fireEvent('showmessage', true, Ngcp.csc.locales.common.save_success[localStorage.getItem('languageSelected')]);
saveTimesetGrid: function(el) {
var storeName = el.id.split('-')[0] + '-Timeset';
var store = Ext.getStore(storeName);
store.sync();
}
// TODO #18401, maybe use a blur or change listener on editors in grid
// editingTimeDone: function () {
//
// }
});

@ -20,7 +20,6 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
var storeListA = Ext.getStore('CallForwardListA') || Ext.create('NgcpCsc.store.CallForwardSourceset', {
storeId: 'CallForwardListA'
});
var storeListB = Ext.getStore('CallForwardListB') || Ext.create('NgcpCsc.store.CallForwardSourceset', {
storeId: 'CallForwardListB'
});
@ -94,20 +93,24 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
xtype: 'panel',
layout: 'hbox',
margin: '15 0 0 0',
items: [{
xtype: 'button',
html: Ngcp.csc.locales.callforward.change_title[localStorage.getItem('languageSelected')],
id: this._firstprefix + this._secondprefix + 'lista_titleField-showButton',
margin: '0 0 0 500',
handler: 'toggleChangeTitle'
}, {
items: [
// NOTE: Commenting out this now, and will tackle it as part of #17651
// {
// xtype: 'button',
// html: Ngcp.csc.locales.callforward.change_title[localStorage.getItem('languageSelected')],
// id: this._firstprefix + this._secondprefix + 'lista_titleField-showButton',
// margin: '0 0 0 500',
// handler: 'toggleChangeTitle'
// },
{
xtype: 'button',
text: Ngcp.csc.locales.callforward.add_new_source[localStorage.getItem('languageSelected')],
id: this._firstprefix + this._secondprefix + 'addListAButton',
margin: '0 0 0 620',
// margin: '0 0 0 10',
width: 135,
margin: '0 0 0 10',
listeners: {
click: 'addEmptyRow'
click: 'addEmptySourcesetRow'
}
}]
}]
@ -154,20 +157,24 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
bind: {
hidden: '{list_b}'
},
items: [{
xtype: 'button',
html: Ngcp.csc.locales.callforward.change_title[localStorage.getItem('languageSelected')],
id: this._firstprefix + this._secondprefix + 'listb_titleField-showButton',
margin: '0 0 0 500',
handler: 'toggleChangeTitle'
}, {
items: [
// NOTE: Commenting out this now, and will tackle it as part of #17651
// {
// xtype: 'button',
// html: Ngcp.csc.locales.callforward.change_title[localStorage.getItem('languageSelected')],
// id: this._firstprefix + this._secondprefix + 'listb_titleField-showButton',
// margin: '0 0 0 500',
// handler: 'toggleChangeTitle'
// },
{
xtype: 'button',
text: Ngcp.csc.locales.callforward.add_new_source[localStorage.getItem('languageSelected')],
id: this._firstprefix + this._secondprefix + 'addListBButton',
width: 135,
margin: '0 0 0 10',
margin: '0 0 0 620',
// margin: '0 0 0 10',
listeners: {
click: 'addEmptyRow'
click: 'addEmptySourcesetRow'
}
}]
}]
@ -278,7 +285,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
hidden: '{online_then_timeout_hidden}'
},
allowBlank: false,
editable: false,
editable: true,
flex: 4,
margin: '0 0 0 10'
}, {
@ -384,7 +391,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
hidden: '{busy_then_timeout_hidden}'
},
allowBlank: false,
editable: false,
editable: true,
flex: 4,
margin: '0 0 0 10'
}, {
@ -490,7 +497,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
hidden: '{offline_then_timeout_hidden}'
},
allowBlank: false,
editable: false,
editable: true,
flex: 4,
margin: '0 0 0 10'
}, {

@ -16,7 +16,10 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardMainGrid', {
markDirty: false,
emptyText: Ngcp.csc.locales.callforward.nowhere[localStorage.getItem('languageSelected')],
deferEmptyText: false,
stripeRows: false
stripeRows: false,
listeners: {
drop: 'destinationDropped'
}
},
// TODO: Leaving this for PUT/PATCH task, as it might make sense to use

@ -1,6 +1,7 @@
Ext.define('NgcpCsc.view.pages.callforward.CallForwardModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.callforward',
// left inline as non-Api data
data: {
after_hours: true,
@ -37,8 +38,10 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardModel', {
source_listb_title: 'List B',
hide_lista_titleField: true,
hide_listb_titleField: true,
afterHours_hideMessage: false,
companyHours_hideMessage: false
list_a_exists_in_api: false,
list_b_exists_in_api: false,
after_hours_exists_in_api: false,
company_hours_exists_in_api: false
},
formulas: {

@ -11,20 +11,15 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardSourcesetGrid', {
clicksToEdit: 1
},
hideHeaders: true,
width: '100%',
listeners: {
edit: 'editingPhoneDone',
beforeedit: 'beforePhoneEdit',
click: {
fn: 'saveGrid',
element: 'el',
delegate: 'a.edit-button'
}
beforeedit: 'beforePhoneEdit'
},
hideHeaders: true,
width: '100%',
initComponent: function() {
this.columns = {
defaults: {

@ -7,6 +7,11 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
markDirty: false
},
// TODO: #18401
// listeners: {
// edit: 'editingTimeDone'
// },
initComponent: function() {
this.columns = {
defaults: {
@ -20,7 +25,7 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
flex: 1
}, {
text: Ngcp.csc.locales.common.from[localStorage.getItem('languageSelected')],
dataIndex: 'time_from',
dataIndex: 'time_from', // TODO: #18401 Add listener
xtype: 'widgetcolumn',
editable: false,
flex: 1,
@ -28,12 +33,13 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
xtype: 'timefield',
tooltip: Ngcp.csc.locales.callforward.tooltips.change_time_from[localStorage.getItem('languageSelected')],
bind: {
disabled: '{record.closed}'
disabled: '{record.closed}',
value: '{record.time_from}'
}
}
}, {
text: Ngcp.csc.locales.common.to[localStorage.getItem('languageSelected')],
dataIndex: 'time_to',
dataIndex: 'time_to', // TODO: #18401 Add listener
xtype: 'widgetcolumn',
editable: false,
flex: 1,
@ -41,7 +47,8 @@ Ext.define('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
xtype: 'timefield',
tooltip: Ngcp.csc.locales.callforward.tooltips.change_time_to[localStorage.getItem('languageSelected')],
bind: {
disabled: '{record.closed}'
disabled: '{record.closed}',
value: '{record.time_to}'
}
}
}, {

@ -19,6 +19,9 @@ Ext.define('NgcpCsc.view.pages.callforward.afterhours.Afterhours', {
var callForwardAfterGrid = Ext.create('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
id: 'cf-timeset-after-grid',
bind: {
hidden: '{!after_hours_exists_in_api}'
},
store: Ext.create('NgcpCsc.store.CallForwardTimeset', {
storeId: 'afterHours-Timeset'
})
@ -47,9 +50,9 @@ Ext.define('NgcpCsc.view.pages.callforward.afterhours.Afterhours', {
items: [{
xtype: 'panel',
margin: '10 0 10 0',
html: 'You have not set your after hours calendar yet.', // TODO: Locales or icon, or both. Will wait for feedback from Andreas in next sync-up
html: Ngcp.csc.locales.callforward.no_after_hours_set[localStorage.getItem('languageSelected')],
bind: {
hidden: '{afterHours_hideMessage}'
hidden: '{after_hours_exists_in_api}'
}
},
callForwardAfterGrid, {
@ -60,7 +63,10 @@ Ext.define('NgcpCsc.view.pages.callforward.afterhours.Afterhours', {
width: 135,
margin: '10 0 10 623',
listeners: {
click: 'saveGrid'
click: 'saveTimesetGrid'
},
bind: {
hidden: '{!after_hours_exists_in_api}'
}
}
]
@ -68,12 +74,18 @@ Ext.define('NgcpCsc.view.pages.callforward.afterhours.Afterhours', {
}, {
xtype: 'panel',
width: '100%',
title: Ngcp.csc.locales.callforward.for_calling_parties[localStorage.getItem('languageSelected')]
title: Ngcp.csc.locales.callforward.for_calling_parties[localStorage.getItem('languageSelected')],
bind: {
hidden: '{!after_hours_exists_in_api}'
}
}, {
xtype: 'cftab',
_tabId: 'afterhours',
_firstPrefixes: ['everybody-', 'listA-', 'listB-'],
_secondprefix: 'afterHours-'
_secondprefix: 'afterHours-',
bind: {
hidden: '{!after_hours_exists_in_api}'
}
}]
}];
this.callParent();

@ -6,7 +6,7 @@ Ext.define('NgcpCsc.view.pages.callforward.companyhours.Companyhours', {
ui: 'cf-mainform',
initComponent: function() {
var cfInitialStore = Ext.create('NgcpCsc.store.CallForward',{
var cfInitialStore = Ext.create('NgcpCsc.store.CallForward', {
storeId: 'CallForwardCompanyHours',
_type: 'companyHours',
autoLoad: true,
@ -22,6 +22,9 @@ Ext.define('NgcpCsc.view.pages.callforward.companyhours.Companyhours', {
var callForwardCompanyGrid = Ext.create('NgcpCsc.view.pages.callforward.CallForwardTimesetGrid', {
id: 'cf-timeset-company-grid',
bind: {
hidden: '{!company_hours_exists_in_api}'
},
store: Ext.create('NgcpCsc.store.CallForwardTimeset', {
storeId: 'companyHours-Timeset'
})
@ -48,13 +51,13 @@ Ext.define('NgcpCsc.view.pages.callforward.companyhours.Companyhours', {
},
userCls: 'big-33 small-100 cf-calls-during-section',
items: [{
xtype: 'panel',
margin: '10 0 10 0',
html: 'You have not set your company hours calendar yet.', // TODO: Locales or icon, or both. Will wait for feedback from Andreas in next sync-up
bind: {
hidden: '{companyHours_hideMessage}'
}
},
xtype: 'panel',
margin: '10 0 10 0',
html: Ngcp.csc.locales.callforward.no_company_hours_set[localStorage.getItem('languageSelected')],
bind: {
hidden: '{company_hours_exists_in_api}'
}
},
callForwardCompanyGrid,
{
text: Ngcp.csc.locales.common.save_caps[localStorage.getItem('languageSelected')],
@ -64,7 +67,10 @@ Ext.define('NgcpCsc.view.pages.callforward.companyhours.Companyhours', {
width: 135,
margin: '10 0 10 585',
listeners: {
click: 'saveGrid'
click: 'saveTimesetGrid'
},
bind: {
hidden: '{!company_hours_exists_in_api}'
}
}
]
@ -72,12 +78,18 @@ Ext.define('NgcpCsc.view.pages.callforward.companyhours.Companyhours', {
}, {
xtype: 'panel',
width: '100%',
title: Ngcp.csc.locales.callforward.for_calling_parties[localStorage.getItem('languageSelected')]
title: Ngcp.csc.locales.callforward.for_calling_parties[localStorage.getItem('languageSelected')],
bind: {
hidden: '{!company_hours_exists_in_api}'
}
}, {
xtype: 'cftab',
_tabId: 'companyhours',
_firstPrefixes: ['everybody-', 'listA-', 'listB-'],
_secondprefix: 'companyHours-'
_secondprefix: 'companyHours-',
bind: {
hidden: '{!company_hours_exists_in_api}'
}
}]
}];
this.callParent();

Loading…
Cancel
Save