Skip to content

Commit 282b81b

Browse files
committed
first commit
0 parents  commit 282b81b

16 files changed

+401
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules
2+
/vendor

Readme.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Litstack FileDownloads
2+
3+
Install:
4+
```shell
5+
composer require litstack/file-downloads
6+
```
7+
8+
Publish the migration and migrate:
9+
```shell
10+
php artisan vendor:publish --tag=lit-file-downloads
11+
php artisan migrate
12+
```
13+
14+
15+
Add the navigation item to your navigation:
16+
```php
17+
$nav->entry('File Downloads', [
18+
'link' => route('lit.file-downloads'),
19+
'icon' => '<i class="fas fa-download"></i>',
20+
]),
21+
```
22+

composer.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "litstack/file-downloads",
3+
"license": "MIT",
4+
"authors": [
5+
{
6+
"name": "jannescb",
7+
"email": "[email protected]"
8+
}
9+
],
10+
"scripts": {
11+
"test": "vendor/bin/phpunit"
12+
},
13+
"autoload": {
14+
"psr-4": {
15+
"Ignite\\FileDownloads\\": "src"
16+
}
17+
},
18+
"require": {
19+
"php": "^8.0"
20+
},
21+
"require-dev": {
22+
"phpunit/phpunit": "^9.5",
23+
"orchestra/testbench": "^6.19",
24+
"mockery/mockery": "^1.4"
25+
},
26+
"extra": {
27+
"laravel": {
28+
"providers": [
29+
"Ignite\\FileDownloads\\FileDownloadsServiceProvider"
30+
]
31+
},
32+
"branch-alias": {
33+
"dev-main": "1.x-dev"
34+
}
35+
},
36+
"minimum-stability": "dev",
37+
"prefer-stable": true
38+
}

dist/index.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mix-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"/dist/index.js": "/dist/index.js"
3+
}

package.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"name": "litstack-file-downloads",
3+
"version": "1.0.0",
4+
"description": "",
5+
"main": "resources/js/index.js",
6+
"scripts": {
7+
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
8+
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
9+
"watch": "npm run development -- --watch",
10+
"dev": "npm run development",
11+
"prod": "npm run production"
12+
},
13+
"author": "Jannes Behrens",
14+
"license": "MIT",
15+
"devDependencies": {
16+
"cross-env": "^7.0.2",
17+
"laravel-mix": "^5.0.9",
18+
"vue-template-compiler": "^2.6.12"
19+
}
20+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
use Illuminate\Support\Facades\Schema;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Database\Migrations\Migration;
6+
7+
class CreateFileDownloadsTable extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*
12+
* @return void
13+
*/
14+
public function up()
15+
{
16+
Schema::create('file_downloads', function (Blueprint $table) {
17+
$table->id();
18+
$table->string('display_name')->nullable();
19+
$table->string('group')->nullable();
20+
$table->string('disk')->nullable();
21+
$table->string('filepath')->nullable();
22+
$table->string('filename')->nullable();
23+
$table->string('mimetype')->nullable();
24+
$table->unsignedBigInteger('size')->nullable();
25+
$table->json('meta')->nullable();
26+
$table->timestamps();
27+
$table->unique(['disk', 'filepath']);
28+
});
29+
}
30+
31+
/**
32+
* Reverse the migrations.
33+
*
34+
* @return void
35+
*/
36+
public function down()
37+
{
38+
Schema::dropIfExists('files');
39+
}
40+
}

resources/js/Files.vue

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<template>
2+
<div class="w-100 pr-2 pl-2">
3+
<div
4+
v-cloak
5+
@drop.prevent="addFile"
6+
@dragover.prevent="active = true"
7+
@dragleave.prevent="active = false"
8+
class="file-download-dropzone mb-4"
9+
:class="{'active': active}"
10+
>
11+
<div class="file-download-dropzone-icon">
12+
<h2 >
13+
<template v-if="!busy">
14+
Drop Files here
15+
</template>
16+
<template v-if="busy">
17+
Uploading
18+
</template>
19+
</h2>
20+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-5 -5 24 24" width="24" fill="currentColor"><path d="M8 6.641l1.121-1.12a1 1 0 0 1 1.415 1.413L7.707 9.763a.997.997 0 0 1-1.414 0L3.464 6.934A1 1 0 1 1 4.88 5.52L6 6.641V1a1 1 0 1 1 2 0v5.641zM1 12h12a1 1 0 0 1 0 2H1a1 1 0 0 1 0-2z"></path></svg>
21+
</div>
22+
</div>
23+
<div v-for="file in files" >
24+
{{ file.filename }}
25+
</div>
26+
</div>
27+
</template>
28+
29+
<script>
30+
import axios from "axios";
31+
32+
33+
34+
export default {
35+
name: 'Files',
36+
props: {
37+
files: {
38+
type: Array,
39+
default: null
40+
}
41+
},
42+
data(){
43+
return {
44+
active: false,
45+
busy: false
46+
}
47+
},
48+
methods: {
49+
async addFile(event){
50+
this.active = false
51+
let files = event.dataTransfer.files;
52+
// let files = event.target.files;
53+
54+
55+
this.busy = true
56+
for (const n in files) {
57+
if (Object.hasOwnProperty.call(files, n)) {
58+
const file = files[n];
59+
await this.submit(file)
60+
}
61+
}
62+
this.busy = false
63+
window.location.reload
64+
},
65+
submit(file){
66+
let formData = new FormData()
67+
formData.append('file', file)
68+
return axios.post('file-downloads', formData)
69+
}
70+
}
71+
};
72+
</script>
73+
<style>
74+
.file-download-dropzone{
75+
position: relative;
76+
width: 100%;
77+
min-height: 150px;
78+
outline: 5px dashed #9c9da5;
79+
padding: 20px;
80+
background: #ccd7e1;
81+
border-radius: 10px;
82+
padding-bottom: 30px;
83+
}
84+
.file-download-dropzone.active{
85+
86+
background: #9c9da5;
87+
}
88+
.file-download-dropzone-icon{
89+
width: 100%;
90+
display: flex;
91+
align-items: center;
92+
flex-direction: column;
93+
opacity: .5;
94+
}
95+
.file-download-dropzone-icon svg{
96+
width: 80px;
97+
height: 80px;
98+
}
99+
</style>

resources/js/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Files from './Files.vue'
2+
3+
window.Lit.booting((Vue) => {
4+
Vue.component('Files', Files);
5+
});

resources/views/files.blade.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{{-- <Files /> --}}

src/Contracts/File.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Ignite\FileDownloads\Contracts;
4+
5+
use Illuminate\Contracts\Filesystem\Filesystem;
6+
use Symfony\Component\HttpFoundation\File\UploadedFile;
7+
8+
interface File
9+
{
10+
public static function newFromUploadedFile(UploadedFile $file, array $attributes = []);
11+
12+
public function getDiskName();
13+
14+
public function getFilepath(): ?string;
15+
16+
public function storage(): Filesystem;
17+
}

src/FileDownload.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Ignite\FileDownloads;
4+
5+
use Ignite\FileDownloads\Traits\IsFile;
6+
use Illuminate\Database\Eloquent\Model;
7+
8+
class FileDownload extends Model
9+
{
10+
use IsFile;
11+
12+
// protected $fileAttachmentModel = self::class;
13+
14+
protected $fillable = [
15+
'display_name', 'group', 'disk', 'filepath', 'filename', 'mimetype',
16+
'size', 'meta',
17+
];
18+
19+
protected $casts = [
20+
'size' => 'int',
21+
'meta' => 'json',
22+
];
23+
24+
protected $attributes = [
25+
'disk' => 'public',
26+
];
27+
}

src/FileDownloadsController.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Ignite\FileDownloads;
4+
5+
use Ignite\Page\Page;
6+
use Illuminate\Http\Request;
7+
8+
class FileDownloadsController
9+
{
10+
public function __invoke()
11+
{
12+
$page = new Page;
13+
$page->component('files');
14+
15+
$page->bind([
16+
'files' => FileDownload::all(),
17+
]);
18+
19+
return $page->title('File Downloads');
20+
}
21+
22+
public function upload(Request $request)
23+
{
24+
$file = FileDownload::newFromUploadedFile($request->file)->save();
25+
26+
return $file;
27+
}
28+
}

src/FileDownloadsServiceProvider.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace Ignite\FileDownloads;
4+
5+
use Ignite\Foundation\Litstack;
6+
use Ignite\Support\Facades\Route as LitstackRoute;
7+
use Illuminate\Support\ServiceProvider;
8+
9+
class FileDownloadsServiceProvider extends ServiceProvider
10+
{
11+
/**
12+
* Register application services.
13+
*
14+
* @return void
15+
*/
16+
public function register()
17+
{
18+
//
19+
}
20+
21+
/**
22+
* Boot application services.
23+
*
24+
* @return void
25+
*/
26+
public function boot()
27+
{
28+
$this->loadViewsFrom(__DIR__.'/../resources/views', 'lit-files');
29+
30+
$this->callAfterResolving('lit', function (Litstack $lit) {
31+
$lit->script(__DIR__.'/../dist/index.js');
32+
});
33+
34+
LitstackRoute::post('/file-downloads', FileDownloadsController::class.'@upload')
35+
->name('lit-file-upload');
36+
LitstackRoute::get('/file-downloads', FileDownloadsController::class)->name('file-downloads');
37+
38+
$this->publishes([
39+
__DIR__.'/../publish/migrations/create_file-downloads_table.php' => database_path('migrations/'.now()->format('Y_m_d_hms').'_create_file-downloads_table.php'),
40+
], 'lit-file-downloads');
41+
}
42+
}

0 commit comments

Comments
 (0)