Message in pusher chat are not refreshing instantly - laravel

I'll need your help there, I have a chat with pusher, vue.js and laravel. Everything is working well execpt one thing, when I receive a message it does not display instantly, I have to refresh the page to see this message so this is kinda annoying. Any help would be really thankful. This is the tutorial that I follow : https://pusher.com/tutorials/chat-laravel
So this is my chat in my app.blade.js :
<div id="app" class="container-chat">
<div class="row">
<div class="col-md-12 col-md-offset-2">
<div class="col-md-12 col-md-offset-2">
<div class="panel-body panel-content" id="mess_cont" :userid="{{Auth::user()->id}}">
<chat-messages id="mess" :messages="messages" :currentuserid="{{Auth::user()->id}}"></chat-messages>
</div>
<div class="panel-footer">
<chat-form
v-on:messagesent="addMessage"
:user="{{ Auth::user() }}"
></chat-form>
</div>
</div>
</div>
</div>
</div>
This is my ChatMessages.vue :
<template>
<ul class="chat messages" >
<li class="clearfix list-group-item" v-for="message in messages" v-bind:class="{
classForUser: (message.user.id === currentuserid),
classForNotUser: (message.user.id !== currentuserid)}" >
<div class="chat-body clearfix" >
<div class="header">
<strong class="primary-font"
v-bind:class="{
classForAuthorSameAsUser: (message.user.id === currentuserid),
classForAuthorDiffThanUser: (message.user.id !== currentuserid)
}">
{{ message.user.firstName }}
{{ message.user.lastName}}
:
</strong>
{{ message.human_readable_time}}
</div>
<p>
{{ message.message }}
</p>
</div>
</li>
</ul>
</template>
<script>
export default {
props: ['messages','currentuserid']
};
</script>
<style scoped>
.classForAuthorSameAsUser {
color: #2FB3FF ;
}
.classForAuthorDiffThanUser {
color: black;
}
.classForUser{
width: 70%;
left: 30%;
}
.classForNotUser{
width: 70%;
}
</style>
This is the ChatForm.vue :
<template>
<form #submit.prevent="sendMessage">
<div class="input-group" >
<input id="btn-input" type="text" name="message" class="form-control input-sm" placeholder="Ecrire..." v-model="newMessage" required>
<span class="input-group-btn">
<button class="btn btn-primary btn-sm" type="submit" id="btn-chat">
&#10003
</button>
</span>
</div>
</form>
</template>
<script>
export default {
props: ['user'],
data() {
return {
newMessage: '',
}
},
methods: {
sendMessage() {
this.$emit('messagesent', {
user: this.user,
message: this.newMessage
});
setTimeout(function() {
const messages = document.getElementById('mess_cont');
messages.scrollTop = messages.scrollHeight;
}, 100);
this.newMessage = '';
}
}
}
</script>
And this is my app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
import Vue from 'vue'
Vue.component('chat-messages', require('./components/ChatMessages.vue').default);
Vue.component('chat-form', require('./components/ChatForm.vue').default);
const app = new Vue({
el: '#app',
data: {
messages: []
},
created() {
this.fetchMessages();
Echo.private('chat')
.listen('MessageSent', (e) => {
this.messages.push({
message: e.message.message,
user: e.user
});
});
},
methods: {
fetchMessages() {
axios.get('/messages').then(response => {
this.messages = response.data;
});
},
addMessage(message) {
this.messages.push(message);
axios.post('/messages', message).then(response => {
console.log(response.data);
});
}
}
});
If you need more informations just ask I just don't want to spam useless code. Thanks

The solution was in the env file,
BROADCAST_DRIVER=pusher
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
I had to put "Pusher" Instead of "Log"

Related

Resource missing error when adding payment method for subscription

