TT#121651 CallRecordings - Integrate CscAudioPlayer

Change-Id: I6858a6eb071cf5102ac4ea28ea5ba57ed9f8def1
mr9.5.2
Carlo Venusino 4 years ago
parent ab1bfa68c4
commit 2609e1b28e

@ -7,6 +7,7 @@ import {
import { import {
getList, getList,
get, get,
getAsBlob,
patchAdd, patchAdd,
patchReplace, patchReplace,
patchRemove, patchRemove,
@ -14,9 +15,11 @@ import {
patchAddFull patchAddFull
} from './common' } from './common'
import { import {
assignNumbers assignNumbers
} from './user' } from './user'
export function getPreferences (id) { export function getPreferences (id) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
Vue.http.get('api/subscriberpreferences/' + id).then((result) => { Vue.http.get('api/subscriberpreferences/' + id).then((result) => {
@ -616,3 +619,9 @@ export async function getSubscriberRegistrations (options) {
}) })
return list return list
} }
export async function getRecordingStream (fileId) {
return await getAsBlob({
path: 'api/callrecordingfiles/' + fileId
})
}

@ -86,16 +86,6 @@
:icon="isRowExpanded(props.row.id) ? 'expand_less' : 'expand_more'" :icon="isRowExpanded(props.row.id) ? 'expand_less' : 'expand_more'"
@click="updateCollapseArray(props.row.id)" @click="updateCollapseArray(props.row.id)"
/> />
<csc-confirmation-dialog
:key="props.row.id"
:ref="'confirmDelete-'+props.row.id"
title-icon="delete"
title-icon-color="negative"
color="negative"
:title="$t('Delete recording', {id: props.row.id})"
:message="$t('You are about to delete recording #{id}', {id: props.row.id})"
@confirm="deleteRecord(props.row.id)"
/>
</q-td> </q-td>
</q-tr> </q-tr>
<q-tr <q-tr
@ -109,7 +99,7 @@
<q-table <q-table
:data="props.row.files" :data="props.row.files"
:columns="filesColumns" :columns="filesColumns"
:loading="$wait.is('csc-call-recordings')" :loading="$wait.is('csc-call-recordings') && $wait.is('loading-stream-' + props.row.id)"
:hide-pagination="true" :hide-pagination="true"
row-key="name" row-key="name"
class="csc-item-odd" class="csc-item-odd"
@ -143,13 +133,22 @@
> >
{{ col.value }} {{ col.value }}
</q-td> </q-td>
<q-td> <q-td
class="row justify-end table-td-action-cont"
>
<csc-audio-player
v-if="innerProps.row.url"
:file-url="innerProps.row.url"
:pausable="true"
class="player-btns"
/>
<q-btn <q-btn
size="md" size="md"
color="primary" color="primary"
icon="download" icon="download"
dense dense
flat flat
class="download-btn"
@click="saveFile(innerProps.row.id)" @click="saveFile(innerProps.row.id)"
/> />
</q-td> </q-td>
@ -170,13 +169,14 @@ import { mapGetters } from 'vuex'
import { mapWaitingActions } from 'vue-wait' import { mapWaitingActions } from 'vue-wait'
import { saveAs } from 'file-saver' import { saveAs } from 'file-saver'
import { showGlobalError, showToast } from 'src/helpers/ui' import { showGlobalError, showToast } from 'src/helpers/ui'
import CscConfirmationDialog from 'components/CscConfirmationDialog' import CscAudioPlayer from 'components/CscAudioPlayer'
import CscPageSticky from 'components/CscPageSticky' import CscPageSticky from 'components/CscPageSticky'
import CscCallRecordingFilters from 'components/pages/CallRecording/CscCallRecordingFilters' import CscCallRecordingFilters from 'components/pages/CallRecording/CscCallRecordingFilters'
import CscRemoveDialog from 'components/CscRemoveDialog'
export default { export default {
name: 'CscCallBlocking', name: 'CscCallBlocking',
components: { components: {
CscConfirmationDialog, CscAudioPlayer,
CscPageSticky, CscPageSticky,
CscCallRecordingFilters CscCallRecordingFilters
}, },
@ -272,7 +272,8 @@ export default {
fetchRecordings: 'csc-call-recordings', fetchRecordings: 'csc-call-recordings',
fetchStreams: 'csc-call-recordings', fetchStreams: 'csc-call-recordings',
deleteRecording: 'csc-call-recordings', deleteRecording: 'csc-call-recordings',
downloadRecording: 'csc-call-recordings' downloadRecording: 'csc-call-recordings',
playStreamFile: 'csc-call-recordings'
}), }),
async fetchPaginatedRecordings (props) { async fetchPaginatedRecordings (props) {
const { page, rowsPerPage, sortBy, descending } = props.pagination const { page, rowsPerPage, sortBy, descending } = props.pagination
@ -301,7 +302,14 @@ export default {
this.showFilters = false this.showFilters = false
}, },
confirmRowDeletion (rowId) { confirmRowDeletion (rowId) {
this.$refs['confirmDelete-' + rowId].open() this.$q.dialog({
component: CscRemoveDialog,
parent: this,
title: this.$t('Delete recording'),
message: this.$t('You are about to delete recording #{id}', { id: rowId })
}).onOk(() => {
this.deleteRecord(rowId)
})
}, },
async deleteRecord (rowId) { async deleteRecord (rowId) {
try { try {
@ -319,12 +327,17 @@ export default {
const rowStatus = this.rowStatus.filter(row => row.id === id)[0] || null const rowStatus = this.rowStatus.filter(row => row.id === id)[0] || null
return rowStatus && rowStatus.expanded return rowStatus && rowStatus.expanded
}, },
updateCollapseArray (id) { async updateCollapseArray (id) {
const recording = this.recordings.filter(rec => rec.id === id)[0] const recording = this.recordings.filter(rec => rec.id === id)[0]
const rowStatus = this.rowStatus.filter(row => row.id === id)[0] const rowStatus = this.rowStatus.filter(row => row.id === id)[0]
rowStatus.expanded = !rowStatus.expanded rowStatus.expanded = !rowStatus.expanded
if (rowStatus.expanded && recording.files.length === 0) { if (rowStatus.expanded && recording.files.length === 0) {
this.fetchStreams(id) this.$wait.start('loading-stream-' + id)
try {
await this.fetchStreams(id)
} finally {
this.$wait.end('loading-stream-' + id)
}
} }
}, },
async saveFile (fileId) { async saveFile (fileId) {
@ -348,4 +361,12 @@ export default {
font-size 15px font-size 15px
.table-td-no-padding .table-td-no-padding
padding 0px !important // needed to override .q-table td padding 0px !important // needed to override .q-table td
.table-td-action-cont
min-width 140px
.player-btns
bottom 9px
left 8px
.download-btn
height 30px
</style> </style>

@ -1,5 +1,5 @@
import Vue from 'vue' import Vue from 'vue'
import { getRecordings, getRecordingStreams, downloadRecordingStream } from '../api/subscriber' import { getRecordings, getRecordingStreams, downloadRecordingStream, getRecordingStream } from '../api/subscriber'
export default { export default {
namespaced: true, namespaced: true,
state: { state: {
@ -15,6 +15,11 @@ export default {
}, },
mutations: { mutations: {
callRecordings (state, res) { callRecordings (state, res) {
(state.recordings || []).forEach(r => {
(r?.files || []).forEach(s => {
if (s.url) URL.revokeObjectURL(s.url)
})
})
state.recordings = res state.recordings = res
}, },
callRecordingStreams (state, data) { callRecordingStreams (state, data) {
@ -33,6 +38,10 @@ export default {
}, },
async fetchStreams (context, recId) { async fetchStreams (context, recId) {
const streams = await getRecordingStreams(recId) const streams = await getRecordingStreams(recId)
await Promise.all(streams.map(async stream => {
const blob = await getRecordingStream(stream.id)
stream.url = blob
}))
context.commit('callRecordingStreams', { context.commit('callRecordingStreams', {
recId: recId, recId: recId,
streams: streams streams: streams

Loading…
Cancel
Save