TT#100755 CallRecordings - As Customer, I want to list CallRecordings

- TT#115519 Create separate page and route "Recordings" under "Call Settings"
- TT#115520 Integrate and configure QTable
- TT#115521 Implement vuex actions, mutations and getters
- TT#115522 Implement expanded section to render Streams meta data

NOTE #1: for populating recording table, please follow these instructions https://sipwise.atlassian.net/wiki/spaces/DEV/pages/1105494098/Recorded+calls+on+dev+environment

NOTE #2: /callrecordingstreams endpoint needs to be fixed (TT#118600 ); in the meantime as workaround to be able to fetch streams you need to go to /usr/share/perl5/NGCP/Panel/Controller/API/CallRecordingStreams.pm on your VM and modify line 30, change 'call' to 'me.call', then execute systemctl restart ngcp-panel

Change-Id: Iac102ef7449cf7621166f2492cd8b200005768e1
mr9.4
Carlo Venusino 4 years ago
parent 571ba6917f
commit 69ab2d448a

@ -17,7 +17,6 @@ import {
import {
assignNumbers
} from './user'
export function getPreferences (id) {
return new Promise((resolve, reject) => {
Vue.http.get('api/subscriberpreferences/' + id).then((result) => {
@ -561,3 +560,39 @@ export async function getBrandingLogo (subscriberId) {
return null
}
}
export async function getRecordings (subscriberId) {
let retArr = []
const res = await Vue.http.get('api/callrecordings/', {
subscriber_id: subscriberId
})
if (res.body.total_count > 0) {
const recordings = getJsonBody(res.body)._embedded['ngcp:callrecordings']
retArr = recordings.map(recording => {
return {
id: recording.id,
time: recording.start_time,
files: []
}
})
}
return retArr
}
export async function getRecordingStreams (recId) {
let streams = []
const res = await Vue.http.get('api/callrecordingstreams/', {
params: {
recording_id: recId
}
})
if (res.body.total_count > 0) {
streams = getJsonBody(res.body)._embedded['ngcp:callrecordingstreams']
}
return streams
}
export async function downloadRecordingStream (fileId) {
const res = await Vue.http.get('api/callrecordingfiles/' + fileId, { responseType: 'blob' })
return res.body
}

@ -3,6 +3,7 @@
ref="dialogComp"
:title="title"
:title-icon="titleIcon"
:title-icon-color="titleIconColor"
:opened="opened"
@close="onClose()"
>
@ -14,7 +15,7 @@
<q-btn
slot="actions"
:icon="titleIcon"
color="primary"
:color="color"
flat
@click="confirm"
>
@ -40,6 +41,10 @@ export default {
type: String,
default: ''
},
titleIconColor: {
type: String,
default: 'primary'
},
message: {
type: String,
default: ''
@ -47,6 +52,10 @@ export default {
opened: {
type: Boolean,
default: false
},
color: {
type: String,
default: 'primary'
}
},
data () {

@ -123,6 +123,12 @@ export default {
icon: 'notification_important',
label: this.$t('Reminder'),
visible: true
},
{
to: '/user/recordings',
icon: 'play_circle',
label: this.$t('Recordings'),
visible: true
}
]
},

@ -118,6 +118,7 @@
"Call back": "Rückruf",
"Call ended": "Beendet",
"Call forwarded": "Anruf weitergeleitet",
"Call recordings": "",
"Calling": "Anrufen",
"Calling {number}...": "{number} wird angerufen...",
"Calls": "Anrufe",
@ -177,6 +178,7 @@
"Delete destination": "",
"Delete forwarding": "",
"Delete from {groupName} forwarding": "",
"Delete recording": "",
"Delete sourceset": "Anruferliste löschen",
"Delete voicemail after email notification is delivered": "Voicemail löschen, wenn die E-Mail-Benachrichtigung gesendet wurde",
"Delete {groupName} forwarding group": "",
@ -236,6 +238,7 @@
"Filter groups": "",
"Fine": "Mittel",
"Forgot password?": "",
"Format": "",
"Forward to Conference": "",
"Forward to Fax2Mail": "",
"Forward to ManagerSecretary": "",
@ -260,6 +263,7 @@
"Hunt Policy": "Klingelschema",
"Hunt Timeout": "Klingeldauer",
"Hunt timeout": "Klingeldauer",
"Id": "",
"If available": "",
"If available and ": "",
"If busy": "",
@ -394,6 +398,8 @@
"Random Ringing": "Zufälliges Klingeln",
"Receive Reports": "",
"Received from IP": "",
"Recording successfully deleted": "",
"Recordings": "",
"Recover password": "",
"Reloading conversation items failed": "Das Laden der Konversationen ist fehlgeschlagen.",
"Reminder": "Erinnerung",
@ -491,6 +497,7 @@
"Show filters": "Filter anzeigen",
"Sign In": "Log-in",
"Slot": "Kurzwahl",
"Something went wrong. Please retry later": "",
"Sound Set": "Soundset",
"Sound Sets": "Sound Sets",
"Sound set is incomplete ({amount})": "Soundset ist unvollständig ({amount})",
@ -527,6 +534,7 @@
"This sound set is incomplete ({amount} file is missing)": "Soundset ist unvollständig ({amount} Sound fehlt)",
"This sound set is incomplete ({amount} files are missing)": "Soundset ist unvollständig ({amount} Sounds fehlen)",
"Thursday": "Donnerstag",
"Time": "",
"Time is invalid": "",
"Time of the day": "Uhrzeit des Tages",
"Timeout": "Klingeldauer",
@ -536,6 +544,7 @@
"Toggled deletion successfully": "Löschen der Voicemail erfolgreich geändert",
"Tu": "",
"Tuesday": "Dienstag",
"Type": "",
"Type something": "",
"Unassign": "",
"Unassigned": "Nicht zugewiesen",
@ -590,6 +599,7 @@
"You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ": "Du bist dabei, dein Login-Passwort zu ändern. Nachdem das Passwort erfolgreich geändert wurde, wirst du automatisch abgemeldet, um dich mit dem neuen Passwort zu authentifizieren.",
"You are about to delete {name} sourceset": "",
"You are about to delete {name} timeset": "",
"You are about to delete recording #{id}": "",
"You are about to delete time range \"{from} - {to}\"": "",
"You are about to delete {destination} from {groupName} call forwarding": "",
"You are about to delete {groupName} call forwarding group": "",
@ -683,4 +693,4 @@
"{field} must have at most {maxLength} letters": "{field} darf höchstens {maxLength} Buchstaben beinhalten",
"{mode} of sources": "{mode} of sources",
"{mode} own phone": "Eigene Rufnummer {mode}"
}
}

@ -118,6 +118,7 @@
"Call back": "Call back",
"Call ended": "Call ended",
"Call forwarded": "Call forwarded",
"Call recordings": "Call recordings",
"Calling": "Calling",
"Calling {number}...": "Calling {number}...",
"Calls": "Calls",
@ -177,6 +178,7 @@
"Delete destination": "Delete destination",
"Delete forwarding": "Delete forwarding",
"Delete from {groupName} forwarding": "Delete from {groupName} forwarding",
"Delete recording": "Delete recording",
"Delete sourceset": "Delete sourceset",
"Delete voicemail after email notification is delivered": "Delete voicemail after email notification is delivered",
"Delete {groupName} forwarding group": "Delete {groupName} forwarding group",
@ -236,6 +238,7 @@
"Filter groups": "Filter groups",
"Fine": "Fine",
"Forgot password?": "Forgot password?",
"Format": "Format",
"Forward to Conference": "Forward to Conference",
"Forward to Fax2Mail": "Forward to Fax2Mail",
"Forward to ManagerSecretary": "Forward to ManagerSecretary",
@ -260,6 +263,7 @@
"Hunt Policy": "Hunt Policy",
"Hunt Timeout": "Hunt Timeout",
"Hunt timeout": "Hunt timeout",
"Id": "Id",
"If available": "If available",
"If available and ": "If available and ",
"If busy": "If busy",
@ -394,6 +398,8 @@
"Random Ringing": "Random Ringing",
"Receive Reports": "Receive Reports",
"Received from IP": "Received from IP",
"Recording successfully deleted": "Recording successfully deleted",
"Recordings": "Recordings",
"Recover password": "Recover password",
"Reloading conversation items failed": "Reloading conversation items failed",
"Reminder": "Reminder",
@ -491,6 +497,7 @@
"Show filters": "Show filters",
"Sign In": "Sign In",
"Slot": "Slot",
"Something went wrong. Please retry later": "Something went wrong. Please retry later",
"Sound Set": "Sound Set",
"Sound Sets": "Sound Sets",
"Sound set is incomplete ({amount})": "Sound set is incomplete ({amount})",
@ -527,6 +534,7 @@
"This sound set is incomplete ({amount} file is missing)": "This sound set is incomplete ({amount} file is missing)",
"This sound set is incomplete ({amount} files are missing)": "This sound set is incomplete ({amount} files are missing)",
"Thursday": "Thursday",
"Time": "Time",
"Time is invalid": "Time is invalid",
"Time of the day": "Time of the day",
"Timeout": "Timeout",
@ -536,6 +544,7 @@
"Toggled deletion successfully": "Toggled deletion successfully",
"Tu": "Tu",
"Tuesday": "Tuesday",
"Type": "Type",
"Type something": "Type something",
"Unassign": "Unassign",
"Unassigned": "Unassigned",
@ -590,6 +599,7 @@
"You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ": "You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ",
"You are about to delete {name} sourceset": "You are about to delete {name} sourceset",
"You are about to delete {name} timeset": "You are about to delete {name} timeset",
"You are about to delete recording #{id}": "You are about to delete recording #{id}",
"You are about to delete time range \"{from} - {to}\"": "You are about to delete time range \"{from} - {to}\"",
"You are about to delete {destination} from {groupName} call forwarding": "You are about to delete {destination} from {groupName} call forwarding",
"You are about to delete {groupName} call forwarding group": "You are about to delete {groupName} call forwarding group",
@ -683,4 +693,4 @@
"{field} must have at most {maxLength} letters": "{field} must have at most {maxLength} letters",
"{mode} of sources": "{mode} of sources",
"{mode} own phone": "{mode} own phone"
}
}

@ -118,6 +118,7 @@
"Call back": "Llamar de vuelta",
"Call ended": "Llamada terminada",
"Call forwarded": "Llamada redirigida",
"Call recordings": "",
"Calling": "Llamando",
"Calling {number}...": "Iniciando ...",
"Calls": "Llamadas",
@ -177,6 +178,7 @@
"Delete destination": "",
"Delete forwarding": "",
"Delete from {groupName} forwarding": "",
"Delete recording": "",
"Delete sourceset": "Eliminar el conjunto de fuentes",
"Delete voicemail after email notification is delivered": "Eliminar el correo de voz después de enviar la notificación por correo electrónico",
"Delete {groupName} forwarding group": "",
@ -236,6 +238,7 @@
"Filter groups": "",
"Fine": "Bien",
"Forgot password?": "",
"Format": "",
"Forward to Conference": "",
"Forward to Fax2Mail": "",
"Forward to ManagerSecretary": "",
@ -260,6 +263,7 @@
"Hunt Policy": "Política de búsqueda",
"Hunt Timeout": "Tiempo de espera de grupo de búsqueda",
"Hunt timeout": "Tiempo de espera de grupo de búsqueda",
"Id": "",
"If available": "",
"If available and ": "",
"If busy": "",
@ -394,6 +398,8 @@
"Random Ringing": "Llamada aleatoria",
"Receive Reports": "",
"Received from IP": "",
"Recording successfully deleted": "",
"Recordings": "",
"Recover password": "",
"Reloading conversation items failed": "Falló la recarga de elementos de conversación",
"Reminder": "Recordatorio",
@ -491,6 +497,7 @@
"Show filters": "Mostrar filtros",
"Sign In": "Iniciar sesión",
"Slot": "Ranura",
"Something went wrong. Please retry later": "",
"Sound Set": "Conjunto de sonido",
"Sound Sets": "Conjuntos de Sonido",
"Sound set is incomplete ({amount})": "El conjunto de sonido está incompleto ({amount})",
@ -527,6 +534,7 @@
"This sound set is incomplete ({amount} file is missing)": "Este conjunto de sonidos está incompleto ({amount} falta archivo)",
"This sound set is incomplete ({amount} files are missing)": "Este conjunto de sonidos está incompleto ({amount} faltan archivos)",
"Thursday": "Jueves",
"Time": "",
"Time is invalid": "",
"Time of the day": "Hora del día",
"Timeout": "Tiempo de espera",
@ -536,6 +544,7 @@
"Toggled deletion successfully": "Eliminación cambiada correctamente",
"Tu": "",
"Tuesday": "Martes",
"Type": "",
"Type something": "",
"Unassign": "",
"Unassigned": "Sin asignar",
@ -590,6 +599,7 @@
"You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ": "Está a punto de cambiar su contraseña de inicio de sesión. Después de que la contraseña se cambie con éxito, se cerrará la sesión automáticamente para autenticarse con la nueva contraseña.",
"You are about to delete {name} sourceset": "",
"You are about to delete {name} timeset": "",
"You are about to delete recording #{id}": "",
"You are about to delete time range \"{from} - {to}\"": "",
"You are about to delete {destination} from {groupName} call forwarding": "",
"You are about to delete {groupName} call forwarding group": "",
@ -683,4 +693,4 @@
"{field} must have at most {maxLength} letters": "{field} debe tener como máximo {maxLength} letras",
"{mode} of sources": "{mode} de fuentes",
"{mode} own phone": "{mode} teléfono propio"
}
}

@ -118,6 +118,7 @@
"Call back": "Rappel",
"Call ended": "Appel terminé",
"Call forwarded": "",
"Call recordings": "",
"Calling": "Appel",
"Calling {number}...": "Appel vers le {number} en cours...",
"Calls": "Appels",
@ -177,6 +178,7 @@
"Delete destination": "",
"Delete forwarding": "",
"Delete from {groupName} forwarding": "",
"Delete recording": "",
"Delete sourceset": "Supprimer la liste de sources",
"Delete voicemail after email notification is delivered": "Supprimer le message vocal une fois la notification e-mail délivrée",
"Delete {groupName} forwarding group": "",
@ -236,6 +238,7 @@
"Filter groups": "",
"Fine": "Fin",
"Forgot password?": "",
"Format": "",
"Forward to Conference": "",
"Forward to Fax2Mail": "",
"Forward to ManagerSecretary": "",
@ -260,6 +263,7 @@
"Hunt Policy": "Politique de groupement dappels",
"Hunt Timeout": "Temporisation des groupements dappels",
"Hunt timeout": "Temporisation des groupements dappels",
"Id": "",
"If available": "",
"If available and ": "",
"If busy": "",
@ -394,6 +398,8 @@
"Random Ringing": "Sonnerie aléatoire",
"Receive Reports": "",
"Received from IP": "",
"Recording successfully deleted": "",
"Recordings": "",
"Recover password": "",
"Reloading conversation items failed": "Le rechargement des conversations a échoué",
"Reminder": "Rappel",
@ -491,6 +497,7 @@
"Show filters": "Afficher les filtre",
"Sign In": "Authentification",
"Slot": "Emplacement",
"Something went wrong. Please retry later": "",
"Sound Set": "",
"Sound Sets": "",
"Sound set is incomplete ({amount})": "",
@ -527,6 +534,7 @@
"This sound set is incomplete ({amount} file is missing)": "",
"This sound set is incomplete ({amount} files are missing)": "",
"Thursday": "Jeudi",
"Time": "",
"Time is invalid": "",
"Time of the day": "Heure de la journée",
"Timeout": "Temporisation",
@ -536,6 +544,7 @@
"Toggled deletion successfully": "La suppression a été activée avec succès",
"Tu": "",
"Tuesday": "Mardi",
"Type": "",
"Type something": "",
"Unassign": "",
"Unassigned": "Non attribué",
@ -590,6 +599,7 @@
"You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ": "",
"You are about to delete {name} sourceset": "",
"You are about to delete {name} timeset": "",
"You are about to delete recording #{id}": "",
"You are about to delete time range \"{from} - {to}\"": "",
"You are about to delete {destination} from {groupName} call forwarding": "",
"You are about to delete {groupName} call forwarding group": "",
@ -683,4 +693,4 @@
"{field} must have at most {maxLength} letters": "{field} doit avoir au maximum {maxLength} caractères",
"{mode} of sources": "Sources {mode}",
"{mode} own phone": "{mode} téléphone personnel"
}
}

@ -118,6 +118,7 @@
"Call back": "Richiama",
"Call ended": "Chiamata terminata",
"Call forwarded": "Chiamata inoltrata",
"Call recordings": "",
"Calling": "Composizione",
"Calling {number}...": "Stai chiamando {number}...",
"Calls": "Chiamate",
@ -177,6 +178,7 @@
"Delete destination": "",
"Delete forwarding": "",
"Delete from {groupName} forwarding": "",
"Delete recording": "",
"Delete sourceset": "Cancella set pattern sorgente",
"Delete voicemail after email notification is delivered": "Cancella il messaggio vocale dopo che l'email di notifica è stata inoltrata",
"Delete {groupName} forwarding group": "",
@ -236,6 +238,7 @@
"Filter groups": "",
"Fine": "Fine",
"Forgot password?": "",
"Format": "",
"Forward to Conference": "",
"Forward to Fax2Mail": "",
"Forward to ManagerSecretary": "",
@ -260,6 +263,7 @@
"Hunt Policy": "Modalità di Ricerca",
"Hunt Timeout": "Timeout Ricerca",
"Hunt timeout": "Timeout Ricerca",
"Id": "",
"If available": "",
"If available and ": "",
"If busy": "",
@ -394,6 +398,8 @@
"Random Ringing": "Squillo Casuale",
"Receive Reports": "",
"Received from IP": "",
"Recording successfully deleted": "",
"Recordings": "",
"Recover password": "",
"Reloading conversation items failed": "Caricamento dell'elenco conversazioni fallito",
"Reminder": "Promemoria",
@ -491,6 +497,7 @@
"Show filters": "Mostra filtri",
"Sign In": "Accedi",
"Slot": "Posizione",
"Something went wrong. Please retry later": "",
"Sound Set": "Set Messaggi",
"Sound Sets": "Annunci",
"Sound set is incomplete ({amount})": "Questo set di messaggi è incompleto ({amount})",
@ -527,6 +534,7 @@
"This sound set is incomplete ({amount} file is missing)": "Questo set di messaggi è incompleto ({amount} files mancanti)",
"This sound set is incomplete ({amount} files are missing)": "Questo set di messaggi è incompleto ({amount} files mancanti)",
"Thursday": "Giovedì",
"Time": "",
"Time is invalid": "",
"Time of the day": "Ora del giorno",
"Timeout": "Timeout",
@ -536,6 +544,7 @@
"Toggled deletion successfully": "Cancellazione modificata con successo",
"Tu": "",
"Tuesday": "Martedì",
"Type": "",
"Type something": "",
"Unassign": "",
"Unassigned": "Non assegnato",
@ -590,6 +599,7 @@
"You are about to change your login password. After the password was changed successfully, you get automatically logged out to authenticate with the new password. ": "Stai per modificare la tua password di login. Una volta che la password sarà modificata, verrai automaticamente disconnesso e dovrai accedere con la nuova password. ",
"You are about to delete {name} sourceset": "",
"You are about to delete {name} timeset": "",
"You are about to delete recording #{id}": "",
"You are about to delete time range \"{from} - {to}\"": "",
"You are about to delete {destination} from {groupName} call forwarding": "",
"You are about to delete {groupName} call forwarding group": "",
@ -683,4 +693,4 @@
"{field} must have at most {maxLength} letters": "Il campo {field} può contenere al massimo {maxLength} lettere",
"{mode} of sources": "{mode} dei pattern sorgente",
"{mode} own phone": "{mode} proprio telefono"
}
}

