123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488 |
- <?php /** @var $client */ ?>
- @extends('layouts.meeting')
- @section('content')
- <style>
- .meeting-pre-content {
- width: 800px;
- }
- .meeting-pre-content .covid-campaign-heading {
- font-size: 1.5rem;
- font-weight: bold;
- }
- .meeting-pre-content .covid-campaign-matter {
- font-size: 1.1rem;
- margin-top: 1rem;
- line-height: 1.5;
- }
- </style>
- <div id="clientCallComponent">
- <div class="d-flex align-items-center py-3 border-bottom px-4">
- <span class="mr-auto">
- Hello {{ $client->name_last }}, {{ $client->name_first }}
- </span>
- <a href="#" class="client-logout">Log Out</a>
- </div>
- <div class="">
- <div class="py-3 text-center" v-if="started">
- <h6 class="text-black font-weight-bold m-0">Call in progress: @{{ timeDisplay() }}</h6>
- </div>
- <div class="py-3 text-center mx-auto alert alert-secondary meeting-pre-content" v-if="noOneElseInCall">
- <!-- <h6 class="text-black font-weight-bold m-0">A pro may pop in here at the next chance. Please wait..</h6> -->
- <h2 class="covid-campaign-heading">Free COVID-19 Safety Kit & Coaching Session.</h2>
- <h2 class="covid-campaign-matter">A coach will be with you shortly. This call will last approximately
- 10 minutes.</h2>
- <h3 class="covid-campaign-matter">Upon the conclusion of this call, the coach will verify your mailing
- address to mail you your kit. Please note that PO Boxes are not deliverable
- by FedEx.</h3>
- </div>
- <div class="main-view mx-auto">
- <div class="thumbs">
- <div id="self-view" class="thumb-view disconnected-view"
- data-name="{{ implode(" ", [$client->name_first, $client->name_last]) }}"
- data-type="CLIENT"></div>
- </div>
- <?php /* <button class="btn btn-danger rounded-circle hang-up"
- v-if="started"
- title="Leave Call"
- v-on:click.prevent="hangUp()">
- <i class="fa fa-phone"></i>
- </button> */ ?>
- </div>
- </div>
- <div class="d-flex justify-content-center mt-3">
- <button v-if="readyToPublish && !publishing"
- class="btn btn-sm btn-primary font-weight-bold"
- v-on:click.prevent="cameraOn()">Start My Camera</button>
- <button v-if="readyToPublish && publishing"
- class="btn btn-sm btn-danger font-weight-bold"
- v-on:click.prevent="cameraOff()">Stop My Camera</button>
- </div>
- </div>
- <script>
- window.clientCallComponent = new Vue({
- el: '#clientCallComponent',
- delimiters: ['@{{', '}}'],
- data: {
- mdPass: true, // set this to true if client has all medicare reqs met
- time: 0,
- startTime: 0,
- started: false,
- client: false,
- pro: false,
- selfName: '',
- selfToken: '',
- clientUid: '{{ $client->uid }}',
- checkInToken: '',
- otSessionId: '{{ $client->opentok_session_id }}',
- otSession: false,
- publisher: false,
- readyToPublish: false,
- publishing: false,
- selfUserType: 'CLIENT',
- selfStreamId: '',
- noOneElseInCall: true,
- heartbeatTimer: false,
- },
- methods: {
- timeDisplay: function() {
- var seconds = this.time / 1000,
- minutes = parseInt(seconds / 60, 10);
- seconds = parseInt(seconds % 60, 10);
- return minutes + " min, " + seconds + " sec";
- },
- hangUp: function() {
- if(this.otSession) {
- try {
- this.otSession.disconnect();
- }
- catch (e) {
- console.log('Was already disconnected.');
- }
- this.otSession = false;
- this.otSessionId = '';
- this.started = false;
- this.startTime = false;
- // window.location = '/join';
- }
- },
- initOpenTok: function() {
- /* fake video feed (temp) */
- const canvas = document.createElement('canvas');
- canvas.width = 640;
- canvas.height = 480;
- const ctx = canvas.getContext('2d');
- var pos = 100;
- window.setInterval(function() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- ctx.font = "20px Georgia";
- ctx.fillStyle = `rgb(220, 220, 220)`;
- ctx.fillText("Video feed from {{ $client->name_first }}", 20, pos);
- pos += 5;
- if(pos > canvas.height) pos = 100;
- }, 1000);
- var self = this;
- var apiKey = '<?= config('stag.tokboxApiKey') ?>';
- var sessionId = this.otSessionId;
- var token = this.selfToken;
- // destroy if existing
- // self.hangUp();
- self.otSession = OT.initSession(apiKey, sessionId);
- // peer connected
- self.otSession.on('streamCreated', function streamCreated(event) {
- console.log('session->streamCreated', arguments);
- var subscriberOptions = {
- insertMode: 'append',
- width: '100%',
- height: '100%'
- };
- var connectionData = JSON.parse(event.stream.connection.data);
- // add a div for remove view
- var remoteViewID = 'remote-view-' + event.stream.id;
- var remoteElem = $('<div id="' + remoteViewID + '" class="remote-view thumb-view" ' +
- 'data-stream="' + event.stream.id + '" ' +
- 'data-connection-data="' + event.stream.connection.data + '" ' +
- 'data-name="' + connectionData.name + '" ' +
- 'data-type="' + connectionData.type + '"></div>');
- remoteElem.appendTo('.thumbs');
- self.otSession.subscribe(event.stream, remoteViewID, subscriberOptions, self.handleOpenTokError_Subscribe);
- if (connectionData.type === 'PRO') {
- self.pro = true;
- }
- self.activateParty(event.stream.id);
- self.noOneElseInCall = false;
- });
- // peer disconnected
- self.otSession.on("streamDestroyed", function(event) {
- onPeerDisconnection(event, event.stream.connection.data);
- });
- // self.otSession.on("connectionDestroyed", function(event) {
- // debugger;
- // console.log('connectionDestroyed from ' + event.connection.data);
- // onPeerDisconnection(event, event.connection.data);
- // });
- function onPeerDisconnection(event, data) {
- console.log('onPeerDisconnection');
- if(event.stream && $('.full-view[data-stream="' + event.stream.id + '"]').length) {
- var allThumbs = $('.thumbs [data-stream]:not([data-stream=""]):not(.disconnected-view):visible');
- if(allThumbs.length) {
- $('.thumbs [data-stream]:not([data-stream=""])').each(function() {
- if($(this).attr('data-stream') !== event.stream.id) {
- self.activateParty($(this).attr('data-stream'));
- return false;
- }
- });
- }
- }
- if(event.stream) {
- var remoteViewElem = $('[data-stream="' + event.stream.id + '"]');
- remoteViewElem.remove();
- // if(remoteViewElem.length) {
- // remoteViewElem.attr('data-stream', '');
- // remoteViewElem.attr('data-connection-data', '');
- // remoteViewElem.attr('data-type', '');
- // remoteViewElem.attr('data-name', '');
- // }
- // remoteViewElem.addClass('disconnected-view')
- }
- // if no other parties in call, hang up
- if(!$('[data-stream]:not([data-stream="' + self.selfStreamId + '"])').length) {
- // self.hangUp();
- console.warn('No other parties in the call!');
- // new Noty({
- // theme: 'mint',
- // type: 'info',
- // text: 'All other participants have left the call',
- // progressBar: false,
- // timeout: 2500,
- // }).show();
- self.startTime = 0;
- self.started = false;
- self.noOneElseInCall = true;
- }
- }
- // self disconnected
- self.otSession.on('sessionDisconnected', function sessionDisconnected(event) {
- console.log('You were disconnected from the session.', event.reason);
- // turn client video off
- $.post('/api/clientVideoVisit/turnClientVideoOff', {}, function(_data) {
- console.log(_data);
- });
- // in case of accidental disconnection
- self.initOpenTok();
- });
- // initialize the publisher
- var publisherOptions = {
- //videoSource: canvas.captureStream(1).getVideoTracks()[0], // TODO: Comment this line to use webcam
- insertMode: 'append',
- width: '100%',
- height: '100%',
- };
- self.publisher = OT.initPublisher('self-view', publisherOptions, self.handleOpenTokError_InitPublisher);
- self.publisher.on('streamCreated', function(event) {
- console.log('publisher->streamCreated');
- var selfView = $('#self-view');
- selfView.attr('data-stream', event.stream.id);
- selfView.attr('data-type', 'CLIENT');
- self.selfStreamId = event.stream.id;
- self.activateParty('self');
- $('#self-view').show();
- self.startTime = new Date().getTime();
- window.setInterval(function() {
- self.time = new Date().getTime() - self.startTime;
- }, 1000);
- self.started = true;
- // turn client video on
- $.post('/api/clientVideoVisit/turnClientVideoOn', {}, function(_data) {
- console.log(_data);
- });
- });
- self.publisher.on('streamDestroyed', function(event) {
- event.preventDefault();
- console.log('publisher->streamDestroyed');
- $('#self-view').hide();
- var allThumbs = $('.thumbs [data-stream]:not([data-stream=""]):visible');
- if(allThumbs.length) {
- $('.thumbs [data-stream]:not([data-stream=""])').each(function() {
- if($(this).attr('data-stream') !== $('#self-view').attr('data-stream')) {
- self.activateParty($(this).attr('data-stream'));
- return false;
- }
- });
- }
- // turn client video off
- $.post('/api/clientVideoVisit/turnClientVideoOff', {}, function(_data) {
- console.log(_data);
- });
- });
- // Connect to the session
- self.otSession.connect(token, function callback(error) {
- if (error) {
- self.handleOpenTokError_SessionConnect(error);
- } else {
- console.info('Connected to OT session :)');
- self.readyToPublish = true;
- // auto start client video
- self.cameraOn();
- }
- });
- },
- cameraOn: function() {
- if(this.readyToPublish) {
- this.otSession.publish(this.publisher, this.handleOpenTokError_Publish);
- this.publishing = true;
- }
- },
- cameraOff: function() {
- this.otSession.unpublish(this.publisher);
- this.publishing = false;
- },
- handleOpenTokError_SessionConnect: function(e) {
- console.log('handleOpenTokError_SessionConnect');
- console.log(e);
- },
- handleOpenTokError_Publish: function(e) {
- console.log('handleOpenTokError_Publish');
- console.log(e);
- },
- handleOpenTokError_Subscribe: function(e) {
- console.log('handleOpenTokError_Subscribe');
- console.log(e);
- },
- handleOpenTokError_InitPublisher: function(e) {
- console.log('handleOpenTokError_InitPublisher');
- console.log(e);
- },
- getClientCheckinToken: function(_done) {
- var self = this;
- $.get('/get-client-checkin-token/' + this.clientUid, function(_data) {
- console.log(_data);
- self.checkInToken = _data.data;
- _done();
- }, 'json');
- },
- getOpenTokSessionId: function(_done) {
- var self = this;
- $.ajax({
- type: 'post',
- url: '/api/clientVideoVisit/startVideoVisitAsClient',
- headers: {
- 'sessionKey': '{{ request()->cookie('sessionKey') }}'
- },
- data: {checkInToken: this.checkInToken},
- dataType: 'json'
- })
- .done(function (_data) {
- console.log(_data);
- if(_data.success) {
- self.otSessionId = _data.data;
- _done();
- }
- else {
- alert(_data.message);
- }
- })
- .fail(function (_data) {
- console.log(_data);
- alert(_data.message);
- });
- },
- activateParty: function(_stream = 'self') {
- var current = $('.full-view');
- if(current.attr('data-stream') === _stream) return;
- current.removeClass('full-view').addClass('thumb-view');
- if(current.attr('data-type') === 'CLIENT') {
- current.prependTo('.thumbs');
- }
- else {
- current.appendTo('.thumbs');
- }
- if(_stream === 'self') {
- $('#self-view')
- .removeClass('thumb-view')
- .removeClass('disconnected-view')
- .addClass('full-view')
- .prependTo('.main-view');
- }
- else {
- $('div[data-stream="' + _stream + '"]')
- .removeClass('thumb-view')
- .removeClass('disconnected-view')
- .addClass('full-view')
- .prependTo('.main-view');
- }
- }
- },
- mounted: function() {
- var self = this;
- this.getClientCheckinToken(function() { // get client check-in token
- self.getOpenTokSessionId(function() { // get opentok session id
- var name = [];
- @if (!empty($client->name_first)) name.push("{{ $client->name_first }}"); @endif
- @if (!empty($client->name_last)) name.push("{{ $client->name_last }}"); @endif
- self.selfName = name.join(' ');
- $.ajax({
- type: 'post',
- url: '/api/openTok/getClientToken',
- headers: {
- 'sessionKey': '{{ request()->cookie('sessionKey') }}'
- },
- data: {
- opentokSessionId: self.otSessionId,
- data: JSON.stringify({
- uid: '{{ $client->uid }}',
- name: self.selfName,
- type: 'CLIENT'
- })
- },
- dataType: 'json'
- })
- .done(function (_data) {
- console.log(_data);
- self.selfToken = _data.data;
- self.initOpenTok();
- })
- .fail(function (_data) {
- console.warn(_data);
- alert(_data.message);
- });
- });
- });
- $(document).on('click', '.thumbs>div[data-stream]', function() {
- self.activateParty($(this).attr('data-stream'));
- return false;
- });
- window.onbeforeunload = function() {
- if(self.started) {
- return "A call is in progress";
- }
- };
- $(document).on('click', '.client-logout', function() {
- // turn client video off
- $.post('/api/clientVideoVisit/turnClientVideoOff', {}, function(_data) {
- console.log(_data);
- // log out
- $.get("/api/session/logOut", function(_data) {
- console.log(_data);
- window.location = '/join';
- })
- });
- return false;
- });
- // start heart beat
- self.heartbeatTimer = window.setInterval(function() {
- $.post('/api/clientVideoVisit/registerClientVideoHeartbeat', {}, function(_data) {
- console.log(_data);
- });
- }, 5000);
- }
- });
- </script>
- @endsection
|