Im using laravel cashier for stripe, im creating a subscription with no card up front and 15 days trial when user registration, im following laravel cashier tutorial to add payment method for user so card can be charged when trial is over but i keep getting error
below is my controller
class BillingController extends Controller {
public function getBilling()
{
return view('dashboard.billing', [
'intent' => Auth::user()->createSetupIntent()
]);
}
}
this is my view and script
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-3">
#include('dashboard.partial.menu')
</div>
<div class="col-9">
<div class="card">
<div class="card-header">
Update Card Info
</div>
<div class="card-body">
#if(Auth::user()->subscribed() && Auth::user()->subscription('monthly')->onTrial())
<h6 class="card-title">Trial ends at: <span class="badge badge-primary">{{$diff = Carbon\Carbon::parse(Auth::user()->subscription('monthly')->trial_ends_at)->diffForHumans()}}</span></h6>
#endif
<h5>Subscription Details</h5>
<p>Monthly Membership - .99 <small>(Renews every month)</small></p>
#if (Auth::user()->hasPaymentMethod())
<h6>Card on file</h6>
<p>{{Auth::user()->card_brand}}: ending in <span class="badge badge-primary">{{Auth::user()->card_last_four}}</span></p>
#endif
<div class="form-group">
<input class="form-control" id="card-holder-name" type="text" placeholder="Cardholder name">
</div>
<!-- Stripe Elements Placeholder -->
<div id="card-element" class="form-control" style='margin-bottom: 1.5em;height: 2.4em; padding-top: .7em;'></div>
<div class="form-group">
<button class="btn btn-primary" id="card-button" data-secret="{{ $intent->client_secret }}">
Update Payment Method
</button>
</div>
</div>
</div>
</div>
</div>
</div>
#endsection #push('scripts')
window.addEventListener('load',function() { const stripe = Stripe('pk_test_xxxxxxxxxxxxxxxxxxxxxxx');
const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;
cardButton.addEventListener('click', async (e) => {
const { setupIntent, error } = await stripe.handleCardSetup(
clientSecret, cardElement, {
payment_method_data: {
billing_details: { name: cardHolderName.value }
}
}
);
if (error) {
console.log(error);
} else {
stripePaymentHandler(setupIntent);
}
});
});
#endpush
and i get this error
Object { type: "invalid_request_error", code: "resource_missing", doc_url: "https://stripe.com/docs/error-codes/resource-missing", message: "No such setupintent: seti_1FjTcII7sKb0v4gBuFe9ZZ5f", param: "intent" }

Select2 form input not change value with vue

