|
@@ -0,0 +1,391 @@
|
|
|
|
+@extends ('layouts.company-client-layout')
|
|
|
|
+@section('company-client-content')
|
|
|
|
+ <script src="https://static.opentok.com/v2/js/opentok.min.js"></script>
|
|
|
|
+ <link rel="stylesheet" href="{{ asset('css/messages.css') }}">
|
|
|
|
+ <div class="">
|
|
|
|
+ <div class="d-flex align-items-center pb-2">
|
|
|
|
+ <h4 class="font-weight-bold m-0 mr-3">Messages</h4>
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <div class="card-body p-0 shadow-sm h-100">
|
|
|
|
+ <div class="im-container">
|
|
|
|
+ <div class="im-rhs p-2">
|
|
|
|
+ @if ($regardingClient)
|
|
|
|
+ @if (!$messages || !count($messages))
|
|
|
|
+ <div class="py-4 text-center text-secondary">
|
|
|
|
+ <h3 class="mb-0"><i class="far fa-comment-dots"></i></h3>
|
|
|
|
+ No messages yet!
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ <div class="im-messages">
|
|
|
|
+ <div class="mh-100 overflow-auto opacity-0" id="im-scroller">
|
|
|
|
+ <?php $messageDates = []; ?>
|
|
|
|
+ @foreach ($messages as $k => $message)
|
|
|
|
+ @if (!in_array(friendly_date($message->created_at), $messageDates))
|
|
|
|
+ <?php array_push($messageDates, friendly_date($message->created_at)); ?>
|
|
|
|
+ <div class="text-center my-4">
|
|
|
|
+ <span style="background:#c2efff"
|
|
|
|
+ class="py-1 px-3 text-secondary rounded text-sm">{{ friendly_date($message->created_at) }}</span>
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ <div class="d-flex align-items-start">
|
|
|
|
+ @if ($message->from_pro_id !== $performer->pro->id)
|
|
|
|
+ <div class="">
|
|
|
|
+ @if (!$message->is_removed)
|
|
|
|
+ @if ($k == 0 || $messages[$k - 1]->from_pro_id !== $messages[$k]->from_pro_id)
|
|
|
|
+ <!-- remove unecessary timestamps -->
|
|
|
|
+ <div class="circle-icon">
|
|
|
|
+ @if ($message->fromPro)
|
|
|
|
+ {{ mb_substr($message->fromPro->name_first, 0, 1) }}
|
|
|
|
+ @else
|
|
|
|
+ {{ mb_substr($message->regardingClient->name_first ?? '', 0, 1) }}
|
|
|
|
+ @endif
|
|
|
|
+ </div>
|
|
|
|
+ @else
|
|
|
|
+ <div class="circle-icon op">
|
|
|
|
+ @if ($message->fromPro)
|
|
|
|
+ {{ mb_substr($message->fromPro->name_first, 0, 1) }}
|
|
|
|
+ @else
|
|
|
|
+ {{ mb_substr($message->regardingClient->name_first ?? '', 0, 1) }}
|
|
|
|
+ @endif
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ @endif
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ <div class="w-100">
|
|
|
|
+ <div class="im-message mt-0 pr-5 {{ $message->from_pro_id === $performer->pro->id ? 'sent' : 'received' }}"
|
|
|
|
+ data-uid="{{ $message->uid }}"
|
|
|
|
+ data-mark-as-read="{{ $message->is_to_shadow_client && !$message->is_read ? 1 : 0 }}">
|
|
|
|
+ <div class="im-message-sender align-items-center">
|
|
|
|
+ @if (!$message->is_removed)
|
|
|
|
+ @if ($k == 0 || $messages[$k - 1]->from_pro_id !== $messages[$k]->from_pro_id)
|
|
|
|
+ <!-- remove unecessary timestamps -->
|
|
|
|
+ @if ($message->from_pro_id !== $performer->pro->id)
|
|
|
|
+ @if ($message->fromPro)
|
|
|
|
+ <small
|
|
|
|
+ class="mr-2 text-secondary">{{ $message->fromPro->displayName() }},</small>
|
|
|
|
+ @else
|
|
|
|
+ <small
|
|
|
|
+ class="mr-2 text-secondary">{{ $message->regardingClient->displayName() }},</small>
|
|
|
|
+ @endif
|
|
|
|
+ @endif
|
|
|
|
+ <small
|
|
|
|
+ class="header-item text-secondary text-sm text-uppercase">{{ friendly_time($message->created_at) }}</small>
|
|
|
|
+ @endif
|
|
|
|
+ @if ($performer->pro->can_proofread && $performer->pro->id == $message->created_by_pro_id && $message->content_text)
|
|
|
|
+ <div class="header-item hidden edit">
|
|
|
|
+ <div moe large relative>
|
|
|
|
+ @if ($k == 0 || $messages[$k - 1]->from_pro_id !== $messages[$k]->from_pro_id)
|
|
|
|
+ <a href="#" start show><i
|
|
|
|
+ class="fa fa-edit on-hover-opaque text-pry text-sm hidden edit"
|
|
|
|
+ style="top:18px;"></i></a>
|
|
|
|
+ @else
|
|
|
|
+ <a href="#" start show><i
|
|
|
|
+ class="fa fa-edit on-hover-opaque text-pry text-sm hidden edit"></i></a>
|
|
|
|
+ @endif
|
|
|
|
+ <form url="/api/internalMessage/edit"
|
|
|
|
+ class="text-left" right>
|
|
|
|
+ <input type="hidden" name="uid"
|
|
|
|
+ value="{{ $message->uid }}">
|
|
|
|
+ <div class="mb-2">
|
|
|
|
+ <label class="mb-1 text-sm">Edit
|
|
|
|
+ Message</label>
|
|
|
|
+ <textarea name="contentText" rows="3" class="form-control form-control-sm">{{ $message->content_text }}</textarea>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="mt-3">
|
|
|
|
+ <button submit
|
|
|
|
+ class="btn btn-sm btn-primary mr-2">Submit</button>
|
|
|
|
+ <button cancel
|
|
|
|
+ class="btn btn-default btn-sm border">Cancel</button>
|
|
|
|
+ </div>
|
|
|
|
+ </form>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ @if ($message->from_pro_id === $performer->pro->id)
|
|
|
|
+ <span class="header-item hidden delete">
|
|
|
|
+ <a href="#" native class="remove-message"
|
|
|
|
+ data-message-uid="{{ $message->uid }}"><i
|
|
|
|
+ class="fa fa-trash-alt text-danger text-sm"></i></a>
|
|
|
|
+ </span>
|
|
|
|
+ @endif
|
|
|
|
+ @endif
|
|
|
|
+ </div>
|
|
|
|
+ @if ($message->is_removed)
|
|
|
|
+ <div class="im-message-content text-secondary font-italic">This
|
|
|
|
+ message was removed.</div>
|
|
|
|
+ @else
|
|
|
|
+ @if (in_array($message->content_text, ['IV1', 'LH_WEBCAM_INTRO_1']))
|
|
|
|
+ <div style="max-width: 500px">
|
|
|
|
+ <script src="https://fast.wistia.com/embed/medias/xm42kdr0l6.jsonp" async></script>
|
|
|
|
+ <script src="https://fast.wistia.com/assets/external/E-v1.js" async></script>
|
|
|
|
+ <div class="wistia_responsive_padding"
|
|
|
|
+ style="padding:56.25% 0 0 0;position:relative;">
|
|
|
|
+ <div class="wistia_responsive_wrapper"
|
|
|
|
+ style="height:100%;left:0;position:absolute;top:0;width:100%;">
|
|
|
|
+ <div class="wistia_embed wistia_async_xm42kdr0l6 videoFoam=true"
|
|
|
|
+ style="height:100%;position:relative;width:100%">
|
|
|
|
+ <div class="wistia_swatch"
|
|
|
|
+ style="height:100%;left:0;opacity:0;overflow:hidden;position:absolute;top:0;transition:opacity 200ms;width:100%;">
|
|
|
|
+ <img src="https://fast.wistia.com/embed/medias/xm42kdr0l6/swatch"
|
|
|
|
+ style="filter:blur(5px);height:100%;object-fit:contain;width:100%;"
|
|
|
|
+ alt="" aria-hidden="true"
|
|
|
|
+ onload="this.parentNode.style.opacity=1;" />
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ @elseif($message->content_text)
|
|
|
|
+ <?php
|
|
|
|
+ $message->content_text = preg_replace_callback(
|
|
|
|
+ '~(?:http|ftp)s?://(?:www\.)?([a-z0-9.-]+\.[a-z]{2,3}(?:/\S*)?)~i',
|
|
|
|
+ function ($match) {
|
|
|
|
+ return '<a native target="_blank" href="' . $match[0] . '">' . $match[0] . '</a>';
|
|
|
|
+ },
|
|
|
|
+ $message->content_text,
|
|
|
|
+ );
|
|
|
|
+ ?>
|
|
|
|
+ <div class="im-message-content">{!! $message->content_text !!}</div>
|
|
|
|
+ @endif
|
|
|
|
+ @if ($message->message_video_file_id)
|
|
|
|
+ <div class="im-video-container">
|
|
|
|
+ <video
|
|
|
|
+ src="{{ route('serve-system-file', ['uid' => $message->videoFile->uid]) }}"
|
|
|
|
+ controls playsinline></video>
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ @endif
|
|
|
|
+ @if (count($message->attachments) && !$message->is_removed)
|
|
|
|
+ <div class="attachments-container mt-1 d-flex align-items-center flex-wrap {{ $message->from_pro_id === $performer->pro->id ? 'justify-content-end' : 'justify-content-start' }}"
|
|
|
|
+ data-message-uid="{{ $message->uid }}"
|
|
|
|
+ data-attachments-loaded="0">
|
|
|
|
+ <span class="my-1 text-primary c-pointer text-sm">
|
|
|
|
+ <i class="fa fa-paperclip"></i>
|
|
|
|
+ {{ count($message->attachments) }}
|
|
|
|
+ attachment{{ count($message->attachments) === 1 ? '' : 's' }}
|
|
|
|
+ </span>
|
|
|
|
+ </div>
|
|
|
|
+ @endif
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ @endforeach
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="im-input">
|
|
|
|
+ <div class="d-flex align-items-end">
|
|
|
|
+ <div class="msg-input">
|
|
|
|
+ <textarea placeholder="Enter your message here..."></textarea>
|
|
|
|
+ <button class="btn btn-sm btn-input" id="im-btn-send"><i
|
|
|
|
+ class="fa fa-paper-plane"></i></button>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="fabs ml-2">
|
|
|
|
+ <div moe-video moe-csrf="{{ csrf_token() }}" moe-question-key="hcp_intro"
|
|
|
|
+ moe-video-url="{{ route('video-test') }}"
|
|
|
|
+ moe-ot-api-key="{{ config('app.opentokApiKey') }}"
|
|
|
|
+ moe-ot-session-id="{{ $otSessionId }}"
|
|
|
|
+ moe-ot-client-token="{{ $otToken }}"
|
|
|
|
+ data-title="Upload or Record Video Message"
|
|
|
|
+ @if (isset($toPro)) to-pro-uid="{{ $toPro->uid }}" @endif
|
|
|
|
+ @if (isset($defaultCompany)) regarding-company-uid="{{ $defaultCompany->uid }}" @endif
|
|
|
|
+ @if (isset($regardingClient)) regarding-client-uid="{{ $regardingClient->uid }}" @endif>
|
|
|
|
+ </div>
|
|
|
|
+ <button class="btn btn-sm btn-info ml-2" id="im-btn-select-file"><i
|
|
|
|
+ class="fa fa-paperclip"></i></button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ <div class="d-flex align-items-end flex-wrap" id="selected-files">
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ @else
|
|
|
|
+ <div class="text-secondary">Nothing to show here!</div>
|
|
|
|
+ @endif
|
|
|
|
+ <div>
|
|
|
|
+ {{ $messages->withQueryString()->links() }}
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <script>
|
|
|
|
+ $(document).ready(function() {
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ jQuery('.mark-as-read').click();
|
|
|
|
+ }, 1000);
|
|
|
|
+
|
|
|
|
+ let inProgress = false;
|
|
|
|
+
|
|
|
|
+ function showSelectedFiles() {
|
|
|
|
+ $('#selected-files').empty();
|
|
|
|
+ $('.im-file-upload').each(function() {
|
|
|
|
+ if (this.files && this.files.length) {
|
|
|
|
+ for (let i = 0; i < this.files.length; i++) {
|
|
|
|
+ $('#selected-files').append($('<div class="selected-file" data-id="' + this.id +
|
|
|
|
+ '" title="Click to remove">').text(this.files[i].name));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function hasError(_data) {
|
|
|
|
+ let msg = 'Unknown error!';
|
|
|
|
+ if (_data) {
|
|
|
|
+ if (_data.success) return false;
|
|
|
|
+ else if (_data.message) msg = _data.message;
|
|
|
|
+ }
|
|
|
|
+ toastr.error(msg);
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ function doSend(_elem) {
|
|
|
|
+ if (inProgress) return false;
|
|
|
|
+ inProgress = true;
|
|
|
|
+ showMask();
|
|
|
|
+ let text = $.trim(_elem.value);
|
|
|
|
+ let formData = new FormData();
|
|
|
|
+ formData.set('fromProUid', '{{ $performer->pro->uid }}');
|
|
|
|
+ formData.set('regardingClientUid', '{{ $regardingClient->uid }}');
|
|
|
|
+ formData.set('regardingCompanyUid', '{{ $defaultCompany->uid }}');
|
|
|
|
+ formData.set('contentText', text);
|
|
|
|
+
|
|
|
|
+ let hasFiles = false;
|
|
|
|
+ $('.im-file-upload').each(function() {
|
|
|
|
+ if (this.files && this.files.length) {
|
|
|
|
+ for (let i = 0; i < this.files.length; i++) {
|
|
|
|
+ formData.append('attachments', this.files[i]);
|
|
|
|
+ hasFiles = true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (!hasFiles && !text) { // either attachment or text or both should be there
|
|
|
|
+ inProgress = false;
|
|
|
|
+ hideMask();
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ jQuery.ajax('/api/internalMessage/create', {
|
|
|
|
+ dataType: 'json',
|
|
|
|
+ data: formData,
|
|
|
|
+ processData: false,
|
|
|
|
+ contentType: false,
|
|
|
|
+ type: 'POST',
|
|
|
|
+ }).done(function(_data) {
|
|
|
|
+ if (!hasError(_data)) {
|
|
|
|
+ fastLoad('/patients/view/{{ $patient->uid }}/messages');
|
|
|
|
+ } else {
|
|
|
|
+ $('.im-input textarea').val('');
|
|
|
|
+ inProgress = false;
|
|
|
|
+ hideMask();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function init() {
|
|
|
|
+ @if ($regardingClient)
|
|
|
|
+ $('.im-input textarea').on('keydown', function(_e) {
|
|
|
|
+ if (_e.which === 13 && !_e.shiftKey) {
|
|
|
|
+ return doSend(this);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $('#im-btn-send').click(function() {
|
|
|
|
+ return doSend($('.im-input textarea')[0]);
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $('#plusBtn').click(function() {
|
|
|
|
+ $('.hide').toggle();
|
|
|
|
+ $('.show').toggle();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $('#im-btn-select-file').click(function() {
|
|
|
|
+ let fiID = Math.floor(Math.random() * 10000);
|
|
|
|
+ let fileInput = $('<input type="file" class="d-none im-file-upload" id="fu-' +
|
|
|
|
+ fiID + '">');
|
|
|
|
+ $('.im-input').append(fileInput)
|
|
|
|
+ fileInput.click();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document).on('change', '.im-file-upload', function() {
|
|
|
|
+ showSelectedFiles();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document)
|
|
|
|
+ .off('click', '.selected-file')
|
|
|
|
+ .on('click', '.selected-file', function() {
|
|
|
|
+ $('#' + $(this).attr('data-id')).remove();
|
|
|
|
+ showSelectedFiles();
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document)
|
|
|
|
+ .off('click.load-attachments', '.attachments-container[data-attachments-loaded="0"]>span')
|
|
|
|
+ .on('click.load-attachments', '.attachments-container[data-attachments-loaded="0"]>span',
|
|
|
|
+ function() {
|
|
|
|
+ let container = $(this).closest('.attachments-container');
|
|
|
|
+ if (inProgress) return false;
|
|
|
|
+ inProgress = true;
|
|
|
|
+ $.get('/patients/view/{{ $patient->uid }}/messages/' + container.attr(
|
|
|
|
+ 'data-message-uid') + '/attachments', (_data) => {
|
|
|
|
+ container.html(_data).attr('data-attachments-loaded', 1);
|
|
|
|
+ }).then(function() {
|
|
|
|
+ inProgress = false;
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document)
|
|
|
|
+ .off('click', '.mark-as-read')
|
|
|
|
+ .on('click', '.mark-as-read', function() {
|
|
|
|
+ $.post('/api/internalMessage/markRead', {
|
|
|
|
+ uid: $(this).attr('data-message-uid')
|
|
|
|
+ }, () => {
|
|
|
|
+ $(this).replaceWith(
|
|
|
|
+ '<i class="fa fa-check text-secondary on-hover-opaque text-sm"></i>'
|
|
|
|
+ );
|
|
|
|
+ let unreadBadge = $('.unread-badge[data-regarding-client-id="' +
|
|
|
|
+ {{ $regardingClient->id }} + '"]').first();
|
|
|
|
+ if (unreadBadge.length) {
|
|
|
|
+ let newCount = (+unreadBadge.text()) - 1;
|
|
|
|
+ if (newCount) {
|
|
|
|
+ unreadBadge.text(newCount);
|
|
|
|
+ } else {
|
|
|
|
+ unreadBadge.remove();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }, 'json');
|
|
|
|
+ return false;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ $(document)
|
|
|
|
+ .off('click', '.remove-message')
|
|
|
|
+ .on('click', '.remove-message', function() {
|
|
|
|
+ $.post('/api/internalMessage/remove', {
|
|
|
|
+ uid: $(this).attr('data-message-uid')
|
|
|
|
+ }, () => {
|
|
|
|
+ $(this).closest('.im-message').html(
|
|
|
|
+ '<div class="im-message-content text-secondary font-italic">This message was removed.</div>'
|
|
|
|
+ );
|
|
|
|
+ }, 'json');
|
|
|
|
+ return false;
|
|
|
|
+ });
|
|
|
|
+ @endif
|
|
|
|
+
|
|
|
|
+ setTimeout(function() {
|
|
|
|
+ var imScroller = document.getElementById("im-scroller");
|
|
|
|
+ imScroller.scrollTop = imScroller.scrollHeight;
|
|
|
|
+ $(imScroller).removeClass('opacity-0');
|
|
|
|
+ }, 100);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ init();
|
|
|
|
+ });
|
|
|
|
+ </script>
|
|
|
|
+ <link rel="stylesheet" href="{{ asset('moe-video/moe-video.css') }}">
|
|
|
|
+ <script src="{{ asset('moe-video/moe-video.js') }}"></script>
|
|
|
|
+
|
|
|
|
+@endsection
|