Merge branch 'snipe-develop' into added-localized-strings
This commit is contained in:
commit
74ed790d20
34 changed files with 1450 additions and 655 deletions
|
@ -96,6 +96,8 @@ RUN \
|
|||
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \
|
||||
&& mkdir -p "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
|
||||
&& chown docker "/var/lib/snipeit/keys/" \
|
||||
&& chown -h docker "/var/www/html/storage/" \
|
||||
&& chmod +x /var/www/html/artisan \
|
||||
|
|
|
@ -14,7 +14,7 @@ class RestoreFromBackup extends Command
|
|||
*/
|
||||
protected $signature = 'snipeit:restore
|
||||
{--force : Skip the danger prompt; assuming you hit "y"}
|
||||
{filename : The zip file to be migrated}
|
||||
{filename : The full path of the .zip file to be migrated}
|
||||
{--no-progress : Don\'t show a progress bar}';
|
||||
|
||||
/**
|
||||
|
@ -22,7 +22,7 @@ class RestoreFromBackup extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Restore from a previously created backup';
|
||||
protected $description = 'Restore from a previously created Snipe-IT backup file';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
|
@ -34,6 +34,8 @@ class RestoreFromBackup extends Command
|
|||
parent::__construct();
|
||||
}
|
||||
|
||||
public static $buffer_size = 1024 * 1024; // use a 1MB buffer, ought to work fine for most cases?
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
|
@ -42,7 +44,10 @@ class RestoreFromBackup extends Command
|
|||
public function handle()
|
||||
{
|
||||
$dir = getcwd();
|
||||
echo "Current working directory is: $dir\n";
|
||||
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
|
||||
\Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
|
||||
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
|
||||
}
|
||||
//
|
||||
$filename = $this->argument('filename');
|
||||
|
||||
|
@ -67,7 +72,7 @@ class RestoreFromBackup extends Command
|
|||
ZipArchive::ER_INCONS => 'Zip archive inconsistent.',
|
||||
ZipArchive::ER_INVAL => 'Invalid argument.',
|
||||
ZipArchive::ER_MEMORY => 'Malloc failure.',
|
||||
ZipArchive::ER_NOENT => 'No such file.',
|
||||
ZipArchive::ER_NOENT => 'No such file ('.$filename.') in directory '.$dir.'.',
|
||||
ZipArchive::ER_NOZIP => 'Not a zip archive.',
|
||||
ZipArchive::ER_OPEN => "Can't open file.",
|
||||
ZipArchive::ER_READ => 'Read error.',
|
||||
|
@ -144,7 +149,7 @@ class RestoreFromBackup extends Command
|
|||
continue;
|
||||
}
|
||||
if (@pathinfo($raw_path)['extension'] == 'sql') {
|
||||
echo "Found a sql file!\n";
|
||||
\Log::debug("Found a sql file!");
|
||||
$sqlfiles[] = $raw_path;
|
||||
$sqlfile_indices[] = $i;
|
||||
continue;
|
||||
|
@ -206,7 +211,13 @@ class RestoreFromBackup extends Command
|
|||
|
||||
$env_vars = getenv();
|
||||
$env_vars['MYSQL_PWD'] = config('database.connections.mysql.password');
|
||||
$proc_results = proc_open('mysql -h '.escapeshellarg(config('database.connections.mysql.host')).' -u '.escapeshellarg(config('database.connections.mysql.username')).' '.escapeshellarg(config('database.connections.mysql.database')), // yanked -p since we pass via ENV
|
||||
// TODO notes: we are stealing the dump_binary_path (which *probably* also has your copy of the mysql binary in it. But it might not, so we might need to extend this)
|
||||
// we unilaterally prepend a slash to the `mysql` command. This might mean your path could look like /blah/blah/blah//mysql - which should be fine. But maybe in some environments it isn't?
|
||||
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').'/mysql';
|
||||
if( ! file_exists($mysql_binary) ) {
|
||||
return $this->error("mysql tool at: '$mysql_binary' does not exist, cannot restore. Please edit DB_DUMP_PATH in your .env to point to a directory that contains the mysqldump and mysql binary");
|
||||
}
|
||||
$proc_results = proc_open("$mysql_binary -h ".escapeshellarg(config('database.connections.mysql.host')).' -u '.escapeshellarg(config('database.connections.mysql.username')).' '.escapeshellarg(config('database.connections.mysql.database')), // yanked -p since we pass via ENV
|
||||
[0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
|
||||
$pipes,
|
||||
null,
|
||||
|
@ -233,9 +244,10 @@ class RestoreFromBackup extends Command
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
while (($buffer = fgets($sql_contents)) !== false) {
|
||||
//$this->info("Buffer is: '$buffer'");
|
||||
$bytes_read = 0;
|
||||
while (($buffer = fgets($sql_contents, self::$buffer_size)) !== false) {
|
||||
$bytes_read += strlen($buffer);
|
||||
// \Log::debug("Buffer is: '$buffer'");
|
||||
$bytes_written = fwrite($pipes[0], $buffer);
|
||||
if ($bytes_written === false) {
|
||||
$stdout = fgets($pipes[1]);
|
||||
|
@ -246,6 +258,10 @@ class RestoreFromBackup extends Command
|
|||
return false;
|
||||
}
|
||||
}
|
||||
if (!feof($sql_contents) || $bytes_read == 0) {
|
||||
return $this->error("Not at end of file for sql file, or zero bytes read. aborting!");
|
||||
}
|
||||
|
||||
fclose($pipes[0]);
|
||||
fclose($sql_contents);
|
||||
|
||||
|
@ -273,7 +289,7 @@ class RestoreFromBackup extends Command
|
|||
$fp = $za->getStream($ugly_file_name);
|
||||
//$this->info("Weird problem, here are file details? ".print_r($file_details,true));
|
||||
$migrated_file = fopen($file_details['dest'].'/'.basename($pretty_file_name), 'w');
|
||||
while (($buffer = fgets($fp)) !== false) {
|
||||
while (($buffer = fgets($fp, self::$buffer_size)) !== false) {
|
||||
fwrite($migrated_file, $buffer);
|
||||
}
|
||||
fclose($migrated_file);
|
||||
|
|
|
@ -171,6 +171,7 @@ class AssetsController extends Controller
|
|||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($assets) && ($request->get('offset') > $assets->count())) ? $assets->count() : $request->get('offset', 0);
|
||||
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
@ -336,6 +337,7 @@ class AssetsController extends Controller
|
|||
return (new $transformer)->transformAssets($assets, $total, $request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns JSON with information about an asset (by tag) for detail view.
|
||||
*
|
||||
|
@ -373,9 +375,19 @@ class AssetsController extends Controller
|
|||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
$assets = Asset::with('assetstatus')->with('assignedTo');
|
||||
|
||||
if ($request->input('deleted', 'false') === 'true') {
|
||||
$assets = $assets->withTrashed();
|
||||
}
|
||||
|
||||
$assets = $assets->where('serial', $serial)->get();
|
||||
if ($assets) {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns JSON with information about an asset for detail view.
|
||||
|
@ -677,6 +689,8 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Restore a soft-deleted asset.
|
||||
*
|
||||
|
@ -899,7 +913,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.$request->input('asset_tag').' not found'));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use App\Models\Setting;
|
|||
use App\Models\User;
|
||||
use App\Notifications\FirstAdminNotification;
|
||||
use App\Notifications\MailTest;
|
||||
use Artisan;
|
||||
use Auth;
|
||||
use Crypt;
|
||||
use DB;
|
||||
|
@ -22,6 +21,8 @@ use Image;
|
|||
use Input;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Settings for
|
||||
|
@ -1018,17 +1019,25 @@ class SettingsController extends Controller
|
|||
$backup_files = Storage::files($path);
|
||||
$files_raw = [];
|
||||
|
||||
|
||||
if (count($backup_files) > 0) {
|
||||
for ($f = 0; $f < count($backup_files); $f++) {
|
||||
|
||||
// Skip dotfiles like .gitignore and .DS_STORE
|
||||
if ((substr(basename($backup_files[$f]), 0, 1) != '.')) {
|
||||
//$lastmodified = Carbon::parse(Storage::lastModified($backup_files[$f]))->toDatetimeString();
|
||||
$file_timestamp = Storage::lastModified($backup_files[$f]);
|
||||
|
||||
|
||||
$files_raw[] = [
|
||||
'filename' => basename($backup_files[$f]),
|
||||
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])),
|
||||
'modified' => Storage::lastModified($backup_files[$f]),
|
||||
'modified_value' => $file_timestamp,
|
||||
'modified_display' => Helper::getFormattedDateObject($file_timestamp, $type = 'datetime', false),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1128,6 +1137,115 @@ class SettingsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uploads a backup file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v6.0]
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
|
||||
public function postUploadBackup(Request $request) {
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
if (!$request->hasFile('file')) {
|
||||
return redirect()->route('settings.backups.index')->with('error', 'No file uploaded');
|
||||
} else {
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
|
||||
$rules = [
|
||||
'file' => 'required|mimes:zip|max:'.$max_file_size,
|
||||
];
|
||||
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
|
||||
if ($validator->passes()) {
|
||||
|
||||
$upload_filename = 'uploaded-'.date('U').'-'.Str::slug(pathinfo($request->file('file')->getClientOriginalName(), PATHINFO_FILENAME)).'.zip';
|
||||
|
||||
Storage::putFileAs('app/backups', $request->file('file'), $upload_filename);
|
||||
|
||||
return redirect()->route('settings.backups.index')->with('success', 'File uploaded');
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the backup file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v6.0]
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function postRestore($filename = null)
|
||||
{
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
$path = 'app/backups';
|
||||
|
||||
if (Storage::exists($path.'/'.$filename)) {
|
||||
|
||||
// grab the user's info so we can make sure they exist in the system
|
||||
$user = User::find(Auth::user()->id);
|
||||
|
||||
|
||||
// TODO: run a backup
|
||||
|
||||
// TODO: add db:wipe
|
||||
|
||||
|
||||
// run the restore command
|
||||
Artisan::call('snipeit:restore',
|
||||
[
|
||||
'--force' => true,
|
||||
'--no-progress' => true,
|
||||
'filename' => storage_path($path).'/'.$filename
|
||||
]);
|
||||
|
||||
$output = Artisan::output();
|
||||
|
||||
|
||||
// If it's greater than 300, it probably worked
|
||||
if (strlen($output) > 300) {
|
||||
\Auth::logout();
|
||||
return redirect()->route('login')->with('success', 'Your system has been restored. Please login again.');
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->with('error', $output);
|
||||
|
||||
}
|
||||
//dd($output);
|
||||
|
||||
// TODO: insert the user if they are not there in the old one
|
||||
|
||||
|
||||
|
||||
|
||||
// log the user out
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
|
||||
}
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a form to allow a super admin to update settings.
|
||||
*
|
||||
|
|
|
@ -21,7 +21,7 @@ class AssetFileRequest extends Request
|
|||
*/
|
||||
public function rules()
|
||||
{
|
||||
$max_file_size = Helper::file_upload_max_size();
|
||||
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
|
||||
|
||||
return [
|
||||
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,webp|max:'.$max_file_size,
|
||||
|
|
|
@ -90,11 +90,6 @@ class ImageUploadRequest extends Request
|
|||
$use_db_field = $db_fieldname;
|
||||
}
|
||||
|
||||
\Log::info('Image path is: '.$path);
|
||||
\Log::debug('Type is: '.$type);
|
||||
\Log::debug('Form fieldname is: '.$form_fieldname);
|
||||
\Log::debug('DB fieldname is: '.$use_db_field);
|
||||
\Log::debug('Trying to upload to '. $path);
|
||||
|
||||
// ConvertBase64ToFiles just changes object type,
|
||||
// as it cannot currently insert files to $this->files
|
||||
|
|
|
@ -93,15 +93,15 @@ class AssetsTransformer
|
|||
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => $field->convertUnicodeDbSlug(),
|
||||
'value' => $value,
|
||||
'field' => e($field->convertUnicodeDbSlug()),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
];
|
||||
|
||||
} else {
|
||||
$fields_array[$field->name] = [
|
||||
'field' => $field->convertUnicodeDbSlug(),
|
||||
'value' => $asset->{$field->convertUnicodeDbSlug()},
|
||||
'field' => e($field->convertUnicodeDbSlug()),
|
||||
'value' => e($asset->{$field->convertUnicodeDbSlug()}),
|
||||
'field_format' => $field->format,
|
||||
];
|
||||
|
||||
|
@ -114,24 +114,13 @@ class AssetsTransformer
|
|||
}
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
'checkout' => Gate::allows('checkout', Asset::class),
|
||||
'checkin' => Gate::allows('checkin', Asset::class),
|
||||
'clone' => false,
|
||||
'restore' => false,
|
||||
'update' => (bool) Gate::allows('update', Asset::class),
|
||||
'delete' => ($asset->assigned_to == '' && Gate::allows('delete', Asset::class)),
|
||||
];
|
||||
|
||||
if ($asset->deleted_at != '') {
|
||||
$permissions_array['available_actions'] = [
|
||||
'checkout' => true,
|
||||
'checkin' => false,
|
||||
'clone' => Gate::allows('create', Asset::class),
|
||||
'restore' => Gate::allows('create', Asset::class),
|
||||
'update' => false,
|
||||
'delete' => false,
|
||||
];
|
||||
}
|
||||
'checkout' => ($asset->deleted_at=='' && Gate::allows('checkout', Asset::class)) ? true : false,
|
||||
'checkin' => ($asset->deleted_at=='' && Gate::allows('checkin', Asset::class)) ? true : false,
|
||||
'clone' => Gate::allows('create', Asset::class) ? true : false,
|
||||
'restore' => ($asset->deleted_at!='' && Gate::allows('create', Asset::class)) ? true : false,
|
||||
'update' => ($asset->deleted_at=='' && Gate::allows('update', Asset::class)) ? true : false,
|
||||
'delete' => ($asset->deleted_at=='' && $asset->assigned_to =='' && Gate::allows('delete', Asset::class)) ? true : false,
|
||||
];
|
||||
|
||||
|
||||
if (request('components')=='true') {
|
||||
|
|
|
@ -76,6 +76,7 @@ abstract class Importer
|
|||
'department' => 'department',
|
||||
'manager_first_name' => 'manager first name',
|
||||
'manager_last_name' => 'manager last name',
|
||||
'min_amt' => 'minimum quantity',
|
||||
];
|
||||
/**
|
||||
* Map of item fields->csv names
|
||||
|
@ -196,11 +197,11 @@ abstract class Importer
|
|||
$val = $default;
|
||||
$key = $this->lookupCustomKey($key);
|
||||
|
||||
// $this->log("Custom Key: ${key}");
|
||||
$this->log("Custom Key: ${key}");
|
||||
if (array_key_exists($key, $array)) {
|
||||
$val = Encoding::toUTF8(trim($array[$key]));
|
||||
}
|
||||
// $this->log("${key}: ${val}");
|
||||
$this->log("${key}: ${val}");
|
||||
return $val;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
| serial number | serial | Asset, license |
|
||||
| status | status | Asset ? All |
|
||||
| supplier | supplier | Asset ? All |
|
||||
| minimum quantity | min_amt | Consumable |
|
||||
| termination date | termination_date | License |
|
||||
| warranty months | warranty_months | Asset |
|
||||
| User Related Fields | assigned_to | Asset |
|
||||
|
|
|
@ -68,6 +68,7 @@ class Consumable extends SnipeModel
|
|||
'purchase_cost',
|
||||
'purchase_date',
|
||||
'qty',
|
||||
'min_amt',
|
||||
'requestable',
|
||||
];
|
||||
|
||||
|
@ -185,6 +186,7 @@ class Consumable extends SnipeModel
|
|||
return $this->belongsTo(\App\Models\Category::class, 'category_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the component -> action logs relationship
|
||||
*
|
||||
|
@ -209,8 +211,8 @@ class Consumable extends SnipeModel
|
|||
if ($this->image) {
|
||||
return Storage::disk('public')->url(app('consumables_upload_path').$this->image);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -225,6 +227,7 @@ class Consumable extends SnipeModel
|
|||
return $this->belongsToMany(\App\Models\User::class, 'consumables_users', 'consumable_id', 'assigned_to')->withPivot('user_id')->withTrashed()->withTimestamps();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether to send a checkin/checkout email based on
|
||||
* asset model category
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6-pre-alpha',
|
||||
'full_app_version' => 'v6-pre-alpha - build 6109-gace7abc1a',
|
||||
'build_version' => '6109',
|
||||
'full_app_version' => 'v6-pre-alpha - build 6506-ge75a5f13e',
|
||||
'build_version' => '6506',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'gace7abc1a',
|
||||
'full_hash' => 'v6-pre-alpha-71-gace7abc1a',
|
||||
'branch' => 'develop-v6-integration',
|
||||
'hash_version' => 'ge75a5f13e',
|
||||
'full_hash' => 'v6-pre-alpha-13-ge75a5f13e',
|
||||
'branch' => 'develop',
|
||||
);
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# A supervisor event listener which terminates supervisord if any of its child
|
||||
# processes enter the FATAL state.
|
||||
# https://stackoverflow.com/a/37527488/119527
|
||||
|
|
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -2955,9 +2955,9 @@
|
|||
"integrity": "sha1-EQPWvADPv6jPyaJZmrUYxVZD2j8="
|
||||
},
|
||||
"bootstrap-table": {
|
||||
"version": "1.18.3",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.18.3.tgz",
|
||||
"integrity": "sha512-/eFLkldDlNFi37qC/d9THfRVxMUGD34E8fQBFtXJLDHLBOVKWDTq7BV+udoP7k3FfCEyhM1jWQnQ0rMQdBv//w=="
|
||||
"version": "1.19.1",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.19.1.tgz",
|
||||
"integrity": "sha512-WvV+l1AI/C+zThaKmfHmi/IuayVNB0qdFyEhFx1jyZhO0oLtNJNANkCR3rvJf6Dkh72dsLElxpE/bzK9seEQLA=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
|
@ -15845,7 +15845,7 @@
|
|||
"jquery": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||
"integrity": "sha1-xyoJ8Vwb3OFC9J2/EXC9+K2sJHA="
|
||||
},
|
||||
"jquery-form-validator": {
|
||||
"version": "2.3.79",
|
||||
|
@ -15881,9 +15881,12 @@
|
|||
"integrity": "sha1-G+i3twTdOFcVJwiu+x1KSzpp+zM="
|
||||
},
|
||||
"jquery-ui": {
|
||||
"version": "1.12.1",
|
||||
"resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.12.1.tgz",
|
||||
"integrity": "sha1-vLQEXI3QU5wTS8FIjN0+dop6nlE="
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/jquery-ui/-/jquery-ui-1.13.0.tgz",
|
||||
"integrity": "sha512-Osf7ECXNTYHtKBkn9xzbIf9kifNrBhfywFEKxOeB/OVctVmLlouV9mfc2qXCp6uyO4Pn72PXKOnj09qXetopCw==",
|
||||
"requires": {
|
||||
"jquery": ">=1.8.0 <4.0.0"
|
||||
}
|
||||
},
|
||||
"jquery-ui-bundle": {
|
||||
"version": "1.12.1",
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"bootstrap-colorpicker": "^2.5.3",
|
||||
"bootstrap-datepicker": "^1.9.0",
|
||||
"bootstrap-less": "^3.3.8",
|
||||
"bootstrap-table": "^1.18.3",
|
||||
"bootstrap-table": "^1.19.1",
|
||||
"chart.js": "^2.9.4",
|
||||
"css-loader": "^3.6.0",
|
||||
"ekko-lightbox": "^5.1.1",
|
||||
|
@ -41,7 +41,7 @@
|
|||
"imagemin": "^5.3.1",
|
||||
"jquery-form-validator": "^2.3.79",
|
||||
"jquery-slimscroll": "^1.3.8",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"jquery-ui": "^1.13.0",
|
||||
"jquery-ui-bundle": "^1.12.1",
|
||||
"jquery.iframe-transport": "^1.0.0",
|
||||
"less": "^4.1.1",
|
||||
|
|
|
@ -554,7 +554,6 @@ th.css-accessory > .th-inner::before {
|
|||
.form-group.has-error label {
|
||||
color: #a94442;
|
||||
}
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
|
4
public/css/dist/all.css
vendored
4
public/css/dist/all.css
vendored
File diff suppressed because one or more lines are too long
3
public/css/dist/bootstrap-table.css
vendored
3
public/css/dist/bootstrap-table.css
vendored
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* @author zhixin wen <wenzhixin2010@gmail.com>
|
||||
* version: 1.18.3
|
||||
* version: 1.19.1
|
||||
* https://github.com/wenzhixin/bootstrap-table/
|
||||
*/
|
||||
.bootstrap-table .fixed-table-toolbar::after {
|
||||
|
@ -203,6 +203,7 @@
|
|||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
z-index: 1000;
|
||||
transition: visibility 0s, opacity 0.15s ease-in-out;
|
||||
opacity: 0;
|
||||
|
|
|
@ -334,6 +334,9 @@ __webpack_require__.r(__webpack_exports__);
|
|||
}, {
|
||||
id: 'model_number',
|
||||
text: "Model Number"
|
||||
}, {
|
||||
id: 'min_amt',
|
||||
text: "Minimum Quantity"
|
||||
}],
|
||||
licenses: [{
|
||||
id: 'asset_tag',
|
||||
|
@ -427,6 +430,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||
return this.columnOptions.general.concat(this.columnOptions.accessories).sort(sorter);
|
||||
|
||||
case 'consumable':
|
||||
console.log('Returned consumable');
|
||||
return this.columnOptions.general.concat(this.columnOptions.consumables).sort(sorter);
|
||||
|
||||
case 'license':
|
||||
|
@ -1695,7 +1699,36 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
|
||||
(function ($, settings) {
|
||||
var Components = {};
|
||||
Components.modals = {}; // confirm delete modal
|
||||
Components.modals = {}; // confirm restore modal
|
||||
|
||||
Components.modals.confirmRestore = function () {
|
||||
var $el = $('table');
|
||||
var events = {
|
||||
'click': function click(evnt) {
|
||||
var $context = $(this);
|
||||
var $restoreConfirmModal = $('#restoreConfirmModal');
|
||||
var href = $context.attr('href');
|
||||
var message = $context.attr('data-content');
|
||||
var title = $context.attr('data-title');
|
||||
$('#restoreConfirmModalLabel').text(title);
|
||||
$restoreConfirmModal.find('.modal-body').text(message);
|
||||
$('#restoreForm').attr('action', href);
|
||||
$restoreConfirmModal.modal({
|
||||
show: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var render = function render() {
|
||||
$el.on('click', '.restore-asset', events['click']);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render
|
||||
};
|
||||
}; // confirm delete modal
|
||||
|
||||
|
||||
Components.modals.confirmDelete = function () {
|
||||
var $el = $('table');
|
||||
|
@ -1731,6 +1764,7 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
|
||||
|
||||
$(function () {
|
||||
new Components.modals.confirmRestore().render();
|
||||
new Components.modals.confirmDelete().render();
|
||||
});
|
||||
})(jQuery, window.snipeit.settings);
|
||||
|
@ -1886,10 +1920,10 @@ $(document).ready(function () {
|
|||
return x !== 0;
|
||||
}); // makes sure we're not selecting the same thing twice for multiples
|
||||
|
||||
var filteredResponse = response.items.filter(function (item) {
|
||||
var filteredResponse = response.results.filter(function (item) {
|
||||
return currentlySelected.indexOf(+item.id) < 0;
|
||||
});
|
||||
var first = currentlySelected.length > 0 ? filteredResponse[0] : response.items[0];
|
||||
var first = currentlySelected.length > 0 ? filteredResponse[0] : response.results[0];
|
||||
|
||||
if (first && first.id) {
|
||||
first.selected = true;
|
||||
|
@ -2095,7 +2129,7 @@ $(document).ready(function () {
|
|||
|
||||
for (var i = 0; i < this.files.length; i++) {
|
||||
total_size += this.files[i].size;
|
||||
$(id + '-info').append('<span class="label label-default">' + this.files[i].name + ' (' + formatBytes(this.files[i].size) + ')</span> ');
|
||||
$(id + '-info').append('<span class="label label-default">' + htmlEntities(this.files[i].name) + ' (' + formatBytes(this.files[i].size) + ')</span> ');
|
||||
}
|
||||
|
||||
console.log('Max size is: ' + max_size);
|
||||
|
@ -2111,10 +2145,15 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
function htmlEntities(str) {
|
||||
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
/**
|
||||
* Toggle disabled
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
$.fn.toggleDisabled = function (callback) {
|
||||
return this.each(function () {
|
||||
|
@ -6282,6 +6321,8 @@ if (typeof jQuery === 'undefined') {
|
|||
/***/ ((module, exports, __webpack_require__) => {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( true ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
|
@ -6290,13 +6331,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||
} else {}
|
||||
} ( function( $ ) {
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.ui = $.ui || {};
|
||||
|
||||
return $.ui.version = "1.12.1";
|
||||
return $.ui.version = "1.13.0";
|
||||
|
||||
} ) );
|
||||
} );
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
@ -6308,7 +6350,7 @@ return $.ui.version = "1.12.1";
|
|||
/***/ ((module, exports, __webpack_require__) => {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
||||
* jQuery UI Widget 1.12.1
|
||||
* jQuery UI Widget 1.13.0
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
|
@ -6323,6 +6365,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
//>>demos: http://jqueryui.com/widget/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( true ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
|
@ -6331,25 +6375,23 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||
} else {}
|
||||
}( function( $ ) {
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
var widgetUuid = 0;
|
||||
var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
|
||||
var widgetSlice = Array.prototype.slice;
|
||||
|
||||
$.cleanData = ( function( orig ) {
|
||||
return function( elems ) {
|
||||
var events, elem, i;
|
||||
for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
|
||||
try {
|
||||
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
|
||||
// Http://bugs.jquery.com/ticket/8235
|
||||
} catch ( e ) {}
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
}
|
||||
orig( elems );
|
||||
};
|
||||
|
@ -6371,12 +6413,12 @@ $.widget = function( name, base, prototype ) {
|
|||
base = $.Widget;
|
||||
}
|
||||
|
||||
if ( $.isArray( prototype ) ) {
|
||||
if ( Array.isArray( prototype ) ) {
|
||||
prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
|
||||
}
|
||||
|
||||
// Create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
|
@ -6416,7 +6458,7 @@ $.widget = function( name, base, prototype ) {
|
|||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
if ( typeof value !== "function" ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
|
@ -6495,7 +6537,7 @@ $.widget.extend = function( target ) {
|
|||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
|
||||
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
|
@ -6544,7 +6586,8 @@ $.widget.bridge = function( name, object ) {
|
|||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
|
||||
if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
|
||||
if ( typeof instance[ options ] !== "function" ||
|
||||
options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name +
|
||||
" widget instance" );
|
||||
}
|
||||
|
@ -6805,12 +6848,30 @@ $.Widget.prototype = {
|
|||
classes: this.options.classes || {}
|
||||
}, options );
|
||||
|
||||
function bindRemoveEvent() {
|
||||
options.element.each( function( _, element ) {
|
||||
var isTracked = $.map( that.classesElementLookup, function( elements ) {
|
||||
return elements;
|
||||
} )
|
||||
.some( function( elements ) {
|
||||
return elements.is( element );
|
||||
} );
|
||||
|
||||
if ( !isTracked ) {
|
||||
that._on( $( element ), {
|
||||
remove: "_untrackClassesElement"
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
function processClassString( classes, checkOption ) {
|
||||
var current, i;
|
||||
for ( i = 0; i < classes.length; i++ ) {
|
||||
current = that.classesElementLookup[ classes[ i ] ] || $();
|
||||
if ( options.add ) {
|
||||
current = $( $.unique( current.get().concat( options.element.get() ) ) );
|
||||
bindRemoveEvent();
|
||||
current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
|
||||
} else {
|
||||
current = $( current.not( options.element ).get() );
|
||||
}
|
||||
|
@ -6822,10 +6883,6 @@ $.Widget.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
this._on( options.element, {
|
||||
"remove": "_untrackClassesElement"
|
||||
} );
|
||||
|
||||
if ( options.keys ) {
|
||||
processClassString( options.keys.match( /\S+/g ) || [], true );
|
||||
}
|
||||
|
@ -6843,6 +6900,8 @@ $.Widget.prototype = {
|
|||
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
|
||||
}
|
||||
} );
|
||||
|
||||
this._off( $( event.target ) );
|
||||
},
|
||||
|
||||
_removeClass: function( element, keys, extra ) {
|
||||
|
@ -6923,7 +6982,7 @@ $.Widget.prototype = {
|
|||
_off: function( element, eventName ) {
|
||||
eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
|
||||
this.eventNamespace;
|
||||
element.off( eventName ).off( eventName );
|
||||
element.off( eventName );
|
||||
|
||||
// Clear the stack to avoid memory leaks (#10056)
|
||||
this.bindings = $( this.bindings.not( element ).get() );
|
||||
|
@ -6989,7 +7048,7 @@ $.Widget.prototype = {
|
|||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
return !( typeof callback === "function" &&
|
||||
callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
|
@ -7011,6 +7070,8 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
} else if ( options === true ) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
|
@ -7038,7 +7099,7 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|||
|
||||
return $.widget;
|
||||
|
||||
} ) );
|
||||
} );
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
|
||||
/*!
|
||||
* jQuery UI Widget 1.12.1
|
||||
* jQuery UI Widget 1.13.0
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
|
|
123
public/js/dist/all.js
vendored
123
public/js/dist/all.js
vendored
|
@ -59472,6 +59472,9 @@ __webpack_require__.r(__webpack_exports__);
|
|||
}, {
|
||||
id: 'model_number',
|
||||
text: "Model Number"
|
||||
}, {
|
||||
id: 'min_amt',
|
||||
text: "Minimum Quantity"
|
||||
}],
|
||||
licenses: [{
|
||||
id: 'asset_tag',
|
||||
|
@ -59565,6 +59568,7 @@ __webpack_require__.r(__webpack_exports__);
|
|||
return this.columnOptions.general.concat(this.columnOptions.accessories).sort(sorter);
|
||||
|
||||
case 'consumable':
|
||||
console.log('Returned consumable');
|
||||
return this.columnOptions.general.concat(this.columnOptions.consumables).sort(sorter);
|
||||
|
||||
case 'license':
|
||||
|
@ -60833,7 +60837,36 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
|
||||
(function ($, settings) {
|
||||
var Components = {};
|
||||
Components.modals = {}; // confirm delete modal
|
||||
Components.modals = {}; // confirm restore modal
|
||||
|
||||
Components.modals.confirmRestore = function () {
|
||||
var $el = $('table');
|
||||
var events = {
|
||||
'click': function click(evnt) {
|
||||
var $context = $(this);
|
||||
var $restoreConfirmModal = $('#restoreConfirmModal');
|
||||
var href = $context.attr('href');
|
||||
var message = $context.attr('data-content');
|
||||
var title = $context.attr('data-title');
|
||||
$('#restoreConfirmModalLabel').text(title);
|
||||
$restoreConfirmModal.find('.modal-body').text(message);
|
||||
$('#restoreForm').attr('action', href);
|
||||
$restoreConfirmModal.modal({
|
||||
show: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var render = function render() {
|
||||
$el.on('click', '.restore-asset', events['click']);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render
|
||||
};
|
||||
}; // confirm delete modal
|
||||
|
||||
|
||||
Components.modals.confirmDelete = function () {
|
||||
var $el = $('table');
|
||||
|
@ -60869,6 +60902,7 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
|
||||
|
||||
$(function () {
|
||||
new Components.modals.confirmRestore().render();
|
||||
new Components.modals.confirmDelete().render();
|
||||
});
|
||||
})(jQuery, window.snipeit.settings);
|
||||
|
@ -61024,10 +61058,10 @@ $(document).ready(function () {
|
|||
return x !== 0;
|
||||
}); // makes sure we're not selecting the same thing twice for multiples
|
||||
|
||||
var filteredResponse = response.items.filter(function (item) {
|
||||
var filteredResponse = response.results.filter(function (item) {
|
||||
return currentlySelected.indexOf(+item.id) < 0;
|
||||
});
|
||||
var first = currentlySelected.length > 0 ? filteredResponse[0] : response.items[0];
|
||||
var first = currentlySelected.length > 0 ? filteredResponse[0] : response.results[0];
|
||||
|
||||
if (first && first.id) {
|
||||
first.selected = true;
|
||||
|
@ -61233,7 +61267,7 @@ $(document).ready(function () {
|
|||
|
||||
for (var i = 0; i < this.files.length; i++) {
|
||||
total_size += this.files[i].size;
|
||||
$(id + '-info').append('<span class="label label-default">' + this.files[i].name + ' (' + formatBytes(this.files[i].size) + ')</span> ');
|
||||
$(id + '-info').append('<span class="label label-default">' + htmlEntities(this.files[i].name) + ' (' + formatBytes(this.files[i].size) + ')</span> ');
|
||||
}
|
||||
|
||||
console.log('Max size is: ' + max_size);
|
||||
|
@ -61249,10 +61283,15 @@ $(document).ready(function () {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
function htmlEntities(str) {
|
||||
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||
}
|
||||
/**
|
||||
* Toggle disabled
|
||||
*/
|
||||
|
||||
|
||||
(function ($) {
|
||||
$.fn.toggleDisabled = function (callback) {
|
||||
return this.each(function () {
|
||||
|
@ -65420,6 +65459,8 @@ if (typeof jQuery === 'undefined') {
|
|||
/***/ ((module, exports, __webpack_require__) => {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( true ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
|
@ -65428,13 +65469,14 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||
} else {}
|
||||
} ( function( $ ) {
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
$.ui = $.ui || {};
|
||||
|
||||
return $.ui.version = "1.12.1";
|
||||
return $.ui.version = "1.13.0";
|
||||
|
||||
} ) );
|
||||
} );
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
@ -65446,7 +65488,7 @@ return $.ui.version = "1.12.1";
|
|||
/***/ ((module, exports, __webpack_require__) => {
|
||||
|
||||
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
|
||||
* jQuery UI Widget 1.12.1
|
||||
* jQuery UI Widget 1.13.0
|
||||
* http://jqueryui.com
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
|
@ -65461,6 +65503,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
//>>demos: http://jqueryui.com/widget/
|
||||
|
||||
( function( factory ) {
|
||||
"use strict";
|
||||
|
||||
if ( true ) {
|
||||
|
||||
// AMD. Register as an anonymous module.
|
||||
|
@ -65469,25 +65513,23 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_
|
|||
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
||||
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
|
||||
} else {}
|
||||
}( function( $ ) {
|
||||
} )( function( $ ) {
|
||||
"use strict";
|
||||
|
||||
var widgetUuid = 0;
|
||||
var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
|
||||
var widgetSlice = Array.prototype.slice;
|
||||
|
||||
$.cleanData = ( function( orig ) {
|
||||
return function( elems ) {
|
||||
var events, elem, i;
|
||||
for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
|
||||
try {
|
||||
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
|
||||
// Http://bugs.jquery.com/ticket/8235
|
||||
} catch ( e ) {}
|
||||
// Only trigger remove when necessary to save time
|
||||
events = $._data( elem, "events" );
|
||||
if ( events && events.remove ) {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
}
|
||||
}
|
||||
orig( elems );
|
||||
};
|
||||
|
@ -65509,12 +65551,12 @@ $.widget = function( name, base, prototype ) {
|
|||
base = $.Widget;
|
||||
}
|
||||
|
||||
if ( $.isArray( prototype ) ) {
|
||||
if ( Array.isArray( prototype ) ) {
|
||||
prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
|
||||
}
|
||||
|
||||
// Create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
$.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
|
@ -65554,7 +65596,7 @@ $.widget = function( name, base, prototype ) {
|
|||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
if ( typeof value !== "function" ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
|
@ -65633,7 +65675,7 @@ $.widget.extend = function( target ) {
|
|||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
|
||||
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
|
@ -65682,7 +65724,8 @@ $.widget.bridge = function( name, object ) {
|
|||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
|
||||
if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
|
||||
if ( typeof instance[ options ] !== "function" ||
|
||||
options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name +
|
||||
" widget instance" );
|
||||
}
|
||||
|
@ -65943,12 +65986,30 @@ $.Widget.prototype = {
|
|||
classes: this.options.classes || {}
|
||||
}, options );
|
||||
|
||||
function bindRemoveEvent() {
|
||||
options.element.each( function( _, element ) {
|
||||
var isTracked = $.map( that.classesElementLookup, function( elements ) {
|
||||
return elements;
|
||||
} )
|
||||
.some( function( elements ) {
|
||||
return elements.is( element );
|
||||
} );
|
||||
|
||||
if ( !isTracked ) {
|
||||
that._on( $( element ), {
|
||||
remove: "_untrackClassesElement"
|
||||
} );
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
function processClassString( classes, checkOption ) {
|
||||
var current, i;
|
||||
for ( i = 0; i < classes.length; i++ ) {
|
||||
current = that.classesElementLookup[ classes[ i ] ] || $();
|
||||
if ( options.add ) {
|
||||
current = $( $.unique( current.get().concat( options.element.get() ) ) );
|
||||
bindRemoveEvent();
|
||||
current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
|
||||
} else {
|
||||
current = $( current.not( options.element ).get() );
|
||||
}
|
||||
|
@ -65960,10 +66021,6 @@ $.Widget.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
this._on( options.element, {
|
||||
"remove": "_untrackClassesElement"
|
||||
} );
|
||||
|
||||
if ( options.keys ) {
|
||||
processClassString( options.keys.match( /\S+/g ) || [], true );
|
||||
}
|
||||
|
@ -65981,6 +66038,8 @@ $.Widget.prototype = {
|
|||
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
|
||||
}
|
||||
} );
|
||||
|
||||
this._off( $( event.target ) );
|
||||
},
|
||||
|
||||
_removeClass: function( element, keys, extra ) {
|
||||
|
@ -66061,7 +66120,7 @@ $.Widget.prototype = {
|
|||
_off: function( element, eventName ) {
|
||||
eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
|
||||
this.eventNamespace;
|
||||
element.off( eventName ).off( eventName );
|
||||
element.off( eventName );
|
||||
|
||||
// Clear the stack to avoid memory leaks (#10056)
|
||||
this.bindings = $( this.bindings.not( element ).get() );
|
||||
|
@ -66127,7 +66186,7 @@ $.Widget.prototype = {
|
|||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
return !( typeof callback === "function" &&
|
||||
callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
|
@ -66149,6 +66208,8 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
} else if ( options === true ) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
|
@ -66176,7 +66237,7 @@ $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
|||
|
||||
return $.widget;
|
||||
|
||||
} ) );
|
||||
} );
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
|
1164
public/js/dist/bootstrap-table.js
vendored
1164
public/js/dist/bootstrap-table.js
vendored
File diff suppressed because it is too large
Load diff
|
@ -172,6 +172,36 @@ pieOptions = {
|
|||
$el.on('click', '.delete-asset', events['click']);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render
|
||||
};
|
||||
|
||||
// confirm restore modal
|
||||
Components.modals.confirmRestore = function () {
|
||||
var $el = $('table');
|
||||
|
||||
var events = {
|
||||
'click': function click(evnt) {
|
||||
var $context = $(this);
|
||||
var $dataConfirmModal = $('#restoreConfirmModal');
|
||||
var href = $context.attr('href');
|
||||
var message = $context.attr('data-content');
|
||||
var title = $context.attr('data-title');
|
||||
|
||||
$('#myModalLabel').text(title);
|
||||
$dataConfirmModal.find('.modal-body').text(message);
|
||||
$('#confirmRestoreForm').attr('action', href);
|
||||
$dataConfirmModal.modal({
|
||||
show: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var render = function render() {
|
||||
$el.on('click', '.restore-modal', events['click']);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=c8a70594c0d99275266d",
|
||||
"/js/build/app.js": "/js/build/app.js?id=16ac5c8f218827150ce0",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=83e39e254b7f9035eddc",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=b1866ec98d44c0a8ceea",
|
||||
"/css/build/app.css": "/css/build/app.css?id=61d5535cb27cce41d422",
|
||||
|
@ -18,15 +18,15 @@
|
|||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=efda2335fa5243175850",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=6a9d0ac448c28b88e5d6",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=c24716a423d375902723",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=138874c5ffe57b679997",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=3480eded2be4cd65a83e",
|
||||
"/css/blue.png": "/css/blue.png?id=e83a6c29e04fe851f212",
|
||||
"/css/blue@2x.png": "/css/blue@2x.png?id=51135dd4d24f88f5de0b",
|
||||
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced",
|
||||
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=93c24b4c89490bbfd73e",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=810d7e520c3057ee500e",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=651427cc4b45d8e68d0c",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=867755a1544f6c0ea828",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=a233dcde4650f5d34491",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=0f09ee116517a9573dd0",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=fbc9a3fb41192f2724e8",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=efda2335fa5243175850",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=6e35fb4cb2f1063b3047",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=ec96c42439cdeb022133",
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
consumables: [
|
||||
{id: 'item_no', text: "Item Number"},
|
||||
{id: 'model_number', text: "Model Number"},
|
||||
{id: 'min_amt', text: "Minimum Quantity"},
|
||||
],
|
||||
licenses: [
|
||||
{id: 'asset_tag', text: 'Assigned To Asset'},
|
||||
|
@ -216,6 +217,7 @@
|
|||
.concat(this.columnOptions.accessories)
|
||||
.sort(sorter);
|
||||
case 'consumable':
|
||||
console.log('Returned consumable');
|
||||
return this.columnOptions.general
|
||||
.concat(this.columnOptions.consumables)
|
||||
.sort(sorter);
|
||||
|
@ -309,4 +311,4 @@
|
|||
select2: require('../select2.vue').default
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -84,6 +84,37 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
var Components = {};
|
||||
Components.modals = {};
|
||||
|
||||
// confirm restore modal
|
||||
Components.modals.confirmRestore = function() {
|
||||
var $el = $('table');
|
||||
|
||||
var events = {
|
||||
'click': function(evnt) {
|
||||
var $context = $(this);
|
||||
var $restoreConfirmModal = $('#restoreConfirmModal');
|
||||
var href = $context.attr('href');
|
||||
var message = $context.attr('data-content');
|
||||
var title = $context.attr('data-title');
|
||||
|
||||
$('#restoreConfirmModalLabel').text(title);
|
||||
$restoreConfirmModal.find('.modal-body').text(message);
|
||||
$('#restoreForm').attr('action', href);
|
||||
$restoreConfirmModal.modal({
|
||||
show: true
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var render = function() {
|
||||
$el.on('click', '.restore-asset', events['click']);
|
||||
};
|
||||
|
||||
return {
|
||||
render: render
|
||||
};
|
||||
};
|
||||
|
||||
// confirm delete modal
|
||||
Components.modals.confirmDelete = function() {
|
||||
var $el = $('table');
|
||||
|
@ -121,6 +152,7 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
|
|||
* Component definition stays out of load event, execution only happens.
|
||||
*/
|
||||
$(function() {
|
||||
new Components.modals.confirmRestore().render();
|
||||
new Components.modals.confirmDelete().render();
|
||||
});
|
||||
}(jQuery, window.snipeit.settings));
|
||||
|
|
|
@ -124,6 +124,8 @@
|
|||
'image' => 'Image',
|
||||
'image_delete' => 'Delete Image',
|
||||
'image_upload' => 'Upload Image',
|
||||
'filetypes_accepted_help' => 'Accepted filetype is :types. Max upload size allowed is :size.|Accepted filetypes are :types. Max upload size allowed is :size.',
|
||||
'filetypes_size_help' => 'Max upload size allowed is :size.',
|
||||
'image_filetypes_help' => 'Accepted filetypes are jpg, webp, png, gif, and svg. Max upload size allowed is :size.',
|
||||
'import' => 'Import',
|
||||
'importing' => 'Importing',
|
||||
|
|
|
@ -58,20 +58,29 @@
|
|||
<td>{{ $field->field_encrypted=='1' ? trans('general.yes') : trans('general.no') }}</td>
|
||||
<td>
|
||||
@if ($field->pivot->required)
|
||||
<a href="{{ route('fields.optional', [$custom_fieldset->id, $field->id]) }}">
|
||||
<i class="fas fa-check text-success" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('admin/custom_fields/general.make_optional') }}</span>
|
||||
</a>
|
||||
<form method="post" action="{{ route('fields.optional', [$custom_fieldset->id, $field->id]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-link"><i class="fa fa-check text-success" aria-hidden="true"></i></button>
|
||||
</form>
|
||||
|
||||
@else
|
||||
<a href="{{ route('fields.required', [$custom_fieldset->id, $field->id]) }}">
|
||||
<i class="fas fa-times text-danger" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('admin/custom_fields/general.make_required') }}</span>
|
||||
</a>
|
||||
|
||||
<form method="post" action="{{ route('fields.required', [$custom_fieldset->id, $field->id]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-link"><i class="fa fa-times text-danger" aria-hidden="true"></i></button>
|
||||
</form>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
@can('update', $custom_fieldset)
|
||||
<<<<<<< HEAD
|
||||
<a href="{{ route('fields.disassociate', [$field, $custom_fieldset->id]) }}" class="btn btn-sm btn-danger">{{ trans('button.remove') }}</a>
|
||||
=======
|
||||
<form method="post" action="{{ route('fields.disassociate', [$field, $custom_fieldset->id]) }}">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-sm btn-danger">Remove</button>
|
||||
</form>
|
||||
>>>>>>> 476e17055beb3a2f989946812010d9f23851ca89
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -109,14 +109,14 @@
|
|||
@if ($snipeSettings->brand == '3')
|
||||
<a class="logo navbar-brand no-hover" href="{{ url('/') }}">
|
||||
@if ($snipeSettings->logo!='')
|
||||
<img class="navbar-brand-img" src="{{ Storage::disk('public')->url('/').e($snipeSettings->logo) }}" alt="{{ $snipeSettings->site_name }} logo">
|
||||
<img class="navbar-brand-img" src="{{ Storage::disk('public')->url($snipeSettings->logo) }}" alt="{{ $snipeSettings->site_name }} logo">
|
||||
@endif
|
||||
{{ $snipeSettings->site_name }}
|
||||
</a>
|
||||
@elseif ($snipeSettings->brand == '2')
|
||||
<a class="logo navbar-brand no-hover" href="{{ url('/') }}">
|
||||
@if ($snipeSettings->logo!='')
|
||||
<img class="navbar-brand-img" src="{{ Storage::disk('public')->url('/').e($snipeSettings->logo) }}" alt="{{ $snipeSettings->site_name }} logo">
|
||||
<img class="navbar-brand-img" src="{{ Storage::disk('public')->url($snipeSettings->logo) }}" alt="{{ $snipeSettings->site_name }} logo">
|
||||
@endif
|
||||
<span class="sr-only">{{ $snipeSettings->site_name }}</span>
|
||||
</a>
|
||||
|
@ -355,10 +355,17 @@
|
|||
@endcan
|
||||
<li class="divider"></li>
|
||||
<li>
|
||||
<a href="{{ url('/logout') }}">
|
||||
<i class="fas fa-sign-out-alt" aria-hidden="true"></i>
|
||||
{{ trans('general.logout') }}
|
||||
|
||||
<a href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||
<i class="fa fa-sign-out fa-fw"></i> {{ trans('general.logout') }}
|
||||
{{ csrf_field() }}
|
||||
</a>
|
||||
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
|
||||
{{ csrf_field() }}
|
||||
</form>
|
||||
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
@ -852,6 +859,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal modal-warning fade" id="restoreConfirmModal" tabindex="-1" role="dialog" aria-labelledby="confirmModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title" id="confirmModalLabel"> </h4>
|
||||
</div>
|
||||
<div class="modal-body"></div>
|
||||
<div class="modal-footer">
|
||||
<form method="post" id="restoreForm" role="form">
|
||||
{{ csrf_field() }}
|
||||
{{ method_field('POST') }}
|
||||
|
||||
<button type="button" class="btn btn-default pull-left" data-dismiss="modal">{{ trans('general.cancel') }}</button>
|
||||
<button type="submit" class="btn btn-outline" id="dataConfirmOK">{{ trans('general.yes') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Javascript files --}}
|
||||
<script src="{{ url(mix('js/dist/all.js')) }}" nonce="{{ csrf_token() }}"></script>
|
||||
|
||||
|
@ -925,6 +954,7 @@
|
|||
@endif
|
||||
|
||||
|
||||
|
||||
@livewireScripts
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
<i class="far fa-list-alt fa-2x" aria-hidden="true"></i>
|
||||
</span>
|
||||
<span class="hidden-xs hidden-sm">{{ trans('admin/licenses/form.seats') }}</span>
|
||||
<badge class="badge badge-secondary">{{ $license->availCount()->count() }} / {{ $license->seats }}</badge>
|
||||
<span class="badge badge-secondary">{{ $license->availCount()->count() }} / {{ $license->seats }}</span>
|
||||
|
||||
</a>
|
||||
</li>
|
||||
|
|
|
@ -7,7 +7,15 @@
|
|||
@stop
|
||||
|
||||
@section('header_right')
|
||||
<a href="{{ route('settings.index') }}" class="btn btn-primary"> {{ trans('general.back') }}</a>
|
||||
<a href="{{ route('settings.index') }}" class="btn btn-default pull-right" style="margin-left: 5px;">
|
||||
{{ trans('general.back') }}
|
||||
</a>
|
||||
|
||||
<form method="POST" style="display: inline">
|
||||
{{ Form::hidden('_token', csrf_token()) }}
|
||||
<button class="btn btn-primary {{ (config('app.lock_passwords')) ? ' disabled': '' }}">{{ trans('admin/settings/general.generate_backup') }}</button>
|
||||
</form>
|
||||
|
||||
@stop
|
||||
|
||||
{{-- Page content --}}
|
||||
|
@ -15,10 +23,16 @@
|
|||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
|
||||
<div class="col-md-8">
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-body">
|
||||
|
||||
|
||||
|
||||
<div class="table-responsive">
|
||||
|
||||
<table
|
||||
data-cookie="true"
|
||||
data-cookie-id-table="system-backups"
|
||||
|
@ -30,10 +44,13 @@
|
|||
id="system-backups"
|
||||
class="table table-striped snipe-table">
|
||||
<thead>
|
||||
<th>File</th>
|
||||
<th>Created</th>
|
||||
<th>Size</th>
|
||||
<tr>
|
||||
<th data-sortable="true">File</th>
|
||||
<th data-sortable="true" data-field="modified_display" data-sort-name="modified_value">Created</th>
|
||||
<th data-field="modified_value" data-visible="false"></th>
|
||||
<th data-sortable="true">Size</th>
|
||||
<th><span class="sr-only">{{ trans('general.delete') }}</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($files as $file)
|
||||
|
@ -43,52 +60,164 @@
|
|||
{{ $file['filename'] }}
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ date("M d, Y g:i A", $file['modified']) }} </td>
|
||||
<td>{{ $file['modified_display'] }} </td>
|
||||
<td>{{ $file['modified_value'] }} </td>
|
||||
<td>{{ $file['filesize'] }}</td>
|
||||
<td>
|
||||
|
||||
@can('superadmin')
|
||||
<a data-html="false"
|
||||
class="btn delete-asset btn-danger btn-sm {{ (config('app.lock_passwords')) ? ' disabled': '' }}" data-toggle="modal" href=" {{ route('settings.backups.destroy', $file['filename']) }}" data-content="{{ trans('admin/settings/message.backup.delete_confirm') }}" data-title="{{ trans('general.delete') }} {{ htmlspecialchars($file['filename']) }} ?" onClick="return false;">
|
||||
class="btn delete-asset btn-danger btn-sm {{ (config('app.lock_passwords')) ? ' disabled': '' }}" data-toggle="modal" href="{{ route('settings.backups.destroy', $file['filename']) }}" data-content="{{ trans('admin/settings/message.backup.delete_confirm') }}" data-title="{{ trans('general.delete') }} {{ e($file['filename']) }} ?" onClick="return false;">
|
||||
<i class="fas fa-trash icon-white" aria-hidden="true"></i>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</a>
|
||||
|
||||
<a data-html="true" href="{{ route('settings.backups.restore', $file['filename']) }}" class="btn btn-warning btn-sm restore-asset {{ (config('app.lock_passwords')) ? ' disabled': '' }}" data-toggle="modal" data-content="Yes, restore it. I acknowledge that this will overwrite any existing data currently in the database. This will also log out all of your existing users (including you)." data-title="Are you sure you wish to restore your database from {{ e($file['filename']) }}?" onClick="return false;">
|
||||
<i class="fas fa-retweet" aria-hidden="true"></i>
|
||||
<span class="sr-only">Restore</span>
|
||||
</a>
|
||||
|
||||
@endcan
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div> <!-- end table-responsive div -->
|
||||
</div> <!-- end box-body div -->
|
||||
</div> <!-- end box div -->
|
||||
</div> <!-- end col-md div -->
|
||||
|
||||
<!-- side address column -->
|
||||
<div class="col-md-4">
|
||||
|
||||
<div class="box box-default">
|
||||
<div class="box-header with-border">
|
||||
<h2 class="box-title">
|
||||
<i class="far fa-file-archive" aria-hidden="true"></i>
|
||||
Upload Backup</h2>
|
||||
<div class="box-tools pull-right">
|
||||
</div>
|
||||
</div><!-- /.box-header -->
|
||||
|
||||
<div class="box-body">
|
||||
|
||||
<p>Backup files on the server are stored in: <code>{{ $path }}</code></p>
|
||||
|
||||
@if (config('app.lock_passwords')===true)
|
||||
<p class="alert alert-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
|
||||
@else
|
||||
|
||||
{{ Form::open([
|
||||
'method' => 'POST',
|
||||
'route' => 'settings.backups.upload',
|
||||
'files' => true,
|
||||
'class' => 'form-horizontal' ]) }}
|
||||
@csrf
|
||||
|
||||
|
||||
<div class="form-group {{ $errors->has((isset($fieldname) ? $fieldname : 'image')) ? 'has-error' : '' }}" style="margin-bottom: 0px;">
|
||||
<div class="col-md-8 col-xs-8">
|
||||
|
||||
|
||||
<!-- displayed on screen -->
|
||||
<label class="btn btn-default col-md-12 col-xs-12" aria-hidden="true">
|
||||
<i class="fas fa-paperclip" aria-hidden="true"></i>
|
||||
{{ trans('button.select_file') }}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- screen reader only -->
|
||||
<input type="file" id="file" name="file" aria-label="file" class="sr-only">
|
||||
|
||||
<input type="file" name="file" class="js-uploadFile" id="uploadFile" data-maxsize="{{ Helper::file_upload_max_size() }}" accept="application/zip" style="display:none;" aria-label="file" aria-hidden="true">
|
||||
|
||||
|
||||
</label>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4 col-xs-4">
|
||||
<button class="btn btn-primary col-md-12 col-xs-12" id="uploadButton" disabled>Upload</button>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
|
||||
<p class="label label-default col-md-12" style="font-size: 120%!important; margin-top: 10px; margin-bottom: 10px;" id="uploadFile-info"></p>
|
||||
|
||||
<p class="help-block" style="margin-top: 10px;" id="uploadFile-status">{{ trans_choice('general.filetypes_accepted_help', 1, ['size' => Helper::file_upload_max_size_readable(), 'types' => '.zip']) }}</p>
|
||||
{!! $errors->first('image', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{{ Form::close() }}
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- side address column -->
|
||||
<div class="col-md-3">
|
||||
|
||||
<form method="POST">
|
||||
{{ Form::hidden('_token', csrf_token()) }}
|
||||
|
||||
<p>
|
||||
<button class="btn btn-primary {{ (config('app.lock_passwords')) ? ' disabled': '' }}">{{ trans('admin/settings/general.generate_backup') }}</button>
|
||||
</p>
|
||||
|
||||
@if (config('app.lock_passwords'))
|
||||
<p class="text-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
|
||||
@endif
|
||||
|
||||
|
||||
</form>
|
||||
<p>Backup files are located in: {{ $path }}</p>
|
||||
|
||||
|
||||
<div class="box box-warning">
|
||||
<div class="box-header with-border">
|
||||
<h2 class="box-title">
|
||||
<i class="fas fa-exclamation-triangle text-orange" aria-hidden="true"></i> Restoring from Backup</h2>
|
||||
<div class="box-tools pull-right">
|
||||
</div>
|
||||
</div><!-- /.box-header -->
|
||||
<div class="box-body">
|
||||
|
||||
<p>
|
||||
Use the restore button <small><span class="btn btn-xs btn-warning"><i class="text-white fas fa-retweet" aria-hidden="true"></i></span></small> to
|
||||
restore from a previous backup. (This does not currently with with S3 file storage.)</p>
|
||||
|
||||
<p>Your <strong>entire {{ config('app.name') }} database and any uploaded files will be completely replaced</strong> by what's in the backup file.
|
||||
</p>
|
||||
|
||||
<p class="text-danger" style="font-weight: bold; font-size: 120%;">
|
||||
You will be logged out once your restore is complete.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Very large backups may time out on the restore attempt and may still need to be run via command line.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- end col-md-12 form div -->
|
||||
</div> <!-- end form group div -->
|
||||
|
||||
</div> <!-- end col-md-3 div -->
|
||||
</div> <!-- end row div -->
|
||||
|
||||
@stop
|
||||
|
||||
@section('moar_scripts')
|
||||
|
||||
@include ('partials.bootstrap-table')
|
||||
|
||||
|
||||
<script>
|
||||
/*
|
||||
* This just disables the upload button via JS unless they have actually selected a file.
|
||||
*
|
||||
* Todo: - key off the javascript response for JS file upload info as well, so that if it fails that
|
||||
* check (file size and type) we should also leave it disabled.
|
||||
*/
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$("#uploadFile").on('change',function(event){
|
||||
|
||||
if ($('#uploadFile').val().length == 0) {
|
||||
$("#uploadButton").attr("disabled", true);
|
||||
} else {
|
||||
$('#uploadButton').removeAttr('disabled');
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@stop
|
||||
|
||||
|
|
|
@ -189,6 +189,14 @@ Route::group(['prefix' => 'admin', 'middleware' => ['auth', 'authorize:superuser
|
|||
[SettingsController::class, 'postBackups']
|
||||
)->name('settings.backups.create');
|
||||
|
||||
Route::post('/restore/{filename}',
|
||||
[SettingsController::class, 'postRestore']
|
||||
)->name('settings.backups.restore');
|
||||
|
||||
Route::post('/upload',
|
||||
[SettingsController::class, 'postUploadBackup']
|
||||
)->name('settings.backups.upload');
|
||||
|
||||
Route::get('/', [SettingsController::class, 'getBackups'])->name('settings.backups.index');
|
||||
});
|
||||
|
||||
|
|
|
@ -8,51 +8,39 @@ use Illuminate\Support\Facades\Route;
|
|||
* Custom Fields Routes
|
||||
*/
|
||||
|
||||
Route::group(['prefix' => 'fields', 'middleware' => ['auth']], function () {
|
||||
|
||||
Route::get(
|
||||
|
||||
Route::group([ 'prefix' => 'fields','middleware' => ['auth'] ], function () {
|
||||
|
||||
Route::post(
|
||||
'required/{fieldset_id}/{field_id}',
|
||||
[
|
||||
CustomFieldsetsController::class,
|
||||
'makeFieldRequired'
|
||||
]
|
||||
[CustomFieldsetsController::class, 'makeFieldRequired']
|
||||
)->name('fields.required');
|
||||
|
||||
Route::get(
|
||||
Route::post(
|
||||
'optional/{fieldset_id}/{field_id}',
|
||||
[
|
||||
CustomFieldsetsController::class,
|
||||
'makeFieldOptional'
|
||||
]
|
||||
[CustomFieldsetsController::class, 'makeFieldOptional']
|
||||
)->name('fields.optional');
|
||||
|
||||
Route::get(
|
||||
Route::post(
|
||||
'{field_id}/fieldset/{fieldset_id}/disassociate',
|
||||
[
|
||||
CustomFieldsetsController::class,
|
||||
'deleteFieldFromFieldset'
|
||||
]
|
||||
[CustomFieldsController::class, 'deleteFieldFromFieldset']
|
||||
)->name('fields.disassociate');
|
||||
|
||||
Route::post(
|
||||
'fieldsets/{id}/associate',
|
||||
[
|
||||
CustomFieldsetsController::class,
|
||||
'associate'
|
||||
]
|
||||
[CustomFieldsController::class, 'associate']
|
||||
)->name('fieldsets.associate');
|
||||
|
||||
Route::resource('fieldsets', CustomFieldsetsController::class, [
|
||||
'parameters' => ['fieldset' => 'field_id', 'field' => 'field_id'],
|
||||
]);
|
||||
'parameters' => ['fieldset' => 'field_id', 'field' => 'field_id']
|
||||
]);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
Route::resource('fields', CustomFieldsController::class, [
|
||||
'parameters' => ['field' => 'field_id'],
|
||||
'middleware' => ['auth'],
|
||||
'parameters' => ['field' => 'field_id', 'fieldset' => 'fieldset_id'],
|
||||
]);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,17 +1,50 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Users;
|
||||
use App\Http\Controllers\Users\UserFilesController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
// User Management
|
||||
Route::post('{userId}/clone', [ 'uses' => 'Users\UsersController@postCreate' ]);
|
||||
Route::post('{userId}/restore', [ 'as' => 'restore/user', 'uses' => 'Users\UsersController@getRestore' ]);
|
||||
Route::get('{userId}/unsuspend', [ 'as' => 'unsuspend/user', 'uses' => 'Users\UsersController@getUnsuspend' ]);
|
||||
Route::post('{userId}/upload', [ 'as' => 'upload/user', 'uses' => 'Users\UserFilesController@store' ]);
|
||||
// User Management
|
||||
Route::post(
|
||||
'{userId}/clone',
|
||||
[
|
||||
Users\UsersController::class,
|
||||
'postCreate'
|
||||
]
|
||||
);
|
||||
|
||||
Route::post(
|
||||
'{userId}/restore',
|
||||
[
|
||||
Users\UsersController::class,
|
||||
'getRestore'
|
||||
]
|
||||
)->name('restore/user');
|
||||
|
||||
Route::get(
|
||||
'{userId}/unsuspend',
|
||||
[
|
||||
Users\UsersController::class,
|
||||
'getUnsuspend'
|
||||
]
|
||||
)->name('unsuspend/user');
|
||||
|
||||
Route::post(
|
||||
'{userId}/upload',
|
||||
[
|
||||
Users\UserFilesController::class,
|
||||
'store'
|
||||
]
|
||||
)->name('upload/user');
|
||||
|
||||
Route::delete(
|
||||
'{userId}/deletefile/{fileId}',
|
||||
[ 'as' => 'userfile.destroy', 'uses' => 'Users\UserFilesController@destroy' ]
|
||||
);
|
||||
[
|
||||
Users\UserFilesController::class,
|
||||
'destroy'
|
||||
]
|
||||
)->name('userfile.destroy');
|
||||
|
||||
|
||||
Route::group(['prefix' => 'users', 'middleware' => ['auth']], function () {
|
||||
|
||||
|
|
|
@ -178,7 +178,7 @@ echo "--------------------------------------------------------\n\n";
|
|||
// can cause issues with funky caching
|
||||
$unused_files = [
|
||||
"bootstrap/cache/compiled.php",
|
||||
"bootsrap/cache/services.php",
|
||||
"bootstrap/cache/services.php",
|
||||
"bootstrap/cache/config.php",
|
||||
];
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue