TT#28062 Change order of destination

What has been done:
- TT#30679, CallForwarding: Implement UI icons and flow
- TT#30395, CallForwarding: Implement api requests
- TT#30680, CallForwarding: Implement store and state management

What is remaining (if we deem it necessary):
- TT#30763, CallForwarding: Create unit test

Change-Id: I0fb606327c12075a72eff43c901a2881b2af9981
changes/22/18522/11
raxelsen 8 years ago committed by Hans-Peter Herzog
parent 38d68c1d6e
commit 8666f25670

@ -119,9 +119,9 @@ export function loadAlwaysEverybodyDestinations(subscriberId) {
Promise.all(cfbPromises)
]);
}).then((res)=>{
computeLowestPriorityAndAddGroupName(res[0], 'cfu');
computeLowestPriorityAndAddGroupName(res[1], 'cfna');
computeLowestPriorityAndAddGroupName(res[2], 'cfb');
addGroupNames(res[0], 'cfu');
addGroupNames(res[1], 'cfna');
addGroupNames(res[2], 'cfb');
resolve({
online: res[0],
offline: res[1],
@ -133,10 +133,8 @@ export function loadAlwaysEverybodyDestinations(subscriberId) {
});
}
export function computeLowestPriorityAndAddGroupName(group, groupName) {
export function addGroupNames(group, groupName) {
group.forEach(destinationset => {
let lowest = _.maxBy(destinationset.destinations, 'priority') || { priority: 1 };
destinationset.lowestPriority = lowest.priority;
destinationset.groupName = groupName;
});
return group;
@ -147,6 +145,9 @@ export function getDestinationsetById(id) {
Vue.http.get('/api/cfdestinationsets/' + id).then((res)=>{
let destinationset = getJsonBody(res.body);
delete destinationset['_links'];
destinationset.destinations.sort((a, b) => {
return parseFloat(a.priority) - parseFloat(b.priority);
});
resolve(destinationset);
}).catch((err)=>{
reject(err);
@ -274,8 +275,11 @@ export function addNewMapping(options) {
'Content-Type': 'application/json-patch+json'
};
return new Promise((resolve, reject) => {
let mappingsToSend = [{ destinationset_id: options.destinationsetId,
sourceset_id: null, timeset_id: null }];
let mappingsToSend = [{
destinationset_id: options.destinationsetId,
sourceset_id: null,
timeset_id: null
}];
Vue.http.patch('/api/cfmappings/' + options.subscriberId, [{
op: 'replace',
path: '/' + options.group,
@ -287,3 +291,88 @@ export function addNewMapping(options) {
});
});
}
export function changePositionOfDestination(options) {
let headers = {
'Content-Type': 'application/json-patch+json'
};
return new Promise((resolve, reject) => {
Vue.http.patch('/api/cfdestinationsets/' + options.id, [{
op: 'replace',
path: '/destinations',
value: options.destinations
}], { headers: headers }).then(result => {
resolve(result);
}).catch(err => {
reject(err);
});
});
}
export function moveDestinationUp(options) {
return new Promise((resolve, reject)=> {
Promise.resolve().then(() => {
let getPromises = [];
getPromises.push(getDestinationsetById(options.prevId));
getPromises.push(getDestinationsetById(options.id));
return Promise.all(getPromises);
}).then((destinationsets) => {
let updatePromises = [];
let lastDestinationPrevId = _.findLast(destinationsets[0].destinations) || {};
let lowestPriorityPrevId = lastDestinationPrevId.priority || 1;
let prevDestinations = destinationsets[0].destinations;
let currentDestinations = destinationsets[1].destinations;
let prevDestinationsMoveToIndex = prevDestinations.length < 2 ?
1 : prevDestinations.length-2;
options.destination.priority = lowestPriorityPrevId;
prevDestinations.splice(prevDestinationsMoveToIndex, 0, options.destination);
currentDestinations.shift();
updatePromises.push(addDestinationToDestinationset({
id: options.prevId,
data: prevDestinations
}));
updatePromises.push(deleteDestinationFromDestinationset({
id: options.id,
data: currentDestinations
}));
return Promise.all(updatePromises);
}).then(() => {
resolve();
}).catch((err) => {
reject(err);
});
});
}
export function moveDestinationDown(options) {
return new Promise((resolve, reject)=> {
Promise.resolve().then(() => {
let getPromises = [];
getPromises.push(getDestinationsetById(options.nextId));
getPromises.push(getDestinationsetById(options.id));
return Promise.all(getPromises);
}).then((destinationsets) => {
let updatePromises = [];
let firstDestinationNextId = _.head(destinationsets[0].destinations) || {};
let highestPriorityNextId = firstDestinationNextId.priority || 1;
let nextDestinations = destinationsets[0].destinations;
let currentDestinations = destinationsets[1].destinations;
options.destination.priority = highestPriorityNextId;
nextDestinations.splice(1, 0, options.destination);
currentDestinations.pop();
updatePromises.push(addDestinationToDestinationset({
id: options.nextId,
data: nextDestinations
}));
updatePromises.push(deleteDestinationFromDestinationset({
id: options.id,
data: currentDestinations
}));
return Promise.all(updatePromises);
}).then(() => {
resolve();
}).catch((err) => {
reject(err);
});
});
}

@ -41,6 +41,7 @@
<script>
import _ from 'lodash'
import { startLoading, stopLoading,
showGlobalError, showToast } from '../../../helpers/ui'
import { normalizeTerminationInput } from '../../../filters/number-format'
@ -128,12 +129,13 @@
},
methods: {
enableForm(type) {
let lastDestination = _.findLast(this.destinations) || {};
this.formEnabled = true;
this.$store.dispatch('callForward/setFormType', type);
this.$store.dispatch('callForward/setActiveForm', this.groupName);
this.$store.dispatch('callForward/setDestinationsetId', this.id);
this.$store.dispatch('callForward/setGroupName', this.groupName);
this.$store.dispatch('callForward/setPriority', this.priority);
this.$store.dispatch('callForward/setPriority', lastDestination.priority || 1);
if (type === 'voicebox') {
this.destinationForm.destination = 'Voicemail';
} else if (type === 'fax2mail') {

@ -25,8 +25,24 @@
</span>
</div>
</q-item-main>
<q-item-side right>
<q-btn color="negative" flat icon="delete"
<q-item-side class="dest-btns" right>
<span v-if="destinations.length > 1">
<q-btn flat
:class="{btnhidden: hasNoDownOption(index)}"
color="secondary"
icon="keyboard_arrow_down"
@click="moveDestination('down', index)">
</q-btn>
<q-btn flat
:class="{btnhidden: hasNoUpOption(index)}"
color="secondary"
icon="keyboard_arrow_up"
@click="moveDestination('up', index)">
</q-btn>
</span>
<q-btn flat
color="negative"
icon="delete"
@click="deleteDestination(index)">
{{ $t('buttons.remove') }}
</q-btn>
@ -36,16 +52,20 @@
</template>
<script>
import { mapState } from 'vuex'
import numberFormat from '../../../filters/number-format'
import _ from 'lodash'
import { showToast } from '../../../helpers/ui'
import { startLoading, stopLoading,
showGlobalError, showToast } from '../../../helpers/ui'
import { QItem, QItemMain, QItemSide, Toast,
Dialog, QBtn } from 'quasar-framework'
export default {
name: 'csc-destination',
props: [
'destinations',
'id'
'id',
'prevDestId',
'nextDestId'
],
components: {
QItem,
@ -56,8 +76,39 @@
QBtn
},
computed: {
...mapState('callForward', [
'changeDestinationState',
'changeDestinationError'
])
},
watch: {
changeDestinationState(state) {
if (state === 'failed') {
stopLoading();
showGlobalError(this.changeDestinationError);
} else if (state === 'succeeded') {
stopLoading();
}
}
},
methods: {
hasNoDownOption(index) {
return index === this.destinations.length-1 && !this.nextDestId;
},
hasNoUpOption(index) {
return index === 0 && !this.prevDestId;
},
moveDestination(direction, index) {
startLoading();
this.$store.dispatch('callForward/changePositionOfDestination', {
destinations: this.destinations,
id: this.id,
index: index,
direction: direction,
nextId: this.nextDestId,
prevId: this.prevDestId
});
},
isNumber(destination) {
let dest = destination.split(/:|@/);
if (dest[2] === 'fax2mail.local') {
@ -110,4 +161,10 @@
.dest-row
.dest-values
font-weight 500
.dest-btns
display inline-block
.btnhidden
opacity 0
.btnvisible
opacity 1
</style>

@ -13,8 +13,10 @@
</div>
</q-item>
</div>
<div v-else v-for="destinationset in group">
<csc-destination v-bind="destinationset">
<div v-else v-for="(destinationset, index) in group">
<csc-destination v-bind="destinationset"
:prev-dest-id="previousDestinationsetId(index)"
:next-dest-id="nextDestinationsetId(index)">
</csc-destination>
</div>
</q-list>
@ -52,9 +54,18 @@
lastDestinationset() {
let destinationset = _.findLast(this.group) || {};
destinationset.groupName = this.groupName;
destinationset.priority = destinationset.lowestPriority || 1;
return destinationset;
}
},
methods: {
previousDestinationsetId(index) {
let destinationset = this.group[index-1] || {};
return destinationset.id || null;
},
nextDestinationsetId(index) {
let destinationset = this.group[index+1] || {};
return destinationset.id || null;
}
}
}
</script>

@ -1,16 +1,16 @@
'use strict';
import _ from 'lodash';
import { getSourcesets,
getDestinationsets,
import _ from 'lodash'; import { getSourcesets, getDestinationsets,
getTimesets,
getMappings,
loadAlwaysEverybodyDestinations,
deleteDestinationFromDestinationset,
addDestinationToDestinationset,
addDestinationToEmptyGroup,
addDestinationToExistingGroup } from '../api/call-forward';
addDestinationToExistingGroup,
changePositionOfDestination,
moveDestinationUp,
moveDestinationDown } from '../api/call-forward';
const AddDestinationState = {
button: 'button',
@ -19,6 +19,13 @@ const AddDestinationState = {
failed: 'failed'
};
const ChangeDestinationState = {
button: 'button',
requesting: 'requesting',
succeeded: 'succeeded',
failed: 'failed'
};
export default {
namespaced: true,
state: {
@ -33,6 +40,8 @@ export default {
},
addDestinationState: AddDestinationState.button,
addDestinationError: null,
changeDestinationState: ChangeDestinationState.button,
changeDestinationError: null,
activeForm: '',
formType: '',
destinationsetId: '',
@ -125,6 +134,18 @@ export default {
addDestinationFailed(state, error) {
state.addDestinationState = AddDestinationState.failed;
state.addDestinationError = error;
},
changeDestinationRequesting(state) {
state.changeDestinationState = ChangeDestinationState.requesting;
state.changeDestinationError = null;
},
changeDestinationSucceeded(state) {
state.changeDestinationState = ChangeDestinationState.succeeded;
state.changeDestinationError = null;
},
changeDestinationFailed(state, error) {
state.changeDestinationState = ChangeDestinationState.failed;
state.changeDestinationError = error;
}
},
actions: {
@ -234,6 +255,64 @@ export default {
});
}
},
changePositionOfDestination(context, options) {
let clonedDestinations = _.cloneDeep(options.destinations);
let clonedDestination = _.clone(options.destinations[options.index]);
let lastIndex = clonedDestinations.length < 1 ?
0 : clonedDestinations.length - 1;
context.commit('changeDestinationRequesting');
if (options.direction === 'up' && options.prevId && options.index === 0) {
return new Promise((resolve, reject) => {
moveDestinationUp({
prevId: options.prevId,
id: options.id,
destination: clonedDestination
}).then(() => {
context.commit('changeDestinationSucceeded');
context.dispatch('loadAlwaysEverybodyDestinations');
}).catch((err) => {
context.commit('changeDestinationFailed', err.message);
});
});
} else if (options.direction === 'down' && options.nextId && options.index === lastIndex) {
return new Promise((resolve, reject) => {
moveDestinationDown({
nextId: options.nextId,
id: options.id,
destination: clonedDestination
}).then(() => {
context.commit('changeDestinationSucceeded');
context.dispatch('loadAlwaysEverybodyDestinations');
}).catch((err) => {
context.commit('changeDestinationFailed', err.message);
});
});
} else {
let adjacentDestination = options.direction === 'up' ?
options.destinations[options.index-1] :
options.destinations[options.index+1];
let adjacentPriority = adjacentDestination ?
adjacentDestination.priority : 1;
let adjacentIndex = options.direction === 'up' ?
options.index - 1 :
options.index + 1;
clonedDestinations.splice(options.index, 1);
clonedDestinations.splice(adjacentIndex, 0, clonedDestination);
clonedDestinations[adjacentIndex].priority = adjacentPriority;
return new Promise((resolve, reject) => {
changePositionOfDestination({
destinations: clonedDestinations,
id: options.id,
subscriberId: context.getters.getSubscriberId
}).then(() => {
context.commit('changeDestinationSucceeded');
context.dispatch('loadAlwaysEverybodyDestinations');
}).catch((err) => {
context.commit('changeDestinationFailed', err.message);
});
});
}
},
setActiveForm(context, value) {
context.commit('setActiveForm', value);
},

Loading…
Cancel
Save