mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-25 05:34:06 -08:00
Merge branch 'develop' into fixes/get-id-for-current-user
This commit is contained in:
commit
d10fe77ee7
2
.github/workflows/tests-mysql.yml
vendored
2
.github/workflows/tests-mysql.yml
vendored
|
@ -76,4 +76,4 @@ jobs:
|
|||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||
DB_USERNAME: root
|
||||
run: php artisan test --parallel
|
||||
run: php artisan test
|
||||
|
|
2
.github/workflows/tests-postgres.yml
vendored
2
.github/workflows/tests-postgres.yml
vendored
|
@ -74,4 +74,4 @@ jobs:
|
|||
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||
DB_USERNAME: snipeit
|
||||
DB_PASSWORD: password
|
||||
run: php artisan test --parallel
|
||||
run: php artisan test
|
||||
|
|
2
.github/workflows/tests-sqlite.yml
vendored
2
.github/workflows/tests-sqlite.yml
vendored
|
@ -58,4 +58,4 @@ jobs:
|
|||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: sqlite_testing
|
||||
run: php artisan test --parallel
|
||||
run: php artisan test
|
||||
|
|
|
@ -6,6 +6,7 @@ use Illuminate\Console\Command;
|
|||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\Console\Helper\ProgressIndicator;
|
||||
|
||||
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
||||
|
@ -29,6 +30,11 @@ class ObjectImportCommand extends Command
|
|||
*/
|
||||
protected $description = 'Import Items from CSV';
|
||||
|
||||
/**
|
||||
* The progress indicator instance.
|
||||
*/
|
||||
protected ProgressIndicator $progressIndicator;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
|
@ -39,8 +45,6 @@ class ObjectImportCommand extends Command
|
|||
parent::__construct();
|
||||
}
|
||||
|
||||
private $bar;
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
|
@ -48,6 +52,8 @@ class ObjectImportCommand extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->progressIndicator = new ProgressIndicator($this->output);
|
||||
|
||||
$filename = $this->argument('filename');
|
||||
$class = title_case($this->option('item-type'));
|
||||
$classString = "App\\Importer\\{$class}Importer";
|
||||
|
@ -61,45 +67,24 @@ class ObjectImportCommand extends Command
|
|||
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
|
||||
// $logFile = $this->option('logfile');
|
||||
// Log::useFiles($logFile);
|
||||
$this->comment('======= Importing Items from '.$filename.' =========');
|
||||
$this->progressIndicator->start('======= Importing Items from '.$filename.' =========');
|
||||
|
||||
$importer->import();
|
||||
|
||||
$this->bar = null;
|
||||
|
||||
if (! empty($this->errors)) {
|
||||
$this->comment('The following Errors were encountered.');
|
||||
foreach ($this->errors as $asset => $error) {
|
||||
$this->comment('Error: Item: '.$asset.' failed validation: '.json_encode($error));
|
||||
}
|
||||
} else {
|
||||
$this->comment('All Items imported successfully!');
|
||||
}
|
||||
$this->comment('');
|
||||
$this->progressIndicator->finish('Import finished.');
|
||||
}
|
||||
|
||||
public function errorCallback($item, $field, $errorString)
|
||||
public function errorCallback($item, $field, $error)
|
||||
{
|
||||
$this->errors[$item->name][$field] = $errorString;
|
||||
$this->output->write("\x0D\x1B[2K");
|
||||
|
||||
$this->warn('Error: Item: '.$item->name.' failed validation: '.json_encode($error));
|
||||
}
|
||||
|
||||
public function progress($count)
|
||||
public function progress($importedItemsCount)
|
||||
{
|
||||
if (! $this->bar) {
|
||||
$this->bar = $this->output->createProgressBar($count);
|
||||
$this->progressIndicator->advance();
|
||||
}
|
||||
static $index = 0;
|
||||
$index++;
|
||||
if ($index < $count) {
|
||||
$this->bar->advance();
|
||||
} else {
|
||||
$this->bar->finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Tracks the current item for error messages
|
||||
private $updating;
|
||||
// An array of errors encountered while parsing
|
||||
private $errors;
|
||||
|
||||
/**
|
||||
* Log a message to file, configurable by the --log-file parameter.
|
||||
|
|
|
@ -1123,6 +1123,7 @@ class Helper
|
|||
'png' => 'far fa-image',
|
||||
'webp' => 'far fa-image',
|
||||
'avif' => 'far fa-image',
|
||||
'svg' => 'fas fa-vector-square',
|
||||
// word
|
||||
'doc' => 'far fa-file-word',
|
||||
'docx' => 'far fa-file-word',
|
||||
|
@ -1135,7 +1136,7 @@ class Helper
|
|||
//Text
|
||||
'txt' => 'far fa-file-alt',
|
||||
'rtf' => 'far fa-file-alt',
|
||||
'xml' => 'far fa-file-alt',
|
||||
'xml' => 'fas fa-code',
|
||||
// Misc
|
||||
'pdf' => 'far fa-file-pdf',
|
||||
'lic' => 'far fa-save',
|
||||
|
@ -1148,41 +1149,7 @@ class Helper
|
|||
return 'far fa-file';
|
||||
}
|
||||
|
||||
public static function show_file_inline($filename)
|
||||
{
|
||||
$extension = substr(strrchr($filename, '.'), 1);
|
||||
|
||||
if ($extension) {
|
||||
switch ($extension) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
case 'gif':
|
||||
case 'png':
|
||||
case 'webp':
|
||||
case 'avif':
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random encrypted password.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateEncyrptedPassword(): string
|
||||
{
|
||||
return bcrypt(self::generateUnencryptedPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random unencrypted password.
|
||||
|
|
|
@ -7,6 +7,7 @@ use Illuminate\Http\Response;
|
|||
use Illuminate\Http\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
class StorageHelper
|
||||
{
|
||||
public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
|
||||
|
@ -25,4 +26,64 @@ class StorageHelper
|
|||
return Storage::disk($disk)->download($filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This determines the file types that should be allowed inline and checks their fileinfo extension
|
||||
* to determine that they are safe to display inline.
|
||||
*
|
||||
* @author <A. Gianotto> [<snipe@snipe.net]>
|
||||
* @since v7.0.14
|
||||
* @param $file_with_path
|
||||
* @return bool
|
||||
*/
|
||||
public static function allowSafeInline($file_with_path) {
|
||||
|
||||
$allowed_inline = [
|
||||
'pdf',
|
||||
'svg',
|
||||
'jpg',
|
||||
'gif',
|
||||
'svg',
|
||||
'avif',
|
||||
'webp',
|
||||
'png',
|
||||
];
|
||||
|
||||
|
||||
// The file exists and is allowed to be displayed inline
|
||||
if (Storage::exists($file_with_path) && (in_array(pathinfo($file_with_path, PATHINFO_EXTENSION), $allowed_inline))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether to show the file inline or download it.
|
||||
*/
|
||||
public static function showOrDownloadFile($file, $filename) {
|
||||
|
||||
$headers = [];
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
// This is NOT allowed as inline - force it to be displayed as text in the browser
|
||||
if (self::allowSafeInline($file) != true) {
|
||||
$headers = array_merge($headers, ['Content-Type' => 'text/plain']);
|
||||
}
|
||||
}
|
||||
|
||||
// Everything else seems okay, but the file doesn't exist on the server.
|
||||
if (Storage::missing($file)) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
return Storage::download($file, $filename, $headers);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,50 +106,29 @@ class AccessoriesFilesController extends Controller
|
|||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function show($accessoryId = null, $fileId = null, $download = true) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
{
|
||||
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
|
||||
|
||||
// the accessory is valid
|
||||
if (isset($accessory->id)) {
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
}
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,8 @@ class StatuslabelsController extends Controller
|
|||
$request->except('deployable', 'pending', 'archived');
|
||||
|
||||
if (! $request->filled('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => ['Status label type is required.']]), 500);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => ['Status label type is required.']]));
|
||||
}
|
||||
|
||||
$statuslabel = new Statuslabel;
|
||||
|
|
|
@ -14,6 +14,7 @@ use App\Http\Transformers\UsersTransformer;
|
|||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
|
@ -371,6 +372,7 @@ class UsersController extends Controller
|
|||
|
||||
$user = new User;
|
||||
$user->fill($request->all());
|
||||
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$user->created_by = auth()->id();
|
||||
|
||||
if ($request->has('permissions')) {
|
||||
|
@ -452,6 +454,10 @@ class UsersController extends Controller
|
|||
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
|
|
@ -61,43 +61,30 @@ class AssetFilesController extends Controller
|
|||
*/
|
||||
public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
{
|
||||
$asset = Asset::find($assetId);
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
if ($asset = Asset::find($assetId)) {
|
||||
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]);
|
||||
|
||||
// Redirect to the hardware management page
|
||||
return redirect()->route('hardware.index')->with('error', $error);
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,7 +17,6 @@ use App\Models\Location;
|
|||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\View\Label;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
|
@ -52,6 +52,10 @@ class BulkAssetsController extends Controller
|
|||
}
|
||||
|
||||
$asset_ids = $request->input('ids');
|
||||
if ($request->input('bulk_actions') === 'checkout') {
|
||||
$request->session()->flashInput(['selected_assets' => $asset_ids]);
|
||||
return redirect()->route('hardware.bulkcheckout.show');
|
||||
}
|
||||
|
||||
// Figure out where we need to send the user after the update is complete, and store that in the session
|
||||
$bulk_back_url = request()->headers->get('referer');
|
||||
|
@ -571,31 +575,34 @@ class BulkAssetsController extends Controller
|
|||
}
|
||||
|
||||
$errors = [];
|
||||
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids, $request) {
|
||||
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference!
|
||||
foreach ($asset_ids as $asset_id) {
|
||||
$asset = Asset::findOrFail($asset_id);
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
|
||||
$checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
|
||||
|
||||
//TODO - I think this logic is duplicated in the checkOut method?
|
||||
if ($target->location_id != '') {
|
||||
$asset->location_id = $target->location_id;
|
||||
$asset->unsetEventDispatcher();
|
||||
// TODO - I don't know why this is being saved without events
|
||||
$asset::withoutEvents(function () use ($asset) {
|
||||
$asset->save();
|
||||
});
|
||||
}
|
||||
|
||||
if ($error) {
|
||||
array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||
if (!$checkout_success) {
|
||||
$errors = array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (! $errors) {
|
||||
// Redirect to the new asset page
|
||||
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids));
|
||||
}
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
|
||||
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
|
||||
}
|
||||
|
|
|
@ -112,40 +112,25 @@ class ComponentsFilesController extends Controller
|
|||
public function show($componentId = null, $fileId = null)
|
||||
{
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$component = Component::find($componentId);
|
||||
|
||||
|
||||
// the component is valid
|
||||
if (isset($component->id)) {
|
||||
if ($component = Component::find($componentId)) {
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
|
|
|
@ -104,7 +104,6 @@ class ConsumablesFilesController extends Controller
|
|||
* @since [v1.4]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Consumable\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null)
|
||||
|
@ -116,36 +115,18 @@ class ConsumablesFilesController extends Controller
|
|||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
|
|
|
@ -112,37 +112,19 @@ class LicenseFilesController extends Controller
|
|||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('NOT EXISTS for '.$file);
|
||||
Log::debug('NOT EXISTS URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
|
|
|
@ -7,9 +7,6 @@ use App\Http\Controllers\Controller;
|
|||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
@ -116,31 +113,30 @@ class UserFilesController extends Controller
|
|||
public function show($userId = null, $fileId = null)
|
||||
{
|
||||
|
||||
|
||||
if (empty($fileId)) {
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
$user = User::find($userId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
if ($user = User::find($userId)) {
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
return Storage::download('private_uploads/users/'.$log->filename);
|
||||
}
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
|
||||
return redirect()->back()->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
// Redirect to the user management page if the user doesn't exist
|
||||
|
|
|
@ -23,7 +23,7 @@ trait MayContainCustomFields
|
|||
return str_starts_with($attributes, '_snipeit_');
|
||||
});
|
||||
// if there are custom fields, find the one's that don't exist on the model's fieldset and add an error to the validator's error bag
|
||||
if (count($request_fields) > 0) {
|
||||
if (count($request_fields) > 0 && $validator->errors()->isEmpty()) {
|
||||
$request_fields->diff($asset_model?->fieldset?->fields?->pluck('db_column'))
|
||||
->each(function ($request_field_name) use ($request_fields, $validator) {
|
||||
if (CustomField::where('db_column', $request_field_name)->exists()) {
|
||||
|
|
|
@ -141,6 +141,8 @@ class ActionlogsTransformer
|
|||
if ($actionlog->item) {
|
||||
if ($actionlog->itemType() == 'asset') {
|
||||
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'accessory') {
|
||||
$file_url = route('show.accessoryfile', ['accessoryId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'license') {
|
||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'user') {
|
||||
|
@ -158,7 +160,6 @@ class ActionlogsTransformer
|
|||
[
|
||||
'url' => $file_url,
|
||||
'filename' => $actionlog->filename,
|
||||
'inlineable' => (bool) Helper::show_file_inline($actionlog->filename),
|
||||
] : null,
|
||||
|
||||
'item' => ($actionlog->item) ? [
|
||||
|
|
|
@ -21,7 +21,6 @@ abstract class Importer
|
|||
* Id of User performing import
|
||||
* @var
|
||||
*/
|
||||
|
||||
protected $created_by;
|
||||
/**
|
||||
* Are we updating items in the import
|
||||
|
@ -149,17 +148,23 @@ abstract class Importer
|
|||
{
|
||||
$headerRow = $this->csv->fetchOne();
|
||||
$this->csv->setHeaderOffset(0); //explicitly sets the CSV document header record
|
||||
$results = $this->normalizeInputArray($this->csv->getRecords($headerRow));
|
||||
|
||||
$this->populateCustomFields($headerRow);
|
||||
|
||||
DB::transaction(function () use (&$results) {
|
||||
DB::transaction(function () use ($headerRow) {
|
||||
$importedItemsCount = 0;
|
||||
Model::unguard();
|
||||
$resultsCount = count($results);
|
||||
foreach ($results as $row) {
|
||||
|
||||
foreach ($this->csv->getRecords($headerRow) as $row) {
|
||||
//Lowercase header values to ensure we're comparing values properly.
|
||||
$row = array_change_key_case($row, CASE_LOWER);
|
||||
|
||||
$this->handle($row);
|
||||
|
||||
$importedItemsCount++;
|
||||
|
||||
if ($this->progressCallback) {
|
||||
call_user_func($this->progressCallback, $resultsCount);
|
||||
call_user_func($this->progressCallback, $importedItemsCount);
|
||||
}
|
||||
|
||||
$this->log('------------- Action Summary ----------------');
|
||||
|
@ -237,22 +242,6 @@ abstract class Importer
|
|||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to lowercase header values to ensure we're comparing values properly.
|
||||
*
|
||||
* @param $results
|
||||
* @return array
|
||||
*/
|
||||
public function normalizeInputArray($results)
|
||||
{
|
||||
$newArray = [];
|
||||
foreach ($results as $index => $arrayToNormalize) {
|
||||
$newArray[$index] = array_change_key_case($arrayToNormalize);
|
||||
}
|
||||
|
||||
return $newArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Figure out the fieldname of the custom field
|
||||
*
|
||||
|
|
|
@ -196,7 +196,6 @@ class Importer extends Component
|
|||
'supplier' => trans('general.supplier'),
|
||||
'purchase_cost' => trans('general.purchase_cost'),
|
||||
'purchase_date' => trans('general.purchase_date'),
|
||||
'purchase_order' => trans('admin/licenses/form.purchase_order'),
|
||||
'asset_notes' => trans('general.item_notes', ['item' => trans('admin/hardware/general.asset')]),
|
||||
'model_notes' => trans('general.item_notes', ['item' => trans('admin/hardware/form.model')]),
|
||||
'manufacturer' => trans('general.manufacturer'),
|
||||
|
|
|
@ -8,9 +8,6 @@ trait CompanyableTrait
|
|||
* This trait is used to scope models to the current company. To use this scope on companyable models,
|
||||
* we use the "use Companyable;" statement at the top of the mode.
|
||||
*
|
||||
* We CANNOT USE THIS ON USERS, as it causes an infinite loop and prevents users from logging in, since this scope will be
|
||||
* applied to the currently logged in (or logging in) user in addition to the user model for viewing lists of users.
|
||||
*
|
||||
* @see \App\Models\Company\Company::scopeCompanyables()
|
||||
* @return void
|
||||
*/
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
"ext-exif": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^7.0",
|
||||
"fakerphp/faker": "^1.16",
|
||||
"larastan/larastan": "^2.9",
|
||||
"mockery/mockery": "^1.4",
|
||||
|
|
156
composer.lock
generated
156
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "3819ab4ef72eb77fabe494c0e746b83b",
|
||||
"content-hash": "5341bc5be02b3c33e28e46e06dd99f29",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alek13/slack",
|
||||
|
@ -11790,101 +11790,6 @@
|
|||
],
|
||||
"time": "2024-04-13T18:00:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brianium/paratest",
|
||||
"version": "v7.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paratestphp/paratest.git",
|
||||
"reference": "551f46f52a93177d873f3be08a1649ae886b4a30"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paratestphp/paratest/zipball/551f46f52a93177d873f3be08a1649ae886b4a30",
|
||||
"reference": "551f46f52a93177d873f3be08a1649ae886b4a30",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"ext-pcre": "*",
|
||||
"ext-reflection": "*",
|
||||
"ext-simplexml": "*",
|
||||
"fidry/cpu-core-counter": "^0.5.1 || ^1.0.0",
|
||||
"jean85/pretty-package-versions": "^2.0.5",
|
||||
"php": "~8.1.0 || ~8.2.0 || ~8.3.0",
|
||||
"phpunit/php-code-coverage": "^10.1.7",
|
||||
"phpunit/php-file-iterator": "^4.1.0",
|
||||
"phpunit/php-timer": "^6.0",
|
||||
"phpunit/phpunit": "^10.4.2",
|
||||
"sebastian/environment": "^6.0.1",
|
||||
"symfony/console": "^6.3.4 || ^7.0.0",
|
||||
"symfony/process": "^6.3.4 || ^7.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^12.0.0",
|
||||
"ext-pcov": "*",
|
||||
"ext-posix": "*",
|
||||
"infection/infection": "^0.27.6",
|
||||
"phpstan/phpstan": "^1.10.40",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1.4",
|
||||
"phpstan/phpstan-phpunit": "^1.3.15",
|
||||
"phpstan/phpstan-strict-rules": "^1.5.2",
|
||||
"squizlabs/php_codesniffer": "^3.7.2",
|
||||
"symfony/filesystem": "^6.3.1 || ^7.0.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/paratest",
|
||||
"bin/paratest.bat",
|
||||
"bin/paratest_for_phpstorm"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ParaTest\\": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Brian Scaturro",
|
||||
"email": "scaturrob@gmail.com",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Filippo Tessarotto",
|
||||
"email": "zoeslam@gmail.com",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Parallel testing for PHP",
|
||||
"homepage": "https://github.com/paratestphp/paratest",
|
||||
"keywords": [
|
||||
"concurrent",
|
||||
"parallel",
|
||||
"phpunit",
|
||||
"testing"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/paratestphp/paratest/issues",
|
||||
"source": "https://github.com/paratestphp/paratest/tree/v7.3.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/sponsors/Slamdunk",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://paypal.me/filippotessarotto",
|
||||
"type": "paypal"
|
||||
}
|
||||
],
|
||||
"time": "2023-10-31T09:24:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "clue/ndjson-react",
|
||||
"version": "v1.3.0",
|
||||
|
@ -12781,65 +12686,6 @@
|
|||
},
|
||||
"time": "2020-07-09T08:09:16+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jean85/pretty-package-versions",
|
||||
"version": "2.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Jean85/pretty-package-versions.git",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer-runtime-api": "^2.0.0",
|
||||
"php": "^7.1|^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^3.2",
|
||||
"jean85/composer-provided-replaced-stub-package": "^1.0",
|
||||
"phpstan/phpstan": "^1.4",
|
||||
"phpunit/phpunit": "^7.5|^8.5|^9.4",
|
||||
"vimeo/psalm": "^4.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Jean85\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alessandro Lai",
|
||||
"email": "alessandro.lai85@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A library to get pretty versions strings of installed dependencies",
|
||||
"keywords": [
|
||||
"composer",
|
||||
"package",
|
||||
"release",
|
||||
"versions"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Jean85/pretty-package-versions/issues",
|
||||
"source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6"
|
||||
},
|
||||
"time": "2024-03-08T09:58:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "justinrainbow/json-schema",
|
||||
"version": "5.3.0",
|
||||
|
|
|
@ -280,7 +280,6 @@ return [
|
|||
Illuminate\Redis\RedisServiceProvider::class,
|
||||
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||
Illuminate\Session\SessionServiceProvider::class,
|
||||
// Illuminate\Translation\TranslationServiceProvider::class, //replaced on next line
|
||||
App\Providers\SnipeTranslationServiceProvider::class, //we REPLACE the default Laravel translator with our own
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
@ -373,7 +372,7 @@ return [
|
|||
'Image' => Intervention\Image\ImageServiceProvider::class,
|
||||
'Carbon' => Carbon\Carbon::class,
|
||||
'Helper' => App\Helpers\Helper::class,
|
||||
// makes it much easier to use 'Helper::blah' in blades (which is where we usually use this)
|
||||
'StorageHelper' => App\Helpers\StorageHelper::class,
|
||||
'Icon' => App\Helpers\IconHelper::class,
|
||||
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v7.0.13',
|
||||
'full_app_version' => 'v7.0.13 - build 15514-gdc0949da7',
|
||||
'build_version' => '15514',
|
||||
'full_app_version' => 'v7.0.13 - build 15666-g03b01689b',
|
||||
'build_version' => '15666',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'gdc0949da7',
|
||||
'full_hash' => 'v7.0.13-265-gdc0949da7',
|
||||
'hash_version' => 'g03b01689b',
|
||||
'full_hash' => 'v7.0.13-144-g03b01689b',
|
||||
'branch' => 'develop',
|
||||
);
|
|
@ -79,6 +79,11 @@ return [
|
|||
'no_assets_selected' => 'You must select at least one asset from the list',
|
||||
],
|
||||
|
||||
'multi-checkout' => [
|
||||
'error' => 'Asset was not checked out, please try again|Assets were not checked out, please try again',
|
||||
'success' => 'Asset checked out successfully.|Assets checked out successfully.',
|
||||
],
|
||||
|
||||
'checkin' => [
|
||||
'error' => 'Asset was not checked in, please try again',
|
||||
'success' => 'Asset checked in successfully.',
|
||||
|
|
|
@ -434,6 +434,7 @@ return [
|
|||
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
||||
'placeholder_kit' => 'Select a kit',
|
||||
'file_not_found' => 'File not found',
|
||||
'log_record_not_found' => 'No record for that log entry was found.',
|
||||
'preview_not_available' => '(no preview)',
|
||||
'setup' => 'Setup',
|
||||
'pre_flight' => 'Pre-Flight',
|
||||
|
|
|
@ -155,99 +155,13 @@
|
|||
@can('accessories.files', $accessory)
|
||||
<div class="tab-pane" id="files">
|
||||
|
||||
<div class="table table-responsive">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table
|
||||
data-cookie-id-table="accessoryUploadsTable"
|
||||
data-id-table="accessoryUploadsTable"
|
||||
id="accessoryUploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-accessories-uploads-{{ str_slug($accessory->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($accessory->uploads->count() > 0)
|
||||
@foreach ($accessory->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
<x-icon type="paperclip" class="fa-2x" />
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ Helper::filetype_icon($file->filename) }}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
@if ( Helper::checkUploadIsImage($file->get_src('accessories')))
|
||||
<a href="{{ route('show.accessoryfile', ['accessoryId' => $accessory->id, 'fileId' => $file->id, 'download' => 'false']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show.accessoryfile', ['accessoryId' => $accessory->id, 'fileId' => $file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->filename }}
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/accessories/'.$file->filename) ? Storage::size('private_uploads/accessories/'.$file->filename) : '') }}">
|
||||
{{ @Helper::formatFilesizeUnits(Storage::exists('private_uploads/accessories/'.$file->filename) ? Storage::size('private_uploads/accessories/'.$file->filename) : '') }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td style="white-space: nowrap;">
|
||||
@if ($file->filename)
|
||||
<a href="{{ route('show.accessoryfile', [$accessory->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-download" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.download') }}</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show.accessoryfile', [$accessory->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $file->created_at }}</td>
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm" href="{{ route('delete/accessoryfile', [$accessory->id, $file->id]) }}" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}" data-title="{{ trans('general.delete') }}">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="8">{{ trans('general.no_results') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<x-filestable
|
||||
filepath="private_uploads/accessories/"
|
||||
showfile_routename="show.accessoryfile"
|
||||
deletefile_routename="delete/accessoryfile"
|
||||
:object="$accessory" />
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /.tab-pane -->
|
||||
|
|
142
resources/views/blade/filestable.blade.php
Normal file
142
resources/views/blade/filestable.blade.php
Normal file
|
@ -0,0 +1,142 @@
|
|||
<!-- begin redirect submit options -->
|
||||
@props([
|
||||
'filepath',
|
||||
'object',
|
||||
'showfile_routename',
|
||||
'deletefile_routename',
|
||||
])
|
||||
|
||||
<!-- begin non-ajaxed file listing table -->
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="{{ str_slug($object->name) }}UploadsTable"
|
||||
data-id-table="{{ str_slug($object->name) }}UploadsTable"
|
||||
id="{{ str_slug($object->name) }}}UploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-license-uploads-{{ str_slug($object->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="false" data-field="id" data-sortable="true">
|
||||
{{trans('general.id')}}
|
||||
</th>
|
||||
<th data-visible="true" data-field="type" data-sortable="true">
|
||||
{{trans('general.file_type')}}
|
||||
</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">
|
||||
{{ trans('general.image') }}
|
||||
</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">
|
||||
{{ trans('general.file_name') }}
|
||||
</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">
|
||||
{{ trans('general.filesize') }}
|
||||
</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">
|
||||
{{ trans('general.notes') }}
|
||||
</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">
|
||||
{{ trans('general.download') }}
|
||||
</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">
|
||||
{{ trans('general.created_at') }}
|
||||
</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_by" data-sortable="true">
|
||||
{{ trans('general.created_by') }}
|
||||
</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">
|
||||
{{ trans('table.actions') }}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($object->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
{{ $file->id }}
|
||||
</td>
|
||||
<td data-sort-value="{{ pathinfo($filepath.$file->filename, PATHINFO_EXTENSION) }}">
|
||||
@if (Storage::exists($filepath.$file->filename))
|
||||
<span class="sr-only">{{ pathinfo($filepath.$file->filename, PATHINFO_EXTENSION) }}</span>
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true" data-tooltip="true" data-title="{{ pathinfo($filepath.$file->filename, PATHINFO_EXTENSION) }}"></i>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
|
||||
@if (($file->filename) && (Storage::exists($filepath.$file->filename)))
|
||||
@if (Helper::checkUploadIsImage($file->get_src(str_plural(strtolower(class_basename(get_class($object)))))))
|
||||
<a href="{{ route($showfile_routename, [$object->id, $file->id, 'inline' => 'true']) }}" data-toggle="lightbox" data-type="image">
|
||||
<img src="{{ route($showfile_routename, [$object->id, $file->id, 'inline' => 'true']) }}" class="img-thumbnail" style="max-width: 50px;">
|
||||
</a>
|
||||
@else
|
||||
{{ trans('general.preview_not_available') }}
|
||||
@endif
|
||||
@else
|
||||
<x-icon type="x" class="text-danger" />
|
||||
{{ trans('general.file_not_found') }}
|
||||
@endif
|
||||
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->filename }}
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists($filepath.$file->filename)) ? Storage::size($filepath.$file->filename) : '' }}">
|
||||
{{ (Storage::exists($filepath.$file->filename)) ? Helper::formatFilesizeUnits(Storage::size($filepath.$file->filename)) : '' }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td style="white-space: nowrap;">
|
||||
@if ($file->filename)
|
||||
@if (Storage::exists($filepath.$file->filename))
|
||||
<a href="{{ route($showfile_routename, [$object->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<x-icon type="download" />
|
||||
<span class="sr-only">
|
||||
{{ trans('general.download') }}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ StorageHelper::allowSafeInline($filepath.$file->filename) ? route($showfile_routename, [$object->id, $file->id, 'inline' => 'true']) : '#' }}" class="btn btn-sm btn-default{{ StorageHelper::allowSafeInline($filepath.$file->filename) ? '' : ' disabled' }}" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->created_at }}
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->created_by }}
|
||||
</td>
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm hidden-print" href="{{ route($deletefile_routename, [$object->id, $file->id]) }}" data-content="Are you sure you wish to delete this file?" data-title="{{ trans('general.delete') }} {{ $file->filename }}?">
|
||||
<x-icon type="delete" />
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- end non-ajaxed file listing table -->
|
|
@ -140,96 +140,14 @@
|
|||
|
||||
@can('components.files', $component)
|
||||
<div class="tab-pane" id="files">
|
||||
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="componentUploadsTable"
|
||||
data-id-table="componentUploadsTable"
|
||||
id="componentUploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-components-uploads-{{ str_slug($component->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($component->uploads->count() > 0)
|
||||
@foreach ($component->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ Helper::filetype_icon($file->filename) }}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
@if ( Helper::checkUploadIsImage($file->get_src('components')))
|
||||
<a href="{{ route('show.componentfile', ['componentId' => $component->id, 'fileId' => $file->id, 'download' => 'false']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show.componentfile', ['componentId' => $component->id, 'fileId' => $file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->filename }}
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/components/'.$file->filename) ? Storage::size('private_uploads/components/'.$file->filename) : '') }}">
|
||||
{{ @Helper::formatFilesizeUnits(Storage::exists('private_uploads/components/'.$file->filename) ? Storage::size('private_uploads/components/'.$file->filename) : '') }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
<nobr><a href="{{ route('show.componentfile', [$component->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<x-icon type="download" />
|
||||
<span class="sr-only">{{ trans('general.download') }}</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show.componentfile', [$component->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
</nobr>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $file->created_at }}</td>
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm" href="{{ route('delete/componentfile', [$component->id, $file->id]) }}" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}" data-title="{{ trans('general.delete') }}">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="8">{{ trans('general.no_results') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<x-filestable
|
||||
filepath="private_uploads/components/"
|
||||
showfile_routename="show.componentfile"
|
||||
deletefile_routename="delete/componentfile"
|
||||
:object="$component" />
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /.tab-pane -->
|
||||
@endcan
|
||||
|
|
|
@ -428,102 +428,18 @@
|
|||
|
||||
|
||||
<div class="tab-pane" id="files">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<x-filestable
|
||||
filepath="private_uploads/consumables/"
|
||||
showfile_routename="show.consumablefile"
|
||||
deletefile_routename="delete/consumablefile"
|
||||
:object="$consumable" />
|
||||
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="table-responsive">
|
||||
|
||||
<table
|
||||
data-cookie-id-table="consumableUploadsTable"
|
||||
data-id-table="consumableUploadsTable"
|
||||
id="consumableUploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-consumables-uploads-{{ str_slug($consumable->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($consumable->uploads->count() > 0)
|
||||
@foreach ($consumable->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ Helper::filetype_icon($file->filename) }}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
@if ( Helper::checkUploadIsImage($file->get_src('consumables')))
|
||||
<a href="{{ route('show.consumablefile', ['consumableId' => $consumable->id, 'fileId' => $file->id, 'download' => 'false']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show.consumablefile', ['consumableId' => $consumable->id, 'fileId' => $file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->filename }}
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/consumables/'.$file->filename) ? Storage::size('private_uploads/consumables/'.$file->filename) : '') }}">
|
||||
{{ @Helper::formatFilesizeUnits(Storage::exists('private_uploads/consumables/'.$file->filename) ? Storage::size('private_uploads/consumables/'.$file->filename) : '') }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{!! nl2br(Helper::parseEscapedMarkedownInline($file->note)) !!}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
<a href="{{ route('show.consumablefile', [$consumable->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-download" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.download') }}</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show.consumablefile', [$consumable->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $file->created_at }}</td>
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm" href="{{ route('delete/consumablefile', [$consumable->id, $file->id]) }}" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}" data-title="{{ trans('general.delete') }}">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="8">{{ trans('general.no_results') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!--/ROW-->
|
||||
|
||||
</div><!--/FILES-->
|
||||
|
||||
<div class="tab-pane" id="history">
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<div class="dashboard small-box bg-teal">
|
||||
<div class="inner">
|
||||
<h3>{{ number_format(\App\Models\Asset::AssetsForShow()->count()) }}</h3>
|
||||
<p>{{ strtolower(trans('general.assets')) }}</p>
|
||||
<p>{{ trans('general.assets') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="assets" />
|
||||
|
@ -54,7 +54,7 @@
|
|||
<div class="dashboard small-box bg-maroon">
|
||||
<div class="inner">
|
||||
<h3>{{ number_format($counts['license']) }}</h3>
|
||||
<p>{{ strtolower(trans('general.licenses')) }}</p>
|
||||
<p>{{ trans('general.licenses') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="licenses" />
|
||||
|
@ -75,7 +75,7 @@
|
|||
<div class="dashboard small-box bg-orange">
|
||||
<div class="inner">
|
||||
<h3> {{ number_format($counts['accessory']) }}</h3>
|
||||
<p>{{ strtolower(trans('general.accessories')) }}</p>
|
||||
<p>{{ trans('general.accessories') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="accessories" />
|
||||
|
@ -96,7 +96,7 @@
|
|||
<div class="dashboard small-box bg-purple">
|
||||
<div class="inner">
|
||||
<h3> {{ number_format($counts['consumable']) }}</h3>
|
||||
<p>{{ strtolower(trans('general.consumables')) }}</p>
|
||||
<p>{{ trans('general.consumables') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="consumables" />
|
||||
|
@ -115,7 +115,7 @@
|
|||
<div class="dashboard small-box bg-yellow">
|
||||
<div class="inner">
|
||||
<h3>{{ number_format($counts['component']) }}</h3>
|
||||
<p>{{ strtolower(trans('general.components')) }}</p>
|
||||
<p>{{ trans('general.components') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="components" />
|
||||
|
@ -135,7 +135,7 @@
|
|||
<div class="dashboard small-box bg-light-blue">
|
||||
<div class="inner">
|
||||
<h3>{{ number_format($counts['user']) }}</h3>
|
||||
<p>{{ strtolower(trans('general.people')) }}</p>
|
||||
<p>{{ trans('general.people') }}</p>
|
||||
</div>
|
||||
<div class="icon" aria-hidden="true">
|
||||
<x-icon type="users" />
|
||||
|
|
|
@ -115,5 +115,12 @@
|
|||
|
||||
@section('moar_scripts')
|
||||
@include('partials/assets-assigned')
|
||||
<script nonce="{{ csrf_token() }}">
|
||||
$(function () {
|
||||
//if there's already a user selected, make sure their checked-out assets show up
|
||||
// (if there isn't one, it won't do anything)
|
||||
$('#assigned_user').change();
|
||||
});
|
||||
</script>
|
||||
|
||||
@stop
|
||||
|
|
|
@ -1362,102 +1362,11 @@
|
|||
<div class="tab-pane fade" id="files">
|
||||
<div class="row{{ ($asset->uploads->count() > 0 ) ? '' : ' hidden-print' }}">
|
||||
<div class="col-md-12">
|
||||
|
||||
@if ($asset->uploads->count() > 0)
|
||||
<table
|
||||
class="table table-striped snipe-table"
|
||||
id="assetFileHistory"
|
||||
data-pagination="true"
|
||||
data-id-table="assetFileHistory"
|
||||
data-search="true"
|
||||
data-side-pagination="client"
|
||||
data-sortable="true"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="desc"
|
||||
data-sort-name="created_at"
|
||||
data-show-export="true"
|
||||
data-export-options='{
|
||||
"fileName": "export-asset-{{ $asset->id }}-files",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'
|
||||
data-cookie-id-table="assetFileHistory">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach ($asset->uploads as $file)
|
||||
<tr>
|
||||
<td><i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i></td>
|
||||
<td>
|
||||
@if ( Helper::checkUploadIsImage($file->get_src('assets')))
|
||||
<a href="{{ route('show/assetfile', ['assetId' => $asset->id, 'fileId' =>$file->id]) }}" data-toggle="lightbox" data-type="image" data-title="{{ $file->filename }}" data-footer="{{ Helper::getFormattedDateObject($asset->last_checkout, 'datetime', false) }}">
|
||||
<img src="{{ route('show/assetfile', ['assetId' => $asset->id, 'fileId' =>$file->id]) }}" style="max-width: 50px;">
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (Storage::exists('private_uploads/assets/'.$file->filename))
|
||||
{{ $file->filename }}
|
||||
@else
|
||||
<del>{{ $file->filename }}</del>
|
||||
@endif
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/assets/'.$file->filename) ? Storage::size('private_uploads/assets/'.$file->filename) : '') }}">
|
||||
{{ @Helper::formatFilesizeUnits(Storage::exists('private_uploads/assets/'.$file->filename) ? Storage::size('private_uploads/assets/'.$file->filename) : '') }}
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (($file->filename) && (Storage::exists('private_uploads/assets/'.$file->filename)))
|
||||
<a href="{{ route('show/assetfile', [$asset->id, $file->id, 'download'=>'true']) }}" class="btn btn-sm btn-default hidden-print">
|
||||
<x-icon type="download" />
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show/assetfile', [$asset->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default hidden-print" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->created_at)
|
||||
{{ Helper::getFormattedDateObject($file->created_at, 'datetime', false) }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@can('update', \App\Models\Asset::class)
|
||||
<a class="btn delete-asset btn-sm btn-danger btn-sm hidden-print" href="{{ route('delete/assetfile', [$asset->id, $file->id]) }}" data-tooltip="true" data-title="Delete" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}">
|
||||
<x-icon type="delete" />
|
||||
</a>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-info alert-block hidden-print">
|
||||
<x-icon type="info-circle" />
|
||||
{{ trans('general.no_results') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<x-filestable
|
||||
filepath="private_uploads/assets/"
|
||||
showfile_routename="show/assetfile"
|
||||
deletefile_routename="delete/modelfile"
|
||||
:object="$asset" />
|
||||
</div> <!-- /.col-md-12 -->
|
||||
</div> <!-- /.row -->
|
||||
</div> <!-- /.tab-pane files -->
|
||||
|
@ -1467,101 +1376,11 @@
|
|||
<div class="row{{ (($asset->model) && ($asset->model->uploads->count() > 0)) ? '' : ' hidden-print' }}">
|
||||
<div class="col-md-12">
|
||||
|
||||
@if (($asset->model) && ($asset->model->uploads->count() > 0))
|
||||
<table
|
||||
class="table table-striped snipe-table"
|
||||
id="assetModelFileHistory"
|
||||
data-pagination="true"
|
||||
data-id-table="assetModelFileHistory"
|
||||
data-search="true"
|
||||
data-side-pagination="client"
|
||||
data-sortable="true"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="desc"
|
||||
data-sort-name="created_at"
|
||||
data-show-export="true"
|
||||
data-export-options='{
|
||||
"fileName": "export-assetmodel-{{ $asset->model->id }}-files",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'
|
||||
data-cookie-id-table="assetFileHistory">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach ($asset->model->uploads as $file)
|
||||
<tr>
|
||||
<td><i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i></td>
|
||||
<td>
|
||||
@if ( Helper::checkUploadIsImage($file->get_src('assetmodels')))
|
||||
<a href="{{ route('show/modelfile', ['modelID' => $asset->model->id, 'fileId' =>$file->id]) }}" data-toggle="lightbox" data-type="image" data-title="{{ $file->filename }}" data-footer="{{ Helper::getFormattedDateObject($asset->last_checkout, 'datetime', false) }}">
|
||||
<img src="{{ route('show/modelfile', ['modelID' => $asset->model->id, 'fileId' =>$file->id]) }}" style="max-width: 50px;">
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (Storage::exists('private_uploads/assetmodels/'.$file->filename))
|
||||
{{ $file->filename }}
|
||||
@else
|
||||
<del>{{ $file->filename }}</del>
|
||||
@endif
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/assetmodels/'.$file->filename)) ? Storage::size('private_uploads/assetmodels/'.$file->filename) : '' }}">
|
||||
{{ (Storage::exists('private_uploads/assetmodels/'.$file->filename)) ? Helper::formatFilesizeUnits(Storage::size('private_uploads/assetmodels/'.$file->filename)) : '' }}
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename)))
|
||||
<a href="{{ route('show/modelfile', [$asset->model->id, $file->id]) }}" class="btn btn-sm btn-default hidden-print">
|
||||
<x-icon type="download" class="hidden-print" />
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show/modelfile', [$asset->model->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default hidden-print" target="_blank">
|
||||
<x-icon type="external-link" class="hidden-print" />
|
||||
</a>
|
||||
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->created_at)
|
||||
{{ Helper::getFormattedDateObject($file->created_at, 'datetime', false) }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@can('update', \App\Models\AssetModel::class)
|
||||
<a class="btn delete-asset btn-sm btn-danger btn-sm hidden-print" href="{{ route('delete/modelfile', [$asset->model->id, $file->id]) }}" data-tooltip="true" data-title="Delete" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}">
|
||||
<x-icon type="delete" class="hidden-print"/></i>
|
||||
</a>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-info alert-block">
|
||||
<x-icon type="info-circle" />
|
||||
{{ trans('general.no_results') }}
|
||||
</div>
|
||||
@endif
|
||||
<x-filestable
|
||||
filepath="private_uploads/assetmodels/"
|
||||
showfile_routename="show/modelfile"
|
||||
deletefile_routename="userfile.destroy"
|
||||
:object="$asset->model" />
|
||||
|
||||
</div> <!-- /.col-md-12 -->
|
||||
</div> <!-- /.row -->
|
||||
|
|
|
@ -464,100 +464,13 @@
|
|||
|
||||
@can('licenses.files', $license)
|
||||
<div class="tab-pane" id="files">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="licenseUploadsTable"
|
||||
data-id-table="licenseUploadsTable"
|
||||
id="licenseUploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-license-uploads-{{ str_slug($license->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if ($license->uploads->count() > 0)
|
||||
@foreach ($license->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ Helper::filetype_icon($file->filename) }}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
@if ((Storage::exists('private_uploads/licenses/'.$file->filename)) && ( Helper::checkUploadIsImage($file->get_src('licenses'))))
|
||||
<a href="{{ route('show.licensefile', ['licenseId' => $license->id, 'fileId' => $file->id, 'download' => 'false']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show.licensefile', ['licenseId' => $license->id, 'fileId' => $file->id]) }}" class="img-thumbnail" style="max-width: 50px;"></a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (Storage::exists('private_uploads/licenses/'.$file->filename))
|
||||
{{ $file->filename }}
|
||||
@else
|
||||
<del>{{ $file->filename }}</del>
|
||||
@endif
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/licenses/'.$file->filename)) ? Storage::size('private_uploads/licenses/'.$file->filename) : '' }}">
|
||||
{{ (Storage::exists('private_uploads/licenses/'.$file->filename)) ? Helper::formatFilesizeUnits(Storage::size('private_uploads/licenses/'.$file->filename)) : '' }}
|
||||
</td>
|
||||
<x-filestable
|
||||
filepath="private_uploads/licenses/"
|
||||
showfile_routename="show.licensefile"
|
||||
deletefile_routename="delete/licensefile"
|
||||
:object="$license" />
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
<a href="{{ route('show.licensefile', [$license->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<x-icon type="download"/>
|
||||
<span class="sr-only">{{ trans('general.download') }}</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show.licensefile', [$license->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $file->created_at }}</td>
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm" href="{{ route('delete/licensefile', [$license->id, $file->id]) }}" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}" data-title="{{ trans('general.delete') }}">
|
||||
<x-icon type="delete" />
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="8">{{ trans('general.no_results') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div> <!-- /.tab-pane -->
|
||||
@endcan
|
||||
|
||||
|
|
|
@ -107,99 +107,11 @@
|
|||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
|
||||
@if ($model->uploads->count() > 0)
|
||||
<table
|
||||
class="table table-striped snipe-table"
|
||||
id="modelFileHistory"
|
||||
data-pagination="true"
|
||||
data-id-table="modelFileHistory"
|
||||
data-search="true"
|
||||
data-side-pagination="client"
|
||||
data-sortable="true"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="desc"
|
||||
data-sort-name="created_at"
|
||||
data-show-export="true"
|
||||
data-export-options='{
|
||||
"fileName": "export-asset-{{ $model->id }}-files",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
|
||||
}'
|
||||
data-cookie-id-table="assetFileHistory">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
@foreach ($model->uploads as $file)
|
||||
<tr>
|
||||
<td><i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i></td>
|
||||
<td>
|
||||
@if ((Storage::exists('private_uploads/assetmodels/'.$file->filename)) && ( Helper::checkUploadIsImage($file->get_src('assetmodels'))))
|
||||
<a href="{{ route('show/modelfile', ['modelID' => $model->id, 'fileId' => $file->id]) }}" data-toggle="lightbox" data-type="image" data-title="{{ $file->filename }}">
|
||||
<img src="{{ route('show/modelfile', ['modelID' => $model->id, 'fileId' =>$file->id]) }}" style="max-width: 50px;">
|
||||
</a>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if (Storage::exists('private_uploads/assetmodels/'.$file->filename))
|
||||
{{ $file->filename }}
|
||||
@else
|
||||
<del>{{ $file->filename }}</del>
|
||||
@endif
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/assetmodels/'.$file->filename)) ? Storage::size('private_uploads/assetmodels/'.$file->filename) : '' }}">
|
||||
{{ (Storage::exists('private_uploads/assetmodels/'.$file->filename)) ? Helper::formatFilesizeUnits(Storage::size('private_uploads/assetmodels/'.$file->filename)) : '' }}
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td style="white-space: nowrap">
|
||||
@if (($file->filename) && (Storage::exists('private_uploads/assetmodels/'.$file->filename)))
|
||||
<a href="{{ route('show/modelfile', [$model->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<i class="fas fa-download" aria-hidden="true"></i>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show/modelfile', [$model->id, $file->id, 'inline'=>'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->created_at)
|
||||
{{ Helper::getFormattedDateObject($file->created_at, 'datetime', false) }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@can('update', \App\Models\AssetModel::class)
|
||||
<a class="btn delete-asset btn-sm btn-danger btn-sm" href="{{ route('delete/assetfile', [$model->id, $file->id]) }}" data-tooltip="true" data-title="Delete" data-content="{{ trans('general.delete_confirm', ['item' => $file->filename]) }}"><i class="fas fa-trash icon-white" aria-hidden="true"></i></a>
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-info alert-block">
|
||||
<i class="fas fa-info-circle"></i>
|
||||
{{ trans('general.no_results') }}
|
||||
</div>
|
||||
@endif
|
||||
<x-filestable
|
||||
filepath="private_uploads/assetmodels/"
|
||||
showfile_routename="show/modelfile"
|
||||
deletefile_routename="delete/modelfile"
|
||||
:object="$model" />
|
||||
|
||||
</div> <!-- /.col-md-12 -->
|
||||
</div> <!-- /.row -->
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
@can('update', \App\Models\Asset::class)
|
||||
<option value="edit">{{ trans('button.edit') }}</option>
|
||||
@endcan
|
||||
@can('checkout', \App\Models\Asset::class)
|
||||
<option value="checkout">{{ trans('general.bulk_checkout') }}</option>
|
||||
@endcan
|
||||
@can('delete', \App\Models\Asset::class)
|
||||
<option value="delete">{{ trans('button.delete') }}</option>
|
||||
@endcan
|
||||
|
|
|
@ -971,102 +971,11 @@
|
|||
<div class="row">
|
||||
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
data-cookie-id-table="userUploadsTable"
|
||||
data-id-table="userUploadsTable"
|
||||
id="userUploadsTable"
|
||||
data-search="true"
|
||||
data-pagination="true"
|
||||
data-side-pagination="client"
|
||||
data-show-columns="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-export="true"
|
||||
data-show-footer="true"
|
||||
data-toolbar="#upload-toolbar"
|
||||
data-show-refresh="true"
|
||||
data-sort-order="asc"
|
||||
data-sort-name="name"
|
||||
class="table table-striped snipe-table"
|
||||
data-export-options='{
|
||||
"fileName": "export-license-uploads-{{ str_slug($user->name) }}-{{ date('Y-m-d') }}",
|
||||
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","delete","download","icon"]
|
||||
}'>
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-visible="true" data-field="icon" data-sortable="true">{{trans('general.file_type')}}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="image">{{ trans('general.image') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="filename" data-sortable="true">{{ trans('general.file_name') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="filesize">{{ trans('general.filesize') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="notes" data-sortable="true">{{ trans('general.notes') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="download">{{ trans('general.download') }}</th>
|
||||
<th class="col-md-2" data-searchable="true" data-visible="true" data-field="created_at" data-sortable="true">{{ trans('general.created_at') }}</th>
|
||||
<th class="col-md-1" data-searchable="true" data-visible="true" data-field="actions">{{ trans('table.actions') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($user->uploads as $file)
|
||||
<tr>
|
||||
<td>
|
||||
<i class="{{ Helper::filetype_icon($file->filename) }} icon-med" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ Helper::filetype_icon($file->filename) }}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
@if (($file->filename) && (Storage::exists('private_uploads/users/'.$file->filename)))
|
||||
@if (Helper::checkUploadIsImage($file->get_src('users')))
|
||||
<a href="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" data-toggle="lightbox" data-type="image"><img src="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" class="img-thumbnail" style="max-width: 50px;"></a>
|
||||
@else
|
||||
{{ trans('general.preview_not_available') }}
|
||||
@endif
|
||||
@else
|
||||
<x-icon type="x" class="text-danger" />
|
||||
{{ trans('general.file_not_found') }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
{{ $file->filename }}
|
||||
</td>
|
||||
<td data-value="{{ (Storage::exists('private_uploads/users/'.$file->filename)) ? Storage::size('private_uploads/users/'.$file->filename) : '' }}">
|
||||
{{ (Storage::exists('private_uploads/users/'.$file->filename)) ? Helper::formatFilesizeUnits(Storage::size('private_uploads/users/'.$file->filename)) : '' }}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
@if ($file->note)
|
||||
{{ $file->note }}
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@if ($file->filename)
|
||||
@if (Storage::exists('private_uploads/users/'.$file->filename))
|
||||
<a href="{{ route('show/userfile', [$user->id, $file->id]) }}" class="btn btn-sm btn-default">
|
||||
<x-icon type="download" />
|
||||
<span class="sr-only">{{ trans('general.download') }}</span>
|
||||
</a>
|
||||
|
||||
<a href="{{ route('show/userfile', [$user->id, $file->id, 'inline' => 'true']) }}" class="btn btn-sm btn-default" target="_blank">
|
||||
<x-icon type="external-link" />
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $file->created_at }}</td>
|
||||
|
||||
<td>
|
||||
<a class="btn delete-asset btn-danger btn-sm hidden-print" href="{{ route('userfile.destroy', [$user->id, $file->id]) }}" data-content="Are you sure you wish to delete this file?" data-title="{{ trans('general.delete') }} {{ $file->filename }}?">
|
||||
<x-icon type="delete" />
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
</td>
|
||||
|
||||
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<x-filestable
|
||||
filepath="private_uploads/users/"
|
||||
showfile_routename="show/userfile"
|
||||
deletefile_routename="userfile.destroy"
|
||||
:object="$user" />
|
||||
</div>
|
||||
</div> <!--/ROW-->
|
||||
</div><!--/FILES-->
|
||||
|
|
20
tests/Unit/BladeComponents/IconComponentTest.php
Normal file
20
tests/Unit/BladeComponents/IconComponentTest.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\BladeComponents;
|
||||
|
||||
use Illuminate\Support\Facades\View;
|
||||
use Illuminate\Support\Str;
|
||||
use Tests\TestCase;
|
||||
|
||||
class IconComponentTest extends TestCase
|
||||
{
|
||||
public function testIconComponentDoesNotEndInNewline()
|
||||
{
|
||||
$renderedTemplateString = View::make('blade.icon', ['type' => 'checkout'])->render();
|
||||
|
||||
$this->assertFalse(
|
||||
Str::endsWith($renderedTemplateString, PHP_EOL),
|
||||
'Newline found at end of icon component. Bootstrap tables will not render if there is a newline at the end of the file.'
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue