MT#56989 Soundset page general UI improvements

Change-Id: I8ccde7784564eae85fd96379d25f99bfeaeb970c
mr11.4
Hugo Zigha 2 years ago
parent d45f67b7e8
commit 9ca8d4ba46

@ -277,3 +277,17 @@ export function setUseParent (options) {
})
})
}
export function removeSoundFile (soundFileId) {
return new Promise((resolve, reject) => {
Vue.http.delete('api/soundfiles/' + soundFileId).then(() => {
resolve()
}).catch((err) => {
if (err.status >= 400) {
reject(new Error(err.body.message))
} else {
reject(err)
}
})
})
}

@ -31,6 +31,7 @@
/>
</div>
<div
v-if="showMoreMenu"
class="csc-list-item-head-menu"
>
<q-btn
@ -51,6 +52,10 @@
</q-list>
</q-menu>
</div>
<slot
name="actions"
class="csc-list-item-head-menu"
/>
</div>
<q-slide-transition>
<div
@ -100,6 +105,10 @@ export default {
odd: {
type: Boolean,
default: false
},
showMoreMenu: {
type: Boolean,
default: true
}
},
data () {

@ -4,8 +4,8 @@
icon="queue_music"
:odd="odd"
:loading="loading"
:expanded="expanded"
@toggle="toggle"
:show-more-menu="soundSet.customer_id"
@click.native="showSoundSetDetails"
>
<template
slot="title"
@ -15,22 +15,25 @@
</csc-list-item-title>
<q-slide-transition>
<csc-list-item-subtitle
v-if="!expanded && soundSet.description"
v-if="soundSet.description"
>
{{ soundSet.description }}
</csc-list-item-subtitle>
</q-slide-transition>
<q-slide-transition>
<csc-list-item-subtitle
v-if="!expanded && soundSet.parent_id && parent"
v-if="soundSet.parent_id && parent"
>
{{ $t('Parent') + ': ' + parent.name }}
</csc-list-item-subtitle>
</q-slide-transition>
<q-slide-transition>
<csc-list-item-subtitle
v-if="!expanded"
v-else
>
{{ $t('No parents assigned') }}
</csc-list-item-subtitle>
</q-slide-transition>
<q-slide-transition>
<csc-list-item-subtitle>
<q-checkbox
:value="soundSet.contract_default"
:label="$t('Default')"
@ -42,105 +45,9 @@
</q-slide-transition>
</template>
<template
slot="body"
v-if="soundSet.customer_id"
slot="menu"
>
<q-input
v-model="changes.name"
:error="$v.changes.name.$error"
:label="$t('Name')"
:disable="!soundSet.customer_id"
@input="$v.changes.name.$touch"
@keyup.enter="save"
>
<template
v-if="hasNameChanged"
v-slot:append
>
<csc-input-button-save
v-if="!$v.changes.name.$error"
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetName"
/>
</template>
</q-input>
<q-input
v-model="changes.description"
:error="$v.changes.description.$error"
:label="$t('Description')"
:disable="!soundSet.customer_id"
@input="$v.changes.description.$touch"
@keyup.enter="save"
>
<template
v-if="hasDescriptionChanged"
v-slot:append
>
<csc-input-button-save
v-if="!$v.changes.description.$error"
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetDescription"
/>
</template>
</q-input>
<q-select
v-model="changes.parent_id"
v-if="(changes.parent_id && parent) || !changes.parent_id"
emit-value
map-options
:disable="!soundSet.customer_id"
:options="getParentOptions"
:label="$t('Parent')"
>
<template
v-if="hasParentChanged"
v-slot:append
>
<csc-input-button-save
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetParent"
/>
</template>
</q-select>
<q-checkbox
:label="$t('Default sound set for all seats and groups')"
:value="soundSet.contract_default"
:disable="!soundSet.customer_id"
@input="saveAsDefault"
/>
<csc-list-spinner
v-if="soundHandlesLoading || soundFilesLoading"
/>
<div
v-if="!soundHandlesLoading && soundHandles.length > 0 && !soundFilesLoading"
class="csc-pbx-sound-set-sound-list"
>
<csc-pbx-sound-set-sound
v-for="(soundHandle, index) in soundHandles"
:key="soundHandle.id"
:odd="(index % 2) === 0"
:sound-handle="soundHandle"
:sound-file="soundFileMap[soundSet.id + '-' + soundHandle.handle]"
:sound-file-url="soundFileUrlMap[soundSet.id + '-' + soundHandle.handle]"
:sound-file-upload-state="soundFileUploadState[soundSet.id + '-' + soundHandle.handle]"
:sound-file-upload-progress="soundFileUploadProgress[soundSet.id + '-' + soundHandle.handle]"
:sound-file-update-state="soundFileUpdateState[soundSet.id + '-' + soundHandle.handle]"
:has-parent="soundSet.parent_id"
:read-only="!soundSet.customer_id"
@play="playSoundFile"
@upload="uploadSoundFile"
@toggle-loop-play="toggleLoopPlay"
@toggle-use-parent="toggleUseParent"
/>
</div>
</template>
<template slot="menu">
<csc-list-menu-item
icon="delete"
icon-color="negative"
@ -156,25 +63,14 @@
import {
mapState
} from 'vuex'
import {
maxLength
} from 'vuelidate/lib/validators'
import CscListItem from '../../CscListItem'
import CscListItemTitle from '../../CscListItemTitle'
import CscListItemSubtitle from '../../CscListItemSubtitle'
import CscListMenuItem from '../../CscListMenuItem'
import CscPbxSoundSetSound from './CscPbxSoundSetSound'
import CscListSpinner from '../../CscListSpinner'
import CscInputButtonSave from 'components/form/CscInputButtonSave'
import CscInputButtonReset from 'components/form/CscInputButtonReset'
export default {
name: 'CscPbxSoundSet',
components: {
CscInputButtonReset,
CscInputButtonSave,
CscListSpinner,
CscPbxSoundSetSound,
CscListMenuItem,
CscListItemSubtitle,
CscListItemTitle,
@ -189,101 +85,17 @@ export default {
type: Boolean,
default: false
},
expanded: {
type: Boolean,
default: false
},
soundSet: {
type: Object,
default: null
},
soundHandles: {
type: Array,
default: () => []
},
soundHandlesLoading: {
type: Boolean,
default: false
},
soundFileMap: {
type: Object,
default: null
},
soundFilesLoading: {
type: Boolean,
default: false
},
soundFileUrlMap: {
type: Object,
default: null
},
soundFileUploadState: {
type: Object,
default: null
},
soundFileUploadProgress: {
type: Object,
default: null
},
soundFileUpdateState: {
type: Object,
default: null
}
},
data () {
return {
changes: this.getDefaultData()
}
},
validations: {
changes: {
name: {
maxLength: maxLength(64)
},
description: {
maxLength: maxLength(255)
}
}
},
computed: {
...mapState('pbxSoundSets', [
'soundSetList'
]),
hasNameChanged () {
return this.changes.name !== this.getDefaultData().name
},
hasDescriptionChanged () {
return this.changes.description !== this.getDefaultData().description
},
parent () {
return this.changes.parent_id ? this.soundSetList.find((soundSet) => this.changes.parent_id === soundSet.id) : null
},
getParentOptions () {
let parentOptions = [
{
label: this.$t('Unassigned'),
value: null
}
]
this.soundSetList.map((soundSet) => {
if (soundSet.id !== this.soundSet.id) {
parentOptions.push({
label: soundSet.name,
value: soundSet.id
})
}
})
return parentOptions
},
hasParentChanged () {
return this.changes.parent_id !== this.getDefaultData().parent_id
}
},
watch: {
expanded (expanded) {
if (expanded) {
this.$emit('require-sound-handles')
}
return this.soundSet.parent_id ? this.soundSetList.find((soundSet) => this.soundSet.parent_id === soundSet.id) : null
}
},
methods: {
@ -299,66 +111,8 @@ export default {
}
this.$emit('remove', this.soundSet.id)
},
toggle () {
if (this.expanded) {
this.$emit('collapse')
} else {
this.$emit('expand')
}
},
getDefaultData () {
return {
name: this.soundSet.name,
description: this.soundSet.description,
contract_default: this.soundSet.contract_default,
parent_id: this.soundSet.parent_id,
customer_id: this.soundSet.customer_id
}
},
resetName () {
this.changes.name = this.getDefaultData().name
},
resetDescription () {
this.changes.description = this.getDefaultData().description
},
resetParent () {
this.changes.parent_id = this.getDefaultData().parent_id
},
playSoundFile (data) {
this.$emit('play-sound-file', data)
},
uploadSoundFile (options) {
this.$emit('upload-sound-file', {
soundSetId: this.soundSet.id,
soundHandle: options.soundHandle,
soundFileData: options.soundFileData
})
},
toggleLoopPlay (options) {
this.$emit('toggle-loop-play', options)
},
toggleUseParent (options) {
this.$emit('toggle-use-parent', options)
},
save () {
if (this.hasNameChanged) {
this.$emit('save-name', {
soundSetId: this.soundSet.id,
name: this.changes.name
})
}
if (this.hasDescriptionChanged) {
this.$emit('save-description', {
soundSetId: this.soundSet.id,
description: this.changes.description
})
}
if (this.hasParentChanged) {
this.$emit('save-parent', {
soundSetId: this.soundSet.id,
parent_id: this.changes.parent_id
})
}
showSoundSetDetails () {
this.$router.push('/user/pbx-configuration/sound-sets/'+ this.soundSet.id)
}
}
}

@ -9,7 +9,7 @@
class="csc-pbx-sound-set-sound-icon"
name="music_note"
size="24px"
/>{{ soundHandle.group }} {{ soundHandle.handle }}
/>{{ soundHandle.handle }}
</div>
<div
class="col-grow"
@ -57,10 +57,21 @@
flat
color="primary"
icon="folder"
:disable="isUpdating || isUploading || isSoundFileRemoving"
@click="openFileSelectionDialog"
>
Select file
</q-btn>
<q-btn
v-if="soundFile && !selectedFile && !readOnly"
flat
color="negative"
icon="delete"
:disable="isUpdating || isSoundFileRemoving"
@click="removeUploadedFile"
>
{{ $t('Remove') }}
</q-btn>
<q-btn
v-if="selectedFile && !isUploading"
flat
@ -88,55 +99,53 @@
<div
class="csc-progress-col col-grow"
>
<q-progress
:percentage="soundFileUploadProgress"
<q-linear-progress
:buffer="soundFileUploadProgress * 0.01"
color="primary"
stripe
animate
height="24px"
/>
</div>
</div>
<div
v-if="hasParent"
class="row items-center"
>
<div
v-if="hasParent"
class="col-auto"
>
<q-checkbox
:value="soundFileUseparent"
:disable="readOnly"
:disable="readOnly || isUploading || isUpdating || isSoundFileRemoving"
:label="$t('Use Parent')"
left-label
@input="toggleUseParent"
/>
</div>
</div>
<div
v-if="soundFile && !selectedFile && this.soundFile.filename"
class="row items-center"
>
<div
class="col-auto"
<template
v-if="soundFile && !selectedFile && this.soundFile.filename"
>
<q-checkbox
:value="soundFileLoopplay"
:label="$t('Loop')"
:disable="readOnly"
left-label
@input="toggleLoopPlay"
/>
</div>
<div
class="csc-col-right col-grow"
>
<csc-audio-player
v-if="this.soundFile && this.soundFile.filename"
:file-url="soundFileUrl"
@load="loadPlay"
/>
</div>
<div
class="col-auto"
>
<q-checkbox
:value="soundFileLoopplay"
:label="$t('Loop')"
:disable="readOnly || isUpdating || isSoundFileRemoving"
left-label
@input="toggleLoopPlay"
/>
</div>
<div
class="csc-col-right col-grow"
>
<csc-audio-player
v-if="this.soundFile && this.soundFile.filename"
:file-url="soundFileUrl"
@load="loadPlay"
/>
</div>
</template>
</div>
</div>
<csc-object-spinner
@ -147,6 +156,9 @@
</template>
<script>
import {
mapGetters
} from 'vuex'
import {
RequestState
} from 'src/store/common'
@ -204,6 +216,9 @@ export default {
}
},
computed: {
...mapGetters('pbxSoundSets', [
'isSoundFileRemoving'
]),
soundFileLoopplay () {
if (this.soundFile && this.soundFile.loopplay) {
return this.soundFile.loopplay
@ -300,6 +315,13 @@ export default {
useParent: !this.soundFileUseparent
})
}
},
removeUploadedFile () {
this.$emit('remove-uploaded-file', {
soundFileId: this.soundFile.id,
soundSetId: this.soundFile.set_id,
soundHandle: this.soundFile.handle
})
}
}
}

