Created
March 29, 2020 15:22
-
-
Save mboynes/62ceea37159867ef00f8bb65ab2343f6 to your computer and use it in GitHub Desktop.
Diff for https://laracasts.com/series/lets-build-a-forum-with-laravel/episodes/36 in Laravel 6.x
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/resources/js/app.js b/resources/js/app.js | |
index 01b8468..8c93dcc 100644 | |
--- a/resources/js/app.js | |
+++ b/resources/js/app.js | |
@@ -7,6 +7,10 @@ | |
require('./bootstrap'); | |
window.Vue = require('vue'); | |
+window.Vue.prototype.authorize = function(handler) { | |
+ const { user } = window.App; | |
+ return !! user ? handler(user) : false; | |
+}; | |
window.events = new Vue(); | |
@@ -26,7 +30,8 @@ window.flash = function(message) { | |
// files.keys().map(key => Vue.component(key.split('/').pop().split('.')[0], files(key).default)) | |
Vue.component('flash', require('./components/Flash.vue').default); | |
-Vue.component('reply', require('./components/Reply.vue').default); | |
+ | |
+Vue.component('thread-view', require('./pages/Thread.vue').default); | |
/** | |
* Next, we will create a fresh Vue application instance and attach it to | |
diff --git a/resources/js/components/Replies.vue b/resources/js/components/Replies.vue | |
new file mode 100644 | |
index 0000000..95a2cc4 | |
--- /dev/null | |
+++ b/resources/js/components/Replies.vue | |
@@ -0,0 +1,33 @@ | |
+<template> | |
+ <div> | |
+ <div v-for="(reply, index) in items"> | |
+ <reply :data="reply" @deleted="remove(index)"></reply> | |
+ </div> | |
+ </div> | |
+</template> | |
+ | |
+<script> | |
+ import Reply from "./Reply"; | |
+ | |
+ export default { | |
+ props: ['data'], | |
+ | |
+ components: { | |
+ Reply, | |
+ }, | |
+ | |
+ data() { | |
+ return { | |
+ items: this.data, | |
+ }; | |
+ }, | |
+ | |
+ methods: { | |
+ remove(index) { | |
+ this.items.splice(index, 1); | |
+ this.$emit('removed'); | |
+ flash('Reply was deleted.'); | |
+ }, | |
+ }, | |
+ } | |
+</script> | |
diff --git a/resources/js/components/Reply.vue b/resources/js/components/Reply.vue | |
index a9bafcc..13adcea 100644 | |
--- a/resources/js/components/Reply.vue | |
+++ b/resources/js/components/Reply.vue | |
@@ -1,21 +1,61 @@ | |
+<template> | |
+ <div :id="`reply-${id}`" class="card mb-3"> | |
+ <div class="card-header level"> | |
+ <h5 class="flex"> | |
+ <a :href="`/profiles/${data.owner.name}`" v-text="data.owner.name"></a> said | |
+ {{ data.created_at }}... | |
+ </h5> | |
+ | |
+ <div v-if="signedIn"> | |
+ <favorite :reply="data"></favorite> | |
+ </div> | |
+ </div> | |
+ <div class="card-body"> | |
+ <div v-if="editing" v-cloak> | |
+ <div class="form-group"> | |
+ <textarea v-model="body" class="form-control" rows="5"></textarea> | |
+ </div> | |
+ <button class="btn btn-sm btn-primary" @click="update">Update</button> | |
+ <button class="btn btn-sm btn-link" @click="editing = false">Cancel</button> | |
+ </div> | |
+ <div v-else v-text="body"></div> | |
+ </div> | |
+ | |
+ <div class="card-footer level" v-if="canUpdate"> | |
+ <button class="btn btn-sm btn-outline-info mr-2" @click="editing = true">Edit</button> | |
+ <button class="btn btn-outline-danger btn-sm" @click="destroy">Delete Reply</button> | |
+ </div> | |
+ </div> | |
+</template> | |
<script> | |
import Favorite from './Favorite'; | |
export default { | |
- props: ['attributes'], | |
+ props: ['data'], | |
data() { | |
return { | |
editing: false, | |
- body: this.attributes.body, | |
+ id: this.data.id, | |
+ body: this.data.body, | |
}; | |
}, | |
components: { Favorite }, | |
+ computed: { | |
+ signedIn() { | |
+ return window.App.signedIn; | |
+ }, | |
+ | |
+ canUpdate() { | |
+ return this.authorize((user) => this.data.user_id === window.App.user.id); | |
+ }, | |
+ }, | |
+ | |
methods: { | |
update() { | |
- axios.patch('/replies/' + this.attributes.id, { | |
+ axios.patch('/replies/' + this.data.id, { | |
body: this.body, | |
}); | |
@@ -24,8 +64,8 @@ | |
}, | |
destroy() { | |
- axios.delete('/replies/' + this.attributes.id); | |
- $(this.$el).fadeOut(700, () => flash('Your reply has been deleted.')); | |
+ axios.delete('/replies/' + this.data.id); | |
+ this.$emit('deleted', this.data.id); | |
}, | |
}, | |
} | |
diff --git a/resources/js/pages/Thread.vue b/resources/js/pages/Thread.vue | |
new file mode 100644 | |
index 0000000..6e23f2d | |
--- /dev/null | |
+++ b/resources/js/pages/Thread.vue | |
@@ -0,0 +1,18 @@ | |
+<script> | |
+ import Replies from "../components/Replies"; | |
+ export default { | |
+ props: [ | |
+ 'initialRepliesCount', | |
+ ], | |
+ | |
+ components: { | |
+ Replies, | |
+ }, | |
+ | |
+ data() { | |
+ return { | |
+ repliesCount: this.initialRepliesCount, | |
+ }; | |
+ }, | |
+ } | |
+</script> | |
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php | |
index 038ac9f..3e22493 100644 | |
--- a/resources/views/layouts/app.blade.php | |
+++ b/resources/views/layouts/app.blade.php | |
@@ -22,6 +22,13 @@ | |
<style> | |
[v-cloak] { display: none; } | |
</style> | |
+ | |
+ <script> | |
+ window.App = {!! json_encode([ | |
+ 'signedIn' => Auth::check(), | |
+ 'user' => Auth::user(), | |
+ ]) !!} | |
+ </script> | |
</head> | |
<body> | |
<div id="app"> | |
diff --git a/resources/views/threads/reply.blade.php b/resources/views/threads/reply.blade.php | |
index 7228866..264f301 100644 | |
--- a/resources/views/threads/reply.blade.php | |
+++ b/resources/views/threads/reply.blade.php | |
@@ -1,4 +1,4 @@ | |
-<reply :attributes="{{ $reply }}" inline-template> | |
+<reply :data="{{ $reply }}" inline-template> | |
<div id="reply-{{ $reply->id }}" class="card mb-3"> | |
<div class="card-header level"> | |
<h5 class="flex"> | |
diff --git a/resources/views/threads/show.blade.php b/resources/views/threads/show.blade.php | |
index 8716b8a..47851c5 100644 | |
--- a/resources/views/threads/show.blade.php | |
+++ b/resources/views/threads/show.blade.php | |
@@ -1,6 +1,7 @@ | |
@extends('layouts.app') | |
@section('content') | |
+ <thread-view :initial-replies-count="{{ $thread->replies_count }}" inline-template> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-8"> | |
@@ -27,11 +28,9 @@ | |
</div> | |
</div> | |
- @foreach($replies as $reply) | |
- @include('threads.reply') | |
- @endforeach | |
+ <replies :data="{{ $thread->replies }}" @removed="repliesCount--"></replies> | |
- {{ $replies->links() }} | |
+ {{-- {{ $replies->links() }}--}} | |
@auth | |
<form action="{{ $thread->path() }}/replies" method="post"> | |
@@ -59,11 +58,13 @@ | |
<div class="card"> | |
<div class="card-body"> | |
This thread was published {{ $thread->created_at->diffForHumans() }} | |
- by <a href="#">{{ $thread->creator->name }}</a> and has {{ $thread->replies_count }} | |
+ by <a href="#">{{ $thread->creator->name }}</a> and has | |
+ <span v-text="repliesCount"></span> | |
{{ Illuminate\Support\Str::plural('comment', $thread->replies_count) }}. | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
+ </thread-view> | |
@endsection |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment