mirror of https://github.com/sipwise/ngcp-csc.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1452 lines
62 KiB
1452 lines
62 KiB
Ext.define('NgcpCsc.view.pages.callforward.CallForwardController', {
|
|
extend: 'Ext.app.ViewController',
|
|
|
|
alias: 'controller.callforward',
|
|
|
|
listen: {
|
|
controller: {
|
|
'*': {
|
|
confirmCFRemoval: 'confirmCFRemoval',
|
|
cfReloadStore: 'cfReLoadStore'
|
|
}
|
|
},
|
|
store: {
|
|
'*': {
|
|
cfStoreLoaded: 'cfStoreLoaded',
|
|
cfTimesetStoreLoaded: 'cfTimesetStoreLoaded',
|
|
cfSourcesetStoreLoaded: 'cfSourcesetStoreLoaded',
|
|
cfStoreBeforeSync: 'cfStoreBeforeSync',
|
|
cfSourcesetBeforeSync: 'cfSourcesetBeforeSync',
|
|
cfTimesetBeforeSync: 'cfTimesetBeforeSync'
|
|
}
|
|
}
|
|
},
|
|
|
|
destinationDropped: function(node, data, overModel, dropPosition, eOpts) {
|
|
var dropRec = data.records[0];
|
|
var store = overModel.store;
|
|
var recIndex = store.indexOf(dropRec);
|
|
var adjacentRec = dropPosition === 'before' ? store.getAt(recIndex + 1) : store.getAt(recIndex - 1);
|
|
var destinationsetId = adjacentRec.get('destinationset_id') === dropRec.get('destinationset_id') ? dropRec.get('destinationset_id') : adjacentRec.get('destinationset_id');
|
|
var destinationsetName = adjacentRec.get('destinationset_name') === dropRec.get('destinationset_name') ? dropRec.get('destinationset_name') : adjacentRec.get('destinationset_name');
|
|
var afterTermination = adjacentRec.get('after_termination') === dropRec.get('after_termination') ? dropRec.get('after_termination') : adjacentRec.get('after_termination');
|
|
var priority = adjacentRec.get('priority') === dropRec.get('priority') ? dropRec.get('priority') : adjacentRec.get('priority');
|
|
var type = adjacentRec.get('type') === dropRec.get('type') ? dropRec.get('type') : adjacentRec.get('type');
|
|
dropRec.set('destinationset_id', destinationsetId);
|
|
dropRec.set('destinationset_name', destinationsetName);
|
|
dropRec.set('after_termination', afterTermination);
|
|
dropRec.set('priority', priority);
|
|
dropRec.set('type', type);
|
|
this.setLabelTerminationType(store);
|
|
store.sync();
|
|
},
|
|
|
|
parseTimesetApiToRecords: function (times) {
|
|
console.log(times);
|
|
var daysOfTheWeek = {
|
|
1: {day: 'Sunday', timeFrom: '', timeTo: ''},
|
|
2: {day: 'Monday', timeFrom: '', timeTo: ''},
|
|
3: {day: 'Tuesday', timeFrom: '', timeTo: ''},
|
|
4: {day: 'Wednesday', timeFrom: '', timeTo: ''},
|
|
5: {day: 'Thursday', timeFrom: '', timeTo: ''},
|
|
6: {day: 'Friday', timeFrom: '', timeTo: ''},
|
|
7: {day: 'Saturday', timeFrom: '', timeTo: ''}
|
|
};
|
|
// XXX: With the help of rfuchs, a better solution to handle the merging
|
|
// would be to have an array for each day, and sort from-to ranges based
|
|
// on from time, and merge them of the adjacent arrays have lower/higher
|
|
// values. Before adding the from-to ranges to the arrays, we need to
|
|
// split on midnight if they cross over, resulting in two from-to ranges
|
|
// to add instead of one. Example object with said day arrays:
|
|
// [ { day: "Sunday", times: [ [0-8], [10-17], [9-20] ] },
|
|
// { day: "Monday", times: [ [8-16] ] },
|
|
// { day: "Tuesday", times: [ [8-], [10-17], [9-20] ] } } ]
|
|
// NOTE: We have two issues we need to solve:
|
|
// 1. We can not account for all possible combination of ranges
|
|
// with the current calendar table. We either need to a) display
|
|
// more time from-to in same row, b) display several rows per
|
|
// wday if needed, c) implement a full calendar view instead,
|
|
// or d) only let the user see the the timeset name, but not
|
|
// change it, and let the superuser change it in a card style
|
|
// view with one card per time object (sort of like in
|
|
// ngcp-panel)
|
|
// 2. Currently we're allowing the user to cross midnight when
|
|
// altering times
|
|
Ext.each(times, function (time) {
|
|
// DONE: Create a range of days, e.g [2, 3, 4, 5]
|
|
var timesFromAndTo = time.hour !== null ? time.hour.split('-') : false;
|
|
var timeFrom = timesFromAndTo[0];
|
|
var timeTo = timesFromAndTo[1];
|
|
var daysFromAndTo = time.wday !== null ? time.wday.split('-') : false;
|
|
var daysRange = [];
|
|
if (!timesFromAndTo || !daysFromAndTo) return;
|
|
for (var i = daysFromAndTo[0]; i <= daysFromAndTo[1]; i++) {
|
|
daysRange.push(parseInt(i));
|
|
};
|
|
daysRange.forEach(function (dayNum) {
|
|
if (daysOfTheWeek[dayNum].timeFrom.length === 0) {
|
|
daysOfTheWeek[dayNum].timeFrom = timeFrom;
|
|
daysOfTheWeek[dayNum].timeTo = timeTo;
|
|
} else {
|
|
|
|
// TODO: Merge days if day object already has values stored
|
|
// for timeFrom and timeTo
|
|
// NOTE: How do we handle the fact that timeFrom might be
|
|
// larger than timeTo?? E.g. "hour": "16-8"... API allows
|
|
// for value from 1-23 from timeFrom and timeTo.
|
|
// Could we use an if statement to handle it separately?:
|
|
// if (timeFrom > timeTo) {
|
|
// // TODO: Figure out how to merge in this scenario
|
|
// }
|
|
// TODO: timeFrom and timeTo can also be same value. Assuming
|
|
// such a rule will be ignore in system, unless minutes
|
|
// are set. So will ignore those for now
|
|
}
|
|
});
|
|
console.log(daysOfTheWeek);
|
|
});
|
|
//
|
|
// TODO: Take this input...
|
|
// "times": [
|
|
// {
|
|
// "hour": "8-16",
|
|
// "mday": null,
|
|
// "minute": null,
|
|
// "month": null,
|
|
// "wday": "2-3",
|
|
// "year": null
|
|
// },
|
|
// {
|
|
// "hour": "10-18",
|
|
// "mday": null,
|
|
// "minute": null,
|
|
// "month": null,
|
|
// "wday": "3",
|
|
// "year": null
|
|
// }
|
|
// ]
|
|
// >>>>>> ... and return this output: >>>>>>
|
|
// [ { "timeFrom": "8", "timeTo": "16", "day": "Monday" },
|
|
// { "timeFrom": "8", "timeTo": "16", "day": "Tuesday" },
|
|
// { "timeFrom": "8", "timeTo": "18", "day": "Wednesday" }
|
|
// ]
|
|
// XXX Temp dummy data XXX
|
|
return [
|
|
{ "timeFrom": "9", "timeTo": "16", "day": "Monday" },
|
|
{ "timeFrom": "12", "timeTo": "16", "day": "Tuesday" },
|
|
{ "timeFrom": "8", "timeTo": "18", "day": "Wednesday" },
|
|
{ "timeFrom": "8", "timeTo": "11", "day": "Thursday" },
|
|
{ "timeFrom": "8", "timeTo": "14", "day": "Friday" }
|
|
];
|
|
},
|
|
|
|
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(timesets, function(timeset) {
|
|
var timesetName = timeset.name;
|
|
var timesetId = timeset.id;
|
|
if (timesetName == 'After Hours' || timesetName == 'Company Hours') {
|
|
// DONE: Currently only takes first object in array. Fix.
|
|
var times = me.parseTimesetApiToRecords(timeset.times);
|
|
Ext.each(times, function (time) {
|
|
var cbModel = Ext.create('NgcpCsc.model.CallForward', {
|
|
id: Ext.id(),
|
|
timeset_name: timesetName,
|
|
timeset_id: timesetId,
|
|
time_from: time.timeFrom,
|
|
time_to: time.timeTo,
|
|
day: time.day,
|
|
closed: false // TODO: (For PUT/PATCH ticket) decide
|
|
// if we should keep this, or solve this
|
|
// differently, or not at all
|
|
});
|
|
arrayOfModels.push(cfModel);
|
|
});
|
|
};
|
|
});
|
|
if (arrayOfModels.length > 0) {
|
|
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;
|
|
};
|
|
},
|
|
|
|
cfSourcesetStoreLoaded: function(store, data) {
|
|
var me = this;
|
|
var arrayOfModels = [];
|
|
if (data.getData()._embedded) {
|
|
var sourcesets = data.getData()._embedded['ngcp:cfsourcesets'];
|
|
store.removeAll();
|
|
store._sourcesets = sourcesets;
|
|
Ext.each(sourcesets, function(sourceset) {
|
|
var sourcesetName = sourceset.name;
|
|
var sourcesetId = sourceset.id;
|
|
me.setVmToTrue(sourcesetName);
|
|
Ext.each(sourceset.sources, function(sourceEntry) {
|
|
arrayOfModels.push(Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
id: Ext.id(),
|
|
sourceset_name: sourcesetName,
|
|
sourceset_id: sourcesetId,
|
|
source: sourceEntry.source
|
|
}))
|
|
});
|
|
});
|
|
}
|
|
me.createSourcesetTabs(sourcesets);
|
|
Ext.defer(function(){
|
|
me.populateSourcesetStores(arrayOfModels);
|
|
},100)
|
|
|
|
},
|
|
|
|
getTimesetFromRoute: function(route) {
|
|
switch (route) {
|
|
case ('#callforward/always'):
|
|
return null;
|
|
break;
|
|
case ('#callforward/afterhours'):
|
|
return 'After Hours';
|
|
break;
|
|
case ('#callforward/companyhours'):
|
|
return 'Company Hours';
|
|
break;
|
|
};
|
|
},
|
|
|
|
getStoreNameFromRoute: function (route) {
|
|
switch (route) {
|
|
case ('#callforward/always'):
|
|
return 'CallForwardAlways';
|
|
break;
|
|
case ('#callforward/afterhours'):
|
|
return 'CallForwardAfterHours';
|
|
break;
|
|
case ('#callforward/companyhours'):
|
|
return 'CallForwardCompanyHours';
|
|
break;
|
|
};
|
|
},
|
|
|
|
sortDestinationsetByPriority: function (destinations) {
|
|
var sorted = destinations.sort(function(a, b) {
|
|
return parseFloat(a.priority) - parseFloat(b.priority);
|
|
});
|
|
return sorted;
|
|
},
|
|
|
|
addCftOwnPhone: function(destinations, timeout) {
|
|
if (destinations.length > 0) {
|
|
destinations.unshift({
|
|
"announcement_id": null,
|
|
"destination": "own phone",
|
|
"priority": 1,
|
|
"timeout": timeout
|
|
})
|
|
}
|
|
},
|
|
|
|
cfStoreLoaded: function(store, data) {
|
|
var me = this;
|
|
var cfTypeArrayOfObjects = [data.get('cfu'), data.get('cft'), data.get('cfb'), data.get('cfna')];
|
|
var cftRingTimeout = data.get('cft_ringtimeout');
|
|
var cfTypes = ['cfu', 'cft', 'cfb', 'cfna'];
|
|
var timeset = store._type;
|
|
var arrayOfModels = [];
|
|
var currentRoute = window.location.hash;
|
|
var routeTimeset = this.getTimesetFromRoute(currentRoute);
|
|
store.removeAll();
|
|
// TODO optimize, too many nested loops affects performance.
|
|
// Ex. Where possible use break Ext.each by return false;
|
|
Ext.Ajax.request({
|
|
url: '/api/cfdestinationsets/?rows=100&subscriber_id=' + localStorage.getItem('subscriber_id'),
|
|
success: function(response, opts) {
|
|
var decodedResponse = Ext.decode(response.responseText);
|
|
if (decodedResponse._embedded) {
|
|
var cfdestinationsets = decodedResponse._embedded['ngcp:cfdestinationsets'];
|
|
Ext.each(cfTypeArrayOfObjects, function (cfTypeObjects, index) {
|
|
var cfType = cfTypes[index];
|
|
Ext.each(cfTypeObjects, function(cfTypeObject) {
|
|
var cfmappings = {};
|
|
cfmappings.destinationsetName = cfTypeObject.destinationset;
|
|
cfmappings.sourcesetName = cfTypeObject.sourceset;
|
|
cfmappings.timesetName = cfTypeObject.timeset;
|
|
if (cfmappings.timesetName == routeTimeset) {
|
|
Ext.each(cfdestinationsets, function(cfdestinationset) {
|
|
if (cfdestinationset.name == cfmappings.destinationsetName && !cfmappings._modelCreated) {
|
|
cfdestinationset.destinations = me.sortDestinationsetByPriority(cfdestinationset.destinations);
|
|
if (cfType === 'cft') {
|
|
if (cfTypeObjects.length > 0) {
|
|
me.addCftOwnPhone(cfdestinationset.destinations, cftRingTimeout);
|
|
}
|
|
};
|
|
for (item in cfdestinationset.destinations) {
|
|
var destinationToDisplayInGrid = me.getDestinationFromSipId(cfdestinationset.destinations[item].destination);
|
|
var destinationAnnouncementId = cfdestinationset.announcement_id;
|
|
var destination = cfdestinationset.destinations[item].destination;
|
|
var priority = cfdestinationset.destinations[item].priority;
|
|
var timeout = cfdestinationset.destinations[item].timeout;
|
|
var destinationId = cfdestinationset.id;
|
|
var destinationName = cfdestinationset.name;
|
|
// Removes timeout if destination is not a number
|
|
var ringFor = !Ext.isNumber(parseInt(destinationToDisplayInGrid)) ? '' : cfdestinationset.destinations[item].timeout;
|
|
var cbModel = Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
type: cfType,
|
|
destination_displayed: destinationToDisplayInGrid,
|
|
destination: destination,
|
|
destination_announcement_id: destinationAnnouncementId,
|
|
priority: priority,
|
|
timeout_displayed: ringFor,
|
|
timeout: timeout,
|
|
sourceset: cfmappings.sourcesetName,
|
|
timeset: cfmappings.timesetName,
|
|
destinationset_id: destinationId,
|
|
destinationset_name: destinationName
|
|
});
|
|
arrayOfModels.push(cbModel);
|
|
cfmappings._modelCreated = true;
|
|
}
|
|
}
|
|
});
|
|
};
|
|
});
|
|
});
|
|
if (arrayOfModels.length > 0) {
|
|
me.populateDestinationStores(arrayOfModels);
|
|
};
|
|
};
|
|
},
|
|
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
destinationIdExistsInArray: function(arr, id) {
|
|
return arr.some(function(arrObj) {
|
|
return id == arrObj.id;
|
|
});
|
|
},
|
|
|
|
cfStoreBeforeSync: function(store, options) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var recordsToSend = [];
|
|
delete options['destroy'];
|
|
delete options['create'];
|
|
delete options['update'];
|
|
Ext.each(store.getRange(), function(record) {
|
|
var data = record.getData();
|
|
if (data.destination !== 'own phone') {
|
|
switch (recordsToSend.length === 0 || !me.destinationIdExistsInArray(recordsToSend, data.destinationset_id)) {
|
|
case true:
|
|
// if recordsToSend array is empty or recordsToSend does not already contain current destinationset already
|
|
if (data.timeout) {
|
|
recordsToSend.push({
|
|
id: data.destinationset_id,
|
|
records: [{
|
|
"announcement_id": null,
|
|
"destination": data.destination,
|
|
"priority": data.priority,
|
|
"timeout": data.timeout
|
|
}]
|
|
});
|
|
} else {
|
|
recordsToSend.push({
|
|
id: data.destinationset_id,
|
|
records: [{
|
|
"announcement_id": null,
|
|
"destination": data.destination,
|
|
"priority": data.priority
|
|
}]
|
|
});
|
|
};
|
|
break;
|
|
case false:
|
|
// if destinationset has already been added to recordsToSend, push to the records field for that destinationset,
|
|
// building up an array of destination objects to write to API
|
|
recordsToSend.forEach(function(obj, index) {
|
|
if (obj.id == data.destinationset_id) {
|
|
if (data.timeout) {
|
|
recordsToSend[index].records.push({
|
|
"announcement_id": null,
|
|
"destination": data.destination,
|
|
"priority": data.priority,
|
|
"timeout": data.timeout
|
|
});
|
|
} else {
|
|
recordsToSend[index].records.push({
|
|
"announcement_id": null,
|
|
"destination": data.destination,
|
|
"priority": data.priority
|
|
});
|
|
};
|
|
};
|
|
});
|
|
break;
|
|
};
|
|
};
|
|
});
|
|
if (recordsToSend.length === 0) {
|
|
var destinationsetId = store.removed[0].data.destinationset_id;
|
|
Ext.Ajax.request({
|
|
url: '/api/cfdestinationsets/' + destinationsetId,
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Content-Type': 'application/json-patch+json'
|
|
},
|
|
jsonData: [{
|
|
"op": "add",
|
|
"path": "/destinations",
|
|
"value": []
|
|
}],
|
|
success: function(response, opts) {
|
|
var currentRoute = window.location.hash;
|
|
var currentStoreName = me.getStoreNameFromRoute(currentRoute);
|
|
Ext.getStore(currentStoreName).load();
|
|
vm.set('last_store_synced', currentStoreName);
|
|
},
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
} else {
|
|
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) {
|
|
var currentRoute = window.location.hash;
|
|
var currentStoreName = me.getStoreNameFromRoute(currentRoute);
|
|
Ext.getStore(currentStoreName).load();
|
|
vm.set('last_store_synced', currentStoreName);
|
|
},
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
});
|
|
};
|
|
return false;
|
|
},
|
|
|
|
cfReLoadStore: function () {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var currentRoute = window.location.hash;
|
|
var currentStoreName = me.getStoreNameFromRoute(currentRoute);
|
|
if (vm.get('last_store_synced').length > 0 && currentStoreName !== vm.get('last_store_synced')) {
|
|
Ext.getStore(currentStoreName).load();
|
|
};
|
|
},
|
|
|
|
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._sourcesetListId;
|
|
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;
|
|
},
|
|
|
|
cfTimesetBeforeSync: function(store, options) {
|
|
delete options['destroy'];
|
|
delete options['create'];
|
|
delete options['update'];
|
|
return false;
|
|
},
|
|
|
|
getDestinationFromSipId: function(destination) {
|
|
var splitDestination = destination === 'own phone' ? [null, null, 'own phone', null, null] : destination.split(/(:|@)/);
|
|
switch (splitDestination[4]) {
|
|
case 'voicebox.local':
|
|
return 'Voicemail';
|
|
break;
|
|
case 'conference.local':
|
|
return 'Conference';
|
|
break;
|
|
case 'fax2mail.local':
|
|
return 'Fax2Mail';
|
|
break;
|
|
default:
|
|
// Returns parsed destination URI/Number types to make them
|
|
// human readable in grid, as well as for any app.local types
|
|
// that might exist (callingcard, callthrough, autoattendant,
|
|
// officehours, customhours, localuser)
|
|
if (!Ext.isNumber(parseInt(splitDestination[2]))) {
|
|
return Ext.util.Format.capitalize(splitDestination[2]);
|
|
} else {
|
|
return splitDestination[2];
|
|
};
|
|
};
|
|
},
|
|
|
|
getGridCategoryFromType: function(type) {
|
|
switch (type) {
|
|
case 'cft':
|
|
case 'cfu':
|
|
return 'CallForwardOnline';
|
|
break;
|
|
case 'cfb':
|
|
return 'CallForwardBusy';
|
|
break;
|
|
case 'cfna':
|
|
return 'CallForwardOffline';
|
|
break;
|
|
};
|
|
},
|
|
|
|
getTypeFromTypeName: function(type, store) {
|
|
switch (type) {
|
|
case 'Online':
|
|
if (store.last()) {
|
|
return 'cfu';
|
|
} else {
|
|
return 'cft';
|
|
};
|
|
break;
|
|
case 'Busy':
|
|
return 'cfb';
|
|
break;
|
|
case 'Offline':
|
|
return 'cfna';
|
|
break;
|
|
};
|
|
},
|
|
|
|
getSourceNameFromSourceSet: function(sourceset) {
|
|
switch (sourceset) {
|
|
case null:
|
|
return 'everybody-';
|
|
break;
|
|
default:
|
|
return sourceset.replace(/ /g, '') + '-';
|
|
}
|
|
},
|
|
|
|
getTimeNameFromTimeSet: function(timeset) {
|
|
switch (timeset) {
|
|
case 'After Hours':
|
|
return 'afterhours-';
|
|
break;
|
|
case 'Company Hours':
|
|
return 'companyhours-';
|
|
break;
|
|
case null:
|
|
return 'always-';
|
|
break;
|
|
}
|
|
},
|
|
|
|
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) {
|
|
case '#callforward/always':
|
|
return 'always';
|
|
break;
|
|
case '#callforward/afterhours':
|
|
return 'afterhours';
|
|
break;
|
|
case '#callforward/companyhours':
|
|
return 'companyhours';
|
|
break;
|
|
};
|
|
},
|
|
|
|
// TODO: Remove when done with this task, but keep for reference for now
|
|
getModelValuesFromTimesData: function (timesData) {
|
|
var times = {};
|
|
var timesFromAndTo = timesData.hour !== null ? timesData.hour.split('-') : [null, null];
|
|
var daysFromAndTo = timesData.wday !== null ? timesData.wday.split('-') : [null, null];
|
|
var weekdayLiterals = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
var timeFrom = timesFromAndTo[0];
|
|
var timeTo = timesFromAndTo[1];
|
|
var dayFrom = daysFromAndTo[0];
|
|
var dayTo = daysFromAndTo[1];
|
|
times.days;
|
|
var weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
|
|
times.timeFrom = timeFrom;
|
|
times.timeTo = timeTo;
|
|
if (!!timesData.wday) {
|
|
var weekdaysArray = weekdayLiterals.slice(dayFrom - 1, dayTo);
|
|
times.days = weekdaysArray;
|
|
} else {
|
|
times.days = null;
|
|
};
|
|
return times;
|
|
},
|
|
|
|
populateTimesetStores: function(models) {
|
|
var vm = this.getViewModel();
|
|
var currentRoute = window.location.hash;
|
|
var moduleName = this.getModuleFromRoute(currentRoute);
|
|
var store = Ext.getStore(moduleName + '-Timeset');
|
|
if (store.getCount() === 0) {
|
|
Ext.each(models, function(model) {
|
|
if (moduleName == 'afterours' && model.get('timeset_name') == 'After Hours') {
|
|
store.add(model);
|
|
} else if (moduleName == 'companyours' && model.get('timeset_name') == 'Company Hours') {
|
|
store.add(model);
|
|
};
|
|
});
|
|
store.commitChanges();
|
|
if (store.getCount() > 0) {
|
|
vm.set(moduleName + '_hideMessage', true);
|
|
};
|
|
};
|
|
},
|
|
|
|
setLabelTerminationType: function(store) {
|
|
var terminationPositionRecord = store.findRecord('destination_displayed', /(Voicemail|Fax2Mail|Conference|Custom-hours|Office-hours|Auto-attendant|Callthrough|Callingcard)/);
|
|
var storeCount = store.getCount();
|
|
// Sets after_termination value for all records after first non-number
|
|
if (terminationPositionRecord && terminationPositionRecord.get('destination_displayed')) {
|
|
var terminationPositionIndex = store.indexOf(terminationPositionRecord);
|
|
var terminationTrueIndexRange = [];
|
|
var terminationFalseIndexRange = [];
|
|
for (i = terminationPositionIndex + 1; i < storeCount; i++) {
|
|
terminationTrueIndexRange.push(i);
|
|
};
|
|
for (i = terminationPositionIndex; i >= 0; i--) {
|
|
terminationFalseIndexRange.push(i);
|
|
};
|
|
terminationTrueIndexRange.map(function(index) {
|
|
store.getAt(index).set('after_termination', true);
|
|
});
|
|
terminationFalseIndexRange.map(function(index) {
|
|
store.getAt(index).set('after_termination', false);
|
|
});
|
|
};
|
|
// "Greyes out" destination if appearing after a terminating destination
|
|
if (store.findRecord('type', 'cfu') && store.findRecord('type', 'cft')) {
|
|
Ext.each(store.getRange(), function(record) {
|
|
if (!record.get('after_termination') && record.get('type') === 'cft') {
|
|
record.set('after_termination', true);
|
|
};
|
|
});
|
|
};
|
|
Ext.each(store.getRange(), function(record) {
|
|
if (record.get('destination') === 'own phone') {
|
|
record.set('label', 'first ring');
|
|
record.set('after_termination', false);
|
|
store.remove(record);
|
|
store.insert(0, record);
|
|
};
|
|
});
|
|
// Sets "first ring", "then forward to ..." and "" (empty) labels
|
|
Ext.each(store.getRange(), function(record, index) {
|
|
if (index === 0) {
|
|
record.set('label', 'first ring');
|
|
} else if (index === 1) {
|
|
record.set('label', 'then forward to ...');
|
|
} else {
|
|
record.set('label', '');
|
|
}
|
|
});
|
|
},
|
|
|
|
populateDestinationStores: function(models) {
|
|
var me = this;
|
|
var store;
|
|
var stores = [];
|
|
Ext.each(models, function(model) {
|
|
var sourcename = me.getSourceNameFromSourceSet(model.get('sourceset'));
|
|
var timename = me.getTimeNameFromTimeSet(model.get('timeset'));
|
|
var type = me.getGridCategoryFromType(model.get('type'));
|
|
var storeName = sourcename + timename + type;
|
|
store = Ext.getStore(storeName);
|
|
if(!store._emptied){
|
|
store.removeAll();
|
|
store._emptied = true;
|
|
}
|
|
if (store) {
|
|
store.add(model);
|
|
stores.push(store);
|
|
}
|
|
});
|
|
if (store) {
|
|
Ext.each(stores, function(store) {
|
|
store.commitChanges();
|
|
me.setLabelTerminationType(store);
|
|
store._emptied = false;
|
|
});
|
|
}
|
|
},
|
|
|
|
createSourcesetTabs: function(sourcesets) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var subscriberId = localStorage.getItem('subscriber_id');
|
|
var cfTabPanels = Ext.ComponentQuery.query('[name=cfTab]');
|
|
var currentRoute = window.location.hash;
|
|
var moduleName = this.getModuleFromRoute(currentRoute);
|
|
if (sourcesets && sourcesets.length > 0) {
|
|
Ext.each(cfTabPanels, function(tabP) {
|
|
if (tabP._tabId == moduleName) {
|
|
Ext.each(sourcesets, function(sourceset, index) {
|
|
var sourcesetName = sourceset.isModel ? sourceset.get('sourceset_name') : sourceset.name;
|
|
var sourcesetId = sourceset.isModel ? sourceset.get('sourceset_id') : sourceset.id;
|
|
var strippedSourcesetName = sourcesetName.replace(/ /g, '');
|
|
tabP._firstPrefixes.push(strippedSourcesetName + '-');
|
|
vm.set('sourceset-' + sourcesetId + '-title', sourcesetName);
|
|
vm.set('sourceset-' + sourcesetId + 'from-title', Ngcp.csc.locales.callforward.from[localStorage.getItem('languageSelected')] + sourcesetName);
|
|
vm.set('sourceset-' + sourcesetId + '-titleField-value', '');
|
|
Ext.defer(function() {
|
|
if (Ext.ComponentQuery.query("[name=" + tabP._tabId + '-tab-' + strippedSourcesetName + "]").length < 1) {
|
|
var newTab = Ext.create('Ext.panel.Panel', {
|
|
bind: {
|
|
title: '{sourceset-' + sourcesetId + 'from-title}'
|
|
},
|
|
name: tabP._tabId + '-tab-' + strippedSourcesetName,
|
|
id: (tabP._tabId + '-tab-' + strippedSourcesetName).toString(),
|
|
items: [
|
|
Ext.create('NgcpCsc.view.pages.callforward.CallForwardMainForm', {
|
|
_isEverybody: false,
|
|
_sourcesetStoreId: strippedSourcesetName,
|
|
_sourcesetListName: sourcesetName,
|
|
_sourcesetListId: sourcesetId,
|
|
_firstprefix: tabP._firstPrefixes[index + 1],
|
|
_secondprefix: tabP._secondprefix
|
|
|
|
})
|
|
]
|
|
});
|
|
tabP.add(newTab);
|
|
}
|
|
}, 100);
|
|
});
|
|
return;
|
|
}
|
|
});
|
|
} else {
|
|
var models = [];
|
|
Ext.Ajax.request({
|
|
url: '/api/cfsourcesets/',
|
|
method: 'POST',
|
|
jsonData: {
|
|
name: 'List A',
|
|
mode: 'whitelist',
|
|
subscriber_id: subscriberId
|
|
},
|
|
success: function(response, opts) {
|
|
var sourcesetId = response.getResponseHeader('Location').split('/')[3];
|
|
models.push(Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
id: Ext.id(),
|
|
sourceset_name: 'List A',
|
|
sourceset_id: sourcesetId
|
|
}));
|
|
Ext.Ajax.request({
|
|
url: '/api/cfsourcesets/',
|
|
method: 'POST',
|
|
jsonData: {
|
|
name: 'List B',
|
|
mode: 'whitelist',
|
|
subscriber_id: subscriberId
|
|
},
|
|
success: function(response, opts) {
|
|
var sourcesetId = response.getResponseHeader('Location').split('/')[3];
|
|
models.push(Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
id: Ext.id(),
|
|
sourceset_name: 'List B',
|
|
sourceset_id: sourcesetId
|
|
}));
|
|
me.createSourcesetTabs(models);
|
|
},
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
},
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
populateSourcesetStores: function(models) {
|
|
var stores = {};
|
|
Ext.each(models, function(model) {
|
|
var tabId = model.get('sourceset_name');
|
|
var strippedSourcesetName = tabId.replace(/ /g, '');
|
|
if(!stores[strippedSourcesetName]){
|
|
stores[strippedSourcesetName] = [];
|
|
}
|
|
stores[strippedSourcesetName].push(model);
|
|
});
|
|
Ext.Object.each(stores, function(storeNameSuffix, models){
|
|
var store = Ext.getStore('CallForwardList_' + storeNameSuffix);
|
|
store.removeAll();
|
|
store.add(models);
|
|
store.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) {
|
|
var record = context.record;
|
|
var grid = context.grid;
|
|
record.set("edit", true);
|
|
},
|
|
|
|
collapsePanel: function(el) {
|
|
var panelId = el.id.split('-')[1];
|
|
var isCollapsed = el.collapsed === false ? false : true;
|
|
var store = Ext.getStore('CallForwardLocalStorage');
|
|
var localStorageRecord = store.getAt(0);
|
|
switch (panelId) {
|
|
case 'afterHours':
|
|
switch (isCollapsed) {
|
|
case true:
|
|
localStorageRecord.set('afterHoursCollapsed', true);
|
|
break;
|
|
case false:
|
|
localStorageRecord.set('afterHoursCollapsed', false);
|
|
break;
|
|
}
|
|
break;
|
|
case 'companyHours':
|
|
switch (isCollapsed) {
|
|
case true:
|
|
localStorageRecord.set('companyHoursCollapsed', true);
|
|
break;
|
|
case false:
|
|
localStorageRecord.set('companyHoursCollapsed', false);
|
|
break;
|
|
}
|
|
break;
|
|
};
|
|
store.sync();
|
|
},
|
|
|
|
onEnterPressed: function(field, el) {
|
|
var me = this;
|
|
if (el.getKey() == el.ENTER) {
|
|
me.addNewDestination(field);
|
|
};
|
|
},
|
|
|
|
toggleChangeTitle: function(button) {
|
|
var vm = this.getViewModel();
|
|
var buttonId = button.id;
|
|
var hiddenKey = 'hide_' + buttonId.split('-')[2];
|
|
vm.set(hiddenKey, !vm.get(hiddenKey));
|
|
},
|
|
|
|
saveNewTitle: function(button) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var buttonId = button.name;
|
|
var keys = buttonId.split('-');
|
|
Ext.Ajax.request({
|
|
url: '/api/cfsourcesets/' + button._sourcesetListId,
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Content-Type': 'application/json-patch+json'
|
|
},
|
|
jsonData: [{
|
|
"op": "replace",
|
|
"path": "/name",
|
|
"value": vm.get('sourceset-' + keys[0] + "-titleField-value")
|
|
}],
|
|
success: function(response, opts) {
|
|
me.updateTabsTitles(keys[0]);
|
|
me.fireEvent('showmessage', true, Ngcp.csc.locales.common.save_success[localStorage.getItem('languageSelected')]);
|
|
},
|
|
failure: function(response, opts) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
},
|
|
|
|
updateTabsTitles: function(sourcesetId, sourcesetTitleValue) {
|
|
var vm = this.getViewModel();
|
|
var me = this;
|
|
var cfTabPanels = Ext.ComponentQuery.query('[name=cfTab]');
|
|
var currentRoute = window.location.hash;
|
|
var moduleName = this.getModuleFromRoute(currentRoute);
|
|
var newTitle = vm.get('sourceset-' + sourcesetId + "-titleField-value");
|
|
|
|
Ext.each(cfTabPanels, function(tabP) { // every CF submdule has its own vm
|
|
if (tabP._tabId !== moduleName) {
|
|
me.updateVMTitle(tabP.up('callforward').getViewModel(), sourcesetId, newTitle);
|
|
} else {
|
|
me.updateVMTitle(vm, sourcesetId, newTitle);
|
|
}
|
|
});
|
|
},
|
|
|
|
updateVMTitle: function(vm, sourcesetId, sourcestTitleValue) {
|
|
vm.set('sourceset-' + sourcesetId + "-title", sourcestTitleValue);
|
|
vm.set('sourceset-' + sourcesetId + "from-title", Ngcp.csc.locales.callforward.from[localStorage.getItem('languageSelected')] + sourcestTitleValue);
|
|
vm.set('sourceset-' + sourcesetId + "-titleField-value", "")
|
|
},
|
|
|
|
cancelNewTitle: function(button) {
|
|
var vm = this.getViewModel();
|
|
var buttonId = button.name;
|
|
var keys = buttonId.split('-');
|
|
vm.set('sourceset-' + keys[0] + "-titleField-value", "");
|
|
},
|
|
|
|
checkIndexOf: function(string, target) {
|
|
return target.indexOf(string) > -1;
|
|
},
|
|
|
|
writeNewSourceToStore: function(grid) {
|
|
var vm = this.getViewModel();
|
|
var store = grid.getStore();
|
|
var plugin = grid.getPlugin('celleditingSource');
|
|
var newRowIndex = store.getCount() + 1;
|
|
|
|
var cfSourcesetModel = Ext.create('NgcpCsc.model.CallForwardSourceset', {
|
|
id: Ext.id(),
|
|
source: " ",
|
|
sourceset_name: vm.get('sourceset-' + grid.up('cfMainForm')._sourcesetListId + "-title"),
|
|
sourceset_id: grid.up('cfMainForm')._sourcesetListId,
|
|
edit: true
|
|
});
|
|
store.add(cfSourcesetModel);
|
|
plugin.startEditByPosition({
|
|
row: newRowIndex,
|
|
column: 0
|
|
});
|
|
},
|
|
|
|
addEmptySourcesetRow: function(button) {
|
|
var buttonIdSplit = button.id.split('-');
|
|
var buttonPrefixOne = buttonIdSplit[0];
|
|
var buttonPrefixTwo = buttonIdSplit[1];
|
|
var buttonSuffix = buttonIdSplit[2];
|
|
var grid = Ext.getCmp(buttonPrefixOne + '-' + buttonPrefixTwo + '-cf-sourceset-list-grid');
|
|
this.writeNewSourceToStore(grid);
|
|
},
|
|
|
|
removeEntry: function(grid, rowIndex, colIndex) {
|
|
var store = grid.getStore();
|
|
var rec = grid.getStore().getAt(rowIndex);
|
|
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')];
|
|
this.fireEvent('showconfirmbox', title, question, sucessMsg, 'confirmCFRemoval', rec);
|
|
},
|
|
|
|
// setCfuAsType() sets type to cfu for all destinations with given destinationset id, and Returns
|
|
// the updated store
|
|
setCfuAsType: function (store, id) {
|
|
Ext.each(store.getRange(), function(record) {
|
|
if (record.get('destinationset_id') === id) {
|
|
record.set('type', 'cfu');
|
|
}
|
|
});
|
|
return store;
|
|
},
|
|
|
|
recordHasStoreAndOwnPhone: function (record) {
|
|
var store = record.store;
|
|
return store && record.get('destination') === 'own phone';
|
|
},
|
|
|
|
confirmCFRemoval: function(record) {
|
|
var $cf = this;
|
|
var store = record.store;
|
|
var subscriberId = localStorage.getItem('subscriber_id');
|
|
if ($cf.recordHasStoreAndOwnPhone(record)) {
|
|
store = $cf.setCfuAsType(store, record.get('destinationset_id'));
|
|
Ext.Ajax.request({
|
|
url: '/api/cfmappings/' + localStorage.getItem('subscriber_id'),
|
|
method: 'GET',
|
|
jsonData: {},
|
|
success: function(response) {
|
|
var decodedResponse = Ext.decode(response.responseText);
|
|
var cfuMappings = decodedResponse['cfu'];
|
|
var cftMappings = decodedResponse['cft'];
|
|
cfuMappings.push({
|
|
"destinationset": record.get('destinationset_name'),
|
|
"sourceset": record.get('sourceset'),
|
|
"timeset": record.get('timeset')
|
|
});
|
|
cftMappings = cftMappings.filter(function( obj ) {
|
|
return obj.destinationset !== record.get('destinationset_name');
|
|
});
|
|
Ext.Ajax.request({
|
|
url: '/api/cfmappings/' + subscriberId,
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Content-Type': 'application/json-patch+json'
|
|
},
|
|
// We are writing to two paths based on the call forwarding
|
|
// types we are manipulating. Removing the mapping from cft
|
|
// and adding a new mapping for cfu
|
|
jsonData: [{
|
|
"op": "add",
|
|
"path": "/cft",
|
|
"value": cftMappings
|
|
}, {
|
|
"op": "add",
|
|
"path": "/cfu",
|
|
"value": cfuMappings
|
|
}],
|
|
success: function (response) {
|
|
store.sync();
|
|
},
|
|
failure: function(response) {
|
|
console.log('server-side failure with status code ' + response.status);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
} else if (store) {
|
|
store.remove(record);
|
|
store.sync();
|
|
$cf.setLabelTerminationType(store);
|
|
};
|
|
},
|
|
|
|
getStoresArrayFromRoute: function(currentRoute, currentSourceset) {
|
|
var view = currentRoute.split('/')[1];
|
|
var prefix = currentSourceset + '-' + view + '-';
|
|
return [prefix + 'CallForwardOnline', prefix + 'CallForwardBusy', prefix + 'CallForwardOffline'];
|
|
},
|
|
|
|
renderDay: function(value, meta, record) {
|
|
if (record.get('closed') === true) {
|
|
return Ext.String.format('<div class="cf-deactivate-day">{0}</div>', value);
|
|
} else {
|
|
return value;
|
|
}
|
|
},
|
|
|
|
toggleClosedState: function(grid, rowIndex, colIndex, item, event, record) {
|
|
record.set('closed', !record.get('closed'));
|
|
this.renderDay(record.get('closed'), null, record);
|
|
},
|
|
|
|
toggleClosedClass: function(val, meta, rec) {
|
|
return rec.get('closed') === true ? Ngcp.csc.icons.square_checked : Ngcp.csc.icons.square;
|
|
},
|
|
|
|
removeSourcelistRecord: function(grid, rowIndex) {
|
|
var store = grid.getStore();
|
|
var rec = grid.getStore().getAt(rowIndex);
|
|
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')];
|
|
this.fireEvent('showconfirmbox', title, question, sucessMsg, 'confirmCFRemoval', rec);
|
|
},
|
|
|
|
renderDestinationColumn: function(value, metaData, record) {
|
|
if (record.get('destination') === 'own phone') {
|
|
return Ext.String.format('Own phone and ring for {0} secs', record.get('timeout'));
|
|
} else if (record.get('timeout_displayed') === '' && !Ext.isNumber(parseInt(value))) {
|
|
return Ext.String.format('{0}', value);
|
|
} else {
|
|
return Ext.String.format('{0} and ring for {1} secs', value, record.get('timeout_displayed'));
|
|
};
|
|
},
|
|
|
|
showHideTimeoutField: function(vm, record, timeoutField) {
|
|
switch (record) {
|
|
case 'Number':
|
|
case 'Own phone':
|
|
vm.set(timeoutField, false);
|
|
break;
|
|
case 'Voicemail':
|
|
case 'Fax2Mail':
|
|
case 'None':
|
|
vm.set(timeoutField, true);
|
|
break;
|
|
};
|
|
},
|
|
|
|
selectRing: function(component, record) {
|
|
var vm = this.getViewModel();
|
|
var cmpIdSplit = component.getId().split('-');
|
|
var timeoutFieldCategory = cmpIdSplit[2].replace(/FirstDest|ThenDest/, '');
|
|
var firstOrThen = cmpIdSplit[2].replace(/online|offline|busy/, '').toLowerCase().replace('dest', '');
|
|
this.showHideTimeoutField(vm, record, timeoutFieldCategory + '_' + firstOrThen + '_timeout_hidden');
|
|
},
|
|
|
|
toggleNewDestinationForm: function(button) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var targetId = button.id;
|
|
switch (true) {
|
|
case (me.checkIndexOf('online', targetId)):
|
|
vm.set('online_add_new_then_hidden', !vm.get('online_add_new_then_hidden'));
|
|
vm.set('online_cancel_button_hidden', !vm.get('online_cancel_button_hidden'));
|
|
vm.set('online_add_button_hidden', !vm.get('online_add_button_hidden'));
|
|
break;
|
|
case (me.checkIndexOf('busy', targetId)):
|
|
vm.set('busy_add_new_then_hidden', !vm.get('busy_add_new_then_hidden'));
|
|
vm.set('busy_cancel_button_hidden', !vm.get('busy_cancel_button_hidden'));
|
|
vm.set('busy_add_button_hidden', !vm.get('busy_add_button_hidden'));
|
|
break;
|
|
case (me.checkIndexOf('offline', targetId)):
|
|
vm.set('offline_add_new_then_hidden', !vm.get('offline_add_new_then_hidden'));
|
|
vm.set('offline_cancel_button_hidden', !vm.get('offline_cancel_button_hidden'));
|
|
vm.set('offline_add_button_hidden', !vm.get('offline_add_button_hidden'));
|
|
break;
|
|
};
|
|
},
|
|
|
|
hideThenFieldsByStoreName: function(vm, storeNameStripped) {
|
|
this.fireEvent('showmessage', true, Ngcp.csc.locales.common.save_success[localStorage.getItem('languageSelected')]);
|
|
switch (storeNameStripped) {
|
|
case 'CallForwardOnline':
|
|
vm.set('online_add_new_then_hidden', true);
|
|
vm.set('online_cancel_button_hidden', true);
|
|
vm.set('online_add_button_hidden', false);
|
|
break;
|
|
case 'CallForwardBusy':
|
|
vm.set('busy_add_new_then_hidden', true);
|
|
vm.set('busy_cancel_button_hidden', true);
|
|
vm.set('busy_add_button_hidden', false);
|
|
break;
|
|
case 'CallForwardOffline':
|
|
vm.set('offline_add_new_then_hidden', true);
|
|
vm.set('offline_cancel_button_hidden', true);
|
|
vm.set('offline_add_button_hidden', false);
|
|
break;
|
|
};
|
|
},
|
|
|
|
validateDestinationForm: function(storeName) {
|
|
var me = this;
|
|
var vm = me.getViewModel();
|
|
var targetStore = Ext.getStore(storeName);
|
|
var storeNameStripped = storeName.split('-')[2];
|
|
var storeNameCategory = storeNameStripped.replace('CallForward', '').toLowerCase();
|
|
var newNumber = vm.get(storeNameCategory + '_then_number');
|
|
var newDest = vm.get(storeNameCategory + '_then_dest');
|
|
var newPhone, newTimeout;
|
|
switch (Ext.isEmpty(newNumber) || newDest === 'Voicemail' || newDest === 'Fax2Mail') {
|
|
case true:
|
|
switch (Ext.isEmpty(newNumber) && newDest === 'Number') {
|
|
case true:
|
|
me.fireEvent('showmessage', false, Ngcp.csc.locales.callforward.number_is_required[localStorage.getItem('languageSelected')]);
|
|
break;
|
|
case false:
|
|
me.writeNewDestinationToStore(targetStore, newDest, "");
|
|
me.hideThenFieldsByStoreName(vm, storeNameStripped);
|
|
break;
|
|
};
|
|
vm.set(storeNameCategory + '_then_number', '');
|
|
break;
|
|
case false:
|
|
switch (Ext.isNumber(parseInt(newNumber))) {
|
|
case false:
|
|
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;
|
|
me.writeNewDestinationToStore(targetStore, newPhone, parseInt(newTimeout));
|
|
vm.set(storeNameCategory + '_then_number', '');
|
|
me.hideThenFieldsByStoreName(vm, storeNameStripped);
|
|
break;
|
|
};
|
|
break;
|
|
};
|
|
},
|
|
|
|
|
|
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 '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/' + localStorage.getItem('subscriber_id'),
|
|
method: 'GET',
|
|
jsonData: {},
|
|
success: function(response) {
|
|
var decodedResponse = Ext.decode(response.responseText);
|
|
var mappings = decodedResponse[newType];
|
|
mappings.push({
|
|
"destinationset": newDestinationsetName,
|
|
"sourceset": newSourceset,
|
|
"timeset": newTimeset
|
|
});
|
|
Ext.Ajax.request({
|
|
url: '/api/cfmappings/' + subscriberId,
|
|
method: 'PATCH',
|
|
headers: {
|
|
'Content-Type': 'application/json-patch+json'
|
|
},
|
|
jsonData: [{
|
|
"op": "add",
|
|
"path": "/" + newType,
|
|
"value": mappings
|
|
}]
|
|
});
|
|
}
|
|
});
|
|
},
|
|
|
|
writeNewDestinationToStore: function(store, destination, timeout) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var simpleDestination = destination;
|
|
var priority = 1;
|
|
var storeCount = store.getCount();
|
|
var activeTab = this.getView().down('tabpanel').getActiveTab().down('cfMainForm');
|
|
// Removes timeout if destination is not a number
|
|
var ringFor = !Ext.isNumber(parseInt(destination)) ? '' : timeout;
|
|
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 = activeTab ? vm.get('sourceset-' + activeTab._sourcesetListId + "-title") : null;
|
|
var newTimeset = this.getTimeSetFromTimeSource(newTimesetName);
|
|
var newType = this.getTypeFromTypeName(newTypeName, store);
|
|
var newDestination = destination === 'Voicemail' ? 'voicebox' : destination.toLowerCase();
|
|
var newTimeout = !timeout ? null : timeout;
|
|
if (!store.last()) { // if store empty we need to create new destset
|
|
var newDestinationsetName = 'csc_' + newType + '_' + Date.now();
|
|
var subscriberId = localStorage.getItem('subscriber_id');
|
|
Ext.Ajax.request({
|
|
url: '/api/cfdestinationsets/',
|
|
method: 'POST',
|
|
jsonData: {
|
|
name: newDestinationsetName,
|
|
subscriber_id: subscriberId
|
|
},
|
|
success: function(response, opts) {
|
|
var destinationsetId = response.getResponseHeader('Location').split('/')[3];
|
|
var cfModel = Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
type: newType,
|
|
destination_displayed: destination,
|
|
destination: newDestination,
|
|
timeout_displayed: ringFor,
|
|
timeout: newTimeout,
|
|
sourceset: newSourceset,
|
|
timeset: newTimeset,
|
|
destinationset_id: destinationsetId,
|
|
destinationset_name: newDestinationsetName
|
|
});
|
|
store.add(cfModel);
|
|
me.setLabelTerminationType(store);
|
|
store.sync();
|
|
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 afterTermination = false;
|
|
switch (true) {
|
|
case (!lastRecordInStore.get('after_termination') && !Ext.isNumber(parseInt(lastRecordInStore.get('destination_displayed')))):
|
|
afterTermination = true;
|
|
break;
|
|
case (lastRecordInStore.get('after_termination')):
|
|
afterTermination = true;
|
|
break;
|
|
};
|
|
var cfModel = Ext.create('NgcpCsc.model.CallForwardDestination', {
|
|
type: lastRecordInStore.get('type'),
|
|
destination_displayed: destination,
|
|
destination: newDestination,
|
|
after_termination: afterTermination,
|
|
priority: lastRecordInStore.get('priority'),
|
|
timeout_displayed: ringFor,
|
|
timeout: newTimeout,
|
|
sourceset: lastRecordInStore.get('sourceset'),
|
|
timeset: lastRecordInStore.get('timeset'),
|
|
destinationset_id: lastRecordInStore.get('destinationset_id'),
|
|
destinationset_name: lastRecordInStore.get('destinationset_name')
|
|
});
|
|
store.add(cfModel);
|
|
me.setLabelTerminationType(store);
|
|
store.sync();
|
|
}
|
|
},
|
|
|
|
addNewDestination: function(element) {
|
|
var me = this;
|
|
var vm = this.getViewModel();
|
|
var targetId = element.id;
|
|
var splitTargetId = targetId.split('-');
|
|
var selectedSourceset = splitTargetId[0];
|
|
var selectedTimeset = splitTargetId[1];
|
|
switch (true) {
|
|
case (me.checkIndexOf('online', targetId)):
|
|
me.validateDestinationForm(selectedSourceset + '-' + selectedTimeset + '-CallForwardOnline');
|
|
break;
|
|
case (me.checkIndexOf('busy', targetId)):
|
|
me.validateDestinationForm(selectedSourceset + '-' + selectedTimeset + '-CallForwardBusy');
|
|
break;
|
|
case (me.checkIndexOf('offline', targetId)):
|
|
me.validateDestinationForm(selectedSourceset + '-' + selectedTimeset + '-CallForwardOffline');
|
|
break;
|
|
};
|
|
},
|
|
|
|
parseRecordsToTimesetApi: function () {
|
|
|
|
},
|
|
|
|
recordsToSendBasedOnTimes: function (store) {
|
|
// Started this, but then discovered the issue leading to creation
|
|
// of #18401. Leaving the code in place for upcoming task #18401
|
|
// DONE: Solve how to convert ExtJS default timevalues to hour only value
|
|
// for /api/cftimesets/ PATCH
|
|
// Ext.each(store.getRange(), function (record) {
|
|
// var timeTo = record.get('time_to');
|
|
// if (timeTo.length === undefined) {
|
|
// console.log(Ext.Date.format(record.get('time_to'), 'G')); // Converts to 24-hour format of an hour without leading zeros
|
|
// } else {
|
|
// console.log(timeTo);
|
|
// }
|
|
// });
|
|
var recordsToSend = [];
|
|
Ext.each(store.getRange(), function(record) {
|
|
var data = record.getData();
|
|
// TODO: First iteration - for each weekday, create a model to
|
|
// append to recordsToSend array. Might make sense to create a
|
|
// separate function that massages the data in recordsToSend array,
|
|
// and returns a merged set of hours and times to send in patch
|
|
// console.log(data.time_from);
|
|
// console.log(data.time_to);
|
|
});
|
|
var mergedRecordsToSend = this.parseRecordsToTimesetApi(recordsToSend);
|
|
return mergedRecordsToSend;
|
|
},
|
|
|
|
cfTimesetBeforeSync: function (store, options) {
|
|
// XXX: Currently cfTimesetStoreLoaded builds arrayOfModels() based on data
|
|
// from proxy, then invokes populateTimesetStores with the array as argument
|
|
// and adds models to correct store.
|
|
// XXX: To implement additional logic we need to:
|
|
// TODO: 1. Handle initial response from proxy fetch of /api/cftimesets/
|
|
// data, also when times value array has several time objects
|
|
// TODO: 2. Handle saving of grid changes by binding timefield widgets
|
|
// to store, and syncing upong pressing "SAVE" button
|
|
delete options['destroy'];
|
|
delete options['create'];
|
|
delete options['update'];
|
|
var timesetId = store.last().get('timeset_id');
|
|
var recordsToSend = this.recordsToSendBasedOnTimes(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;
|
|
},
|
|
|
|
saveGrid: function(el) {
|
|
var storeName = el.id.split('-')[0] + '-Timeset';
|
|
var store = Ext.getStore(storeName);
|
|
store.sync();
|
|
}
|
|
|
|
});
|