TT#43554 Call: Refactor CSC call vue.js component

Change-Id: Icefd79362d414bca9ffb857857af461ad3564c24
changes/96/23696/2
Hans-Peter Herzog 7 years ago
parent 68ee7088ba
commit 82a98ed539

@ -3,21 +3,11 @@
<audio <audio
ref="incomingSound" ref="incomingSound"
loop loop
playsinline
preload="auto" preload="auto"
src="statics/ring.mp3" src="statics/ring.mp3"
></audio>
<q-card
flat
color="secondary"
>
<q-card-title>
<span v-if="isRinging || isInitiating || isIncoming">
<q-spinner-rings
color="primary"
:size="50"
/> />
</span> <div class="csc-call-title absolute-top-left">
<q-icon <q-icon
v-if="isPreparing" v-if="isPreparing"
name="call" name="call"
@ -42,7 +32,6 @@
color="primary" color="primary"
size="26px" size="26px"
/> />
<span <span
v-if="isPreparing" v-if="isPreparing"
class="text" class="text"
@ -79,7 +68,10 @@
> >
{{ $t('call.call') }} {{ $t('call.call') }}
</span> </span>
</div>
<div
class="csc-call-top-actions absolute-top-right"
>
<q-btn <q-btn
v-if="isFullscreenEnabled && !isMobile" v-if="isFullscreenEnabled && !isMobile"
round round
@ -88,6 +80,7 @@
class="no-shadow" class="no-shadow"
@click="toggleFullscreen()" @click="toggleFullscreen()"
icon="fullscreen exit" icon="fullscreen exit"
color="default"
/> />
<q-btn <q-btn
v-else-if="!isMobile" v-else-if="!isMobile"
@ -97,6 +90,7 @@
class="no-shadow" class="no-shadow"
@click="toggleFullscreen()" @click="toggleFullscreen()"
icon="fullscreen" icon="fullscreen"
color="default"
/> />
<q-btn <q-btn
round round
@ -105,9 +99,18 @@
class="no-shadow" class="no-shadow"
@click="close()" @click="close()"
icon="clear" icon="clear"
color="default"
/> />
</q-card-title> </div>
<q-card-main> <div
class="csc-call-spinner row justify-center"
v-if="isRinging || isInitiating || isIncoming"
>
<q-spinner-rings
color="primary"
:size="50"
/>
</div>
<q-alert <q-alert
v-if="desktopSharingInstall" v-if="desktopSharingInstall"
v-model="desktopSharingInstall" v-model="desktopSharingInstall"
@ -116,16 +119,18 @@
> >
{{ $t('call.desktopSharingNotInstalled') }} {{ $t('call.desktopSharingNotInstalled') }}
</q-alert> </q-alert>
<div class="csc-call-info">
<csc-phone-number-input <csc-phone-number-input
ref="phoneNumberInput"
v-if="isPreparing" v-if="isPreparing"
class="csc-phone-number-input"
ref="phoneNumberInput"
:enabled="isPhoneNumberInputEnabled" :enabled="isPhoneNumberInputEnabled"
:dialpad-button="true"
@toggle-dialpad="toggleDialpad()"
@key-return="call('audioOnly')"
/> />
<div <div
v-if="!isPreparing" v-if="!isPreparing"
class="phone-number" class="csc-phone-number"
> >
<q-icon <q-icon
v-if="isCalling && (localMediaType == 'audioVideo' || remoteMediaType == 'audioVideo')" v-if="isCalling && (localMediaType == 'audioVideo' || remoteMediaType == 'audioVideo')"
@ -143,20 +148,16 @@
</div> </div>
<div <div
v-if="isEnded" v-if="isEnded"
class="ended-reason" class="csc-call-ended-reason"
> >
{{ getEndedReason }} {{ getEndedReason | startCase }}
</div> </div>
<csc-call-dialpad <div
class="csc-call-dialpad" :class="callMediaClasses"
v-if="isDialpadEnabled" v-show="isCalling || isEstablished"
@inserted="dialpadInserted" >
/>
</div>
<div class="csc-call-media">
<csc-media <csc-media
:class="mediaPreviewClasses" class="csc-media-local"
id="local-media" id="local-media"
:muted="true" :muted="true"
v-show="isCalling" v-show="isCalling"
@ -170,9 +171,19 @@
:stream="remoteMediaStream" :stream="remoteMediaStream"
/> />
</div> </div>
<div
</q-card-main> :class="callControlClasses"
<q-card-actions align="center"> >
<csc-call-dialpad
class="csc-call-dialpad"
v-if="isDialpadEnabled"
@inserted="dialpadInserted"
@remove="dialpadRemove"
@remove-all="dialpadRemoveAll"
/>
<div
class="csc-call-actions"
>
<q-btn <q-btn
v-if="isEstablished" v-if="isEstablished"
round round
@ -261,14 +272,6 @@
@click="accept('audioScreen')" @click="accept('audioScreen')"
icon="computer" icon="computer"
/> />
<q-btn
v-if="isDialpadButtonEnabled"
round
:small="!isFullscreenEnabled"
color="primary"
@click="toggleDialpad()"
icon="dialpad"
/>
<q-btn <q-btn
v-if="isIncoming" v-if="isIncoming"
round round
@ -277,8 +280,8 @@
@click="decline()" @click="decline()"
icon="call end" icon="call end"
/> />
</q-card-actions> </div>
</q-card> </div>
</div> </div>
</template> </template>
@ -350,6 +353,16 @@
this.$refs.phoneNumberInput.concat(value); this.$refs.phoneNumberInput.concat(value);
} }
}, },
dialpadRemove() {
if(!this.isEstablished) {
this.$refs.phoneNumberInput.remove();
}
},
dialpadRemoveAll() {
if(!this.isEstablished) {
this.$refs.phoneNumberInput.removeAll();
}
},
focusNumberInput() { focusNumberInput() {
this.$refs.phoneNumberInput.focusInput(); this.$refs.phoneNumberInput.focusInput();
}, },
@ -474,13 +487,6 @@
return 'volume up'; return 'volume up';
} }
}, },
mediaPreviewClasses() {
var classes = [];
if(this.isEstablished && this.hasRemoteVideo) {
classes.push('csc-media-preview');
}
return classes;
},
localMediaStream() { localMediaStream() {
if(this.$store.state.call.localMediaStream !== null) { if(this.$store.state.call.localMediaStream !== null) {
return this.$store.state.call.localMediaStream.getStream(); return this.$store.state.call.localMediaStream.getStream();
@ -544,18 +550,34 @@
isDialpadEnabled() { isDialpadEnabled() {
return this.dialpadEnabled && (this.isPreparing || this.isEstablished); return this.dialpadEnabled && (this.isPreparing || this.isEstablished);
}, },
isDialpadButtonEnabled() {
return this.isPreparing || this.isEstablished;
},
callClasses() { callClasses() {
let callClasses = ['csc-call']; let classes = ['csc-call', 'call-state-' + this.callState];
if(this.isEstablished) { if (this.isFullscreenEnabled) {
callClasses.push('csc-call-established'); classes.push('csc-call-fullscreen');
}
if (this.isMobile) {
classes.push('csc-call-mobile');
} }
return callClasses; return classes;
},
callMediaClasses() {
let classes = ['csc-call-media'];
if (this.hasVideo) {
classes.push('csc-call-media-video');
}
return classes;
},
callControlClasses() {
let classes = ['csc-call-controls'];
return classes;
} }
}, },
watch: { watch: {
isEstablished(established) {
if(established) {
this.dialpadEnabled = false;
}
},
callState(state) { callState(state) {
if(state === 'incoming') { if(state === 'incoming') {
showCallNotification(numberFormat(this.getNumber)); showCallNotification(numberFormat(this.getNumber));
@ -566,6 +588,9 @@
} }
else if (state === 'input') { else if (state === 'input') {
this.stopIncomingSound(); this.stopIncomingSound();
if(this.isMobile) {
this.dialpadEnabled = true;
}
} }
else { else {
this.stopIncomingSound(); this.stopIncomingSound();
@ -577,77 +602,165 @@
<style lang="stylus" rel="stylesheet/stylus"> <style lang="stylus" rel="stylesheet/stylus">
@import '../themes/quasar.variables.styl'; @import '../themes/quasar.variables.styl';
.csc-call
.csc-call { position relative
width: inherit; z-index 2
} padding-top 64px
height 100%
.csc-call .q-card { .csc-call-title
margin: 0; z-index 11
} padding 16px
color white
.csc-call .q-card-main { font-size 16px
padding: 0; line-height: 40px
} .csc-call-top-actions
z-index 10
.csc-call .q-field { padding 16px
margin: 0px; .csc-phone-number-input
padding-left: 16px; position relative
padding-right: 16px; z-index 9
} margin 0
padding 16px
.csc-call .q-card-actions {
padding: 16px;
}
.csc-spinner {
text-align: center;
margin-bottom: 16px;
}
.q-card-title .text {
color: #adb3b8;
}
.csc-call-fullscreen .csc-call .q-card-title .text {
color: white;
}
.csc-call .phone-number {
font-size: 18px;
text-align: center;
color: #adb3b8;
margin-bottom: 16px;
}
.csc-call-fullscreen .csc-call .phone-number {
color: white;
}
.csc-call .ended-reason {
font-size: 18px;
text-align: center;
color: #adb3b8;
}
.csc-call-media {
position: relative;
}
.csc-media.csc-media-preview {
position: absolute;
bottom: 0;
left: 0;
width: 25%;
z-index: 10;
}
.csc-call .q-alert-container {
margin-bottom: 16px;
}
.csc-call.csc-call-established
.csc-call-dialpad .csc-call-dialpad
position relative
z-index 8
padding 16px
.csc-call-actions
display flex
flex-direction row
position relative
z-index 7
padding 16px
padding-top 8px
justify-content center
.q-btn
margin-right 16px
display flex
.q-btn:last-child
margin-right 0
.csc-call-ended-reason
color indianred
text-align center
padding 16px
padding-top 0 padding-top 0
position relative
z-index 6
font-size 16px
.csc-phone-number
text-align center
padding 16px
color white
position relative
z-index 6
font-size 16px
.q-icon
vertical-align middle
.csc-media-local
position relative
.csc-call-media.csc-call-media-video
padding-top 16px
padding-bottom 16px padding-bottom 16px
position relative
z-index 2
.csc-call-spinner
position relative
padding 16px
z-index 3
.csc-call.csc-call-fullscreen
.csc-call-title
font-size 20px
line-height: 56px
.csc-call-controls
padding: 32px
.csc-call-actions
.q-btn
margin-right 16px
.q-btn:last-child
margin-right 0
.csc-call-media
padding 0
position absolute
top 0
left 0
right 0
bottom 0
.csc-media-local
position relative
padding 0
width: 100%
height: 100%
.csc-phone-number
font-size: 20px
.csc-call-ended-reason
font-size: 20px
.csc-call.csc-call-fullscreen.call-state-initiating,
.csc-call.csc-call-fullscreen.call-state-ringing
.csc-call-controls
position absolute
bottom 0
right 0
left 0
background-color alpha($secondary, 0.4)
.csc-call.call-state-established
.csc-call-media
.csc-media-local
position absolute
width 30%
height auto
z-index 2
bottom 24px
left 8px
-webkit-box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
.csc-media-remote
position relative
width 100%
height 100%
z-index 1
.csc-call.csc-call-fullscreen.call-state-established
.csc-call-media
.csc-media-local
bottom 16px
left 16px
width 20%
-webkit-box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
-moz-box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
box-shadow: 0px 0px 29px -4px rgba(0,0,0,0.75);
.csc-call-controls
position absolute
bottom 0
right 0
left 0
background-color alpha($secondary, 0.4)
.csc-call.csc-call-fullscreen.csc-call-mobile
padding-top 72px
.csc-call-title
padding 8px
padding-left 16px
font-size 20 px
line-height 56px
.csc-call-top-actions
padding 8px
.csc-phone-number-input
margin 0
padding 16px
.csc-call-dialpad
padding 4px
.csc-call-actions
padding 4px
.q-btn
margin-right 16px
.q-btn:last-child
margin-right 0
.csc-call.csc-call-fullscreen.csc-call-mobile.call-state-established
.csc-media-local
bottom 120px
left: 32px
.csc-call-controls
.csc-call-actions
padding-bottom 0
</style> </style>

@ -3,6 +3,34 @@
<div <div
class="column" class="column"
> >
<div
class="csc-dialpad-btn-group csc-dialpad-btn-group-special"
>
<div
class="csc-dialpad-btn"
>
<q-btn
color="primary"
round
outline
small
@click="remove()"
icon="backspace"
/>
</div>
<div
class="csc-dialpad-btn"
>
<q-btn
color="primary"
round
outline
small
@click="removeAll()"
icon="cancel"
/>
</div>
</div>
<div <div
class="csc-dialpad-btn-group" class="csc-dialpad-btn-group"
v-for="(keyRow, rowIndex) in keys" v-for="(keyRow, rowIndex) in keys"
@ -81,6 +109,12 @@
if(this.isEstablished) { if(this.isEstablished) {
this.$store.dispatch('call/sendDTMF', value); this.$store.dispatch('call/sendDTMF', value);
} }
},
remove() {
this.$emit('remove');
},
removeAll() {
this.$emit('remove-all');
} }
} }
} }
@ -94,7 +128,8 @@
padding-bottom 0 padding-bottom 0
.csc-dialpad-btn .csc-dialpad-btn
display inline-block display flex
flex-direction column
margin-left 16px margin-left 16px
.q-btn-inner .q-btn-inner
font-size 22px font-size 22px
@ -106,8 +141,15 @@
margin-left 0 margin-left 0
.csc-dialpad-btn-group .csc-dialpad-btn-group
display: block display: flex
flex-direction row
margin-bottom 8px margin-bottom 8px
justify-content: flex-end
.csc-dialpad-btn-group.csc-dialpad-btn-group-special
justify-content: center
.q-btn
font-size 14px
.csc-dialpad-btn-group:last-child .csc-dialpad-btn-group:last-child
margin-bottom 0 margin-bottom 0

@ -1,9 +1,23 @@
<template> <template>
<div class="csc-media"> <div
<div v-show="loading" class="csc-spinner"> class="csc-media"
<q-spinner-mat color="primary" :size="60" /> >
<div
v-show="loading"
class="csc-spinner"
>
<q-spinner-mat
color="primary"
:size="60"
/>
</div> </div>
<video v-show="!loading && hasVideo" ref="media" autoplay :muted="muted"></video> <video
v-show="!loading && hasVideo"
ref="media"
autoplay
:muted="muted"
playsinline
/>
</div> </div>
</template> </template>
@ -70,11 +84,20 @@
</script> </script>
<style lang="stylus" rel="stylesheet/stylus"> <style lang="stylus" rel="stylesheet/stylus">
.csc-media {
.csc-media
position: relative; position: relative;
} font-size 0
.csc-media video {
video
position: relative; position: relative;
width: 100%; width: 100%;
}
.csc-spinner
display flex
flex-direction row
justify-content center
.q-spinner-mat
display flex
flex-direction column
</style> </style>

@ -1,5 +1,6 @@
<template> <template>
<q-field <q-field
v-if="!isMobile"
dark dark
:count="maxLength" :count="maxLength"
:helper="helperMessage" :helper="helperMessage"
@ -19,6 +20,32 @@
@input="inputPhoneNumber" @input="inputPhoneNumber"
@keypress.space.prevent @keypress.space.prevent
@keydown.space.prevent @keydown.space.prevent
@keyup.space.prevent
:after="inputButtons"
@keyup.enter="keyReturn()"
/>
</q-field>
<q-field
v-else
dark
:error="$v.phoneNumber.$error"
:error-label="errorMessage"
>
<q-input
ref="inputField"
dark
clearable
type="text"
:placeholder="$t('call.number')"
:value="phoneNumber"
:error="$v.phoneNumber.$error"
:max-length="maxLength"
:readonly="!enabled"
@input="inputPhoneNumber"
@keypress.space.prevent
@keydown.space.prevent
@keyup.space.prevent
:after="inputButtons"
/> />
</q-field> </q-field>
</template> </template>
@ -64,6 +91,10 @@
enabled: { enabled: {
type: Boolean, type: Boolean,
default: true default: true
},
dialpadButton: {
type: Boolean,
default: false
} }
}, },
mixins: [ mixins: [
@ -78,9 +109,27 @@
}, },
inputReadonly() { inputReadonly() {
return this.isMobile; return this.isMobile;
},
inputButtons() {
let self = this;
let buttons = [];
if (this.dialpadButton) {
buttons.push({
icon: 'dialpad',
error: false,
handler (event) {
event.stopPropagation();
self.toggleDialpad();
}
});
}
return buttons;
} }
}, },
methods: { methods: {
keyReturn() {
this.$emit('key-return');
},
inputPhoneNumber(value) { inputPhoneNumber(value) {
this.phoneNumber = normalizeNumber(value, this.isMobile); this.phoneNumber = normalizeNumber(value, this.isMobile);
this.$v.phoneNumber.$touch(); this.$v.phoneNumber.$touch();
@ -106,6 +155,18 @@
Vue.nextTick(() => { Vue.nextTick(() => {
this.$refs.inputField.blur(); this.$refs.inputField.blur();
}); });
},
remove() {
this.phoneNumber = _.trim(this.phoneNumber.substring(0, this.phoneNumber.length - 1));
if (this.phoneNumber === '+') {
this.phoneNumber = '';
}
},
removeAll() {
this.phoneNumber = '';
},
toggleDialpad() {
this.$emit('toggle-dialpad');
} }
} }
} }

@ -581,11 +581,7 @@
} }
.csc-call-fullscreen .csc-call .q-card-actions { .csc-call-fullscreen .csc-call .q-card-actions {
position: absolute;
bottom: 0;
right: 0;
left: 0;
z-index: 6001;
} }
.csc-call-fullscreen .csc-call .q-card-main { .csc-call-fullscreen .csc-call .q-card-main {

@ -5,9 +5,11 @@ import NumberFormatFilter from './number-format'
import { normalizeDestination } from './number-format' import { normalizeDestination } from './number-format'
import DateFilter from './date' import DateFilter from './date'
import { smartTime } from './date' import { smartTime } from './date'
import { startCase } from './string'
Vue.filter('number', NumberFilter); Vue.filter('number', NumberFilter);
Vue.filter('readableDate', DateFilter); Vue.filter('readableDate', DateFilter);
Vue.filter('numberFormat', NumberFormatFilter); Vue.filter('numberFormat', NumberFormatFilter);
Vue.filter('destinationFormat', normalizeDestination); Vue.filter('destinationFormat', normalizeDestination);
Vue.filter('smartTime', smartTime); Vue.filter('smartTime', smartTime);
Vue.filter('startCase', startCase);

@ -0,0 +1,6 @@
import _ from 'lodash'
export function startCase(str) {
return _.startCase(str);
}
Loading…
Cancel
Save