@ -0,0 +1,263 @@
<template>
<csc-page
class="q-pa-lg"
>
<template>
<div class="q-pa-md">
<q-table
:data="data"
:columns="columns"
:loading="$wait.is('csc-call-recordings')"
row-key="name"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
class="table-th"
>
{{ col.label }}
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template
v-slot:body="props"
>
<q-tr
:props="props"
>
<q-td auto-width>
<q-btn
size="sm"
color="primary"
round
dense
:icon="isRowExpanded(props.row.id) ? 'remove' : 'add'"
@click="updateCollapseArray(props.row.id)"
/>
</q-td>
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ col.value }}
</q-td>
<q-td>
<csc-more-menu>
<csc-popup-menu-item-delete
color="negative"
@click="confirmRowDeletion(props.row.id)"
/>
</csc-more-menu>
<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-tr>
<q-tr
v-show="isRowExpanded(props.row.id)"
no-hover
>
<q-td
colspan="100%"
class="table-td-no-padding"
>
<q-table
:data="props.row.files"
:columns="filesColumns"
:loading="$wait.is('csc-call-recordings')"
:hide-pagination="true"
row-key="name"
>
<template v-slot:header="props">
<q-tr :props="props">
<q-th
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ col.label }}
</q-th>
<q-th auto-width />
</q-tr>
</template>
<template v-slot:body="props">
<q-tr :props="props">
<q-td
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ col.value }}
</q-td>
<q-td>
<q-btn
size="sm"
color="primary"
icon="download"
dense
@click="saveFile(props.row.id)"
/>
</q-td>
</q-tr>
</template>
</q-table>
</q-td>
</q-tr>
</template>
</q-table>
</div>
</template>
</csc-page>
</template>
<script>
import {
mapGetters
} from 'vuex'
import {
mapWaitingActions
} from 'vue-wait'
import CscPage from 'components/CscPage'
import CscMoreMenu from 'components/CscMoreMenu'
import CscPopupMenuItemDelete from 'components/CscPopupMenuItemDelete'
import CscConfirmationDialog from 'components/CscConfirmationDialog'
import { showGlobalError, showToast } from 'src/helpers/ui'
import { saveAs } from 'file-saver'
export default {
name: 'CscCallBlocking',
components: {
CscPage,
CscMoreMenu,
CscPopupMenuItemDelete,
CscConfirmationDialog
},
data () {
return {
columns: [
{
name: 'id',
required: true,
label: this.$t('Id'),
align: 'left',
field: row => row.id,
format: val => `${val}`,
sortable: true
},
{
name: 'time',
required: true,
align: 'left',
label: this.$t('Time'),
field: row => row.time,
sortable: true
}
],
filesColumns: [
{
name: 'id',
required: true,
label: '#',
align: 'left',
field: row => row.id,
format: val => `${val}`,
sortable: true
},
{
name: 'type',
required: true,
align: 'left',
label: this.$t('Type'),
field: row => row.type,
sortable: true
},
{
name: 'format',
required: true,
align: 'left',
label: this.$t('Format'),
field: row => row.format,
sortable: true
}
],
data: [],
rowStatus: []
}
},
computed: {
...mapGetters('callRecordings', [
'recordings'
])
},
watch: {
recordings () {
this.data = this.recordings
this.rowStatus = this.recordings.map(rec => {
return {
id: rec.id,
expanded: false
}
})
}
},
async mounted () {
await this.fetchRecordings()
},
methods: {
...mapWaitingActions('callRecordings', {
fetchRecordings: 'csc-call-recordings',
fetchStreams: 'csc-call-recordings',
deleteRecording: 'csc-call-recordings',
downloadRecording: 'csc-call-recordings'
}),
confirmRowDeletion (rowId) {
this.$refs['confirmDelete-' + rowId].open()
},
async deleteRecord (rowId) {
try {
await this.deleteRecording(rowId)
showToast(this.$t('Recording successfully deleted'))
await this.fetchRecordings()
} catch (err) {
showGlobalError(this.$t('Something went wrong. Please retry later'))
}
},
isRowExpanded (id) {
const rowStatus = this.rowStatus.filter(row => row.id === id)[0] || null
return rowStatus && rowStatus.expanded
},
updateCollapseArray (id) {
const recording = this.recordings.filter(rec => rec.id === id)[0]
const rowStatus = this.rowStatus.filter(row => row.id === id)[0]
rowStatus.expanded = !rowStatus.expanded
if (rowStatus.expanded && recording.files.length === 0) {
this.fetchStreams(id)
}
},
async saveFile (fileId) {
const file = await this.downloadRecording(fileId)
saveAs(file, 'call-recording-' + fileId + '.wav')
}
}
}
</script>
<style lang="stylus" rel="stylesheet/stylus" scoped>
.table-th
font-size 15px
.table-td-no-padding
padding 0px !important // needed to override .q-table td
</style>