@ -1,6 +1,7 @@
{
"&lt;{destination}&gt; as {filetype}": "&lt;{destination}&gt; as {filetype}",
"&quot;Music on Hold&quot; - if set to true and a music on hold file is provided, a calling party gets that file played when put on hold": "&quot;Music on Hold&quot; - if set to true and a music on hold file is provided, a calling party gets that file played when put on hold",
"(empty)": "(empty)",
"404 Not Found": "404 Not Found",
"ACL": "ACL",
"Accepted email address to allow mail2fax transmission.": "Accepted email address to allow mail2fax transmission.",
@ -277,6 +278,7 @@
"No messages": "No messages",
"No numbers assigned": "No numbers assigned",
"No numbers found": "No numbers found",
"No parents assigned": "No parents assigned",
"No seats": "No seats",
"No seats created yet": "No seats created yet",
"No sound sets created yet": "No sound sets created yet",
@ -463,6 +465,7 @@
"Updated {field} for manager secretary config {msConfig} successfully": "Updated {field} for manager secretary config {msConfig} successfully",
"Updated {field} for sound set {soundSet} successfully": "Updated {field} for sound set {soundSet} successfully",
"Upload": "Upload",
"Use Parent": "Use Parent",
"Use RegExp": "Use RegExp",
"Use as default for all seats and groups": "Use as default for all seats and groups",
"Use custom number": "Use custom number",

@ -0,0 +1,382 @@
<template>
<csc-page-sticky
id="csc-page-pbx-sound-set-details"
ref="pageSticky"
>
<template
v-slot:header
>
<q-breadcrumbs
v-if="soundSetSelected"
class="absolute-left q-ml-md text-weight-light"
active-color="primary"
separator-color="primary"
>
<q-breadcrumbs-el
key="soundSets"
class="cursor-pointer"
to="/user/pbx-configuration/sound-sets"
:label="$t('Sound Sets')"
icon="queue_music"
/>
<q-breadcrumbs-el
key="soundSet"
:label="soundSetSelected.name"
/>
</q-breadcrumbs>
</template>
<q-item
class="col col-xs-12"
>
<q-list
v-if="changes"
class="col col-xs-12"
side
top
no-wrap
>
<q-input
v-model="changes.name"
:error="$v.changes.name.$error"
:label="$t('Name')"
:disable="!soundSetSelected.customer_id || isSoundSetUpdating"
@input="$v.changes.name.$touch"
@keyup.enter="save"
>
<template
v-if="hasNameChanged"
v-slot:append
>
<csc-input-button-save
v-if="!$v.changes.name.$error"
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetName"
/>
</template>
</q-input>
<q-input
v-model="changes.description"
:error="$v.changes.description.$error"
:label="$t('Description')"
:disable="!soundSetSelected.customer_id || isSoundSetUpdating"
@input="$v.changes.description.$touch"
@keyup.enter="save"
>
<template
v-if="hasDescriptionChanged"
v-slot:append
>
<csc-input-button-save
v-if="!$v.changes.description.$error"
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetDescription"
/>
</template>
</q-input>
<q-select
v-model="changes.parent_id"
v-if="(changes.parent_id && parent) || !changes.parent_id"
emit-value
map-options
:disable="!soundSetSelected.customer_id || isSoundSetUpdating"
:options="getParentOptions"
:label="$t('Parent')"
>
<template
v-if="hasParentChanged"
v-slot:append
>
<csc-input-button-save
@click.stop="save"
/>
<csc-input-button-reset
@click.stop="resetParent"
/>
</template>
</q-select>
<q-checkbox
:label="$t('Default sound set for all seats and groups')"
:value="soundSetSelected.contract_default"
:disable="!soundSetSelected.customer_id || isSoundSetUpdating"
@input="saveAsDefault"
/>
<csc-list-spinner
v-if="isSoundHandleListRequesting || isSoundFileListRequesting(soundSetSelected.id)"
/>
<div
v-if="!isSoundHandleListRequesting && !isSoundFileListRequesting(soundSetSelected.id) && soundHandleGroups.length > 0"
class="csc-pbx-sound-set-sound-list"
>
<csc-list-item
v-for="(group, index) in soundHandleGroups"
:key="group"
:odd="(index % 2) === 0"
ref="soundFiles"
icon="music_note"
:expanded="expanded[group]"
:show-more-menu="false"
@toggle="toggle(group)"
>
<template
slot="title"
>
<csc-list-item-title>
{{ group }}
</csc-list-item-title>
</template>
<template
slot="body"
>
<csc-pbx-sound-set-sound
v-for="(soundHandle, index) in soundHandleList[group]"
:key="soundHandle.id"
:odd="(index % 2) === 0"
:sound-handle="soundHandle"
:sound-file="soundFileMap[soundSetSelected.id + '-' + soundHandle.handle]"
:sound-file-url="soundFileUrlMap[soundSetSelected.id + '-' + soundHandle.handle]"
:sound-file-upload-state="soundFileUploadState[soundSetSelected.id + '-' + soundHandle.handle]"
:sound-file-upload-progress="soundFileUploadProgress[soundSetSelected.id + '-' + soundHandle.handle]"
:sound-file-update-state="soundFileUpdateState[soundSetSelected.id + '-' + soundHandle.handle]"
:has-parent="soundSetSelected.parent_id"
:read-only="!soundSetSelected.customer_id"
@play="playSoundFile"
@upload="uploadFile"
@toggle-loop-play="setLoopPlay"
@toggle-use-parent="setUseParent"
@remove-uploaded-file="removeUploadedFile"
/>
</template>
<template
slot="actions"
>
<q-btn
size="md"
color="primary"
round
flat
:icon="expanded[group] ? 'expand_less' : 'expand_more'"
@click.stop="toggle(group)"
/>
</template>
</csc-list-item>
</div>
</q-list>
</q-item>
</csc-page-sticky>
</template>
<script>
import _ from 'lodash'
import {
mapState, mapGetters, mapMutations, mapActions
} from 'vuex'
import {
showGlobalError,
showToast
} from 'src/helpers/ui'
import {
RequestState
} from 'src/store/common'
import {
maxLength
} from 'vuelidate/lib/validators'
import CscPbxSoundSetSound from 'components/pages/PbxConfiguration/CscPbxSoundSetSound'
import CscListSpinner from 'components/CscListSpinner'
import CscInputButtonSave from 'components/form/CscInputButtonSave'
import CscInputButtonReset from 'components/form/CscInputButtonReset'
import CscPageSticky from 'components/CscPageSticky'
import CscListItem from 'components/CscListItem'
import CscListItemTitle from 'components/CscListItemTitle'
export default {
name: 'CscPbxSoundSet',
components: {
CscInputButtonReset,
CscInputButtonSave,
CscListSpinner,
CscPbxSoundSetSound,
CscPageSticky,
CscListItemTitle,
CscListItem
},
async mounted () {
this.selectSoundSet(this.$route.params.id)
await this.loadSoundSetResources(this.$route.params.id)
if (this.soundHandleGroups.length > 0) {
this.soundHandleGroups.map((group) => {
this.$set(this.expanded, group, false)
})
}
},
data () {
return {
changes: null,
expanded: {}
}
},
validations: {
changes: {
name: {
maxLength: maxLength(64)
},
description: {
maxLength: maxLength(255)
}
}
},
computed: {
...mapState('pbxSoundSets', [
'soundSetList',
'soundSetUpdateState',
'soundSetUpdateError',
'soundSetSelected',
'soundHandleList',
'soundFileMap',
'soundFileUrlMap',
'soundFileUploadState',
'soundFileUploadProgress',
'soundFileUpdateState',
'soundHandleGroups'
]),
...mapGetters('pbxSoundSets', [
'isSoundFileListRequesting',
'getSoundSetUpdateToastMessage',
'isSoundHandleListRequesting',
'isSoundSetUpdating'
]),
hasNameChanged () {
return this.changes.name !== this.getSoundSetData().name
},
hasDescriptionChanged () {
return this.changes.description !== this.getSoundSetData().description
},
parent () {
return this.changes.parent_id ? this.soundSetList.find((soundSet) => this.changes.parent_id === soundSet.id) : null
},
getParentOptions () {
let parentOptions = [
{
label: this.$t('Unassigned'),
value: null
}
]
this.soundSetList.map((soundSet) => {
if (soundSet.id !== this.soundSetSelected.id) {
parentOptions.push({
label: soundSet.name,
value: soundSet.id
})
}
})
return parentOptions
},
hasParentChanged () {
return this.changes.parent_id !== this.getSoundSetData().parent_id
}
},
watch: {
soundSetUpdateState (state) {
if (state === RequestState.succeeded) {
showToast(this.getSoundSetUpdateToastMessage)
} else if (state === RequestState.failed) {
showGlobalError(this.soundSetUpdateError)
}
},
soundSetSelected () {
this.changes = this.getSoundSetData()
},
soundHandleGroups (state) {
if (state.length > 0) {
state.map((group) => {
this.$set(this.expanded, group, false)
})
}
}
},
methods: {
...mapMutations('pbxSoundSets', [
'selectSoundSet'
]),
...mapActions('pbxSoundSets', [
'loadSoundSetResources',
'setAsDefaultSoundSet',
'playSoundFile',
'uploadSoundFile',
'setLoopPlay',
'setUseParent',
'removeSoundFile',
'setSoundSetName',
'setSoundSetDescription',
'setSoundSetParent'
]),
saveAsDefault () {
this.setAsDefaultSoundSet({
soundSetId: this.soundSetSelected.id,
contractDefault: !this.soundSetSelected.contract_default
})
},
getSoundSetData () {
return {
name: this.soundSetSelected.name,
description: this.soundSetSelected.description,
contract_default: this.soundSetSelected.contract_default,
parent_id: this.soundSetSelected.parent_id,
customer_id: this.soundSetSelected.customer_id
}
},
resetName () {
this.changes.name = this.getSoundSetData().name
},
resetDescription () {
this.changes.description = this.getSoundSetData().description
},
resetParent () {
this.changes.parent_id = this.getSoundSetData().parent_id
},
uploadFile (options) {
this.uploadSoundFile({
soundSetId: this.soundSetSelected.id,
soundHandle: options.soundHandle,
soundFileData: options.soundFileData
})
},
removeUploadedFile (options) {
this.removeSoundFile(options)
},
toggle (group) {
this.$set(this.expanded, group, !this.expanded[group])
},
save () {
if (this.hasNameChanged) {
this.setSoundSetName({
soundSetId: this.soundSetSelected.id,
name: this.changes.name
})
}
if (this.hasDescriptionChanged) {
this.setSoundSetDescription({
soundSetId: this.soundSetSelected.id,
description: this.changes.description
})
}
if (this.hasParentChanged) {
this.setSoundSetParent({
soundSetId: this.soundSetSelected.id,
parent_id: this.changes.parent_id
})
}
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus">
.csc-pbx-sound-set-sound-list
margin-top $flex-gutter-sm
</style>

@ -4,7 +4,7 @@
class="q-pa-lg"
>
<csc-list-actions
class="row justify-center q-mb-lg"
class="row justify-center q-mb-xs"
>
<csc-list-action-button
v-if="!isSoundSetAddFormEnabled"
@ -15,6 +15,7 @@
@click="enableSoundSetAddForm"
/>
</csc-list-actions>
<q-separator />
<q-slide-transition>
<div
v-if="isSoundSetAddFormEnabled"
@ -39,10 +40,11 @@
/>
</div>
<csc-list-spinner
v-if="isSoundSetListRequesting && !soundSetListVisible"
v-if="isSoundSetListRequesting || isSoundSetUpdating || isSoundSetRemoving || isSoundSetCreating"
/>
<csc-list
v-if="!isSoundSetListRequesting || soundSetListVisible"
<q-list
v-if="!isSoundSetListRequesting && soundSetListVisible && !isSoundSetCreating"
class="row justify-start items-start"
>
<csc-fade
v-for="(soundSet, index) in soundSetList"
@ -50,33 +52,15 @@
>
<csc-pbx-sound-set
:key="soundSet.id"
:class="'col-xs-12 col-md-6 col-lg-4 csc-item-' + ((index % 2 === 0)?'odd':'even')"
:odd="(index % 2) === 0"
:expanded="isSoundSetExpanded(soundSet.id)"
:loading="isSoundSetLoading(soundSet.id)"
:loading="isSoundSetLoading(soundSet.id) || isSoundSetUpdating || isSoundSetRemoving"
:sound-set="soundSet"
:sound-handles="soundHandleList"
:sound-handles-loading="isSoundHandleListRequesting"
:sound-files-loading="isSoundFileListRequesting(soundSet.id)"
:sound-file-map="soundFileMap"
:sound-file-url-map="soundFileUrlMap"
:sound-file-upload-state="soundFileUploadState"
:sound-file-upload-progress="soundFileUploadProgress"
:sound-file-update-state="soundFileUpdateState"
@require-sound-handles="loadSoundSetResources(soundSet.id)"
@remove="openSoundSetRemovalDialog(soundSet.id)"
@save-as-default="setAsDefaultSoundSet"
@save-name="setSoundSetName"
@save-description="setSoundSetDescription"
@save-parent="setSoundSetParent"
@expand="expandSoundSet(soundSet.id)"
@collapse="collapseSoundSet"
@play-sound-file="playSoundFile"
@upload-sound-file="uploadSoundFile"
@toggle-loop-play="setLoopPlay"
@toggle-use-parent="setUseParent"
@remove="openSoundSetRemovalDialog(soundSet.id)"
/>
</csc-fade>
</csc-list>
</q-list>
<div
v-if="isSoundSetListEmpty && !isSoundSetListRequesting"
class="row justify-center csc-no-entities"
@ -109,7 +93,6 @@ import {
mapGetters
} from 'vuex'
import CscPage from 'components/CscPage'
import CscList from 'components/CscList'
import CscFade from 'components/transitions/CscFade'
import CscListActions from 'components/CscListActions'
import CscListActionButton from 'components/CscListActionButton'
@ -127,7 +110,6 @@ export default {
CscListActionButton,
CscListActions,
CscFade,
CscList,
CscPage
},
data () {
@ -140,18 +122,12 @@ export default {
'soundSetList',
'soundSetListCurrentPage',
'soundSetListLastPage',
'soundHandleList',
'soundFileMap',
'soundFileUrlMap',
'soundFileUploadState',
'soundFileUploadProgress',
'soundFileUpdateState',
'soundSetCreationState',
'soundSetCreationError',
'soundSetUpdateState',
'soundSetUpdateError',
'soundSetRemovalState',
'soundSetRemovalError'
'soundSetRemovalError',
'soundSetUpdateState',
'soundSetUpdateError'
]),
...mapGetters('pbxSoundSets', [
'isSoundSetListEmpty',
@ -159,15 +135,13 @@ export default {
'isSoundSetAddFormEnabled',
'isSoundSetListPaginationActive',
'isSoundSetCreating',
'isSoundSetUpdating',
'isSoundSetLoading',
'isSoundSetExpanded',
'getSoundSetRemoveDialogMessage',
'isSoundHandleListRequesting',
'isSoundFileListRequesting',
'getSoundSetCreationToastMessage',
'getSoundSetRemovalToastMessage',
'getSoundSetUpdateToastMessage',
'getSoundSetRemovalToastMessage'
'isSoundSetUpdating',
'isSoundSetRemoving'
])
},
watch: {
@ -203,23 +177,13 @@ export default {
'enableSoundSetAddForm',
'disableSoundSetAddForm',
'soundSetRemovalRequesting',
'soundSetRemovalCanceled',
'expandSoundSet',
'collapseSoundSet'
'soundSetRemovalCanceled'
]),
...mapActions('pbxSoundSets', [
'loadSoundSetList',
'createSoundSet',
'removeSoundSet',
'setAsDefaultSoundSet',
'setSoundSetName',
'setSoundSetDescription',
'setSoundSetParent',
'loadSoundSetResources',
'playSoundFile',
'uploadSoundFile',
'setLoopPlay',
'setUseParent'
'setAsDefaultSoundSet'
]),
loadSoundSetListPaginated (page) {
this.loadSoundSetList({

@ -34,6 +34,7 @@ import CscPagePbxSettingsAutoAttendant from 'pages/CscPagePbxSettingsAutoAttenda
import CscPageDashboard from 'pages/CscPageDashboard'
import CscPagePbxSettingsMsConfigs from 'pages/CscPagePbxSettingsMsConfigs'
import CscPagePbxSettingsCallQueues from 'pages/CscPagePbxSettingsCallQueues'
import CscPagePbxSoundSetDetails from 'src/pages/CscPagePbxSoundSetDetails'
const getToken = (route) => {
return {
@ -257,6 +258,18 @@ export default function routes (app) {
profileAttribute: PROFILE_ATTRIBUTE_MAP.soundSet
}
},
{
path: 'pbx-configuration/sound-sets/:id',
component: CscPagePbxSoundSetDetails,
meta: {
get title () {
return i18n.t('PBX Configuration')
},
get subtitle () {
return i18n.t('Sound Sets')
}
}
},
{
path: 'pbx-configuration/ms-configs',
component: CscPagePbxMsConfigs,

@ -17,7 +17,7 @@ import {
getAllSoundFilesBySoundSetId,
getSoundFile,
uploadSoundFile,
setLoopPlay, unsetAsDefault, setUseParent
setLoopPlay, unsetAsDefault, setUseParent, removeSoundFile
} from '../api/pbx-soundsets'
import _ from 'lodash'
import {
@ -53,7 +53,7 @@ export default {
soundSetUpdating: null,
soundSetUpdatingField: null,
soundSetSelected: null,
soundHandleList: [],
soundHandleList: {},
soundHandleListState: RequestState.initiated,
soundFileMap: {},
soundFileUrlMap: {},
@ -61,7 +61,9 @@ export default {
soundFileState: {},
soundFileUploadState: {},
soundFileUploadProgress: {},
soundFileUpdateState: {}
soundFileUpdateState: {},
soundFileRemoveState: {},
soundHandleGroups: []
},
getters: {
isSoundSetListEmpty (state) {
@ -97,11 +99,6 @@ export default {
state.soundSetUpdating !== null && state.soundSetUpdating.id === id)
}
},
isSoundSetExpanded (state) {
return (id) => {
return state.soundSetSelected !== null && state.soundSetSelected.id === id
}
},
getSoundSetRemoveDialogMessage (state) {
if (state.soundSetRemoving !== null) {
const id = _.get(state, 'soundSetRemoving.id', null)
@ -147,6 +144,9 @@ export default {
return state.soundFileListStates[soundSetId] &&
state.soundFileListStates[soundSetId] === RequestState.requesting
}
},
isSoundFileRemoving (state) {
return state.soundFileRemoveState === RequestState.requesting
}
},
mutations: {
@ -184,8 +184,14 @@ export default {
state.soundSetUpdating = state.soundSetMap[options.soundSetId]
state.soundSetUpdatingField = options.field
},
soundSetUpdateSucceeded (state) {
soundSetUpdateSucceeded (state, soundSet) {
state.soundSetUpdateState = RequestState.succeeded
const index = state.soundSetList.findIndex((soundSetItem) => soundSetItem.id === soundSet.id)
Vue.set(state.soundSetMap, soundSet.id, soundSet)
state.soundSetList[index] = soundSet
if (state.soundSetSelected.id === soundSet.id) {
state.soundSetSelected = soundSet
}
},
soundSetUpdateFailed (state, err) {
state.soundSetUpdateState = RequestState.failed
@ -201,8 +207,11 @@ export default {
state.soundSetRemovalState = RequestState.initiated
state.soundSetRemoving = null
},
soundSetRemovalSucceeded (state) {
soundSetRemovalSucceeded (state, soundSetId) {
state.soundSetRemovalState = RequestState.succeeded
const index = state.soundSetList.findIndex((soundSetItem) => soundSetItem.id === soundSetId)
Vue.delete(state.soundSetMap, soundSetId)
state.soundSetList.splice(index, 1)
},
soundSetRemovalFailed (state, err) {
state.soundSetRemovalState = RequestState.failed
@ -214,18 +223,20 @@ export default {
disableSoundSetAddForm (state) {
state.soundSetCreationState = CreationState.initiated
},
expandSoundSet (state, soundSetId) {
state.soundSetSelected = state.soundSetMap[soundSetId]
},
collapseSoundSet (state) {
state.soundSetSelected = null
},
soundHandlesRequesting (state) {
state.soundHandleListState = RequestState.requesting
},
soundHandlesSucceeded (state, soundHandles) {
state.soundHandleListState = RequestState.succeeded
state.soundHandleList = _.get(soundHandles, 'items', [])
const soundHandleList = _.get(soundHandles, 'items', [])
soundHandleList.map((soundHandle) => {
if (!state.soundHandleGroups.includes(soundHandle.group)) {
state.soundHandleGroups.push(soundHandle.group)
}
})
state.soundHandleGroups.map((group) => {
Vue.set(state.soundHandleList, group, soundHandleList.filter((soundHandle) => group === soundHandle.group))
})
},
soundFilesRequesting (state, soundSetId) {
Vue.delete(state.soundFileListStates, soundSetId)
@ -310,6 +321,37 @@ export default {
})
Vue.delete(state.soundFileUpdateState, soundFileIntId)
Vue.set(state.soundFileUpdateState, soundFileIntId, RequestState.failed)
},
soundFileRemoveRequesting (state, options) {
const soundFileIntId = toFileId({
soundSetId: options.soundSetId,
soundHandle: options.soundHandle
})
Vue.delete(state.soundFileRemoveState, soundFileIntId)
Vue.set(state.soundFileRemoveState, soundFileIntId, RequestState.requesting)
},
soundFileRemoveSucceeded (state, soundFile) {
const soundFileIntId = toFileId({
soundSetId: soundFile.soundSetId,
soundHandle: soundFile.soundHandle
})
Vue.delete(state.soundFileRemoveState, soundFileIntId)
Vue.set(state.soundFileRemoveState, soundFileIntId, RequestState.succeeded)
Vue.delete(state.soundFileMap, soundFileIntId)
},
soundFileRemoveFailed (state, options) {
const soundFileIntId = toFileId({
soundSetId: options.soundSetId,
soundHandle: options.soundHandle
})
Vue.delete(state.soundFileRemoveState, soundFileIntId)
Vue.set(state.soundFileRemoveState, soundFileIntId, RequestState.failed)
},
selectSoundSet (state, soundSetId) {
state.soundSetSelected = state.soundSetMap[soundSetId]
},
resetSelectedSoundSet (state) {
state.soundSetSelected = null
}
},
actions: {
@ -354,12 +396,7 @@ export default {
removeSoundSet (context) {
context.commit('soundSetRemovalRequesting')
removeSoundSet(context.state.soundSetRemoving.id).then(() => {
return context.dispatch('loadSoundSetList', {
listVisible: true,
page: context.state.soundSetListCurrentPage
})
}).then(() => {
context.commit('soundSetRemovalSucceeded')
context.commit('soundSetRemovalSucceeded', context.state.soundSetRemoving.id)
}).catch((err) => {
context.commit('soundSetRemovalFailed', err.message)
})
@ -373,13 +410,8 @@ export default {
if (options.contractDefault !== true) {
func = unsetAsDefault
}
func(options.soundSetId).then(() => {
return context.dispatch('loadSoundSetList', {
listVisible: true,
page: context.state.soundSetListCurrentPage
})
}).then(() => {
context.commit('soundSetUpdateSucceeded')
func(options.soundSetId).then((soundSet) => {
context.commit('soundSetUpdateSucceeded', soundSet)
}).catch((err) => {
context.commit('soundSetUpdateFailed', err.message)
})
@ -389,13 +421,8 @@ export default {
soundSetId: options.soundSetId,
field: i18n.t('name')
})
setSoundSetName(options.soundSetId, options.name).then(() => {
return context.dispatch('loadSoundSetList', {
listVisible: true,
page: context.state.soundSetListCurrentPage
})
}).then(() => {
context.commit('soundSetUpdateSucceeded')
setSoundSetName(options.soundSetId, options.name).then((soundSet) => {
context.commit('soundSetUpdateSucceeded', soundSet)
}).catch((err) => {
context.commit('soundSetUpdateFailed', err.message)
})
@ -405,13 +432,8 @@ export default {
soundSetId: options.soundSetId,
field: i18n.t('description')
})
setSoundSetDescription(options.soundSetId, options.description).then(() => {
return context.dispatch('loadSoundSetList', {
listVisible: true,
page: context.state.soundSetListCurrentPage
})
}).then(() => {
context.commit('soundSetUpdateSucceeded')
setSoundSetDescription(options.soundSetId, options.description).then((soundSet) => {
context.commit('soundSetUpdateSucceeded', soundSet)
}).catch((err) => {
context.commit('soundSetUpdateFailed', err.message)
})
@ -421,13 +443,8 @@ export default {
soundSetId: options.soundSetId,
field: i18n.t('parent')
})
setSoundSetParent(options.soundSetId, options.parent_id).then(() => {
return context.dispatch('loadSoundSetList', {
listVisible: true,
page: context.state.soundSetListCurrentPage
})
}).then(() => {
context.commit('soundSetUpdateSucceeded')
setSoundSetParent(options.soundSetId, options.parent_id).then((soundSet) => {
context.commit('soundSetUpdateSucceeded', soundSet)
}).catch((err) => {
context.commit('soundSetUpdateFailed', err.message)
})
@ -533,6 +550,15 @@ export default {
console.debug(err)
context.commit('soundFileUpdateFailed', options)
})
},
removeSoundFile (context, options) {
context.commit('soundFileRemoveRequesting', options)
removeSoundFile(options.soundFileId).then(() => {
context.commit('soundFileRemoveSucceeded', options)
}).catch((err) => {
console.debug(err)
context.commit('soundFileRemoveFailed', options)
})
}
}
}

Loading…
Cancel
Save