- TT#45658 NuCall: As a Customer, I want to be able to initiate a call from the start page - TT#45662 NuCall: As a Customer, I want to see the initiating call state - TT#45669 NuCall: As a Customer, I want to see the call in ringing mode on caller side - TT#45659 NuCall: As a Customer, I want to be able to see an incoming call - TT#45660 NuCall: As a Customer, I want to be able to see established call - TT#45665 NuCall: As a Customer, I want to be able see the call minimised after leaving the start page Change-Id: I0c46359e5668cee9ef6313c5e3fe49cccc3d66eechanges/08/24408/12
parent
2fe7281f73
commit
8c4375583c
@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<div
|
||||
class="csc-alert-error row no-vert-gutter no-wrap"
|
||||
>
|
||||
<div
|
||||
class="col col-2"
|
||||
>
|
||||
<q-icon
|
||||
name="error"
|
||||
size="32px"
|
||||
color="white"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-alert-error-text"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
QIcon
|
||||
} from 'quasar-framework'
|
||||
export default {
|
||||
name: 'csc-alert-error',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
QIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" rel="stylesheet/stylus">
|
||||
@import '../themes/quasar.variables'
|
||||
.csc-alert-error
|
||||
background-color $negative
|
||||
padding $flex-gutter-md
|
||||
margin-bottom $flex-gutter-lg
|
||||
.csc-alert-error-text
|
||||
line-height 1.4em
|
||||
color $white
|
||||
</style>
|
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div
|
||||
class="csc-alert-info row no-vert-gutter no-wrap"
|
||||
>
|
||||
<div
|
||||
class="csc-alert-icon ol col-2"
|
||||
>
|
||||
<q-icon
|
||||
name="info"
|
||||
size="32px"
|
||||
color="white"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-alert-info-text col-10"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
QIcon
|
||||
} from 'quasar-framework'
|
||||
export default {
|
||||
name: 'csc-alert-info',
|
||||
data () {
|
||||
return {}
|
||||
},
|
||||
components: {
|
||||
QIcon
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" rel="stylesheet/stylus">
|
||||
@import '../themes/quasar.variables'
|
||||
.csc-alert-info
|
||||
background-color $info
|
||||
padding $flex-gutter-md
|
||||
margin-bottom $flex-gutter-lg
|
||||
.csc-alert-icon
|
||||
text-align left
|
||||
.csc-alert-info-text
|
||||
line-height 1.4em
|
||||
color $white
|
||||
</style>
|
@ -1,770 +0,0 @@
|
||||
<template>
|
||||
<div :class="callClasses">
|
||||
<audio
|
||||
ref="incomingSound"
|
||||
loop
|
||||
playsinline
|
||||
preload="auto"
|
||||
src="statics/ring.mp3"
|
||||
/>
|
||||
<div class="csc-call-title absolute-top-left">
|
||||
<q-icon
|
||||
v-if="isPreparing"
|
||||
name="call"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
<q-icon
|
||||
v-if="isEstablished && isCaller"
|
||||
name="call made"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
<q-icon
|
||||
v-if="isEstablished && isCallee"
|
||||
name="call received"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
<q-icon
|
||||
v-if="isEnded"
|
||||
name="error"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
<span
|
||||
v-if="isPreparing"
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.startNew') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="isInitiating"
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.initiating') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="isRinging"
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.ringing') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="isEnded"
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.ended') }}
|
||||
</span>
|
||||
<span
|
||||
v-else-if="isIncoming"
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.incoming') }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="text"
|
||||
>
|
||||
{{ $t('call.call') }}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-top-actions absolute-top-right"
|
||||
>
|
||||
<q-btn
|
||||
v-if="isFullscreenEnabled && !isMobile"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
slot="right"
|
||||
class="no-shadow"
|
||||
@click="toggleFullscreen()"
|
||||
icon="fullscreen exit"
|
||||
color="default"
|
||||
/>
|
||||
<q-btn
|
||||
v-else-if="!isMobile"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
slot="right"
|
||||
class="no-shadow"
|
||||
@click="toggleFullscreen()"
|
||||
icon="fullscreen"
|
||||
color="default"
|
||||
/>
|
||||
<q-btn
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
slot="right"
|
||||
class="no-shadow"
|
||||
@click="close()"
|
||||
icon="clear"
|
||||
color="default"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-spinner row justify-center"
|
||||
v-if="isRinging || isInitiating || isIncoming"
|
||||
>
|
||||
<q-spinner-rings
|
||||
color="primary"
|
||||
:size="50"
|
||||
/>
|
||||
</div>
|
||||
<q-alert
|
||||
v-if="desktopSharingInstall"
|
||||
v-model="desktopSharingInstall"
|
||||
color="warning"
|
||||
:actions="desktopSharingAlertActions"
|
||||
>
|
||||
{{ $t('call.desktopSharingNotInstalled') }}
|
||||
</q-alert>
|
||||
<csc-phone-number-input
|
||||
v-if="isPreparing"
|
||||
class="csc-phone-number-input"
|
||||
ref="phoneNumberInput"
|
||||
:enabled="isPhoneNumberInputEnabled"
|
||||
:dialpad-button="true"
|
||||
@toggle-dialpad="toggleDialpad()"
|
||||
@key-return="call('audioOnly')"
|
||||
/>
|
||||
<div
|
||||
v-if="!isPreparing"
|
||||
class="csc-phone-number"
|
||||
>
|
||||
<q-icon
|
||||
v-if="isCalling && (localMediaType == 'audioVideo' || remoteMediaType == 'audioVideo')"
|
||||
name="videocam"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
<q-icon
|
||||
v-else-if="isCalling && (localMediaType == 'audioOnly' || remoteMediaType == 'audioVideo')"
|
||||
name="mic"
|
||||
color="primary"
|
||||
size="26px"
|
||||
/>
|
||||
{{ getNumber | destinationFormat }}
|
||||
</div>
|
||||
<div
|
||||
v-if="isEnded"
|
||||
class="csc-call-ended-reason"
|
||||
>
|
||||
{{ getEndedReason | startCase }}
|
||||
</div>
|
||||
<div
|
||||
:class="callMediaClasses"
|
||||
v-show="isCalling || isEstablished"
|
||||
>
|
||||
<csc-media
|
||||
class="csc-media-local"
|
||||
id="local-media"
|
||||
:muted="true"
|
||||
v-show="isCalling"
|
||||
:stream="localMediaStream"
|
||||
/>
|
||||
<csc-media
|
||||
class="csc-media-remote"
|
||||
id="remote-media"
|
||||
:muted="isMuted"
|
||||
v-show="isEstablished"
|
||||
:stream="remoteMediaStream"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="callControlClasses"
|
||||
>
|
||||
<csc-call-dialpad
|
||||
class="csc-call-dialpad"
|
||||
v-if="isDialpadEnabled"
|
||||
@inserted="dialpadInserted"
|
||||
@remove="dialpadRemove"
|
||||
@remove-all="dialpadRemoveAll"
|
||||
/>
|
||||
<div
|
||||
class="csc-call-actions"
|
||||
>
|
||||
<q-btn
|
||||
v-if="isEstablished"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="toggleAudio()"
|
||||
:icon="toggleAudioIcon"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEstablished && localMediaType == 'audioVideo'"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="toggleVideo()"
|
||||
:icon="toggleVideoIcon"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEstablished"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="toggleMute()"
|
||||
:icon="toggleMuteIcon"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isPreparing"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="call('audioOnly')"
|
||||
icon="mic"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isPreparing"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="call('audioVideo')"
|
||||
icon="videocam"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isPreparing && !isMobile"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="call('audioScreen')"
|
||||
icon="computer"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isCalling"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="negative"
|
||||
@click="hangUp()"
|
||||
icon="call end"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEnded"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="negative"
|
||||
@click="init()"
|
||||
icon="clear"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isIncoming"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="accept('audioOnly')"
|
||||
icon="mic"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isIncoming"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="accept('audioVideo')"
|
||||
icon="videocam"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isIncoming && !isMobile"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="primary"
|
||||
@click="accept('audioScreen')"
|
||||
icon="computer"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isIncoming"
|
||||
round
|
||||
:small="!isFullscreenEnabled"
|
||||
color="negative"
|
||||
@click="decline()"
|
||||
icon="call end"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import platformMixin from '../mixins/platform'
|
||||
import { mapGetters } from 'vuex'
|
||||
import CscMedia from './CscMedia'
|
||||
import numberFormat from '../filters/number-format'
|
||||
import { showCallNotification } from '../helpers/ui'
|
||||
import { getChromeExtensionUrl } from '../helpers/cdk-lib'
|
||||
import CscCallDialpad from './CscCallDialpad'
|
||||
import CscPhoneNumberInput from './call/CscPhoneNumberInput'
|
||||
import { showGlobalError } from '../helpers/ui'
|
||||
import {
|
||||
QLayout,
|
||||
QCard,
|
||||
QCardTitle,
|
||||
QCardSeparator,
|
||||
QCardMain,
|
||||
QField,
|
||||
QInput,
|
||||
QCardActions,
|
||||
QBtn,
|
||||
QIcon,
|
||||
QSpinnerRings,
|
||||
Dialog,
|
||||
QAlert
|
||||
} from 'quasar-framework'
|
||||
|
||||
export default {
|
||||
name: 'csc-call',
|
||||
props: ['region', 'fullscreen'],
|
||||
data () {
|
||||
return {
|
||||
phoneNumber: '',
|
||||
phoneNumberError: false,
|
||||
validationEnabled: false,
|
||||
dialpadEnabled: false
|
||||
}
|
||||
},
|
||||
mixins: [
|
||||
platformMixin
|
||||
],
|
||||
components: {
|
||||
QLayout,
|
||||
QCard,
|
||||
QCardTitle,
|
||||
QCardSeparator,
|
||||
QCardMain,
|
||||
QField,
|
||||
QInput,
|
||||
QCardActions,
|
||||
QBtn,
|
||||
QIcon,
|
||||
QSpinnerRings,
|
||||
CscMedia,
|
||||
QAlert,
|
||||
CscCallDialpad,
|
||||
CscPhoneNumberInput
|
||||
},
|
||||
mounted() {
|
||||
this.dialpadEnabled = this.isMobile;
|
||||
},
|
||||
methods: {
|
||||
dialpadInserted(value) {
|
||||
if(this.isEstablished) {
|
||||
this.$store.dispatch('call/sendDTMF', value);
|
||||
}
|
||||
else {
|
||||
this.$refs.phoneNumberInput.concat(value);
|
||||
}
|
||||
},
|
||||
dialpadRemove() {
|
||||
if(!this.isEstablished) {
|
||||
this.$refs.phoneNumberInput.remove();
|
||||
}
|
||||
},
|
||||
dialpadRemoveAll() {
|
||||
if(!this.isEstablished) {
|
||||
this.$refs.phoneNumberInput.removeAll();
|
||||
}
|
||||
},
|
||||
focusNumberInput() {
|
||||
this.$refs.phoneNumberInput.focusInput();
|
||||
},
|
||||
blurNumberInput() {
|
||||
this.$refs.phoneNumberInput.blurInput();
|
||||
},
|
||||
init() {
|
||||
this.phoneNumber = '';
|
||||
this.validationEnabled = false;
|
||||
this.phoneNumberError = false;
|
||||
this.$store.commit('call/inputNumber');
|
||||
},
|
||||
phoneNumberFocus() {
|
||||
this.validationEnabled = true;
|
||||
},
|
||||
phoneNumberBlur() {
|
||||
this.validationEnabled = false;
|
||||
},
|
||||
call(localMedia) {
|
||||
if(this.$refs.phoneNumberInput.hasPhoneNumber()) {
|
||||
this.$store.dispatch('call/start', {
|
||||
number: this.$refs.phoneNumberInput.getPhoneNumber(),
|
||||
localMedia: localMedia
|
||||
});
|
||||
}
|
||||
else {
|
||||
showGlobalError(this.$t('validationErrors.inputValidNumber'));
|
||||
}
|
||||
},
|
||||
accept(localMedia) {
|
||||
this.$store.dispatch('call/accept', localMedia);
|
||||
},
|
||||
decline() {
|
||||
this.hangUp();
|
||||
this.$emit('close');
|
||||
},
|
||||
hangUp() {
|
||||
this.$store.dispatch('call/hangUp');
|
||||
},
|
||||
close() {
|
||||
if(this.isPreparing || this.isEnded) {
|
||||
this.init();
|
||||
this.$emit('close');
|
||||
}
|
||||
else {
|
||||
Dialog.create({
|
||||
title: this.$t('call.endCall'),
|
||||
message: this.$t('call.endCallDialog'),
|
||||
buttons: [
|
||||
'Cancel',
|
||||
{
|
||||
label: this.$t('call.endCall'),
|
||||
color: 'negative',
|
||||
handler: ()=>{
|
||||
this.hangUp();
|
||||
this.$emit('close');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
},
|
||||
playIncomingSound() {
|
||||
this.$refs.incomingSound.play();
|
||||
},
|
||||
stopIncomingSound() {
|
||||
this.$refs.incomingSound.pause();
|
||||
},
|
||||
toggleAudio() {
|
||||
if(this.isAudioEnabled) {
|
||||
this.$store.dispatch('call/disableAudio');
|
||||
}
|
||||
else {
|
||||
this.$store.dispatch('call/enableAudio');
|
||||
}
|
||||
},
|
||||
toggleVideo() {
|
||||
if(this.isVideoEnabled) {
|
||||
this.$store.dispatch('call/disableVideo');
|
||||
}
|
||||
else {
|
||||
this.$store.dispatch('call/enableVideo');
|
||||
}
|
||||
},
|
||||
toggleMute() {
|
||||
if(this.isMuted) {
|
||||
this.$store.commit('call/unmute');
|
||||
}
|
||||
else {
|
||||
this.$store.commit('call/mute');
|
||||
}
|
||||
},
|
||||
toggleFullscreen() {
|
||||
this.$emit('fullscreen');
|
||||
},
|
||||
toggleDialpad() {
|
||||
this.dialpadEnabled = !this.dialpadEnabled;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isFullscreenEnabled() {
|
||||
return this.fullscreen;
|
||||
},
|
||||
toggleAudioIcon() {
|
||||
if(this.isAudioEnabled) {
|
||||
return 'mic'
|
||||
}
|
||||
else {
|
||||
return 'mic off';
|
||||
}
|
||||
},
|
||||
toggleVideoIcon() {
|
||||
if(this.isVideoEnabled) {
|
||||
return 'videocam'
|
||||
}
|
||||
else {
|
||||
return 'videocam off';
|
||||
}
|
||||
},
|
||||
toggleMuteIcon() {
|
||||
if(this.isMuted) {
|
||||
return 'volume off'
|
||||
}
|
||||
else {
|
||||
return 'volume up';
|
||||
}
|
||||
},
|
||||
localMediaStream() {
|
||||
if(this.$store.state.call.localMediaStream !== null) {
|
||||
return this.$store.state.call.localMediaStream.getStream();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
remoteMediaStream() {
|
||||
if(this.$store.state.call.remoteMediaStream !== null) {
|
||||
return this.$store.state.call.remoteMediaStream.getStream();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
...mapGetters('call', [
|
||||
'isPreparing',
|
||||
'isInitiating',
|
||||
'isTrying',
|
||||
'isRinging',
|
||||
'isCalling',
|
||||
'isEnded',
|
||||
'isIncoming',
|
||||
'isEstablished',
|
||||
'getNumber',
|
||||
'getEndedReason',
|
||||
'hasRemoteVideo',
|
||||
'hasVideo',
|
||||
'isAudioEnabled',
|
||||
'isVideoEnabled',
|
||||
'isMuted',
|
||||
'localMediaType',
|
||||
'remoteMediaType',
|
||||
'isCaller',
|
||||
'isCallee',
|
||||
'callState',
|
||||
'desktopSharingInstall'
|
||||
]),
|
||||
desktopSharingAlertActions() {
|
||||
var self = this;
|
||||
return [
|
||||
{
|
||||
label: 'Install',
|
||||
handler () {
|
||||
self.$store.commit('call/desktopSharingInstallReset');
|
||||
window.open(getChromeExtensionUrl());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Cancel',
|
||||
handler () {
|
||||
self.$store.commit('call/desktopSharingInstallReset');
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
isPhoneNumberInputEnabled () {
|
||||
return !(this.isDialpadEnabled && this.isMobile);
|
||||
},
|
||||
isDialpadEnabled() {
|
||||
return this.dialpadEnabled && (this.isPreparing || this.isEstablished);
|
||||
},
|
||||
callClasses() {
|
||||
let classes = ['csc-call', 'call-state-' + this.callState];
|
||||
if (this.isFullscreenEnabled) {
|
||||
classes.push('csc-call-fullscreen');
|
||||
}
|
||||
if (this.isMobile) {
|
||||
classes.push('csc-call-mobile');
|
||||
}
|
||||
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: {
|
||||
isEstablished(established) {
|
||||
if(established) {
|
||||
this.dialpadEnabled = false;
|
||||
}
|
||||
},
|
||||
callState(state) {
|
||||
if(state === 'incoming') {
|
||||
showCallNotification(numberFormat(this.getNumber));
|
||||
this.playIncomingSound();
|
||||
}
|
||||
else if (state === 'ringing') {
|
||||
this.playIncomingSound();
|
||||
}
|
||||
else if (state === 'input') {
|
||||
this.stopIncomingSound();
|
||||
if(this.isMobile) {
|
||||
this.dialpadEnabled = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.stopIncomingSound();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" rel="stylesheet/stylus">
|
||||
@import '../themes/quasar.variables.styl';
|
||||
.csc-call
|
||||
position relative
|
||||
z-index 2
|
||||
padding-top 64px
|
||||
height 100%
|
||||
.csc-call-title
|
||||
z-index 11
|
||||
padding 16px
|
||||
color white
|
||||
font-size 16px
|
||||
line-height: 40px
|
||||
.csc-call-top-actions
|
||||
z-index 10
|
||||
padding 16px
|
||||
.csc-phone-number-input
|
||||
position relative
|
||||
z-index 9
|
||||
margin 0
|
||||
padding 16px
|
||||
.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
|
||||
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
|
||||
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>
|
@ -0,0 +1,736 @@
|
||||
<template>
|
||||
<div
|
||||
:class="componentClasses"
|
||||
>
|
||||
<audio
|
||||
ref="callSound"
|
||||
loop
|
||||
playsinline
|
||||
preload="auto"
|
||||
src="statics/ring.mp3"
|
||||
/>
|
||||
<div
|
||||
v-show="isContentVisible"
|
||||
class="csc-call-content"
|
||||
>
|
||||
<div
|
||||
v-if="isInitiating || isRinging || isIncoming || isEnded"
|
||||
class="csc-call-info full-height"
|
||||
>
|
||||
<div
|
||||
class="row justify-center items-center full-height"
|
||||
>
|
||||
<div
|
||||
class="csc-call-info-content col col-md-6 text-center"
|
||||
>
|
||||
<q-spinner-rings
|
||||
v-if="isInitiating || isRinging || isIncoming"
|
||||
class="csc-call-spinner"
|
||||
color="primary"
|
||||
:size="64"
|
||||
/>
|
||||
<div
|
||||
v-if="isInitiating || isRinging || isIncoming"
|
||||
class="csc-phone-number"
|
||||
>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-if="isVideoCall"
|
||||
name="videocam"
|
||||
size="24px"
|
||||
/>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-else
|
||||
name="mic"
|
||||
size="24px"
|
||||
/>
|
||||
<span
|
||||
v-if="isInitiating"
|
||||
>{{ $t('call.initiating', {number: callNumberFormatted}) }}</span>
|
||||
<span
|
||||
v-else-if="isRinging"
|
||||
>{{ $t('call.ringing', {number: callNumberFormatted}) }}</span>
|
||||
<span
|
||||
v-else-if="isIncoming"
|
||||
>{{ $t('call.incoming', {number: callNumberFormatted}) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isEnded"
|
||||
class="csc-call-error"
|
||||
>
|
||||
{{ endedReason | startCase }} ({{callNumberFormatted}})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isEstablished"
|
||||
class="csc-call-info-established"
|
||||
>
|
||||
<div
|
||||
class="row justify-center items-center"
|
||||
>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-if="isVideoCall"
|
||||
name="videocam"
|
||||
size="24px"
|
||||
/>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-else
|
||||
name="mic"
|
||||
size="24px"
|
||||
/>
|
||||
<div
|
||||
>
|
||||
{{ $t('call.established', {number: callNumberFormatted}) }}
|
||||
</div>
|
||||
<q-btn
|
||||
v-if="!dialpadOpened"
|
||||
class="csc-dialpad-button"
|
||||
icon="dialpad"
|
||||
round
|
||||
small
|
||||
@click="toggleDialpad"
|
||||
color="default"
|
||||
/>
|
||||
<q-btn
|
||||
v-else
|
||||
class="csc-dialpad-button"
|
||||
icon="expand_more"
|
||||
round
|
||||
small
|
||||
@click="toggleDialpad"
|
||||
color="default"
|
||||
/>
|
||||
</div>
|
||||
<csc-call-dialpad
|
||||
v-if="dialpadOpened"
|
||||
:show-backspace-button="false"
|
||||
:show-clear-button="false"
|
||||
@click="dialpadClick"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-media-local"
|
||||
>
|
||||
<csc-media
|
||||
v-show="isActive && !minimized && hasLocalVideo"
|
||||
:muted="true"
|
||||
:stream="localMediaStream"
|
||||
fit="width"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-show="isEstablished && !(isMobile && minimized)"
|
||||
class="csc-call-media-remote transition-generic"
|
||||
>
|
||||
<div
|
||||
v-show="!hasRemoteVideo && !minimized"
|
||||
class="csc-call-media-icon row justify-center items-center full-height"
|
||||
>
|
||||
<q-icon
|
||||
name="person"
|
||||
size="128px"
|
||||
color="white"
|
||||
/>
|
||||
</div>
|
||||
<csc-media
|
||||
v-show="hasRemoteVideo || minimized"
|
||||
:muted="!remoteVolumeEnabled"
|
||||
:stream="remoteMediaStream"
|
||||
:fit="remoteMediaFit"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-content-minimized transition-generic"
|
||||
@click="maximizeMobile"
|
||||
>
|
||||
<div
|
||||
class="csc-call-actions row justify-center"
|
||||
>
|
||||
<q-btn
|
||||
v-if="isEstablished && !(isMobile && minimized)"
|
||||
class="csc-call-button"
|
||||
:color="colorToggleMicrophone"
|
||||
:icon="iconToggleMicrophone"
|
||||
round
|
||||
@click="toggleMicrophone()"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEstablished && hasLocalVideo && !(isMobile && minimized)"
|
||||
class="csc-call-button"
|
||||
:color="colorToggleCamera"
|
||||
:icon="iconToggleCamera"
|
||||
round
|
||||
@click="toggleCamera()"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isEstablished && !(isMobile && minimized)"
|
||||
class="csc-call-button"
|
||||
:color="colorToggleRemoteVolume"
|
||||
:icon="iconToggleRemoteVolume"
|
||||
round
|
||||
@click="toggleRemoteVolume()"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="isActive"
|
||||
class="csc-call-button"
|
||||
color="negative"
|
||||
icon="call_end"
|
||||
round
|
||||
@click="endCall"
|
||||
/>
|
||||
<q-btn
|
||||
v-if="canClose"
|
||||
class="csc-call-button"
|
||||
color="negative"
|
||||
icon="clear"
|
||||
round
|
||||
@click="closeCall()"
|
||||
/>
|
||||
<q-fab
|
||||
ref="startButton"
|
||||
v-if="canStart"
|
||||
class="csc-call-button"
|
||||
color="primary"
|
||||
icon="call"
|
||||
direction="up"
|
||||
>
|
||||
<q-fab-action
|
||||
v-if="!isMobile"
|
||||
color="primary"
|
||||
icon="computer"
|
||||
@click="startCall('audioScreen')"
|
||||
/>
|
||||
<q-fab-action
|
||||
color="primary"
|
||||
icon="videocam"
|
||||
@click="startCall('audioVideo')"
|
||||
/>
|
||||
<q-fab-action
|
||||
color="primary"
|
||||
icon="mic"
|
||||
@click="startCall('audioOnly')"
|
||||
/>
|
||||
</q-fab>
|
||||
</div>
|
||||
<div
|
||||
v-if="minimized"
|
||||
class="csc-call-info-minimized"
|
||||
>
|
||||
<div
|
||||
v-if="isCalling"
|
||||
class="csc-call-info-loading"
|
||||
>
|
||||
<q-spinner-rings
|
||||
class="csc-call-spinner"
|
||||
color="primary"
|
||||
size="64px"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-info-icon"
|
||||
>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-if="isActive && isVideoCall"
|
||||
name="videocam"
|
||||
size="24px"
|
||||
color="white"
|
||||
/>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-else-if="isActive"
|
||||
name="mic"
|
||||
size="24px"
|
||||
color="white"
|
||||
/>
|
||||
<q-icon
|
||||
class="csc-media-icon"
|
||||
v-else-if="isEnded"
|
||||
name="error"
|
||||
size="24px"
|
||||
color="white"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-if="isActive"
|
||||
class="csc-call-info-text"
|
||||
>
|
||||
<div
|
||||
v-if="isActive"
|
||||
>
|
||||
<div
|
||||
class="csc-call-info-phrase"
|
||||
>
|
||||
{{ $t('call.' + callState + 'Short') }}
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-info-number"
|
||||
>
|
||||
{{ callNumberFormatted }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="isEnded"
|
||||
class="csc-call-info-text csc-call-error"
|
||||
>
|
||||
<div
|
||||
class="csc-call-info-phrase"
|
||||
>
|
||||
{{ endedReason | startCase }}
|
||||
</div>
|
||||
<div
|
||||
class="csc-call-info-number"
|
||||
>
|
||||
{{ callNumberFormatted }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<q-btn
|
||||
class="csc-call-btn-fullscreen"
|
||||
v-if="isEstablished && minimized && !isMobile"
|
||||
icon="fullscreen"
|
||||
round
|
||||
color="default"
|
||||
@click="maximize"
|
||||
/>
|
||||
<q-btn
|
||||
class="csc-call-btn-fullscreen-small"
|
||||
v-else-if="isEstablished && maximizable && !isMobile"
|
||||
icon="fullscreen_exit"
|
||||
round
|
||||
small
|
||||
color="default"
|
||||
@click="minimize"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import platformMixin from '../../mixins/platform'
|
||||
import numberFormat from '../../filters/number-format'
|
||||
import {
|
||||
showCallNotification
|
||||
} from '../../helpers/ui'
|
||||
import {
|
||||
normalizeDestination
|
||||
} from '../../filters/number-format'
|
||||
import {
|
||||
QFab,
|
||||
QFabAction,
|
||||
QBtn,
|
||||
QSpinnerRings,
|
||||
QIcon
|
||||
} from 'quasar-framework'
|
||||
import CscMedia from '../CscMedia'
|
||||
import CscCallDialpad from "../CscCallDialpad";
|
||||
export default {
|
||||
name: 'csc-call',
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
mixins: [
|
||||
platformMixin
|
||||
],
|
||||
props: [
|
||||
'callState',
|
||||
'callNumber',
|
||||
'endedReason',
|
||||
'fullView',
|
||||
'localMediaStream',
|
||||
'remoteMediaStream',
|
||||
'minimized',
|
||||
'closed',
|
||||
'isVideoCall',
|
||||
'hasLocalVideo',
|
||||
'hasRemoteVideo',
|
||||
'microphoneEnabled',
|
||||
'cameraEnabled',
|
||||
'remoteVolumeEnabled',
|
||||
'maximizable',
|
||||
'dialpadOpened'
|
||||
],
|
||||
components: {
|
||||
CscCallDialpad,
|
||||
QFab,
|
||||
QFabAction,
|
||||
QBtn,
|
||||
CscMedia,
|
||||
QSpinnerRings,
|
||||
QIcon
|
||||
},
|
||||
computed: {
|
||||
remoteMediaFit() {
|
||||
if(this.minimized) {
|
||||
return 'width';
|
||||
}
|
||||
else {
|
||||
return 'full';
|
||||
}
|
||||
},
|
||||
componentClasses() {
|
||||
let classes = [
|
||||
'transition-generic',
|
||||
'csc-call',
|
||||
'csc-call-' + this.callState
|
||||
];
|
||||
if(this.fullView) {
|
||||
classes.push('csc-call-full-width');
|
||||
}
|
||||
if(this.minimized) {
|
||||
classes.push('csc-call-minimized');
|
||||
}
|
||||
if(this.isVideoCall) {
|
||||
classes.push('csc-call-video');
|
||||
}
|
||||
if(this.isMobile) {
|
||||
classes.push('csc-call-mobile');
|
||||
}
|
||||
return classes;
|
||||
},
|
||||
isCalling() {
|
||||
return this.isInitiating || this.isRinging || this.isIncoming;
|
||||
},
|
||||
isActive() {
|
||||
return this.isCalling || this.isEstablished;
|
||||
},
|
||||
isInitiating() {
|
||||
return this.callState === 'initiating';
|
||||
},
|
||||
isRinging() {
|
||||
return this.callState === 'ringing';
|
||||
},
|
||||
isEstablished() {
|
||||
return this.callState === 'established';
|
||||
},
|
||||
isIncoming() {
|
||||
return this.callState === 'incoming';
|
||||
},
|
||||
isEnded() {
|
||||
return this.callState === 'ended';
|
||||
},
|
||||
canStart() {
|
||||
return this.callState === 'input' || this.callState === 'incoming';
|
||||
},
|
||||
canClose() {
|
||||
return this.callState === 'ended';
|
||||
},
|
||||
callNumberFormatted() {
|
||||
return normalizeDestination(this.callNumber);
|
||||
},
|
||||
isContentVisible() {
|
||||
return (!this.minimized && (this.isInitiating ||
|
||||
this.isRinging || this.isIncoming ||
|
||||
this.isEnded || this.isEstablished));
|
||||
},
|
||||
iconToggleMicrophone() {
|
||||
if(this.microphoneEnabled) {
|
||||
return 'mic';
|
||||
}
|
||||
else {
|
||||
return 'mic_off';
|
||||
}
|
||||
},
|
||||
colorToggleMicrophone() {
|
||||
if(this.microphoneEnabled) {
|
||||
return 'primary';
|
||||
}
|
||||
else {
|
||||
return 'faded';
|
||||
}
|
||||
},
|
||||
iconToggleCamera() {
|
||||
if(this.cameraEnabled) {
|
||||
return 'videocam';
|
||||
}
|
||||
else {
|
||||
return 'videocam_off';
|
||||
}
|
||||
},
|
||||
colorToggleCamera() {
|
||||
if(this.cameraEnabled) {
|
||||
return 'primary';
|
||||
}
|
||||
else {
|
||||
return 'faded';
|
||||
}
|
||||
},
|
||||
iconToggleRemoteVolume() {
|
||||
if(this.remoteVolumeEnabled) {
|
||||
return 'volume_up';
|
||||
}
|
||||
else {
|
||||
return 'volume_off';
|
||||
}
|
||||
},
|
||||
colorToggleRemoteVolume() {
|
||||
if(this.remoteVolumeEnabled) {
|
||||
return 'primary';
|
||||
}
|
||||
else {
|
||||
return 'faded';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
startCall(media) {
|
||||
if(this.callState === 'input') {
|
||||
this.$emit('start-call', media);
|
||||
}
|
||||
else if(this.callState === 'incoming') {
|
||||
this.$emit('accept-call', media);
|
||||
}
|
||||
},
|
||||
endCall(event) {
|
||||
event.stopPropagation();
|
||||
this.$emit('end-call');
|
||||
},
|
||||
closeCall() {
|
||||
this.$emit('close-call');
|
||||
},
|
||||
playCallSound() {
|
||||
this.$refs.callSound.play();
|
||||
},
|
||||
stopCallSound() {
|
||||
this.$refs.callSound.pause();
|
||||
},
|
||||
toggleDialpad() {
|
||||
this.$emit('toggle-dialpad');
|
||||
},
|
||||
toggleMicrophone() {
|
||||
this.$emit('toggle-microphone');
|
||||
},
|
||||
toggleCamera() {
|
||||
this.$emit('toggle-camera');
|
||||
},
|
||||
toggleRemoteVolume() {
|
||||
this.$emit('toggle-remote-volume');
|
||||
},
|
||||
dialpadClick(value) {
|
||||
this.$emit('click-dialpad', value);
|
||||
},
|
||||
maximize() {
|
||||
this.$emit('maximize-call');
|
||||
},
|
||||
minimize() {
|
||||
this.$emit('minimize-call');
|
||||
},
|
||||
maximizeMobile() {
|
||||
if(this.isMobile && this.isEstablished) {
|
||||
this.maximize();
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
callState(state) {
|
||||
if(state === 'ringing' || state === 'incoming') {
|
||||
this.playCallSound();
|
||||
if(state === 'incoming') {
|
||||
showCallNotification(numberFormat(this.callNumber));
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.stopCallSound();
|
||||
}
|
||||
},
|
||||
closed(closed) {
|
||||
if(closed && this.$refs.startButton) {
|
||||
this.$refs.startButton.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" rel="stylesheet/stylus">
|
||||
@import '../../themes/quasar.variables'
|
||||
$call-footer-height = $toolbar-min-height
|
||||
$call-footer-height-big = $call-footer-height * 2
|
||||
$call-footer-action-margin = 27px
|
||||
$call-footer-height-mobile = $call-footer-height * 1.4
|
||||
.csc-call
|
||||
left $layout-aside-left-width
|
||||
top $call-footer-height
|
||||
position fixed
|
||||
bottom 0
|
||||
right 0
|
||||
z-index 40
|
||||
.q-btn.q-btn-round
|
||||
box-shadow none
|
||||
.csc-call-content
|
||||
position absolute
|
||||
bottom $call-footer-height
|
||||
top 0
|
||||
right 0
|
||||
left 0
|
||||
z-index 2
|
||||
background-color white
|
||||
.csc-call-info
|
||||
.csc-call-info-content
|
||||
margin-top -80px
|
||||
.csc-call-error
|
||||
color $negative
|
||||
.csc-call-spinner
|
||||
margin-bottom $flex-gutter-sm
|
||||
.csc-call-media-local
|
||||
position absolute
|
||||
bottom $flex-gutter-sm
|
||||
left $flex-gutter-sm
|
||||
width 20%
|
||||
height auto
|
||||
overflow hidden
|
||||
z-index 2
|
||||
font-size 0
|
||||
.csc-call-info-established
|
||||
position absolute
|
||||
bottom $call-footer-action-margin * 2
|
||||
right 0
|
||||
left 0
|
||||
justify-items center
|
||||
z-index 3
|
||||
color white
|
||||
.csc-media-icon
|
||||
margin-right $flex-gutter-xs
|
||||
.csc-dialpad-button
|
||||
vertical-align center
|
||||
margin-left $flex-gutter-sm
|
||||
.csc-call-media-remote
|
||||
position absolute
|
||||
top 0
|
||||
bottom $call-footer-height
|
||||
right 0
|
||||
left 0
|
||||
z-index 1
|
||||
background-color black
|
||||
font-size 0
|
||||
.csc-call-media-icon
|
||||
opacity 0.5
|
||||
.csc-call-content-minimized
|
||||
position absolute
|
||||
bottom 0
|
||||
left 0
|
||||
right 0
|
||||
height $call-footer-height
|
||||
background-color $secondary
|
||||
z-index 3
|
||||
display flex
|
||||
flex-wrap no-wrap
|
||||
align-items center
|
||||
justify-content center
|
||||
.csc-call-info-minimized
|
||||
display flex
|
||||
flex-wrap no-wrap
|
||||
align-items center
|
||||
margin-bottom -16px
|
||||
.csc-call-info-text
|
||||
color white
|
||||
padding-left $flex-gutter-xs
|
||||
.csc-call-info-phrase
|
||||
margin-bottom 4px
|
||||
.csc-call-info-number
|
||||
font-size 14px
|
||||
.csc-call-info-loading
|
||||
margin-right $flex-gutter-sm
|
||||
.csc-call-btn-fullscreen
|
||||
position absolute
|
||||
right $flex-gutter-md
|
||||
top 50%
|
||||
bottom 50%
|
||||
margin-top -27px
|
||||
.csc-call-btn-fullscreen-small
|
||||
position absolute
|
||||
right $flex-gutter-sm
|
||||
top 50%
|
||||
bottom 50%
|
||||
margin-top -20px
|
||||
.csc-call-actions
|
||||
position absolute
|
||||
left 0
|
||||
right 0
|
||||
top 0
|
||||
margin-top -27px
|
||||
.q-btn.q-btn-round
|
||||
box-shadow none
|
||||
.csc-call-button
|
||||
margin-right $flex-gutter-sm
|
||||
.csc-call-button:last-child
|
||||
margin-right 0
|
||||
.csc-phone-number
|
||||
color white
|
||||
text-align center
|
||||
.csc-call.csc-call-input
|
||||
top auto
|
||||
.csc-call.csc-call-established
|
||||
.csc-call-content
|
||||
background-color transparent
|
||||
.csc-call.csc-call-minimized
|
||||
height $call-footer-height-big
|
||||
top auto
|
||||
bottom ($call-footer-height-big + $call-footer-action-margin) * -1
|
||||
.csc-call-media-remote
|
||||
top auto
|
||||
bottom $call-footer-height-big + $flex-gutter-sm
|
||||
right $flex-gutter-sm
|
||||
left auto
|
||||
height auto
|
||||
width 20%
|
||||
z-index 1
|
||||
font-size 0
|
||||
.csc-call-content-minimized
|
||||
height $call-footer-height-big
|
||||
.csc-call-actions
|
||||
margin-bottom $call-footer-action-margin
|
||||
.csc-call.csc-call-minimized.csc-call-incoming,
|
||||
.csc-call.csc-call-minimized.csc-call-initiating,
|
||||
.csc-call.csc-call-minimized.csc-call-ringing
|
||||
.csc-call-actions
|
||||
margin-bottom 8px
|
||||
.csc-call.csc-call-minimized.csc-call-incoming,
|
||||
.csc-call.csc-call-minimized.csc-call-initiating,
|
||||
.csc-call.csc-call-minimized.csc-call-ringing,
|
||||
.csc-call.csc-call-minimized.csc-call-established,
|
||||
.csc-call.csc-call-minimized.csc-call-ended
|
||||
bottom 0
|
||||
.csc-call.csc-call-full-width
|
||||
left 0
|
||||
.csc-call.csc-call-mobile
|
||||
.csc-call-content
|
||||
.csc-call-media-local
|
||||
font-size 0
|
||||
top $flex-gutter-sm
|
||||
left $flex-gutter-sm
|
||||
bottom auto
|
||||
width 30%
|
||||
height auto
|
||||
overflow hidden
|
||||
.csc-call.csc-call-mobile.csc-call-minimized
|
||||
.csc-call-content-minimized
|
||||
height $call-footer-height-big
|
||||
.csc-call.csc-call-mobile.csc-call-minimized.csc-call-ended,
|
||||
.csc-call.csc-call-mobile.csc-call-minimized.csc-call-established
|
||||
.csc-call-content-minimized
|
||||
height $call-footer-height * 1.4
|
||||
justify-content left
|
||||
padding-left $flex-gutter-sm
|
||||
.csc-call-info-minimized
|
||||
margin-bottom 0
|
||||
.csc-call-actions
|
||||
position absolute
|
||||
margin auto
|
||||
margin-top -27px
|
||||
top 50%
|
||||
right $flex-gutter-sm
|
||||
left auto
|
||||
.csc-call-button
|
||||
margin-right $flex-gutter-sm
|
||||
.csc-call-button:last-child
|
||||
margin-right 0
|
||||
|
||||
</style>
|
@ -1,10 +1,18 @@
|
||||
|
||||
const userInfoRegExp = new RegExp(/^[-_.!~*'&=+$,;?/%a-zA-Z0-9]+$/);
|
||||
const macAddressRegExp = new RegExp(/^(?:[0-9A-Fa-f]{2}(?=([-:]|))(?:\1[0-9A-Fa-f]{2}){5})$/);
|
||||
|
||||
export function userInfo (value) {
|
||||
var regex = new RegExp(/^[-_.!~*'&=+$,;?/%a-zA-Z0-9]+$/);
|
||||
return regex.test(value);
|
||||
return userInfoRegExp.test(value);
|
||||
}
|
||||
|
||||
export function userInfoAndEmpty(value) {
|
||||
if(value === '') {
|
||||
return true;
|
||||
}
|
||||
return userInfo(value);
|
||||
}
|
||||
|
||||
export function customMacAddress (value) {
|
||||
var regex = new RegExp(/^(?:(?:[0-9A-Fa-f]{2}(?=([-:]|))(?:\1[0-9A-Fa-f]{2}){5}))$/);
|
||||
return regex.test(value);
|
||||
return macAddressRegExp.test(value);
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
sides: {
|
||||
left: true,
|
||||
right: false
|
||||
},
|
||||
fullscreenEnabled: false
|
||||
},
|
||||
getters: {
|
||||
right(state) {
|
||||
return state.sides.right;
|
||||
},
|
||||
left(state) {
|
||||
return state.sides.left;
|
||||
},
|
||||
isFullscreenEnabled(state) {
|
||||
return state.fullscreenEnabled;
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
updateSides(state, sides) {
|
||||
state.sides = sides;
|
||||
},
|
||||
showRight(state) {
|
||||
state.sides.right = true;
|
||||
},
|
||||
hideRight(state){
|
||||
state.sides.right = false;
|
||||
},
|
||||
showLeft(state){
|
||||
state.sides.left = true;
|
||||
},
|
||||
hideLeft(state){
|
||||
state.sides.left = false;
|
||||
},
|
||||
toggleFullscreen(state) {
|
||||
state.fullscreenEnabled = !state.fullscreenEnabled;
|
||||
},
|
||||
enableFullscreen(state) {
|
||||
state.fullscreenEnabled = true;
|
||||
},
|
||||
disableFullscreen(state) {
|
||||
state.fullscreenEnabled = false;
|
||||
}
|
||||
},
|
||||
actions: {}
|
||||
};
|
Loading…
Reference in new issue