@ -13,6 +13,7 @@ import CscPageCallForwardAfterHours from 'src/pages/CscPageCallForwardAfterHours
import CscPageCallBlockingIncoming from 'src/pages/CscPageCallBlockingIncoming'
import CscPageCallBlockingOutgoing from 'src/pages/CscPageCallBlockingOutgoing'
import CscPageCallBlockingPrivacy from 'src/pages/CscPageCallBlockingPrivacy'
import CscPageCallRecording from 'src/pages/CscPageCallRecording'
import CscPageReminder from 'src/pages/CscPageReminder'
import CscPageSpeedDial from 'src/pages/CscPageSpeedDial'
import CscPagePbxGroups from 'src/pages/CscPagePbxGroups'
@ -117,6 +118,14 @@ export default function routes (app) {
subtitle: i18n.t('Privacy')
}
},
{
path: 'recordings',
component: CscPageCallRecording,
meta: {
title: i18n.t('Recordings'),
subtitle: i18n.t('Call recordings')
}
},
{
path: 'reminder',
component: CscPageReminder,

@ -0,0 +1,45 @@
import Vue from 'vue'
import { getRecordings, getRecordingStreams, downloadRecordingStream } from '../api/subscriber'
export default {
namespaced: true,
state: {
recordings: []
},
getters: {
subscriberId (state, getters, rootState, rootGetters) {
return parseInt(rootGetters['user/getSubscriberId'])
},
recordings (state, getters, rootState, rootGetters) {
return state.recordings
}
},
mutations: {
callRecordings (state, res) {
state.recordings = res
},
callRecordingStreams (state, data) {
const recording = state.recordings.filter(rec => rec.id === data.recId)[0]
recording.files = data.streams
}
},
actions: {
async fetchRecordings (context) {
const recs = await getRecordings(context.getters.subscriberId)
context.commit('callRecordings', recs)
},
async fetchStreams (context, recId) {
const streams = await getRecordingStreams(recId)
context.commit('callRecordingStreams', {
recId: recId,
streams: streams
})
},
async deleteRecording (context, recId) {
await Vue.http.delete('api/callrecordings/' + recId + '?force_delete=1')
},
async downloadRecording (context, fileId) {
const fileBody = await downloadRecordingStream(fileId)
return fileBody
}
}
}

@ -10,6 +10,7 @@ import CallForwardModule from './call-forward'
import CallForwardingModule from './call-forwarding'
import NewCallForwardModule from './new-call-forward'
import CallModule, { errorVisibilityTimeout } from './call'
import CallRecordingsModule from './call-recordings'
import CallSettingsModule from './call-settings'
import ConversationsModule from './conversations'
@ -57,6 +58,7 @@ export default function (/* { ssrContext } */) {
callBlocking: CallBlockingModule,
callForward: CallForwardModule,
newCallForward: NewCallForwardModule,
callRecordings: CallRecordingsModule,
call: CallModule,
callSettings: CallSettingsModule,
conversations: ConversationsModule,

Loading…
Cancel
Save