Fixes #5859 - add file name/size to file upload UI (#5861)

* Fixes #5859 - add file name/size to file upload UI

* Reverting assetcontroller

Not sure exactly what happened here…

* Production assets
This commit is contained in:
snipe 2018-07-16 20:09:53 -07:00 committed by GitHub
parent b5de5ac19c
commit a4799a495a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 475 additions and 489 deletions

View file

@ -30,8 +30,8 @@ class AssetFilesController extends Controller
$destinationPath = config('app.private_uploads').'/assets';
if ($request->hasFile('assetfile')) {
foreach ($request->file('assetfile') as $file) {
if ($request->hasFile('file')) {
foreach ($request->file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$filename = 'hardware-'.$asset->id.'-'.str_random(8);
$filename .= '-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;

View file

@ -60,14 +60,14 @@ class AssetsController extends Controller
}
/**
* Returns a view that invokes the ajax tables which actually contains
* the content for the assets listing, which is generated in getDatatable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return View
*/
* Returns a view that invokes the ajax tables which actually contains
* the content for the assets listing, which is generated in getDatatable.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @return View
*/
public function index(Request $request)
{
$this->authorize('index', Asset::class);
@ -104,12 +104,12 @@ class AssetsController extends Controller
}
/**
* Validate and process new asset form data.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
* Validate and process new asset form data.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @return Redirect
*/
public function store(AssetRequest $request)
{
$this->authorize(Asset::class);
@ -195,7 +195,7 @@ class AssetsController extends Controller
}
}
// Was the asset created?
// Was the asset created?
if ($asset->save()) {
@ -223,13 +223,13 @@ class AssetsController extends Controller
}
/**
* Returns a view that presents a form to edit an existing asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
* Returns a view that presents a form to edit an existing asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
public function edit($assetId = null)
{
if (!$item = Asset::find($assetId)) {
@ -246,13 +246,13 @@ class AssetsController extends Controller
/**
* Returns a view that presents information about an asset for detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
* Returns a view that presents information about an asset for detail view.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
public function show($assetId = null)
{
$asset = Asset::withTrashed()->find($assetId);
@ -289,13 +289,13 @@ class AssetsController extends Controller
/**
* Validate and process asset edit form.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Redirect
*/
* Validate and process asset edit form.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Redirect
*/
public function update(AssetRequest $request, $assetId = null)
{
@ -404,13 +404,13 @@ class AssetsController extends Controller
}
/**
* Delete a given asset (mark as deleted).
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Redirect
*/
* Delete a given asset (mark as deleted).
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Redirect
*/
public function destroy($assetId)
{
// Check if the asset exists
@ -450,13 +450,13 @@ class AssetsController extends Controller
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
}
/**
* Return a QR code for the asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Response
*/
* Return a QR code for the asset
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return Response
*/
public function getQrCode($assetId = null)
{
$settings = Setting::getSettings();
@ -516,13 +516,13 @@ class AssetsController extends Controller
}
/**
* Returns a view that presents a form to clone an asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
* Returns a view that presents a form to clone an asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
public function getClone($assetId = null)
{
// Check if the asset exists
@ -540,9 +540,9 @@ class AssetsController extends Controller
$asset->assigned_to = '';
return view('hardware/edit')
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList())
->with('item', $asset);
->with('statuslabel_list', Helper::statusLabelList())
->with('statuslabel_types', Helper::statusTypeList())
->with('item', $asset);
}
/**
@ -641,15 +641,15 @@ class AssetsController extends Controller
$item[$asset_tag][$batch_counter]['user_id'] = $user->id;
Actionlog::firstOrCreate(array(
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
'action_type' => 'checkout',
));
'item_id' => $asset->id,
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer',
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
'target_type' => User::class,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
'action_type' => 'checkout',
));
$asset->assigned_to = $user->id;
@ -682,14 +682,14 @@ class AssetsController extends Controller
$asset_batch[$x]['real_checkin'] = $checkin_date;
Actionlog::firstOrCreate(array(
'item_id' => $asset_batch[$x]['asset_id'],
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by ' . Auth::user()->present()->fullName() . ' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
));
'item_id' => $asset_batch[$x]['asset_id'],
'item_type' => Asset::class,
'user_id' => Auth::user()->id,
'note' => 'Checkin imported by ' . Auth::user()->present()->fullName() . ' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin'
));
}
}
}
@ -698,13 +698,13 @@ class AssetsController extends Controller
}
/**
* Retore a deleted asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
* Retore a deleted asset.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @param int $assetId
* @since [v1.0]
* @return View
*/
public function getRestore($assetId = null)
{
// Get asset information
@ -775,14 +775,14 @@ class AssetsController extends Controller
if ($request->hasFile('image')) {
$file = $request->file('image');
try {
$destinationPath = config('app.private_uploads').'/audits';
$extension = $file->getClientOriginalExtension();
$filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
$file->move($destinationPath, $filename);
} catch (\Exception $e) {
\Log::error($e);
}
try {
$destinationPath = config('app.private_uploads').'/audits';
$extension = $file->getClientOriginalExtension();
$filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
$file->move($destinationPath, $filename);
} catch (\Exception $e) {
\Log::error($e);
}
}
$asset->logAudit($request->input('note'), $request->input('location_id'), $filename);

View file

@ -1,6 +1,7 @@
<?php
namespace App\Http\Controllers;
use App\Http\Requests\AssetFileRequest;
use Assets;
use Illuminate\Support\Facades\Session;
use Input;
@ -495,7 +496,7 @@ class LicensesController extends Controller
* @param int $licenseId
* @return \Illuminate\Http\RedirectResponse
*/
public function postUpload(Request $request, $licenseId = null)
public function postUpload(AssetFileRequest $request, $licenseId = null)
{
$license = License::find($licenseId);
// the license is valid
@ -504,18 +505,9 @@ class LicensesController extends Controller
if (isset($license->id)) {
$this->authorize('update', $license);
if (Input::hasFile('licensefile')) {
if (Input::hasFile('file')) {
foreach (Input::file('licensefile') as $file) {
$rules = array(
'licensefile' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar,rtf,xml,lic'
);
$validator = Validator::make(array('licensefile'=> $file), $rules);
if ($validator->fails()) {
return redirect()->back()->with('error', trans('admin/licenses/message.upload.invalidfiles'));
}
foreach (Input::file('file') as $file) {
$extension = $file->getClientOriginalExtension();
$filename = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
$upload_success = $file->move($destinationPath, $filename);

View file

@ -25,7 +25,7 @@ class AssetFileRequest extends Request
{
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
return [
'file.*' => 'required|mimes:png,gif,jpg,jpeg,doc,docx,pdf,txt,zip,rar|max:'.$max_file_size,
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,lic|max:'.$max_file_size,
];
}

540
npm-shrinkwrap.json generated

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

30
public/js/dist/all.js vendored

File diff suppressed because one or more lines are too long

View file

@ -3,12 +3,12 @@
"/css/AdminLTE.css": "/css/AdminLTE.css?id=5e72463a66acbcc740d5",
"/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405",
"/css/overrides.css": "/css/overrides.css?id=2d81c3704393bac77011",
"/js/build/vue.js.map": "/js/build/vue.js.map?id=66ce10b11abd9159c4f7",
"/js/build/vue.js.map": "/js/build/vue.js.map?id=0deaf852882fe2d65263",
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=0be7790b84909dca6a0a",
"/css/app.css.map": "/css/app.css.map?id=96b5c985e860716e6a16",
"/css/overrides.css.map": "/css/overrides.css.map?id=f7ce9ca49027594ac402",
"/css/dist/all.css": "/css/dist/all.css?id=98db4e9b7650453c8b00",
"/js/dist/all.js": "/js/dist/all.js?id=8b3cca34ec5a6828bcee",
"/js/dist/all.js": "/js/dist/all.js?id=9d02373ef452329336d3",
"/css/build/all.css": "/css/build/all.css?id=98db4e9b7650453c8b00",
"/js/build/all.js": "/js/build/all.js?id=8b3cca34ec5a6828bcee"
"/js/build/all.js": "/js/build/all.js?id=9d02373ef452329336d3"
}

View file

@ -344,9 +344,9 @@ $(document).ready(function () {
function formatBytes(bytes) {
if(bytes < 1024) return bytes + " Bytes";
else if(bytes < 1048576) return(bytes / 1024).toFixed(3) + " KB";
else if(bytes < 1073741824) return(bytes / 1048576).toFixed(3) + " MB";
else return(bytes / 1073741824).toFixed(3) + " GB";
else if(bytes < 1048576) return(bytes / 1024).toFixed(2) + " KB";
else if(bytes < 1073741824) return(bytes / 1048576).toFixed(2) + " MB";
else return(bytes / 1073741824).toFixed(2) + " GB";
};
// File size validation
@ -356,18 +356,24 @@ $(document).ready(function () {
$('.badfile').remove();
$('.badfile').remove();
$('.previewSize').hide();
$('#upload-file-info').html('');
var max_size = $('#uploadFile').data('maxsize');
var actual_size = this.files[0].size;
var total_size = 0;
if (actual_size > max_size) {
$('#upload-file-status').addClass('text-danger').removeClass('help-block').prepend('<i class="badfile fa fa-times"></i> ').append('<span class="previewSize">This file is ' + formatBytes(actual_size) + '.</span>');
for (var i = 0; i < this.files.length; i++) {
total_size += this.files[i].size;
$('#upload-file-info').append('<span class="label label-default">' + this.files[i].name + ' (' + formatBytes(this.files[i].size) + ')</span> ');
}
if (total_size > max_size) {
$('#upload-file-status').addClass('text-danger').removeClass('help-block').prepend('<i class="badfile fa fa-times"></i> ').append('<span class="previewSize"> Upload is ' + formatBytes(total_size) + '.</span>');
} else {
$('#upload-file-status').addClass('text-success').removeClass('help-block').prepend('<i class="goodfile fa fa-check"></i> ');
readURL(this);
$('#imagePreview').fadeIn();
}
$('#upload-file-info').html(this.files[0].name);
});

View file

@ -206,7 +206,7 @@
'unknown_admin' => 'Unknown Admin',
'username_format' => 'Username Format',
'update' => 'Update',
'upload_filetypes_help' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, and rar. Max upload size allowed is :size.',
'upload_filetypes_help' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, xls, txt, lic, zip, and rar. Max upload size allowed is :size.',
'uploaded' => 'Uploaded',
'user' => 'User',
'accepted' => 'accepted',

View file

@ -94,9 +94,11 @@
<li>
<a href="#files" data-toggle="tab"><span class="hidden-lg hidden-md"><i class="fa fa-files-o"></i></span> <span class="hidden-xs hidden-sm">{{ trans('general.files') }}</span></a>
</li>
<li class="pull-right">
<!-- <a href="#" data-toggle="modal" data-target="#uploadFileModal"><i class="fa fa-paperclip"></i> </a> -->
@can('update', \App\Models\Asset::class)
<li class="pull-right"><a href="#" data-toggle="modal" data-target="#uploadFileModal">
<i class="fa fa-paperclip"></i> {{ trans('button.upload') }}</a>
</li>
@endcan
</ul>
<div class="tab-content">
<div class="tab-pane fade in active" id="details">
@ -769,33 +771,6 @@
<div class="tab-pane fade" id="files">
<div class="row">
@can('update', \App\Models\Asset::class)
{{ Form::open([
'method' => 'POST',
'route' => ['upload/asset', $asset->id],
'files' => true, 'class' => 'form-horizontal' ]) }}
<div class="col-md-2">
<span class="btn btn-default btn-file">Browse for file...
{{ Form::file('assetfile[]', ['multiple' => 'multiple']) }}
</span>
</div>
<div class="col-md-7">
{{ Form::text('notes', Input::old('notes', Input::old('notes')), array('class' => 'form-control','placeholder' => 'Notes')) }}
</div>
<div class="col-md-3">
<button type="submit" class="btn btn-primary">{{ trans('button.upload') }}</button>
</div>
<div class="col-md-12">
<p>{{ trans('general.upload_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}</p>
<hr>
</div>
{{ Form::close() }}
@endcan
<div class="col-md-12">
<table
class="table table-striped snipe-table"
@ -881,11 +856,14 @@
</div> <!-- /.nav-tabs-custom -->
</div> <!-- /. col-md-12 -->
</div> <!-- /. row -->
@can('update', \App\Models\Asset::class)
@include ('modals.upload-file', ['item_type' => 'asset', 'item_id' => $asset->id])
@endcan
@stop
@section('moar_scripts')
@include ('partials.bootstrap-table')
@stop

View file

@ -270,10 +270,6 @@
<div class="tab-pane" id="uploads">
<div class="table-responsive">
<div id="upload-toolbar">
<a href="#" data-toggle="modal" data-target="#uploadFileModal" class="btn btn-default"><i class="fa fa-paperclip"></i> {{ trans('button.upload') }}</a>
</div>
<table
data-cookie-id-table="licenseUploadsTable"
data-id-table="licenseUploadsTable"
@ -390,41 +386,9 @@
</div> <!-- /.col -->
</div> <!-- /.row -->
<!-- Modal -->
<div class="modal fade" id="uploadFileModal" tabindex="-1" role="dialog" aria-labelledby="uploadFileModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="uploadFileModalLabel">Upload File</h4>
</div>
{{ Form::open([
'method' => 'POST',
'route' => ['upload/license', $license->id],
'files' => true, 'class' => 'form-horizontal' ]) }}
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<div class="modal-body">
<p>{{ trans('general.upload_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}</p>
<div class="form-group col-md-12">
<div class="input-group col-md-12">
<input class="col-md-12 form-control" type="text" name="notes" id="notes" placeholder="Notes">
</div>
</div>
<div class="form-group col-md-12">
<div class="input-group col-md-12">
{{ Form::file('licensefile[]', ['multiple' => 'multiple']) }}
</div>
</div>
</div> <!-- /.modal-body-->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('button.cancel') }}</button>
<button type="submit" class="btn btn-primary btn-sm">{{ trans('button.upload') }}</button>
</div>
{{ Form::close() }}
</div>
</div>
</div>
@can('update', \App\Models\License::class)
@include ('modals.upload-file', ['item_type' => 'license', 'item_id' => $license->id])
@endcan
@stop

View file

@ -0,0 +1,46 @@
<!-- Modal -->
<div class="modal fade" id="uploadFileModal" tabindex="-1" role="dialog" aria-labelledby="uploadFileModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="uploadFileModalLabel">Upload File</h4>
</div>
{{ Form::open([
'method' => 'POST',
'route' => ['upload/'.$item_type, $item_id],
'files' => true,
'class' => 'form-horizontal' ]) }}
<input type="hidden" name="_token" value="{{ csrf_token() }}" />
<div class="modal-body">
<div class="row">
<div class="col-md-3">
<label class="btn btn-default">
{{ trans('button.select_file') }}
<input type="file" name="file[]" multiple="true" id="uploadFile" data-maxsize="{{ \App\Helpers\Helper::file_upload_max_size() }}" accept="image/*,.csv,.zip,.rar,.doc,.docx,.xls,.xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel,text/plain,.pdf" style="display:none">
</label>
</div>
<div class="col-md-9">
<span id="upload-file-info"></span>
</div>
<div class="col-md-12">
<p class="help-block" id="upload-file-status">{{ trans('general.upload_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}</p>
</div>
<div class="col-md-12">
{{ Form::textarea('notes', Input::old('notes', Input::old('notes')), ['class' => 'form-control','placeholder' => 'Notes (Optional)', 'rows'=>3]) }}
</div>
</div>
</div> <!-- /.modal-body-->
<div class="modal-footer">
<a href="#" class="pull-left" data-dismiss="modal">{{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-primary">{{ trans('button.upload') }}</button>
</div>
{{ Form::close() }}
</div>
</div>
</div>