mirror of
https://github.com/snipe/snipe-it.git
synced 2024-12-25 21:54:14 -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_DATABASE: snipeit
|
||||||
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||||
DB_USERNAME: root
|
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_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||||
DB_USERNAME: snipeit
|
DB_USERNAME: snipeit
|
||||||
DB_PASSWORD: password
|
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
|
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||||
env:
|
env:
|
||||||
DB_CONNECTION: sqlite_testing
|
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\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Illuminate\Support\Facades\Log;
|
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('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
|
||||||
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
||||||
|
@ -29,6 +30,11 @@ class ObjectImportCommand extends Command
|
||||||
*/
|
*/
|
||||||
protected $description = 'Import Items from CSV';
|
protected $description = 'Import Items from CSV';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The progress indicator instance.
|
||||||
|
*/
|
||||||
|
protected ProgressIndicator $progressIndicator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
*
|
*
|
||||||
|
@ -39,8 +45,6 @@ class ObjectImportCommand extends Command
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
private $bar;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*
|
*
|
||||||
|
@ -48,6 +52,8 @@ class ObjectImportCommand extends Command
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$this->progressIndicator = new ProgressIndicator($this->output);
|
||||||
|
|
||||||
$filename = $this->argument('filename');
|
$filename = $this->argument('filename');
|
||||||
$class = title_case($this->option('item-type'));
|
$class = title_case($this->option('item-type'));
|
||||||
$classString = "App\\Importer\\{$class}Importer";
|
$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
|
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
|
||||||
// $logFile = $this->option('logfile');
|
// $logFile = $this->option('logfile');
|
||||||
// Log::useFiles($logFile);
|
// Log::useFiles($logFile);
|
||||||
$this->comment('======= Importing Items from '.$filename.' =========');
|
$this->progressIndicator->start('======= Importing Items from '.$filename.' =========');
|
||||||
|
|
||||||
$importer->import();
|
$importer->import();
|
||||||
|
|
||||||
$this->bar = null;
|
$this->progressIndicator->finish('Import finished.');
|
||||||
|
|
||||||
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('');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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->progressIndicator->advance();
|
||||||
$this->bar = $this->output->createProgressBar($count);
|
|
||||||
}
|
}
|
||||||
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.
|
* Log a message to file, configurable by the --log-file parameter.
|
||||||
|
|
|
@ -1123,6 +1123,7 @@ class Helper
|
||||||
'png' => 'far fa-image',
|
'png' => 'far fa-image',
|
||||||
'webp' => 'far fa-image',
|
'webp' => 'far fa-image',
|
||||||
'avif' => 'far fa-image',
|
'avif' => 'far fa-image',
|
||||||
|
'svg' => 'fas fa-vector-square',
|
||||||
// word
|
// word
|
||||||
'doc' => 'far fa-file-word',
|
'doc' => 'far fa-file-word',
|
||||||
'docx' => 'far fa-file-word',
|
'docx' => 'far fa-file-word',
|
||||||
|
@ -1135,7 +1136,7 @@ class Helper
|
||||||
//Text
|
//Text
|
||||||
'txt' => 'far fa-file-alt',
|
'txt' => 'far fa-file-alt',
|
||||||
'rtf' => 'far fa-file-alt',
|
'rtf' => 'far fa-file-alt',
|
||||||
'xml' => 'far fa-file-alt',
|
'xml' => 'fas fa-code',
|
||||||
// Misc
|
// Misc
|
||||||
'pdf' => 'far fa-file-pdf',
|
'pdf' => 'far fa-file-pdf',
|
||||||
'lic' => 'far fa-save',
|
'lic' => 'far fa-save',
|
||||||
|
@ -1148,41 +1149,7 @@ class Helper
|
||||||
return 'far fa-file';
|
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.
|
* Get a random unencrypted password.
|
||||||
|
|
|
@ -7,6 +7,7 @@ use Illuminate\Http\Response;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||||
|
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||||
class StorageHelper
|
class StorageHelper
|
||||||
{
|
{
|
||||||
public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
|
public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
|
||||||
|
@ -25,4 +26,64 @@ class StorageHelper
|
||||||
return Storage::disk($disk)->download($filename);
|
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 $accessoryId
|
||||||
* @param int $fileId
|
* @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
|
// the accessory is valid
|
||||||
if (isset($accessory->id)) {
|
if ($accessory = Accessory::find($accessoryId)) {
|
||||||
$this->authorize('view', $accessory);
|
$this->authorize('view', $accessory);
|
||||||
$this->authorize('accessories.files', $accessory);
|
$this->authorize('accessories.files', $accessory);
|
||||||
|
|
||||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
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'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = 'private_uploads/accessories/'.$log->filename;
|
$file = 'private_uploads/accessories/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
try {
|
||||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
Log::debug('URL should be '.Storage::url($file));
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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_does_not_exist', ['id' => $fileId]));
|
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');
|
$request->except('deployable', 'pending', 'archived');
|
||||||
|
|
||||||
if (! $request->filled('type')) {
|
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;
|
$statuslabel = new Statuslabel;
|
||||||
|
|
|
@ -14,6 +14,7 @@ use App\Http\Transformers\UsersTransformer;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\Accessory;
|
use App\Models\Accessory;
|
||||||
|
use App\Models\Company;
|
||||||
use App\Models\Consumable;
|
use App\Models\Consumable;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -371,6 +372,7 @@ class UsersController extends Controller
|
||||||
|
|
||||||
$user = new User;
|
$user = new User;
|
||||||
$user->fill($request->all());
|
$user->fill($request->all());
|
||||||
|
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||||
$user->created_by = auth()->id();
|
$user->created_by = auth()->id();
|
||||||
|
|
||||||
if ($request->has('permissions')) {
|
if ($request->has('permissions')) {
|
||||||
|
@ -452,6 +454,10 @@ class UsersController extends Controller
|
||||||
|
|
||||||
$user->fill($request->all());
|
$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')) {
|
if ($user->id == $request->input('manager_id')) {
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
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
|
public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||||
{
|
{
|
||||||
$asset = Asset::find($assetId);
|
if ($asset = Asset::find($assetId)) {
|
||||||
// the asset is valid
|
|
||||||
if (isset($asset->id)) {
|
|
||||||
$this->authorize('view', $asset);
|
$this->authorize('view', $asset);
|
||||||
|
|
||||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = 'private_uploads/assets/'.$log->filename;
|
$file = 'private_uploads/assets/'.$log->filename;
|
||||||
|
|
||||||
if ($log->action_type == 'audit') {
|
if ($log->action_type == 'audit') {
|
||||||
$file = 'private_uploads/audits/'.$log->filename;
|
$file = 'private_uploads/audits/'.$log->filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! Storage::exists($file)) {
|
try {
|
||||||
return response('File '.$file.' not found on server', 404)
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
->header('Content-Type', 'text/plain');
|
} 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', trans('admin/hardware/message.does_not_exist'));
|
||||||
return redirect()->route('hardware.index')->with('error', $error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,6 @@ use App\Models\Location;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\Statuslabel;
|
use App\Models\Statuslabel;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use App\View\Label;
|
use App\View\Label;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
|
@ -52,6 +52,10 @@ class BulkAssetsController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$asset_ids = $request->input('ids');
|
$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
|
// 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');
|
$bulk_back_url = request()->headers->get('referer');
|
||||||
|
@ -571,31 +575,34 @@ class BulkAssetsController extends Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors = [];
|
$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) {
|
foreach ($asset_ids as $asset_id) {
|
||||||
$asset = Asset::findOrFail($asset_id);
|
$asset = Asset::findOrFail($asset_id);
|
||||||
$this->authorize('checkout', $asset);
|
$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 != '') {
|
if ($target->location_id != '') {
|
||||||
$asset->location_id = $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();
|
$asset->save();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($error) {
|
if (!$checkout_success) {
|
||||||
array_merge_recursive($errors, $asset->getErrors()->toArray());
|
$errors = array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (! $errors) {
|
if (! $errors) {
|
||||||
// Redirect to the new asset page
|
// 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
|
// 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) {
|
} catch (ModelNotFoundException $e) {
|
||||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
|
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)
|
public function show($componentId = null, $fileId = null)
|
||||||
{
|
{
|
||||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||||
$component = Component::find($componentId);
|
|
||||||
|
|
||||||
// the component is valid
|
// the component is valid
|
||||||
if (isset($component->id)) {
|
if ($component = Component::find($componentId)) {
|
||||||
$this->authorize('view', $component);
|
$this->authorize('view', $component);
|
||||||
$this->authorize('components.files', $component);
|
$this->authorize('components.files', $component);
|
||||||
|
|
||||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = 'private_uploads/components/'.$log->filename;
|
$file = 'private_uploads/components/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
try {
|
||||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
Log::debug('URL should be '.Storage::url($file));
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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]));
|
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]
|
* @since [v1.4]
|
||||||
* @param int $consumableId
|
* @param int $consumableId
|
||||||
* @param int $fileId
|
* @param int $fileId
|
||||||
* @return \Symfony\Consumable\HttpFoundation\Response
|
|
||||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||||
*/
|
*/
|
||||||
public function show($consumableId = null, $fileId = null)
|
public function show($consumableId = null, $fileId = null)
|
||||||
|
@ -116,36 +115,18 @@ class ConsumablesFilesController extends Controller
|
||||||
$this->authorize('view', $consumable);
|
$this->authorize('view', $consumable);
|
||||||
$this->authorize('consumables.files', $consumable);
|
$this->authorize('consumables.files', $consumable);
|
||||||
|
|
||||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = 'private_uploads/consumables/'.$log->filename;
|
$file = 'private_uploads/consumables/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
try {
|
||||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
Log::debug('URL should be '.Storage::url($file));
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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]));
|
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('view', $license);
|
||||||
$this->authorize('licenses.files', $license);
|
$this->authorize('licenses.files', $license);
|
||||||
|
|
||||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
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');
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = 'private_uploads/licenses/'.$log->filename;
|
$file = 'private_uploads/licenses/'.$log->filename;
|
||||||
|
|
||||||
if (Storage::missing($file)) {
|
try {
|
||||||
Log::debug('NOT EXISTS for '.$file);
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
Log::debug('NOT EXISTS URL should be '.Storage::url($file));
|
} catch (\Exception $e) {
|
||||||
|
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
|
||||||
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);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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]));
|
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\Http\Requests\UploadFileRequest;
|
||||||
use App\Models\Actionlog;
|
use App\Models\Actionlog;
|
||||||
use App\Models\User;
|
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 Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
|
@ -116,31 +113,30 @@ class UserFilesController extends Controller
|
||||||
public function show($userId = null, $fileId = null)
|
public function show($userId = null, $fileId = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
if (empty($fileId)) {
|
if (empty($fileId)) {
|
||||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||||
}
|
}
|
||||||
|
|
||||||
$user = User::find($userId);
|
if ($user = User::find($userId)) {
|
||||||
|
|
||||||
// the license is valid
|
|
||||||
if (isset($user->id)) {
|
|
||||||
|
|
||||||
$this->authorize('view', $user);
|
$this->authorize('view', $user);
|
||||||
|
|
||||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||||
|
$file = 'private_uploads/users/'.$log->filename;
|
||||||
|
|
||||||
// Display the file inline
|
try {
|
||||||
if (request('inline') == 'true') {
|
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||||
$headers = [
|
} catch (\Exception $e) {
|
||||||
'Content-Disposition' => 'inline',
|
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||||
];
|
}
|
||||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// Redirect to the user management page if the user doesn't exist
|
||||||
|
|
|
@ -23,7 +23,7 @@ trait MayContainCustomFields
|
||||||
return str_starts_with($attributes, '_snipeit_');
|
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 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'))
|
$request_fields->diff($asset_model?->fieldset?->fields?->pluck('db_column'))
|
||||||
->each(function ($request_field_name) use ($request_fields, $validator) {
|
->each(function ($request_field_name) use ($request_fields, $validator) {
|
||||||
if (CustomField::where('db_column', $request_field_name)->exists()) {
|
if (CustomField::where('db_column', $request_field_name)->exists()) {
|
||||||
|
|
|
@ -141,6 +141,8 @@ class ActionlogsTransformer
|
||||||
if ($actionlog->item) {
|
if ($actionlog->item) {
|
||||||
if ($actionlog->itemType() == 'asset') {
|
if ($actionlog->itemType() == 'asset') {
|
||||||
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
$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') {
|
} elseif ($actionlog->itemType() == 'license') {
|
||||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||||
} elseif ($actionlog->itemType() == 'user') {
|
} elseif ($actionlog->itemType() == 'user') {
|
||||||
|
@ -158,7 +160,6 @@ class ActionlogsTransformer
|
||||||
[
|
[
|
||||||
'url' => $file_url,
|
'url' => $file_url,
|
||||||
'filename' => $actionlog->filename,
|
'filename' => $actionlog->filename,
|
||||||
'inlineable' => (bool) Helper::show_file_inline($actionlog->filename),
|
|
||||||
] : null,
|
] : null,
|
||||||
|
|
||||||
'item' => ($actionlog->item) ? [
|
'item' => ($actionlog->item) ? [
|
||||||
|
|
|
@ -21,7 +21,6 @@ abstract class Importer
|
||||||
* Id of User performing import
|
* Id of User performing import
|
||||||
* @var
|
* @var
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected $created_by;
|
protected $created_by;
|
||||||
/**
|
/**
|
||||||
* Are we updating items in the import
|
* Are we updating items in the import
|
||||||
|
@ -149,17 +148,23 @@ abstract class Importer
|
||||||
{
|
{
|
||||||
$headerRow = $this->csv->fetchOne();
|
$headerRow = $this->csv->fetchOne();
|
||||||
$this->csv->setHeaderOffset(0); //explicitly sets the CSV document header record
|
$this->csv->setHeaderOffset(0); //explicitly sets the CSV document header record
|
||||||
$results = $this->normalizeInputArray($this->csv->getRecords($headerRow));
|
|
||||||
|
|
||||||
$this->populateCustomFields($headerRow);
|
$this->populateCustomFields($headerRow);
|
||||||
|
|
||||||
DB::transaction(function () use (&$results) {
|
DB::transaction(function () use ($headerRow) {
|
||||||
|
$importedItemsCount = 0;
|
||||||
Model::unguard();
|
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);
|
$this->handle($row);
|
||||||
|
|
||||||
|
$importedItemsCount++;
|
||||||
|
|
||||||
if ($this->progressCallback) {
|
if ($this->progressCallback) {
|
||||||
call_user_func($this->progressCallback, $resultsCount);
|
call_user_func($this->progressCallback, $importedItemsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->log('------------- Action Summary ----------------');
|
$this->log('------------- Action Summary ----------------');
|
||||||
|
@ -237,22 +242,6 @@ abstract class Importer
|
||||||
return $key;
|
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
|
* Figure out the fieldname of the custom field
|
||||||
*
|
*
|
||||||
|
|
|
@ -196,7 +196,6 @@ class Importer extends Component
|
||||||
'supplier' => trans('general.supplier'),
|
'supplier' => trans('general.supplier'),
|
||||||
'purchase_cost' => trans('general.purchase_cost'),
|
'purchase_cost' => trans('general.purchase_cost'),
|
||||||
'purchase_date' => trans('general.purchase_date'),
|
'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')]),
|
'asset_notes' => trans('general.item_notes', ['item' => trans('admin/hardware/general.asset')]),
|
||||||
'model_notes' => trans('general.item_notes', ['item' => trans('admin/hardware/form.model')]),
|
'model_notes' => trans('general.item_notes', ['item' => trans('admin/hardware/form.model')]),
|
||||||
'manufacturer' => trans('general.manufacturer'),
|
'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,
|
* 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 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()
|
* @see \App\Models\Company\Company::scopeCompanyables()
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -74,7 +74,6 @@
|
||||||
"ext-exif": "*"
|
"ext-exif": "*"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"brianium/paratest": "^7.0",
|
|
||||||
"fakerphp/faker": "^1.16",
|
"fakerphp/faker": "^1.16",
|
||||||
"larastan/larastan": "^2.9",
|
"larastan/larastan": "^2.9",
|
||||||
"mockery/mockery": "^1.4",
|
"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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "3819ab4ef72eb77fabe494c0e746b83b",
|
"content-hash": "5341bc5be02b3c33e28e46e06dd99f29",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "alek13/slack",
|
"name": "alek13/slack",
|
||||||
|
@ -11790,101 +11790,6 @@
|
||||||
],
|
],
|
||||||
"time": "2024-04-13T18:00:56+00:00"
|
"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",
|
"name": "clue/ndjson-react",
|
||||||
"version": "v1.3.0",
|
"version": "v1.3.0",
|
||||||
|
@ -12781,65 +12686,6 @@
|
||||||
},
|
},
|
||||||
"time": "2020-07-09T08:09:16+00:00"
|
"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",
|
"name": "justinrainbow/json-schema",
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
|
|
|
@ -280,7 +280,6 @@ return [
|
||||||
Illuminate\Redis\RedisServiceProvider::class,
|
Illuminate\Redis\RedisServiceProvider::class,
|
||||||
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||||
Illuminate\Session\SessionServiceProvider::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
|
App\Providers\SnipeTranslationServiceProvider::class, //we REPLACE the default Laravel translator with our own
|
||||||
Illuminate\Validation\ValidationServiceProvider::class,
|
Illuminate\Validation\ValidationServiceProvider::class,
|
||||||
Illuminate\View\ViewServiceProvider::class,
|
Illuminate\View\ViewServiceProvider::class,
|
||||||
|
@ -373,7 +372,7 @@ return [
|
||||||
'Image' => Intervention\Image\ImageServiceProvider::class,
|
'Image' => Intervention\Image\ImageServiceProvider::class,
|
||||||
'Carbon' => Carbon\Carbon::class,
|
'Carbon' => Carbon\Carbon::class,
|
||||||
'Helper' => App\Helpers\Helper::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,
|
'Icon' => App\Helpers\IconHelper::class,
|
||||||
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
|
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
return array (
|
return array (
|
||||||
'app_version' => 'v7.0.13',
|
'app_version' => 'v7.0.13',
|
||||||
'full_app_version' => 'v7.0.13 - build 15514-gdc0949da7',
|
'full_app_version' => 'v7.0.13 - build 15666-g03b01689b',
|
||||||
'build_version' => '15514',
|
'build_version' => '15666',
|
||||||
'prerelease_version' => '',
|
'prerelease_version' => '',
|
||||||
'hash_version' => 'gdc0949da7',
|
'hash_version' => 'g03b01689b',
|
||||||
'full_hash' => 'v7.0.13-265-gdc0949da7',
|
'full_hash' => 'v7.0.13-144-g03b01689b',
|
||||||
'branch' => 'develop',
|
'branch' => 'develop',
|
||||||
);
|
);
|
|
@ -79,6 +79,11 @@ return [
|
||||||
'no_assets_selected' => 'You must select at least one asset from the list',
|
'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' => [
|
'checkin' => [
|
||||||
'error' => 'Asset was not checked in, please try again',
|
'error' => 'Asset was not checked in, please try again',
|
||||||
'success' => 'Asset checked in successfully.',
|
'success' => 'Asset checked in successfully.',
|
||||||
|
|
|
@ -434,6 +434,7 @@ return [
|
||||||
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
'alt_uploaded_image_thumbnail' => 'Uploaded thumbnail',
|
||||||
'placeholder_kit' => 'Select a kit',
|
'placeholder_kit' => 'Select a kit',
|
||||||
'file_not_found' => 'File not found',
|
'file_not_found' => 'File not found',
|
||||||
|
'log_record_not_found' => 'No record for that log entry was found.',
|
||||||
'preview_not_available' => '(no preview)',
|
'preview_not_available' => '(no preview)',
|
||||||
'setup' => 'Setup',
|
'setup' => 'Setup',
|
||||||
'pre_flight' => 'Pre-Flight',
|
'pre_flight' => 'Pre-Flight',
|
||||||
|
|
|
@ -155,99 +155,13 @@
|
||||||
@can('accessories.files', $accessory)
|
@can('accessories.files', $accessory)
|
||||||
<div class="tab-pane" id="files">
|
<div class="tab-pane" id="files">
|
||||||
|
|
||||||
<div class="table table-responsive">
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<table
|
<x-filestable
|
||||||
data-cookie-id-table="accessoryUploadsTable"
|
filepath="private_uploads/accessories/"
|
||||||
data-id-table="accessoryUploadsTable"
|
showfile_routename="show.accessoryfile"
|
||||||
id="accessoryUploadsTable"
|
deletefile_routename="delete/accessoryfile"
|
||||||
data-search="true"
|
:object="$accessory" />
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div> <!-- /.tab-pane -->
|
</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)
|
@can('components.files', $component)
|
||||||
<div class="tab-pane" id="files">
|
<div class="tab-pane" id="files">
|
||||||
|
<div class="row">
|
||||||
<div class="table-responsive">
|
<div class="col-md-12">
|
||||||
<table
|
<x-filestable
|
||||||
data-cookie-id-table="componentUploadsTable"
|
filepath="private_uploads/components/"
|
||||||
data-id-table="componentUploadsTable"
|
showfile_routename="show.componentfile"
|
||||||
id="componentUploadsTable"
|
deletefile_routename="delete/componentfile"
|
||||||
data-search="true"
|
:object="$component" />
|
||||||
data-pagination="true"
|
</div>
|
||||||
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>
|
</div>
|
||||||
</div> <!-- /.tab-pane -->
|
</div> <!-- /.tab-pane -->
|
||||||
@endcan
|
@endcan
|
||||||
|
|
|
@ -428,102 +428,18 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="tab-pane" id="files">
|
<div class="tab-pane" id="files">
|
||||||
|
|
||||||
<div class="row">
|
<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>
|
</div>
|
||||||
</div> <!--/ROW-->
|
|
||||||
</div><!--/FILES-->
|
</div><!--/FILES-->
|
||||||
|
|
||||||
<div class="tab-pane" id="history">
|
<div class="tab-pane" id="history">
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<div class="dashboard small-box bg-teal">
|
<div class="dashboard small-box bg-teal">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ number_format(\App\Models\Asset::AssetsForShow()->count()) }}</h3>
|
<h3>{{ number_format(\App\Models\Asset::AssetsForShow()->count()) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.assets')) }}</p>
|
<p>{{ trans('general.assets') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="assets" />
|
<x-icon type="assets" />
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
<div class="dashboard small-box bg-maroon">
|
<div class="dashboard small-box bg-maroon">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ number_format($counts['license']) }}</h3>
|
<h3>{{ number_format($counts['license']) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.licenses')) }}</p>
|
<p>{{ trans('general.licenses') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="licenses" />
|
<x-icon type="licenses" />
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
<div class="dashboard small-box bg-orange">
|
<div class="dashboard small-box bg-orange">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3> {{ number_format($counts['accessory']) }}</h3>
|
<h3> {{ number_format($counts['accessory']) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.accessories')) }}</p>
|
<p>{{ trans('general.accessories') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="accessories" />
|
<x-icon type="accessories" />
|
||||||
|
@ -96,7 +96,7 @@
|
||||||
<div class="dashboard small-box bg-purple">
|
<div class="dashboard small-box bg-purple">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3> {{ number_format($counts['consumable']) }}</h3>
|
<h3> {{ number_format($counts['consumable']) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.consumables')) }}</p>
|
<p>{{ trans('general.consumables') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="consumables" />
|
<x-icon type="consumables" />
|
||||||
|
@ -115,7 +115,7 @@
|
||||||
<div class="dashboard small-box bg-yellow">
|
<div class="dashboard small-box bg-yellow">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ number_format($counts['component']) }}</h3>
|
<h3>{{ number_format($counts['component']) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.components')) }}</p>
|
<p>{{ trans('general.components') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="components" />
|
<x-icon type="components" />
|
||||||
|
@ -135,7 +135,7 @@
|
||||||
<div class="dashboard small-box bg-light-blue">
|
<div class="dashboard small-box bg-light-blue">
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<h3>{{ number_format($counts['user']) }}</h3>
|
<h3>{{ number_format($counts['user']) }}</h3>
|
||||||
<p>{{ strtolower(trans('general.people')) }}</p>
|
<p>{{ trans('general.people') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="icon" aria-hidden="true">
|
<div class="icon" aria-hidden="true">
|
||||||
<x-icon type="users" />
|
<x-icon type="users" />
|
||||||
|
|
|
@ -115,5 +115,12 @@
|
||||||
|
|
||||||
@section('moar_scripts')
|
@section('moar_scripts')
|
||||||
@include('partials/assets-assigned')
|
@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
|
@stop
|
||||||
|
|
|
@ -1362,102 +1362,11 @@
|
||||||
<div class="tab-pane fade" id="files">
|
<div class="tab-pane fade" id="files">
|
||||||
<div class="row{{ ($asset->uploads->count() > 0 ) ? '' : ' hidden-print' }}">
|
<div class="row{{ ($asset->uploads->count() > 0 ) ? '' : ' hidden-print' }}">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
<x-filestable
|
||||||
@if ($asset->uploads->count() > 0)
|
filepath="private_uploads/assets/"
|
||||||
<table
|
showfile_routename="show/assetfile"
|
||||||
class="table table-striped snipe-table"
|
deletefile_routename="delete/modelfile"
|
||||||
id="assetFileHistory"
|
:object="$asset" />
|
||||||
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
|
|
||||||
|
|
||||||
</div> <!-- /.col-md-12 -->
|
</div> <!-- /.col-md-12 -->
|
||||||
</div> <!-- /.row -->
|
</div> <!-- /.row -->
|
||||||
</div> <!-- /.tab-pane files -->
|
</div> <!-- /.tab-pane files -->
|
||||||
|
@ -1467,101 +1376,11 @@
|
||||||
<div class="row{{ (($asset->model) && ($asset->model->uploads->count() > 0)) ? '' : ' hidden-print' }}">
|
<div class="row{{ (($asset->model) && ($asset->model->uploads->count() > 0)) ? '' : ' hidden-print' }}">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
||||||
@if (($asset->model) && ($asset->model->uploads->count() > 0))
|
<x-filestable
|
||||||
<table
|
filepath="private_uploads/assetmodels/"
|
||||||
class="table table-striped snipe-table"
|
showfile_routename="show/modelfile"
|
||||||
id="assetModelFileHistory"
|
deletefile_routename="userfile.destroy"
|
||||||
data-pagination="true"
|
:object="$asset->model" />
|
||||||
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
|
|
||||||
|
|
||||||
</div> <!-- /.col-md-12 -->
|
</div> <!-- /.col-md-12 -->
|
||||||
</div> <!-- /.row -->
|
</div> <!-- /.row -->
|
||||||
|
|
|
@ -464,100 +464,13 @@
|
||||||
|
|
||||||
@can('licenses.files', $license)
|
@can('licenses.files', $license)
|
||||||
<div class="tab-pane" id="files">
|
<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>
|
<x-filestable
|
||||||
<td>
|
filepath="private_uploads/licenses/"
|
||||||
@if ($file->filename)
|
showfile_routename="show.licensefile"
|
||||||
@if ((Storage::exists('private_uploads/licenses/'.$file->filename)) && ( Helper::checkUploadIsImage($file->get_src('licenses'))))
|
deletefile_routename="delete/licensefile"
|
||||||
<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>
|
:object="$license" />
|
||||||
@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>
|
|
||||||
|
|
||||||
<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 -->
|
</div> <!-- /.tab-pane -->
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
|
|
|
@ -107,99 +107,11 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
|
|
||||||
@if ($model->uploads->count() > 0)
|
<x-filestable
|
||||||
<table
|
filepath="private_uploads/assetmodels/"
|
||||||
class="table table-striped snipe-table"
|
showfile_routename="show/modelfile"
|
||||||
id="modelFileHistory"
|
deletefile_routename="delete/modelfile"
|
||||||
data-pagination="true"
|
:object="$model" />
|
||||||
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
|
|
||||||
|
|
||||||
</div> <!-- /.col-md-12 -->
|
</div> <!-- /.col-md-12 -->
|
||||||
</div> <!-- /.row -->
|
</div> <!-- /.row -->
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
@can('update', \App\Models\Asset::class)
|
@can('update', \App\Models\Asset::class)
|
||||||
<option value="edit">{{ trans('button.edit') }}</option>
|
<option value="edit">{{ trans('button.edit') }}</option>
|
||||||
@endcan
|
@endcan
|
||||||
|
@can('checkout', \App\Models\Asset::class)
|
||||||
|
<option value="checkout">{{ trans('general.bulk_checkout') }}</option>
|
||||||
|
@endcan
|
||||||
@can('delete', \App\Models\Asset::class)
|
@can('delete', \App\Models\Asset::class)
|
||||||
<option value="delete">{{ trans('button.delete') }}</option>
|
<option value="delete">{{ trans('button.delete') }}</option>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
|
@ -971,102 +971,11 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-md-12 col-sm-12">
|
<div class="col-md-12 col-sm-12">
|
||||||
<div class="table-responsive">
|
<x-filestable
|
||||||
<table
|
filepath="private_uploads/users/"
|
||||||
data-cookie-id-table="userUploadsTable"
|
showfile_routename="show/userfile"
|
||||||
data-id-table="userUploadsTable"
|
deletefile_routename="userfile.destroy"
|
||||||
id="userUploadsTable"
|
:object="$user" />
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
</div> <!--/ROW-->
|
</div> <!--/ROW-->
|
||||||
</div><!--/FILES-->
|
</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