TT#47520 Change an existing SoundSet

Change-Id: Ibabe2cd4ea5622a2d53249a5ef1037102acd0372
changes/55/27655/8
Robert Axelsen 7 years ago
parent f1f5bc3583
commit 125cdd80e7

@ -721,3 +721,65 @@ export function getSoundFilesGrouped(options) {
export function removeSoundSet(id) { export function removeSoundSet(id) {
return Vue.http.delete('api/soundsets/' + id); return Vue.http.delete('api/soundsets/' + id);
} }
export function getSoundSet(id) {
return new Promise((resolve, reject)=>{
get({
path: 'api/soundsets/' + id
}).then((soundSet)=>{
resolve(soundSet);
}).catch((err)=>{
reject(err);
});
});
}
export function editSoundSetFields(id, fields) {
return new Promise((resolve, reject)=>{
Promise.resolve().then(()=>{
return getSoundSet(id);
}).then((result)=>{
let prefs = Object.assign(result, fields);
delete fields._links;
return Vue.http.put('api/soundsets/' + id, prefs);
}).then(()=>{
resolve();
}).catch((err)=>{
reject(err);
});
});
}
export function setSoundSetName(id, value) {
return editSoundSetFields(id, { name: value });
}
export function setSoundSetDescription(id, value) {
return editSoundSetFields(id, { description: value });
}
export function setSoundSetContractDefault(id, value) {
return editSoundSetFields(id, { contract_default: value });
}
export function getSoundSetWithFiles(id) {
return new Promise((resolve, reject)=>{
let soundSet;
Promise.resolve().then(()=>{
return getSoundSet(id);
}).then((result)=>{
delete result._links;
soundSet = result;
return getSoundFilesGrouped({
params: {
set_id: id
}
});
}).then((data)=>{
Object.assign(soundSet, data);
resolve(soundSet);
}).catch((err)=>{
reject(err);
});
});
}

@ -88,14 +88,18 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'
import CscPage from '../../CscPage' import CscPage from '../../CscPage'
import CscPbxGroup from './CscPbxGroup' import CscPbxGroup from './CscPbxGroup'
import CscPbxGroupAddForm from './CscPbxGroupAddForm' import CscPbxGroupAddForm from './CscPbxGroupAddForm'
import CscRemoveDialog from '../../CscRemoveDialog' import CscRemoveDialog from '../../CscRemoveDialog'
import aliasNumberOptions from '../../../mixins/alias-number-options' import aliasNumberOptions from '../../../mixins/alias-number-options'
import itemError from '../../../mixins/item-error' import itemError from '../../../mixins/item-error'
import { showToast } from '../../../helpers/ui' import {
mapGetters
} from 'vuex'
import {
showToast
} from '../../../helpers/ui'
import { import {
QChip, QChip,
QCard, QCard,
@ -231,28 +235,28 @@
}, },
watch: { watch: {
addState(state) { addState(state) {
if(state === 'succeeded') { if (state === 'succeeded') {
this.disableAddForm(); this.disableAddForm();
showToast(this.$t('pbxConfig.toasts.addedGroupToast', { group: this.lastAddedGroup })); showToast(this.$t('pbxConfig.toasts.addedGroupToast', { group: this.lastAddedGroup }));
} }
}, },
removeState(state) { removeState(state) {
if(state === 'succeeded') { if (state === 'succeeded') {
showToast(this.$t('pbxConfig.toasts.removedGroupToast', { group: this.lastRemovedGroup })); showToast(this.$t('pbxConfig.toasts.removedGroupToast', { group: this.lastRemovedGroup }));
} }
}, },
updateState(state) { updateState(state) {
if(state === 'succeeded') { if (state === 'succeeded') {
showToast(this.$t('pbxConfig.toasts.changedFieldToast', this.lastUpdatedField)); showToast(this.$t('pbxConfig.toasts.changedFieldToast', this.lastUpdatedField));
} }
}, },
updateAliasNumbersState(state) { updateAliasNumbersState(state) {
if(state === 'succeeded') { if (state === 'succeeded') {
showToast(this.$t('pbxConfig.toasts.updatedAliasNumbersToast')); showToast(this.$t('pbxConfig.toasts.updatedAliasNumbersToast'));
} }
}, },
updateGroupsAndSeatsState(state) { updateGroupsAndSeatsState(state) {
if(state === 'succeeded') { if (state === 'succeeded') {
showToast(this.$t('pbxConfig.toasts.updatedSeatsInGroupToast', {group: this.seat})); showToast(this.$t('pbxConfig.toasts.updatedSeatsInGroupToast', {group: this.seat}));
} }
} }

@ -29,7 +29,7 @@
{{ $t('pbxConfig.description') }}: {{ $t('pbxConfig.description') }}:
</span> </span>
<span class="csc-item-value"> <span class="csc-item-value">
{{ set.description }} {{ setDescription }}
</span> </span>
</div> </div>
</q-item-tile> </q-item-tile>
@ -37,18 +37,47 @@
v-if="expanded" v-if="expanded"
class="csc-list-item-main" class="csc-list-item-main"
> >
<q-field label="Name"> <q-field
class="csc-form-field"
:label="$t('pbxConfig.name')"
:error-label="nameErrorMessage"
>
<q-input <q-input
dark dark
readonly v-model="changes.name"
:value="set.name" :after="nameButtons"
@keyup.enter="saveName"
@input="$v.changes.name.$touch"
@blur="$v.changes.name.$touch"
:error="$v.changes.name.$error"
/> />
</q-field> </q-field>
<q-field label="Description"> <q-field
class="csc-form-field"
:label="$t('pbxConfig.description')"
:error-label="descriptionErrorMessage"
>
<q-input <q-input
dark dark
readonly v-model="changes.description"
:value="set.description" :after="descriptionButtons"
@keyup.enter="saveDescription"
@input="$v.changes.description.$touch"
@blur="$v.changes.description.$touch"
:error="$v.changes.description.$error"
/>
</q-field>
<q-field
dark
class="csc-form-field"
:label="$t('pbxConfig.defaultForSubscribers')"
>
<q-toggle
:class="contractDefaultClasses"
v-model="changes.contract_default"
@input="toggleContractDefault"
checked-icon="check_circle"
unchecked-icon="check_circle"
/> />
</q-field> </q-field>
</q-item-tile> </q-item-tile>
@ -88,7 +117,7 @@
/> />
</q-item-tile> </q-item-tile>
</q-item-side> </q-item-side>
<q-inner-loading :visible="loading"> <q-inner-loading :visible="isLoading">
<q-spinner-mat <q-spinner-mat
size="60px" size="60px"
color="primary" color="primary"
@ -106,13 +135,16 @@
QItemTile, QItemTile,
QBtn, QBtn,
QIcon, QIcon,
QCollapsible,
QCheckbox,
QField, QField,
QInput, QInput,
QInnerLoading, QInnerLoading,
QSpinnerMat QSpinnerMat,
QToggle
} from 'quasar-framework' } from 'quasar-framework'
import {
maxLength
} from 'vuelidate/lib/validators'
import { showGlobalError } from '../../../helpers/ui'
export default { export default {
name: 'csc-pbx-sound-set', name: 'csc-pbx-sound-set',
props: { props: {
@ -128,19 +160,27 @@
QItemTile, QItemTile,
QBtn, QBtn,
QIcon, QIcon,
QCollapsible,
QCheckbox,
QField, QField,
QInput, QInput,
QInnerLoading, QInnerLoading,
QSpinnerMat QSpinnerMat,
QToggle
}, },
data () { data () {
return { return {
expanded: false expanded: false,
changes: this.getSet()
} }
}, },
mounted() { validations: {
changes: {
name: {
maxLength: maxLength(64)
},
description: {
maxLength: maxLength(255)
}
},
}, },
computed: { computed: {
itemClasses() { itemClasses() {
@ -160,6 +200,135 @@
else { else {
return 'keyboard arrow up'; return 'keyboard arrow up';
} }
},
name() {
return this.set.name;
},
nameHasChanged() {
return this.name + "" !== this.changes.name + "";
},
description() {
return this.set.description;
},
descriptionHasChanged() {
return this.description + "" !== this.changes.description + "";
},
nameButtons() {
let buttons = [];
let self = this;
if (this.nameHasChanged && this.$v.changes.name.$error) {
buttons.push({
icon: 'clear',
error: true,
handler (event) {
event.stopPropagation();
self.resetName();
}
}
);
}
else if (this.nameHasChanged) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveName();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetName();
}
}
);
}
return buttons;
},
descriptionButtons() {
let buttons = [];
let self = this;
if (this.descriptionHasChanged && this.$v.changes.description.$error) {
buttons.push({
icon: 'clear',
error: true,
handler (event) {
event.stopPropagation();
self.resetDescription();
}
}
);
}
else if (this.descriptionHasChanged) {
buttons.push({
icon: 'check',
error: false,
handler (event) {
event.stopPropagation();
self.saveDescription();
}
}, {
icon: 'clear',
error: false,
handler (event) {
event.stopPropagation();
self.resetDescription();
}
}
);
}
return buttons;
},
setModel() {
return {
id: this.set.id,
name: this.changes.name,
description: this.changes.description,
contract_default: this.changes.contract_default
}
},
contractDefaultClasses() {
let classes = [];
if(this.attach) {
classes.push('csc-toggle-enabled');
}
else {
classes.push('csc-toggle-disabled');
}
return classes;
},
nameErrorMessage() {
if (!this.$v.changes.name.maxLength) {
return this.$t('validationErrors.maxLength', {
field: this.$t('pbxConfig.name'),
maxLength: this.$v.changes.name.$params.maxLength.max
});
}
},
descriptionErrorMessage() {
if (!this.$v.changes.description.maxLength) {
return this.$t('validationErrors.maxLength', {
field: this.$t('pbxConfig.description'),
maxLength: this.$v.changes.description.$params.maxLength.max
});
}
},
isLoading() {
return this.loading;
},
setDescription() {
let descriptionLength = this.set.description.length;
if (this.mobile && descriptionLength > 17) {
return this.set.description.substring(0, 14) + '...';
}
else if (!this.mobile && descriptionLength > 67) {
return this.set.description.substring(0, 64) + '...';
}
else {
return this.set.description;
}
} }
}, },
methods: { methods: {
@ -168,6 +337,43 @@
}, },
remove() { remove() {
this.$emit('remove', this.set); this.$emit('remove', this.set);
},
getSet() {
return {
name: this.set.name,
description: this.set.description,
contract_default: this.set.contract_default
}
},
resetName() {
this.changes.name = this.set.name;
},
saveName() {
if (this.$v.changes.$invalid) {
showGlobalError(this.$t('validationErrors.generic'));
}
else if (this.nameHasChanged) {
this.$emit('save-name', this.setModel);
}
},
resetDescription() {
this.changes.description = this.set.description;
},
saveDescription() {
if (this.$v.changes.$invalid) {
showGlobalError(this.$t('validationErrors.generic'));
}
else if (this.descriptionHasChanged) {
this.$emit('save-description', this.setModel);
}
},
toggleContractDefault() {
if (this.$v.changes.$invalid) {
showGlobalError(this.$t('validationErrors.generic'));
}
else {
this.$emit('save-contract-default', this.setModel);
}
} }
}, },
watch: { watch: {

@ -2,6 +2,15 @@
<csc-page <csc-page
:is-list="true" :is-list="true"
> >
<div
v-if="isListLoadingVisible"
class="row justify-center"
>
<q-spinner-dots
color="primary"
:size="40"
/>
</div>
<q-list <q-list
striped-odd striped-odd
no-border no-border
@ -10,11 +19,14 @@
> >
<csc-pbx-sound-set <csc-pbx-sound-set
v-for="set in soundSets" v-for="set in soundSets"
:loading="soundSetFilesLoading(set.id)" :loading="isItemLoading(set.id)"
:key="set.id" :key="set.id"
:set="set" :set="set"
:mobile="isMobile" :mobile="isMobile"
@remove="removeSoundSetDialog" @remove="removeSoundSetDialog"
@save-name="saveSoundSetName"
@save-description="saveSoundSetDescription"
@save-contract-default="saveContractDefault"
/> />
</q-list> </q-list>
<div <div
@ -39,10 +51,15 @@
import { import {
mapGetters mapGetters
} from 'vuex' } from 'vuex'
import {
showToast
} from '../../../helpers/ui'
import { import {
Platform, Platform,
QList, QList,
QBtn QBtn,
QInnerLoading,
QSpinnerDots
} from 'quasar-framework' } from 'quasar-framework'
export default { export default {
components: { components: {
@ -50,7 +67,9 @@
CscPbxSoundSet, CscPbxSoundSet,
CscRemoveDialog, CscRemoveDialog,
QList, QList,
QBtn QBtn,
QInnerLoading,
QSpinnerDots
}, },
data () { data () {
return { return {
@ -64,7 +83,12 @@
...mapGetters('pbxConfig', [ ...mapGetters('pbxConfig', [
'soundSets', 'soundSets',
'soundSetFilesLoading', 'soundSetFilesLoading',
'isSoundSetsRequesting' 'isSoundSetsRequesting',
'isUpdating',
'updateItemId',
'updateState',
'lastUpdatedField',
'isListLoadingVisible'
]), ]),
isMobile() { isMobile() {
return !!Platform.is.mobile; return !!Platform.is.mobile;
@ -83,10 +107,28 @@
this.$refs.removeDialog.open(); this.$refs.removeDialog.open();
}, },
removeSoundSet() { removeSoundSet() {
this.$store.dispatch('pbxConfig/removeSoundSet', this.currentRemovingSoundSet) this.$store.dispatch('pbxConfig/removeSoundSet', this.currentRemovingSoundSet);
},
saveSoundSetName(set) {
this.$store.dispatch('pbxConfig/saveSoundSetName', set);
},
saveSoundSetDescription(set) {
this.$store.dispatch('pbxConfig/saveSoundSetDescription', set);
},
saveContractDefault(set) {
this.$store.dispatch('pbxConfig/saveContractDefault', set);
},
isItemLoading(setId) {
return (this.isUpdating && this.updateItemId + "" === setId + "") ||
this.soundSetFilesLoading(setId) || this.isSoundSetsRequesting;
} }
}, },
watch: { watch: {
updateState(state) {
if (state === 'succeeded') {
showToast(this.$t('pbxConfig.toasts.changedFieldToast', this.lastUpdatedField));
}
}
} }
} }
</script> </script>

@ -442,7 +442,8 @@
"noSoundUploaded": "No sound uploaded", "noSoundUploaded": "No sound uploaded",
"playingInLoop": "Playing in loop", "playingInLoop": "Playing in loop",
"playInLoop": "Play sound in loop", "playInLoop": "Play sound in loop",
"dontPlayInLoop": "Don't play sound in loop" "dontPlayInLoop": "Don't play sound in loop",
"defaultForSubscribers": "Default For Subscribers"
}, },
"callBlocking": { "callBlocking": {
"privacyEnabledToast": "Your number is hidden to the callee", "privacyEnabledToast": "Your number is hidden to the callee",

@ -40,7 +40,11 @@ import {
removeCallQueue, removeCallQueue,
getAllSoundSets, getAllSoundSets,
getSoundFilesGrouped, getSoundFilesGrouped,
removeSoundSet removeSoundSet,
setSoundSetName,
setSoundSetDescription,
setSoundSetContractDefault,
getSoundSetWithFiles
} from '../../api/pbx-config' } from '../../api/pbx-config'
export default { export default {
@ -593,5 +597,56 @@ export default {
}).catch((err) => { }).catch((err) => {
context.commit('removeItemFailed', err.message); context.commit('removeItemFailed', err.message);
}); });
},
saveSoundSetName(context, set) {
context.commit('updateItemRequesting', set);
context.commit('lastUpdatedField', {name: set.name, type: 'sound set name'});
setSoundSetName(set.id, set.name).then(() => {
return context.dispatch('reloadSoundSet', set);
}).then(() => {
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
saveSoundSetDescription(context, set) {
context.commit('updateItemRequesting', set);
context.commit('lastUpdatedField', {name: set.name, type: 'sound set name'});
setSoundSetDescription(set.id, set.description).then(() => {
return context.dispatch('reloadSoundSet', set);
}).then(() => {
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
saveContractDefault(context, set) {
let defaultName = set.contract_default ? 'on' : 'off';
context.commit('updateItemRequesting', set);
context.commit('lastUpdatedField', {name: defaultName, type: 'default for subscribers'});
setSoundSetContractDefault(set.id, set.contract_default).then(() => {
return context.dispatch('reloadSoundSet', set);
}).then(() => {
context.commit('updateItemSucceeded');
}).catch((err) => {
context.commit('updateItemFailed', err.message);
});
},
reloadSoundSet(context, set) {
return new Promise((resolve, reject) => {
context.commit('soundSetReloading', set);
getSoundSetWithFiles(set.id).then(($set) => {
context.commit('soundSetReloaded', $set);
}).catch((err)=>{
context.commit('soundSetReloadingFailed', {
set: set,
error: err.message
});
}).then(() => {
resolve();
}).catch((err) => {
reject(err);
});
});
} }
} }

@ -473,10 +473,12 @@ export default {
reactiveSet(state[type + 'Errors'], id, error); reactiveSet(state[type + 'Errors'], id, error);
}, },
listSoundSetsRequesting(state) { listSoundSetsRequesting(state) {
state.listState = RequestState.requesting;
state.listSoundSetsState = RequestState.requesting; state.listSoundSetsState = RequestState.requesting;
state.listSoundSetsError = null; state.listSoundSetsError = null;
}, },
listSoundSetsSucceeded(state, sets) { listSoundSetsSucceeded(state, sets) {
state.listState = RequestState.succeeded;
state.listSoundSetsState = RequestState.succeeded; state.listSoundSetsState = RequestState.succeeded;
state.listSoundSetsError = null; state.listSoundSetsError = null;
state.soundSets = {}; state.soundSets = {};
@ -487,6 +489,7 @@ export default {
}); });
}, },
listSoundSetsFailed(state, error) { listSoundSetsFailed(state, error) {
state.listState = RequestState.failed;
state.listSoundSetsState = RequestState.failed; state.listSoundSetsState = RequestState.failed;
state.listSoundSetsError = error; state.listSoundSetsError = error;
}, },
@ -503,5 +506,24 @@ export default {
id = id + ""; id = id + "";
reactiveSet(state.soundSetFilesStates, id, RequestState.failed); reactiveSet(state.soundSetFilesStates, id, RequestState.failed);
reactiveSet(state.soundSetFilesErrors, id, error); reactiveSet(state.soundSetFilesErrors, id, error);
},
soundSetReloading(state, set) {
state.soundSetReloadingState = RequestState.requesting;
state.soundSetReloadingError = null;
state.soundSetReloading = set;
},
soundSetReloaded(state, set) {
state.soundSetReloadingState = RequestState.succeeded;
state.soundSetReloadingError = null;
Vue.set(state.soundSets, set.id, set);
for (let i = 0; i < state.soundSetsOrdered.length; i++) {
if(state.soundSetsOrdered[i].id === set.id) {
state.soundSetsOrdered[i] = set;
}
}
},
soundSetReloadingFailed(state, err) {
state.soundSetReloadingState = RequestState.failed;
state.soundSetReloadingError = err;
} }
} }

@ -84,5 +84,8 @@ export default {
soundSets: {}, soundSets: {},
soundSetsOrdered: [], soundSetsOrdered: [],
soundSetFilesStates: {}, soundSetFilesStates: {},
soundSetFilesErrors: {} soundSetFilesErrors: {},
soundSetReloading: null,
soundSetReloadingState: RequestState.initiated,
soundSetReloadingError: null
} }

Loading…
Cancel
Save