Skip to content

Commit 1b45533

Browse files
authored
Dev into Main (#2)
* feat: add config file for default * register config files for default settings and added publishable vendor * feat: add facades support * feat: add migration table media * feat: create media model * feat: create media trait for models * update HasMedia Trait * feat: add default_disk configuration to media settings * feat: implement upload method in LaravelMedia class with MediaHandler integration * feat: enhance upload method in LaravelMedia class for improved error handling * remove space from LaravelMedia.php * refactor: change init method to constructor in LaravelMedia class for improved clarity * refactor: update media configuration to include default_disk, path_prefix, and default_collection settings * refactor: inject MediaHandler dependency into LaravelMedia instantiation * docs: update README.md to include new configuration options for media management * docs: fix formatting in README.md by removing extra newline * refactor: update media migration to include default values for disk and collection, and adjust model morphs * feat: enhance upload method in MediaHandler to support original file name preservation and improved path management * feat: add support for dynamic model and collection in LaravelMedia class, and implement test method * Update README.md * feat: add LaravelMediaPicker component for media selection in views * feat: load views and routes, publish assets, and register Blade component in LaravelMediaServiceProvider * feat: add routes for media browser and upload functionality in web.php * feat: add media grid partial for displaying media items in the view * feat: create media picker component with modal for media selection and upload functionality * feat: implement JavaScript functions for media modal handling, including media fetching and upload form submission * feat: add CSS styles for media modal and grid layout to enhance media selection interface
1 parent 93b7277 commit 1b45533

File tree

15 files changed

+359
-18
lines changed

15 files changed

+359
-18
lines changed

README.md

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Laravel Media :frame_with_picture:
1+
# Laravel Media \:frame\_with\_picture:
22

33
[![Latest Version](https://img.shields.io/packagist/v/exitdump/laravel-media.svg?style=flat-square)](https://packagist.org/packages/exitdump/laravel-media)
44
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.md)
@@ -9,15 +9,52 @@ A WordPress-like media management system for Laravel with modal library, image p
99

1010
## Features ✨
1111

12-
- 🖼️ **WordPress-style Media Library Modal**
13-
- 📁 **Multiple Storage Disks** (Local, S3, etc.)
14-
-**Image Processing** (Thumbnails, Cropping)
15-
- 🔗 **Morphable Media Attachments**
16-
- 🚀 **AJAX Uploads with Progress**
17-
- 🔍 **Search & Filter Media**
18-
- 🎨 **Frontend Components Included**
12+
* 🖼️ **WordPress-style Media Library Modal**
13+
* 📁 **Multiple Storage Disks** (Local, S3, etc.)
14+
***Image Processing** (Thumbnails, Cropping)
15+
* 🔗 **Morphable Media Attachments**
16+
***Frontend Media Picker Component**
17+
* 🚀 **AJAX Uploads with Progress**
18+
* 🔍 **Search & Filter Media**
19+
* 🎨 **Easy Blade Component Integration**
1920

2021
## Installation 💻
2122

2223
```bash
2324
composer require exitdump/laravel-media
25+
```
26+
27+
Then publish the assets:
28+
29+
```bash
30+
php artisan vendor:publish --tag=laravel-media-assets
31+
```
32+
33+
## Usage ✨
34+
35+
Add the media picker component in your Blade view:
36+
37+
```blade
38+
<x-media-picker name="media_id" />
39+
```
40+
41+
This will render a button. Clicking it opens a modal with existing media and an upload form.
42+
43+
## Configuration Options
44+
45+
In `config/laravel-media.php`:
46+
47+
* `default_disk` — Filesystem disk to store uploaded files. Default: `public`
48+
* `path_prefix` — Path prefix in storage. Default: `media`
49+
* `default_collection` — Used if no collection specified
50+
* `preserve_original_name` — Whether to keep original filename
51+
52+
## Advanced
53+
54+
* Auto-generates responsive UI
55+
* Built-in routes, views, and JS/CSS assets
56+
* Easily extendable via Livewire or AlpineJS
57+
58+
## License
59+
60+
MIT

config/laravel-media.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
return [
4+
'default_disk' => env('MEDIA_DISK', 'public'),
5+
6+
// Optional path prefix (e.g., media/yyyy/mm/dd)
7+
'path_prefix' => env('MEDIA_PATH_PREFIX', 'media'),
8+
9+
// Default collection name
10+
'default_collection' => 'default',
11+
12+
// Whether to use original filename or hash it
13+
'preserve_original_name' => false,
14+
];
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
public function up(): void
10+
{
11+
Schema::create('media', function (Blueprint $table) {
12+
$table->id();
13+
$table->string('name');
14+
$table->string('file_name'); // stored path
15+
$table->string('mime_type');
16+
$table->string('disk')->default('public');
17+
$table->unsignedBigInteger('size');
18+
$table->string('collection')->default('default');
19+
// Polymorphic relation (model_type + model_id)
20+
$table->nullableMorphs('model');
21+
$table->timestamps();
22+
});
23+
}
24+
25+
public function down(): void
26+
{
27+
Schema::dropIfExists('media');
28+
}
29+
};

resources/css/laravel-media.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
.media-modal {
2+
position: fixed; top: 10%; left: 10%;
3+
background: #fff; border: 1px solid #ccc;
4+
padding: 20px; z-index: 9999;
5+
width: 80%; height: 70%;
6+
overflow: auto;
7+
}
8+
9+
.hidden { display: none; }
10+
11+
.media-grid {
12+
display: flex;
13+
flex-wrap: wrap;
14+
gap: 10px;
15+
}
16+
17+
.media-thumb img {
18+
width: 100px;
19+
height: 100px;
20+
object-fit: cover;
21+
border: 2px solid #ccc;
22+
cursor: pointer;
23+
}

resources/js/laravel-media.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function openMediaModal() {
2+
document.querySelector('#mediaModal').classList.remove('hidden');
3+
fetchMedia();
4+
}
5+
6+
function closeMediaModal() {
7+
document.querySelector('#mediaModal').classList.add('hidden');
8+
}
9+
10+
function fetchMedia() {
11+
fetch(mediaBrowserUrl)
12+
.then(res => res.text())
13+
.then(html => document.querySelector('#media-gallery').innerHTML = html);
14+
}
15+
16+
document.addEventListener('DOMContentLoaded', function () {
17+
document.querySelector('#media-upload-form')?.addEventListener('submit', function (e) {
18+
e.preventDefault();
19+
const formData = new FormData(this);
20+
21+
fetch(mediaUploadUrl, {
22+
method: 'POST',
23+
body: formData,
24+
headers: { 'X-CSRF-TOKEN': csrf }
25+
}).then(() => fetchMedia());
26+
});
27+
});
28+
29+
function selectMedia(id) {
30+
document.querySelector('#selectedMediaId').value = id;
31+
closeMediaModal();
32+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<div>
2+
<button type="button" onclick="openMediaModal()">📁 Select Media</button>
3+
<input type="hidden" name="media_id" id="selectedMediaId">
4+
5+
<div id="mediaModal" class="media-modal hidden">
6+
<div class="media-modal-content">
7+
<h2>📸 Media Library</h2>
8+
<form id="media-upload-form" enctype="multipart/form-data">
9+
<input type="file" name="file" required>
10+
<button type="submit">Upload</button>
11+
</form>
12+
13+
<div id="media-gallery" class="media-grid mt-4"></div>
14+
15+
<button onclick="closeMediaModal()">❌ Close</button>
16+
</div>
17+
</div>
18+
</div>
19+
20+
<link rel="stylesheet" href="{{ asset('vendor/laravel-media/media.css') }}">
21+
<script src="{{ asset('vendor/laravel-media/laravel-media.js') }}"></script>
22+
<script>
23+
const mediaBrowserUrl = "{{ route('laravel-media.browser') }}";
24+
const mediaUploadUrl = "{{ route('laravel-media.upload') }}";
25+
const csrf = '{{ csrf_token() }}';
26+
</script>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@foreach($media as $item)
2+
<div onclick="selectMedia({{ $item->id }})" class="media-thumb">
3+
<img src="{{ Storage::disk($item->disk)->url($item->file_name) }}" alt="{{ $item->name }}" />
4+
</div>
5+
@endforeach

routes/web.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
use Illuminate\Support\Facades\Route;
3+
use Illuminate\Http\Request;
4+
use Exitdump\LaravelMedia\Models\Media;
5+
use Exitdump\LaravelMedia\MediaHandler;
6+
7+
Route::prefix('laravel-media')->name('laravel-media.')->group(function () {
8+
Route::get('/browser', function () {
9+
$media = Media::latest()->get();
10+
return view('laravel-media::partials.media-grid', compact('media'));
11+
})->name('browser');
12+
13+
Route::post('/upload', function (Request $request) {
14+
$request->validate(['file' => 'required|file|max:2048']);
15+
$handler = new MediaHandler();
16+
$handler->upload($request->file('file'));
17+
return response()->json(['success' => true]);
18+
})->name('upload');
19+
});

src/Facades/LaravelMedia.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Exitdump\LaravelMedia\Facades;
4+
5+
use Illuminate\Support\Facades\Facade;
6+
7+
class LaravelMedia extends Facade
8+
{
9+
protected static function getFacadeAccessor()
10+
{
11+
return 'laravel-media';
12+
}
13+
}

src/LaravelMedia.php

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,40 @@
22

33
namespace Exitdump\LaravelMedia;
44

5+
use App\Models\User;
6+
use Illuminate\Http\UploadedFile;
7+
use Exitdump\LaravelMedia\MediaHandler;
8+
59
class LaravelMedia
610
{
7-
public function handle()
11+
protected $handler;
12+
protected $collection = 'default';
13+
protected $model = null;
14+
15+
public function __construct(MediaHandler $handler)
16+
{
17+
$this->handler = $handler;
18+
}
19+
20+
21+
public function upload(UploadedFile $file)
822
{
9-
return 'its working';
23+
return $this->handler->upload($file, $this->model, $this->collection);
24+
}
25+
26+
public function associateWith($model)
27+
{
28+
$this->model = $model;
29+
return $this;
30+
}
31+
32+
public function toCollection($collection)
33+
{
34+
$this->collection = $collection;
35+
return $this;
36+
}
37+
38+
public function test(){
39+
dd('test pass from pkg entry point');
1040
}
11-
}
41+
}

0 commit comments

Comments
 (0)