Skip to content

Instantly share code, notes, and snippets.

@JordanDalton
Last active July 14, 2018 22:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JordanDalton/8ccd2d2e6bc48d6cdbc5b0ea41489c91 to your computer and use it in GitHub Desktop.
Save JordanDalton/8ccd2d2e6bc48d6cdbc5b0ea41489c91 to your computer and use it in GitHub Desktop.
A beauty of leveraging Eloquent to prepare your urls is that your Vue components no longer care about the urls, just that a url is provided.
<stream-chat messages_url="{{ $stream->messages_url }}" store_message_url="{{$stream->store_message_url }}" inline-template>
<div class="flex-1 flex flex-col bg-white overflow-hidden">
<!-- Top bar -->
<div class="border-b px-6 py-2 items-center flex-none">
<div>
<h3 class="text-grey-darkest mb-1 font-extrabold">Chat</h3>
</div>
</div>
<!-- Chat messages -->
<div class="px-6 py-4 flex-1 overflow-y-scroll" ref="chat">
<!-- A message -->
<div class="flex items-start mb-4 text-sm" v-for="message in messages">
<img src="message.sendable.photo" class="w-10 h-10 rounded mr-3" v-if="message.type === 'user'">
<div class="flex-1 overflow-hidden" v-if="message.type === 'user'">
<div>
<span class="font-bold">@{{ message.sendable.username }}</span>
<span class="text-grey text-xs">
@{{ message.created_ago }}
</span>
</div>
<p class="text-black leading-normal">@{{ message.message }}</p>
</div>
<div class="flex-1 overflow-hidden" v-if="message.type === 'stream'">
<p class="text-red font-bold leading-normal">@{{ message.message }}</p>
</div>
</div>
</div>
@if($stream->isLive())
@auth()
<div class="pb-6 px-4 flex-none">
<div class="flex rounded-lg border-2 border-grey overflow-hidden">
<textarea type="text" class="w-full p-4" placeholder="Message #general" v-model="form.message" @keyup.enter.exact.prevent="storeMessage"></textarea>
</div>
</div>
@endauth
@endif
</div>
</stream-chat>
<script>
export default {
props : [
'messages_url',
'store_message_url'
],
data(){
return {
messages : [],
form : {
message : '',
}
}
},
methods : {
fetchMessages(){
axios.get(this.messages_url).then(response => {
this.messages = response.data;
this.scrollToBottom();
})
},
storeMessage(){
if(this.submittable){
axios.post(this.store_message_url, this.form).then(response => {
this.messages.push(response.data[0]);
this.scrollToBottom();
this.form.message = '';
})
}
},
scrollToBottom()
{
this.$nextTick(() => {
var targetDiv = this.$refs.chat;
targetDiv.scrollTop = targetDiv.scrollHeight;
});
}
},
computed : {
submittable(){
return this.form.message.trim().length > 1;
}
},
mounted() {
this.fetchMessages();
}
}
</script>
<?php
namespace App;
use App\Http\Resources\Message\SendableStreamResource;
use App\Models\Model;
use DateTime;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
class Stream extends Model
{
/**
* The accessors to append to the model's array form.
*
* @var array
*/
protected $appends = [
'messages_url',
'store_message_url',
];
/**
* Return the url to obain all the messages for the stream.
*/
public function getMessagesUrlAttribute() : string
{
return route('streams.messages.index', [$this->user, $this]);
}
/**
* Return the url that will be used when storing a new message to a stream.
*/
public function getStoreMessageUrlAttribute() : string
{
return route('streams.messages.store', [$this->user, $this]);
}
/**
* Is the stream currently live?
*/
public function isLive() : bool
{
return $this->starts_at && $this->started_at && ! $this->ended_at;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment