Merge pull request #1842 from cuneytsenturk/master

File group drag and drop developement
This commit is contained in:
Cüneyt Şentürk 2021-02-10 12:46:46 +03:00 committed by GitHub
commit baa9bc64d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 256 additions and 66 deletions

View File

@ -66,7 +66,17 @@ class Payments extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('purchases.payments.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'vendors', 'categories', 'payment_methods'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('purchases.payments.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'vendors', 'categories', 'payment_methods', 'file_types'));
}
/**
@ -166,7 +176,17 @@ class Payments extends Controller
$date_format = $this->getCompanyDateFormat();
return view('purchases.payments.edit', compact('payment', 'accounts', 'currencies', 'currency', 'vendors', 'categories', 'payment_methods', 'date_format'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('purchases.payments.edit', compact('payment', 'accounts', 'currencies', 'currency', 'vendors', 'categories', 'payment_methods', 'date_format', 'file_types'));
}
/**

View File

@ -66,7 +66,17 @@ class Revenues extends Controller
$payment_methods = Modules::getPaymentMethods();
return view('sales.revenues.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'customers', 'categories', 'payment_methods'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('sales.revenues.create', compact('accounts', 'currencies', 'account_currency_code', 'currency', 'customers', 'categories', 'payment_methods', 'file_types'));
}
/**
@ -166,7 +176,17 @@ class Revenues extends Controller
$date_format = $this->getCompanyDateFormat();
return view('sales.revenues.edit', compact('revenue', 'accounts', 'currencies', 'currency', 'customers', 'categories', 'payment_methods', 'date_format'));
$file_type_mimes = explode(',', config('filesystems.mimes'));
$file_types = [];
foreach ($file_type_mimes as $mime) {
$file_types[] = '.' . $mime;
}
$file_types = implode(',', $file_types);
return view('sales.revenues.edit', compact('revenue', 'accounts', 'currencies', 'currency', 'customers', 'categories', 'payment_methods', 'date_format', 'file_types'));
}
/**

View File

@ -148,6 +148,7 @@ class Kernel extends HttpKernel
'company.currencies' => \App\Http\Middleware\LoadCurrencies::class,
'company.settings' => \App\Http\Middleware\LoadSettings::class,
'company.signed' => \App\Http\Middleware\SignedCompany::class,
'dropzone' => \App\Http\Middleware\Dropzone::class,
'header.x' => \App\Http\Middleware\AddXHeader::class,
'menu.admin' => \App\Http\Middleware\AdminMenu::class,
'menu.portal' => \App\Http\Middleware\PortalMenu::class,

View File

@ -0,0 +1,65 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Arr;
class Dropzone
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (($request->method() != 'POST') && ($request->method() != 'PATCH')) {
return $next($request);
}
$multiple = false;
foreach ($request->all() as $key => $value) {
if (!is_array($value)) {
continue;
}
$files = [];
$uploaded = [];
foreach ($value as $index => $parameter) {
// single file uploaded..
if (!is_array($parameter) && !$multiple) {
if (!Arr::has($value, 'dropzone')) {
continue;
}
$request->request->set('uploaded_' . $key, $value);
unset($request[$key]);
break;
}
// multiple file uploaded..
if (!Arr::has($parameter, 'dropzone')) {
$files[] = $parameter;
continue;
}
$multiple = true;
$uploaded[] = $parameter;
}
if ($multiple && $uploaded) {
$request->request->set('uploaded_' . $key, $uploaded);
$request->request->set($key, $files);
}
}
return $next($request);
}
}

View File

@ -41,7 +41,7 @@ class Transaction extends FormRequest
'contact_id' => 'nullable|integer',
'category_id' => 'required|integer',
'payment_method' => 'required|string',
'attachment' => $attachment,
'attachment.*' => $attachment,
];
}

View File

@ -37,9 +37,11 @@ class CreateTransaction extends Job
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, 'transactions');
$this->transaction->attachMedia($media, 'attachment');
$this->transaction->attachMedia($media, 'attachment');
}
}
// Recurring

View File

@ -37,9 +37,15 @@ class UpdateTransaction extends Job
// Upload attachment
if ($this->request->file('attachment')) {
$media = $this->getMedia($this->request->file('attachment'), 'transactions');
$this->deleteMediaModel($this->transaction, 'attachment', $this->request);
$this->transaction->attachMedia($media, 'attachment');
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, 'transactions');
$this->transaction->attachMedia($media, 'attachment');
}
} elseif (!$this->request->file('attachment') && $this->transaction->attachment) {
$this->deleteMediaModel($this->transaction, 'attachment', $this->request);
}
// Recurring

View File

@ -46,13 +46,15 @@ class UpdateDocument extends Job
\DB::transaction(function () {
// Upload attachment
if ($this->request->file('attachment')) {
$this->document->delete_attachment();
$this->deleteMediaModel($this->document, 'attachment', $this->request);
foreach ($this->request->file('attachment') as $attachment) {
$media = $this->getMedia($attachment, Str::plural($this->document->type));
$this->document->attachMedia($media, 'attachment');
}
} elseif (!$this->request->file('attachment') && $this->document->attachment) {
$this->deleteMediaModel($this->document, 'attachment', $this->request);
}
$this->deleteRelationships($this->document, ['items', 'item_taxes', 'totals']);

View File

@ -3,6 +3,7 @@
namespace App\Models\Banking;
use App\Abstracts\Model;
use App\Models\Common\Media as MediaModel;
use App\Models\Setting\Category;
use App\Scopes\Transaction as Scope;
use App\Traits\Currencies;
@ -320,7 +321,16 @@ class Transaction extends Model
return false;
}
return $this->getMedia('attachment')->last();
return $this->getMedia('attachment')->all();
}
public function delete_attachment()
{
if ($attachments = $this->attachment) {
foreach ($attachments as $file) {
MediaModel::where('id', $file->id)->delete();
}
}
}
/**

View File

@ -3,10 +3,10 @@
namespace App\Traits;
use MediaUploader;
use App\Models\Common\Media as MediaModel;
trait Uploads
{
public function getUploadedFilePath($file, $folder = 'settings', $company_id = null)
{
$path = '';
@ -63,4 +63,35 @@ trait Uploads
return MediaUploader::importPath($disk, $path);
}
public function deleteMediaModel($model, $parameter, $request = null)
{
$medias = $model->$parameter;
if (!$medias) {
return;
}
$already_uploaded = [];
if ($request && isset($request['uploaded_' . $parameter])) {
$uploaded = $request['uploaded_' . $parameter];
if (count($medias) == count($uploaded)) {
return;
}
foreach ($uploaded as $old_media) {
$already_uploaded[] = $old_media['id'];
}
}
foreach ((array)$medias as $media) {
if (in_array($media->id, $already_uploaded)) {
continue;
}
MediaModel::where('id', $media->id)->delete();
}
}
}

View File

@ -11,6 +11,10 @@
<div v-if="preview == 'single'" class="dz-preview dz-preview-single" :class="previewClasses" ref="previewSingle">
<div class="dz-preview-cover">
<img class="dz-preview-img" data-dz-thumbnail>
<i class="fas fa-file-image display-3 d-none" data-dz-thumbnail-image></i>
<i class="far fa-file-pdf display-3 d-none" data-dz-thumbnail-pdf></i>
<i class="far fa-file-word d-none" data-dz-thumbnail-word></i>
<i class="far fa-file-excel d-none" data-dz-thumbnail-excel></i>
</div>
</div>
@ -20,6 +24,10 @@
<div class="col-auto">
<div class="avatar">
<img class="avatar-img rounded" data-dz-thumbnail>
<i class="fas fa-file-image display-3 d-none" data-dz-thumbnail-image></i>
<i class="far fa-file-pdf display-3 d-none" data-dz-thumbnail-pdf></i>
<i class="far fa-file-word d-none" data-dz-thumbnail-word></i>
<i class="far fa-file-excel d-none" data-dz-thumbnail-excel></i>
</div>
</div>
@ -133,6 +141,24 @@ export default {
} else {
self.$emit('change', self.files);
}
if (file.type.indexOf("image") == -1) {
var ext = file.name.split('.').pop();
if (ext == "pdf") {
file.previewElement.querySelector("[data-dz-thumbnail]").classList.add("d-none");
file.previewElement.querySelector("[data-dz-thumbnail-pdf]").classList.remove("d-none");
} else if ((ext.indexOf("doc") != -1) || (ext.indexOf("docx") != -1)) {
file.previewElement.querySelector("[data-dz-thumbnail]").classList.add("d-none");
file.previewElement.querySelector("[data-dz-thumbnail-word]").classList.remove("d-none");
} else if ((ext.indexOf("xls") != -1) || (ext.indexOf("xlsx") != -1)) {
file.previewElement.querySelector("[data-dz-thumbnail]").classList.add("d-none");
file.previewElement.querySelector("[data-dz-thumbnail-excel]").classList.remove("d-none");
} else {
file.previewElement.querySelector("[data-dz-thumbnail]").classList.add("d-none");
file.previewElement.querySelector("[data-dz-thumbnail-image]").classList.remove("d-none");
}
}
}),
dropzone.on('removedfile', function (file) {
@ -163,15 +189,27 @@ export default {
if (self.attachments.length) {
setTimeout(() => {
self.attachments.forEach(async (attachment) => {
let blob = await self.getAttachmentContent(attachment.path);
let file = new File([blob], attachment.name, { type: blob.type });
var mockFile = {
id: attachment.id,
name: attachment.name,
size: attachment.size,
type: attachment.type,
download: attachment.downloadPath,
dropzone: 'edit',
};
dropzone.displayExistingFile(file, attachment.path, () => {
if (attachment.downloadPath) {
file.previewElement.querySelector("[data-dz-download]").href = attachment.downloadPath;
file.previewElement.querySelector("[data-dz-download]").classList.remove("d-none");
}
});
dropzone.emit("addedfile", mockFile);
dropzone.options.thumbnail.call(dropzone, mockFile, attachment.path);
// Make sure that there is no progress bar, etc...
dropzone.emit("complete", mockFile);
});
self.files.forEach(async (attachment) => {
if (attachment.download) {
attachment.previewElement.querySelector("[data-dz-download]").href = attachment.download;
attachment.previewElement.querySelector("[data-dz-download]").classList.remove("d-none");
}
});
if (self.preview == 'single' && self.attachments.length == 1) {
@ -186,12 +224,6 @@ export default {
preview.innerHTML = '';
},
async getAttachmentContent(imageUrl) {
return await axios.get(imageUrl, { responseType: 'blob' }).then(function (response) {
return response.data;
});
}
},
async mounted() {

View File

@ -347,7 +347,11 @@ export default class Form {
submit() {
FormData.prototype.appendRecursive = function(data, wrapper = null) {
for(var name in data) {
for (var name in data) {
if (name == "previewElement" || name == "previewTemplate") {
continue;
}
if (wrapper) {
if ((typeof data[name] == 'object' || Array.isArray(data[name])) && ((data[name] instanceof File != true ) && (data[name] instanceof Blob != true))) {
this.appendRecursive(data[name], wrapper + '[' + name + ']');

View File

@ -45,17 +45,24 @@
@foreach($value as $attachment)
@php
$attachments[] = [
'id' => $attachment->id,
'name' => $attachment->filename . '.' . $attachment->extension,
'path' => route('uploads.get', $attachment->id),
'downloadPath' => route('uploads.download', $attachment->id)
'path' => route('uploads.get', $attachment->id),
'type' => $attachment->mime_type,
'size' => $attachment->size,
'downloadPath' => route('uploads.download', $attachment->id),
];
@endphp
@endforeach
@elseif ($value instanceof \Plank\Mediable\Media)
@php
$attachments[] = [
'id' => $value->id,
'name' => $value->filename . '.' . $value->extension,
'path' => route('uploads.get', $value->id)
'path' => route('uploads.get', $value->id),
'type' => $value->mime_type,
'size' => $value->size,
'downloadPath' => false,
];
@endphp
@else
@ -63,12 +70,16 @@
$attachment = \Plank\Mediable\Media::find($value);
$attachments[] = [
'id' => $attachment->id,
'name' => $attachment->filename . '.' . $attachment->extension,
'path' => route('uploads.get', $attachment->id)
'path' => route('uploads.get', $attachment->id),
'type' => $attachment->mime_type,
'size' => $attachment->size,
'downloadPath' => false,
];
@endphp
@endif
:attachments="{{ json_encode($attachments) }}"
@endif

View File

@ -38,9 +38,9 @@
{{ Form::textGroup('reference', trans('general.reference'), 'file', []) }}
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'form-file']) }}
{{ Form::selectGroup('document_id', trans_choice('general.bills', 1), 'file-invoice', [], null, ['disabled' => 'true']) }}
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'w-100', 'multiple' => 'multiple', 'options' => ['acceptedFiles' => $file_types]], null, 'col-md-12') }}
</div>
</div>

View File

@ -57,19 +57,12 @@
{{ Form::textGroup('reference', trans('general.reference'), 'file',[]) }}
@if ($payment->attachment)
<div class="col-md-6">
@php $file = $payment->attachment; @endphp
@include('partials.media.file')
</div>
@else
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'form-file']) }}
@endif
@if ($payment->bill)
{{ Form::textGroup('document', trans_choice('general.bills', 1), 'file-invoice', ['disabled' => 'true'], $payment->bill->document_number) }}
{{ Form::hidden('document_id', $payment->bill->id) }}
@endif
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'w-100', 'multiple' => 'multiple', 'options' => ['acceptedFiles' => $file_types]], $payment->attachment, 'col-md-12') }}
</div>
</div>

View File

@ -38,9 +38,9 @@
{{ Form::textGroup('reference', trans('general.reference'), 'file', []) }}
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'form-file']) }}
{{ Form::selectGroup('document_id', trans_choice('general.invoices', 1), 'file-invoice', [], null, ['disabled' => 'true']) }}
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'w-100', 'multiple' => 'multiple', 'options' => ['acceptedFiles' => $file_types]], null, 'col-md-12') }}
</div>
</div>

View File

@ -57,19 +57,12 @@
{{ Form::textGroup('reference', trans('general.reference'), 'file',[]) }}
@if ($revenue->attachment)
<div class="col-md-6">
@php $file = $revenue->attachment; @endphp
@include('partials.media.file')
</div>
@else
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'form-file']) }}
@endif
@if ($revenue->invoice)
{{ Form::textGroup('document', trans_choice('general.invoices', 1), 'file-invoice', ['disabled' => 'true'], $revenue->invoice->document_number) }}
{{ Form::hidden('document_id', $revenue->invoice->id) }}
@endif
{{ Form::fileGroup('attachment', trans('general.attachment'), '', ['dropzone-class' => 'w-100', 'multiple' => 'multiple', 'options' => ['acceptedFiles' => $file_types]], $revenue->attachment, 'col-md-12') }}
</div>
</div>

View File

@ -18,7 +18,7 @@ Route::group(['prefix' => 'common'], function () {
Route::get('companies/{company}/switch', 'Common\Companies@switch')->name('companies.switch');
Route::get('companies/{company}/enable', 'Common\Companies@enable')->name('companies.enable');
Route::get('companies/{company}/disable', 'Common\Companies@disable')->name('companies.disable');
Route::resource('companies', 'Common\Companies');
Route::resource('companies', 'Common\Companies', ['middleware' => ['dropzone']]);
Route::get('dashboards/{dashboard}/switch', 'Common\Dashboards@switch')->name('dashboards.switch');
Route::get('dashboards/{dashboard}/enable', 'Common\Dashboards@enable')->name('dashboards.enable');
@ -37,7 +37,7 @@ Route::group(['prefix' => 'common'], function () {
Route::get('items/export', 'Common\Items@export')->name('items.export');
Route::get('items/{item}/enable', 'Common\Items@enable')->name('items.enable');
Route::get('items/{item}/disable', 'Common\Items@disable')->name('items.disable');
Route::resource('items', 'Common\Items', ['middleware' => ['money']]);
Route::resource('items', 'Common\Items', ['middleware' => ['money', 'dropzone']]);
Route::resource('search', 'Common\Search');
@ -61,7 +61,7 @@ Route::group(['prefix' => 'auth'], function () {
Route::get('users/{user}/read-invoices', 'Auth\Users@readOverdueInvoices')->name('users.read.invoices');
Route::get('users/{user}/enable', 'Auth\Users@enable')->name('users.enable');
Route::get('users/{user}/disable', 'Auth\Users@disable')->name('users.disable');
Route::resource('users', 'Auth\Users');
Route::resource('users', 'Auth\Users', ['middleware' => ['dropzone']]);
Route::resource('roles', 'Auth\Roles');
@ -79,12 +79,12 @@ Route::group(['prefix' => 'sales'], function () {
Route::get('invoices/addItem', 'Sales\Invoices@addItem')->middleware(['money'])->name('invoice.add.item');
Route::post('invoices/import', 'Sales\Invoices@import')->name('invoices.import');
Route::get('invoices/export', 'Sales\Invoices@export')->name('invoices.export');
Route::resource('invoices', 'Sales\Invoices', ['middleware' => ['date.format', 'money']]);
Route::resource('invoices', 'Sales\Invoices', ['middleware' => ['date.format', 'money', 'dropzone']]);
Route::get('revenues/{revenue}/duplicate', 'Sales\Revenues@duplicate')->name('revenues.duplicate');
Route::post('revenues/import', 'Sales\Revenues@import')->name('revenues.import');
Route::get('revenues/export', 'Sales\Revenues@export')->name('revenues.export');
Route::resource('revenues', 'Sales\Revenues', ['middleware' => ['date.format', 'money']]);
Route::resource('revenues', 'Sales\Revenues', ['middleware' => ['date.format', 'money', 'dropzone']]);
Route::get('customers/currency', 'Sales\Customers@currency');
Route::get('customers/{customer}/duplicate', 'Sales\Customers@duplicate')->name('customers.duplicate');
@ -107,12 +107,12 @@ Route::group(['prefix' => 'purchases'], function () {
Route::get('bills/addItem', 'Purchases\Bills@addItem')->middleware(['money'])->name('bill.add.item');
Route::post('bills/import', 'Purchases\Bills@import')->name('bills.import');
Route::get('bills/export', 'Purchases\Bills@export')->name('bills.export');
Route::resource('bills', 'Purchases\Bills', ['middleware' => ['date.format', 'money']]);
Route::resource('bills', 'Purchases\Bills', ['middleware' => ['date.format', 'money', 'dropzone']]);
Route::get('payments/{payment}/duplicate', 'Purchases\Payments@duplicate')->name('payments.duplicate');
Route::post('payments/import', 'Purchases\Payments@import')->name('payments.import');
Route::get('payments/export', 'Purchases\Payments@export')->name('payments.export');
Route::resource('payments', 'Purchases\Payments', ['middleware' => ['date.format', 'money']]);
Route::resource('payments', 'Purchases\Payments', ['middleware' => ['date.format', 'money', 'dropzone']]);
Route::get('vendors/currency', 'Purchases\Vendors@currency');
Route::get('vendors/{vendor}/duplicate', 'Purchases\Vendors@duplicate')->name('vendors.duplicate');
@ -121,7 +121,7 @@ Route::group(['prefix' => 'purchases'], function () {
Route::get('vendors/{vendor}/enable', 'Purchases\Vendors@enable')->name('vendors.enable');
Route::get('vendors/{vendor}/currency', 'Purchases\Vendors@currency')->name('vendors.currency');
Route::get('vendors/{vendor}/disable', 'Purchases\Vendors@disable')->name('vendors.disable');
Route::resource('vendors', 'Purchases\Vendors');
Route::resource('vendors', 'Purchases\Vendors', ['middleware' => ['dropzone']]);
});
Route::group(['prefix' => 'banking'], function () {
@ -162,7 +162,7 @@ Route::group(['prefix' => 'settings'], function () {
Route::group(['as' => 'settings.'], function () {
Route::get('settings', 'Settings\Settings@index')->name('index');
Route::patch('settings', 'Settings\Settings@update')->name('update');
Route::get('company', 'Settings\Company@edit')->name('company.edit');
Route::get('company', 'Settings\Company@edit')->middleware('dropzone')->name('company.edit');
Route::get('localisation', 'Settings\Localisation@edit')->name('localisation.edit');
Route::get('invoice', 'Settings\Invoice@edit')->name('invoice.edit');
Route::get('default', 'Settings\Defaults@edit')->name('default.edit');
@ -174,7 +174,7 @@ Route::group(['prefix' => 'settings'], function () {
Route::group(['as' => 'settings.'], function () {
Route::get('{alias}/settings', 'Settings\Modules@edit')->name('module.edit');
Route::patch('{alias}/settings', 'Settings\Modules@update')->name('module.update');
Route::patch('{alias}/settings', 'Settings\Modules@update')->middleware('dropzone')->name('module.update');
});
Route::group(['as' => 'apps.', 'prefix' => 'apps'], function () {
@ -232,6 +232,6 @@ Route::group(['as' => 'modals.', 'prefix' => 'modals'], function () {
Route::patch('invoice-templates', 'Modals\InvoiceTemplates@update')->name('invoice-templates.update');
Route::get('documents/item-columns/edit', 'Modals\DocumentItemColumns@edit')->name('documents.item-columns.edit');
Route::patch('documents/item-columns', 'Modals\DocumentItemColumns@update')->name('documents.item-columns.update');
Route::resource('documents/{document}/transactions', 'Modals\DocumentTransactions', ['names' => 'documents.document.transactions', 'middleware' => ['date.format', 'money']]);
Route::resource('documents/{document}/transactions', 'Modals\DocumentTransactions', ['names' => 'documents.document.transactions', 'middleware' => ['date.format', 'money', 'dropzone']]);
Route::resource('taxes', 'Modals\Taxes');
});

View File

@ -20,7 +20,7 @@ Route::group(['as' => 'portal.'], function () {
Route::resource('payments', 'Portal\Payments');
Route::get('profile/read-invoices', 'Portal\Profile@readOverdueInvoices')->name('invoices.read');
Route::resource('profile', 'Portal\Profile');
Route::resource('profile', 'Portal\Profile', ['middleware' => ['dropzone']]);
Route::get('logout', 'Auth\Login@destroy')->name('logout');
});