Skip to content

Commit

Permalink
feat: Infinite scroll on Dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
ChrisToxz committed Jul 14, 2023
1 parent 0525624 commit 5d51d3c
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 25 deletions.
34 changes: 34 additions & 0 deletions app/Events/SlipUploaded.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class SlipUploaded implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;

/**
* Create a new event instance.
*/
public function __construct()
{

}

/**
* Get the channels the event should broadcast on.
*
* @return array<int, Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('ss'),
];
}
}
28 changes: 11 additions & 17 deletions app/Http/Controllers/SlipController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@

namespace App\Http\Controllers;

use App\Enums\VideoType;
use App\Events\SlipUploaded;
use App\Jobs\CreateSlip;
use App\Jobs\GenerateThumb;
use App\Jobs\UploadSlip;
use App\Models\Slip;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Storage;
use ProtoneMedia\LaravelFFMpeg\Support\FFMpeg;
use Validator;

class SlipController extends Controller
{
public function index()
{
// $slips = Slip::latest()->with(['mediable' => function ($q) {
// $q->select('id', 'type', 'duration', 'height', 'path');
// }])->get();

$slips = Slip::latest()->with('mediable')->get();
$slips = Slip::latest()->with('mediable')->paginate(6);

return inertia('Dashboard', [
'slips' => $slips
Expand All @@ -40,17 +35,15 @@ public function show(Slip $slip)

public function store(Request $request)
{
// we need to fix the model binding in form input btw
$type = $request->get('type');
// $file = new UploadedFile(storage_path('app/' . $request->get('path')), $request->get('originalFileName'));
// dd($request->files->set('file', $file));
/**
* TODO
* Validation selected type (Cross check with enum)
* Validation check correct mimemtypes that we could accept
* Trigger jobs to save file and run converting if selected
*/
$mimeType = Storage::disk('local')->mimeType($request->get('file'));

$type = $request->get('type');

$request->validate([
'title' => 'nullable|string|max:200',
'description' => 'nullable|string|max:200',
Expand All @@ -66,17 +59,18 @@ public function store(Request $request)

// Generate Thumbnail
GenerateThumb::dispatchSync($slip, $request->get('file'));

// To the final processing

CreateSlip::dispatch($slip, $request->get('file'), $type);
// Dispatch event to reload Dashboard
SlipUploaded::dispatch();

}


public function tempUpload(Request $request)
{
if ($request->file) {
$validator = \Validator::make($request->all(), [
$validator = Validator::make($request->all(), [
'file' => 'file|mimetypes:video/mp4,video/mpeg|max:999999'
]);
if ($validator->fails()) {
Expand All @@ -91,7 +85,7 @@ public function tempUpload(Request $request)

public function destroy(Slip $slip)
{
if (!File::deleteDirectory(storage_path('app/public/slips/' . $slip->token))) {
if (!File::deleteDirectory(storage_path('app/public/slips/'.$slip->token))) {
return redirect()->back()->withErrors(['message' => 'Something went wrong, Slip have not been deleted!']);
}

Expand Down
2 changes: 1 addition & 1 deletion database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public function run(): void
{

// Video::factory(20)->for(Slip::factory(), 'slip')->create();
Slip::factory(50)->for(
Slip::factory(20)->for(
Video::factory(), 'mediable'
)->create();
// \App\Models\User::factory()->create([https://laravel.com/docs/10.x/eloquent-factories#polymorphic-relationships
Expand Down
7 changes: 4 additions & 3 deletions resources/js/Components/Upload/UploadModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,10 @@ const getUploadedFile = (e) => {
}
const saveMedia = () => {
form.post('/slips', {
onSuccess: () => closeModal(),
})
form.post('/slips', {
onSuccess: () => closeModal(),
})
closeModal()
}
const closeModal = () => {
Expand Down
55 changes: 51 additions & 4 deletions resources/js/Pages/Dashboard.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,56 @@
<script setup>
import {Head, router} from '@inertiajs/vue3'
import {Head, router, usePage} from '@inertiajs/vue3'
import {useSnackbar, Vue3Snackbar} from 'vue3-snackbar'
import MainLayout from '@/Layouts/MainLayout.vue'
import VideoCard from '@/Components/Dashboard/VideoCard.vue'
import {onMounted, reactive, ref} from 'vue'
const snackbar = useSnackbar()
const props = defineProps({
slips: Object,
})
const snackbar = useSnackbar()
let allSlips = reactive({data: props.slips.data})
const initUrl = usePage().url
const loadMoreIntersect = ref(null)
function loadMoreSlips() {
if (props.slips.next_page_url === null) {
return
}
router.get(props.slips.next_page_url, {}, {
preserveState: true,
preserveScroll: true,
only: ['slips'],
onSuccess: (page) => {
allSlips.data = [...allSlips.data, ...page.props.slips.data]
window.history.replaceState({}, '' , initUrl)
},
})
}
onMounted(() => {
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
loadMoreSlips()
}
})
}, {
rootMargin: '-100px 0px 0px 0px',
})
observer.observe(loadMoreIntersect.value)
})
/* Websockets
TODO: Move to composable
*/
window.Echo.channel('ss').listen('SlipProcessFinished', (e) => {
router.reload(route('dashboard'), {
router.reload({
preserveState: true,
only:['slips'],
onSuccess: (page) => {
allSlips.data = page.props.slips.data
},
})
if(!e.failed){
snackbar.add({
Expand All @@ -26,7 +63,16 @@ window.Echo.channel('ss').listen('SlipProcessFinished', (e) => {
text: 'Processing failed for ' + e.slip.title,
})
}
})
window.Echo.channel('ss').listen('SlipUploaded', (e) => {
router.reload({
preserveState: true,
only: ['slips'],
onSuccess: (page) => {
allSlips.data = page.props.slips.data
},
})
})
</script>

Expand All @@ -35,9 +81,10 @@ window.Echo.channel('ss').listen('SlipProcessFinished', (e) => {
<MainLayout>
<div class="w-full flex justify-center">
<div class="w-[calc(100%-3rem)] grid lg:grid-cols-3 md:grid-cols-2 grid-cols-1 gap-7">
<VideoCard v-for="slip in slips" :key="slip.token" :slip="slip" />
<VideoCard v-for="slip in allSlips.data" :key="slip.token" :slip="slip" />
</div>
</div>
<span ref="loadMoreIntersect" />
</MainLayout>
<vue3-snackbar top right />
</template>
Expand Down

0 comments on commit 5d51d3c

Please sign in to comment.