i need help. So basicly, when i used ordinary select form, i have succeed pass the data. but when i change to select2. Why my select2 not change value like select2 form??
This is with my select form ordinary with success pass data
<template>
<div class="col-md-3 col-sm-4">
<div class="filter-sidebar">
<div class="col-md-12 form-title">
<h2>Find the OPD</h2>
</div>
<form id="search" role="form" class="" #submit.stop.prevent="searchOpdForm" method="post">
<div class="col-md-12 form-group category">
<label class="control-label" for="category">Instansi / OPD</label>
<select id="opd" name="opd" class="form-control" v-model="selectopd.opd">
<option v-for="opd in opds" :key="opd.index" :value="opd.id">{{opd.nama_opd}}</option>
</select>
</div>
<div class="col-md-12 form-group button">
<button type="submit" class="btn tp-btn-primary tp-btn-lg btn-block">Cari</button>
<router-link :to="{name: 'listings'}" class="btn btn-reset"><i class="fa fa-repeat"></i>Reset</router-link>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
import {API_BASE} from '../Config/config'
export default {
name: 'Sidebar',
data() {
return {
opds: [],
selectopd: {}
}
},
created() {
this.fetchOpds();
},
methods: {
searchOpdForm() {
let urlpost = `${API_BASE}/listings/search/opd`
console.log('submiting')
axios.post(urlpost, this.selectopd)
.then(response => {
this.$router.push({name: 'searchlistingopd', params: {listings: response.data.listings}})
console.log('successful')
})
.catch(error => {
console.log(error)
})
},
fetchOpds() {
let url = `${API_BASE}/get-opds`
axios.get(url)
.then(response => {
this.opds = response.data.opds
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
And this is with example selected id's :
And if i changes to this, and a bit search with select2 form format, and my code is like this
<template>
<div class="col-md-3 col-sm-4">
<div class="filter-sidebar">
<div class="col-md-12 form-title">
<h2>Find the OPD</h2>
</div>
<form id="search" role="form" class="" #submit.stop.prevent="searchOpdForm" method="post">
<div class="col-md-12 form-group category">
<label class="control-label" for="category">Instansi / OPD</label>
<select id="opd" name="opd" class="form-control" v-model="selectopd.opd">
<option v-for="opd in opds" :key="opd.index" :value="opd.id">{{opd.nama_opd}}</option>
</select>
</div>
<div class="col-md-12 form-group button">
<button type="submit" class="btn tp-btn-primary tp-btn-lg btn-block">Cari</button>
<router-link :to="{name: 'listings'}" class="btn btn-reset"><i class="fa fa-repeat"></i>Reset</router-link>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios'
import {API_BASE} from '../Config/config'
import jQuery from 'jquery'
let $ = jQuery
require('select2')
export default {
name: 'Sidebar',
data() {
return {
opds: [],
selectopd: {}
}
},
created() {
this.fetchOpds();
},
mounted() {
$("#opd").select2()
},
methods: {
searchOpdForm() {
let urlpost = `${API_BASE}/listings/search/opd`
console.log('submiting')
axios.post(urlpost, this.selectopd)
.then(response => {
this.$router.push({name: 'searchlistingopd', params: {listings: response.data.listings}})
console.log('successful')
})
.catch(error => {
console.log(error)
})
},
fetchOpds() {
let url = `${API_BASE}/get-opds`
axios.get(url)
.then(response => {
this.opds = response.data.opds
})
.catch(error => {
console.log(error)
})
}
}
}
</script>
Now when i choose value, it doesn't change anything. Just like this
Am I doing wrong with select2 code to use it in my component? Or i missing something to add like native jquery in ordinary?
You could change
<select id="opd" name="opd" class="form-control" v-model="selectopd.opd">
for
<select id="opd" name="opd" class="form-control" v-model="selectopd">

VueJs With Laravel

I am learning Vuejs. I am making a system where users can set a message as favourite.
But i am getting the below error. Any help to resolve would be appreciated.
[Vue warn]: Failed to mount component: template or render function not
defined. found in
---> Favorite Root
Below is my code =>
Favorite.vue
<template>
<span>
<a href="#" v-if="isFavorited" #click.prevent="unFavorite(post)">
<i class="fa fa-heart"></i>
</a>
<a href="#" v-else #click.prevent="favorite(post)">
<i class="fa fa-heart-o"></i>
</a>
</span>
</template>
<script>
export default {
name: 'favorite',
props: ['post', 'favorited'],
data: function() {
return {
isFavorited: '',
}
},
mounted() {
this.isFavorited = this.isFavorite ? true : false;
},
computed: {
isFavorite() {
return this.favorited;
},
},
methods: {
favorite(post) {
axios.post('/favorite/'+post)
.then(response => this.isFavorited = true)
.catch(response => console.log(response.data));
},
unFavorite(post) {
axios.post('/unfavorite/'+post)
.then(response => this.isFavorited = false)
.catch(response => console.log(response.data));
}
}
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
app.js
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('Favorite', require('./components/Favorite.vue'));
const app = new Vue({
el: '#app'
});
index.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel">
<h3>All Posts</h3>
<hr>
</div>
#forelse ($posts as $post)
<div class="card">
<div class="card-header">
{{ $post->title }}
</div>
<div class="card-body mb-2">
{{ $post->body }}
</div>
#if (Auth::check())
<div class="card-footer mb-2">
<favorite
:post={{ $post->id }}
:favorited={{ $post->favorited() ? 'true' : 'false' }}
></favorite>
</div>
#endif
</div>
#empty
<p>No post created.</p>
#endforelse
{{ $posts->links() }}
</div>
</div>
</div>
#endsection
Try Vue.component('Favorite', require('./components/Favorite.vue').default); with .default at the end.

Vue-resource + FormData File Upload with Laravel Backend

I Already asked my question on VueJS Forum : https://forum.vuejs.org/t/file-upload-with-formdata-vue-resource/20952/3
But ! For duplicate my chances to success I'll ask you about my problem.
Simply I have a input type file (without form parent node) and I'm trying to upload asynchronously a file with FormData and Vue-resource http to my Laravel 5.5 API Backend..
To test my upload my controller return a JSON response with a dump of my $request.
Well, I have a 200 code and but unfortunetly my response is empty..
Thank you for your helping :)
Request payload here
Client code
export default {
name: 'profile',
data () {
return {
user: {},
files: [],
filepath: false,
imageData: ''
}
},
mounted () {
this.user = this.$store.getters.user
},
methods: {
reset: function () {
this.remove()
},
upload: function (e) {
var data = new FormData()
var file = this.files[0]
data.append('test', 1234)
data.append('avatar', file)
this.$http({
url: this.user.actions.updateAvatar,
body: data,
method: 'POST',
responseType: 'json',
before: function (request) {
console.log(request)
}
})
.then((response) => {
console.log(response)
})
.catch((errorResponse) => {
console.log(errorResponse)
})
},
sync: function (e) {
e.preventDefault()
this.files = e.target.files || e.dataTransfer.files
if (!this.files.length) {
return
}
this.createFile(e, this.files[0])
},
createFile: function (e, file) {
this.filepath = URL.createObjectURL(file)
},
remove: function () {
URL.revokeObjectURL(this.filepath)
this.filepath = false
this.files = []
document.getElementById('avatar').value = ''
}
}
}
<template>
<!-- header profile -->
<div id="profile">
<section class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2">
<div class="profile">
<input type="hidden" name="_method" value="PUT"/>
<header>
<label for="avatar" class="avatar" v-if="!filepath">
<img :src="user.avatar || 'http://placehold.it/50x50'" alt="avatar">
</label>
<div class="avatar" #click="reset" v-if="filepath">
<img :src="filepath" alt="avatar">
</div>
<!-- Trigger a preview -->
<input #change="sync" id="avatar" name="avatar" type="file" accept="image/*;" class="hide">
<div class="info">
<span class="name">John Snow
<router-link :to="{ name: 'UserSettings' }">
<span class="ico gear"></span>
</router-link>
</span>
<span class="desc">Une bio de 40 caractères</span>
<span class="social">
<span class="ico fb"></span>
<span class="ico tw"></span>
</span>
</div>
</header>
<!-- Trigger upload -->
<span #click="upload" class="btn-save" v-if="filepath">
Enregistrer
</span>
</div>
</div>
<div class="col-lg-8 col-lg-offset-2">
<div class="col-lg-12">
<router-link :to="{ name: 'UserPosts' }">
<span for="dechet" class="nb-dechet">122 déchêts postés</span>
</router-link>
|
<router-link :to="{ name: 'UserBookmarks' }">
<span for="dechet" class="nb-dechet">122 déchêts sauvegardés</span>
</router-link>
|
<router-link :to="{ name: 'UserTrophies' }">
<span for="reward" class="nb-dechet">1 trophé obtenu</span>
</router-link>
</div>
</div>
</div>
</section>
<hr>
<!-- posts -->
<section class="container">
<div class="row">
<router-view></router-view>
</div>
</section>
</div>
</template>
Server-side code
Route | Dummy Controller
Well there is nothing wrong with your code, its just that response()->json() is not able to convert Illuminate\Http\UploadedFile to json.
Your file is being uploaded, try to check it like
return response()->json([
'avatar' => $request->file('avatar')->getClientOriginalName()
]);
and you'll get the name of the file in response.
Reason
Reason for why it is unable to convert Illuminate\Http\UploadedFile to JSON response is it doesn't implements Illuminate\Contracts\Support\Jsonable

Call method other component in vue

How to call method other component in Vue?
I have component HeaderSearch
<template>
<form action="">
<div class="form-group">
<div class="input-group">
<span class="input-group-btn">
<button class="btn" type="button">
<i class="fa fa-search"></i>
</button>
</span>
<input type="text" #keyup="search(keyword)" v-model="keyword" class="form-control" placeholder="Search...">
</div>
</div>
</form>
</template>
<script>
export default {
data(){
return { keyword: "" };
},
methods: {
search: function(keyword){
if(keyword == ''){
// Want call method fetchPost in PostHome component here
}else{
}
}
}
}
</script>
And I have component PostHome
<template>
<div>
<div class="box r_8 box_shadow" v-for="post in posts">
<div class="box_header">
<a :href="post.url">
<h3 class="mg_bottom_10" v-text="post.title"></h3>
</a>
<small v-text="post.description"></small>
<a :href="post.url" class="box_header_readmore">Read more</a>
</div>
<div class="box_body">
<a :href="post.url" v-show="post.thumbnail">
<img :src="post.thumbnail" class="img_responsive" style="min-height: 300px;background-color: #f1f1f1;
">
</a>
</div>
<div class="box_footer" v-show="post.tags.length > 0">
<ul>
<li v-for="tag in post.tags">
<a v-text="tag.name" href="javascript:void(0)"></a>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
posts: null,
}
},
methods: {
fetchPosts: function(){
var url = base_url + '/user/posts'
this.$http.get(url).then(res => {
this.posts = res.data;
});
}
},
created: function(){
this.fetchPosts();
}
}
</script>
I want when user type keyup to search then if
keyword == ''
call method fetchPost method in PostHome component
You can use Mixins if that method is reusable.
Reference: https://v2.vuejs.org/v2/guide/mixins.html

Resources