Merge remote-tracking branch 'origin/develop'

This commit is contained in:
snipe 2023-10-26 16:00:22 +01:00
commit 38f10e0b21
21 changed files with 253 additions and 89 deletions

View file

@ -179,9 +179,14 @@ class AssetModelsController extends Controller
if ($model->save()) { if ($model->save()) {
if ($model->wasChanged('eol')) { if ($model->wasChanged('eol')) {
if ($model->eol > 0) {
$newEol = $model->eol; $newEol = $model->eol;
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false) $model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]); ->update(['asset_eol_date' => DB::raw('DATE_ADD(purchase_date, INTERVAL ' . $newEol . ' MONTH)')]);
} elseif ($model->eol == 0) {
$model->assets()->whereNotNull('purchase_date')->where('eol_explicit', false)
->update(['asset_eol_date' => DB::raw('null')]);
}
} }
return redirect()->route('models.index')->with('success', trans('admin/models/message.update.success')); return redirect()->route('models.index')->with('success', trans('admin/models/message.update.success'));
} }

View file

@ -137,7 +137,7 @@ class AssetsController extends Controller
$asset->warranty_months = request('warranty_months', null); $asset->warranty_months = request('warranty_months', null);
$asset->purchase_cost = request('purchase_cost'); $asset->purchase_cost = request('purchase_cost');
$asset->purchase_date = request('purchase_date', null); $asset->purchase_date = request('purchase_date', null);
$asset->asset_eol_date = request('asset_eol_date', $asset->present()->eol_date()); $asset->asset_eol_date = request('asset_eol_date', null);
$asset->assigned_to = request('assigned_to', null); $asset->assigned_to = request('assigned_to', null);
$asset->supplier_id = request('supplier_id', null); $asset->supplier_id = request('supplier_id', null);
$asset->requestable = request('requestable', 0); $asset->requestable = request('requestable', 0);
@ -309,14 +309,15 @@ class AssetsController extends Controller
$asset->warranty_months = $request->input('warranty_months', null); $asset->warranty_months = $request->input('warranty_months', null);
$asset->purchase_cost = $request->input('purchase_cost', null); $asset->purchase_cost = $request->input('purchase_cost', null);
$asset->purchase_date = $request->input('purchase_date', null); $asset->purchase_date = $request->input('purchase_date', null);
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && $asset->model->eol) { if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
$asset->purchase_date = $request->input('purchase_date', null); $asset->purchase_date = $request->input('purchase_date', null);
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d'); $asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
$asset->eol_explicit = false;
} elseif ($request->filled('asset_eol_date')) { } elseif ($request->filled('asset_eol_date')) {
$asset->asset_eol_date = $request->input('asset_eol_date', null); $asset->asset_eol_date = $request->input('asset_eol_date', null);
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date); $months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
if($asset->model->eol) { if($asset->model->eol) {
if($months != $asset->model->eol) { if($months != $asset->model->eol > 0) {
$asset->eol_explicit = true; $asset->eol_explicit = true;
} else { } else {
$asset->eol_explicit = false; $asset->eol_explicit = false;
@ -324,6 +325,9 @@ class AssetsController extends Controller
} else { } else {
$asset->eol_explicit = true; $asset->eol_explicit = true;
} }
} elseif (!$request->filled('asset_eol_date') && (($asset->model->eol) == 0)) {
$asset->asset_eol_date = null;
$asset->eol_explicit = false;
} }
$asset->supplier_id = $request->input('supplier_id', null); $asset->supplier_id = $request->input('supplier_id', null);
$asset->expected_checkin = $request->input('expected_checkin', null); $asset->expected_checkin = $request->input('expected_checkin', null);

View file

@ -112,7 +112,8 @@ class BulkAssetsController extends Controller
public function update(Request $request) public function update(Request $request)
{ {
$this->authorize('update', Asset::class); $this->authorize('update', Asset::class);
$error_bag = []; $has_errors = 0;
$error_array = array();
// Get the back url from the session and then destroy the session // Get the back url from the session and then destroy the session
$bulk_back_url = route('hardware.index'); $bulk_back_url = route('hardware.index');
@ -120,7 +121,6 @@ class BulkAssetsController extends Controller
$bulk_back_url = $request->session()->pull('bulk_back_url'); $bulk_back_url = $request->session()->pull('bulk_back_url');
} }
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray(); $custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
if (Session::exists('ids')) { if (Session::exists('ids')) {
@ -160,7 +160,6 @@ class BulkAssetsController extends Controller
$this->conditionallyAddItem('purchase_date') $this->conditionallyAddItem('purchase_date')
->conditionallyAddItem('expected_checkin') ->conditionallyAddItem('expected_checkin')
->conditionallyAddItem('model_id')
->conditionallyAddItem('order_number') ->conditionallyAddItem('order_number')
->conditionallyAddItem('requestable') ->conditionallyAddItem('requestable')
->conditionallyAddItem('status_id') ->conditionallyAddItem('status_id')
@ -187,6 +186,7 @@ class BulkAssetsController extends Controller
$this->update_array['purchase_cost'] = $request->input('purchase_cost'); $this->update_array['purchase_cost'] = $request->input('purchase_cost');
} }
if ($request->filled('company_id')) { if ($request->filled('company_id')) {
$this->update_array['company_id'] = $request->input('company_id'); $this->update_array['company_id'] = $request->input('company_id');
if ($request->input('company_id') == 'clear') { if ($request->input('company_id') == 'clear') {
@ -208,61 +208,95 @@ class BulkAssetsController extends Controller
} }
$changed = []; $changed = [];
$assetCollection = Asset::where('id' ,$assetId)->get(); $asset = Asset::find($assetId);
foreach ($this->update_array as $key => $value) { foreach ($this->update_array as $key => $value) {
if ($this->update_array[$key] != $assetCollection->toArray()[0][$key]) { if ($this->update_array[$key] != $asset->{$key}) {
$changed[$key]['old'] = $assetCollection->toArray()[0][$key]; $changed[$key]['old'] = $asset->{$key};
$changed[$key]['new'] = $this->update_array[$key]; $changed[$key]['new'] = $this->update_array[$key];
} }
} }
$logAction = new Actionlog();
$logAction->item_type = Asset::class;
$logAction->item_id = $assetId;
$logAction->created_at = date("Y-m-d H:i:s");
$logAction->user_id = Auth::id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
if ($custom_fields_present) { if ($custom_fields_present) {
$asset = Asset::find($assetId);
$assetCustomFields = $asset->model()->first()->fieldset; $model = $asset->model()->first();
// Use the rules of the new model fieldsets if the model changed
if ($request->filled('model_id')) {
$this->update_array['model_id'] = $request->input('model_id');
$model = \App\Models\AssetModel::find($request->input('model_id'));
}
// Make sure this model is valid
$assetCustomFields = ($model) ? $model->fieldset : null;
if ($assetCustomFields && $assetCustomFields->fields) { if ($assetCustomFields && $assetCustomFields->fields) {
foreach ($assetCustomFields->fields as $field) { foreach ($assetCustomFields->fields as $field) {
if (array_key_exists($field->db_column, $this->update_array)) {
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted=='1')) {
$decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
/*
* Check if the decrypted existing value is different from one we just submitted
* and if not, pull it out of the object since it shouldn't really be updating at all.
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
* different times will have different values, so it will *look* like it was updated
* but it wasn't.
*/
if ($decrypted_old != $this->update_array[$field->db_column]) {
$asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
} else {
/*
* Remove the encrypted custom field from the update_array, since nothing changed
*/
unset($this->update_array[$field->db_column]);
unset($asset->{$field->db_column});
}
/*
* These custom fields aren't encrypted, just carry on as usual
*/
} else {
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
// Check if this is an array, and if so, flatten it
if (is_array($this->update_array[$field->db_column])) {
$asset->{$field->db_column} = implode(', ', $this->update_array[$field->db_column]);
} else {
$asset->{$field->db_column} = $this->update_array[$field->db_column]; $asset->{$field->db_column} = $this->update_array[$field->db_column];
$saved = $asset->save();
if(!$saved) {
$error_bag[] = $asset->getErrors();
}
continue;
} else {
$array = $this->update_array;
array_except($array, $field->db_column);
$asset->save($array);
}
if (!$asset->save()) {
$error_bag[] = $asset->getErrors();
} }
} }
} }
} else {
Asset::find($assetId)->update($this->update_array); } // endforeach
} // end custom field check
} // end custom fields handler
// Check if it passes validation, and then try to save
if (!$asset->update($this->update_array)) {
// Build the error array
foreach ($asset->getErrors()->toArray() as $key => $message) {
for ($x = 0; $x < count($message); $x++) {
$error_array[$key][] = trans('general.asset') . ' ' . $asset->id . ': ' . $message[$x];
$has_errors++;
} }
} }
if(!empty($error_bag)) {
$errors = []; } // end if saved
//find the customfield name from the name of the messagebag items
foreach ($error_bag as $key => $bag) { } // end asset foreach
foreach($bag->keys() as $key => $value) {
CustomField::where('db_column', $value)->get()->map(function($item) use (&$errors) { if ($has_errors > 0) {
$errors[] = $item->name; return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
});
}
}
return redirect($bulk_back_url)->with('bulk_errors', array_unique($errors));
} }
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success')); return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
} }
// no values given, nothing to update // no values given, nothing to update

View file

@ -3,6 +3,7 @@ namespace App\Http\Transformers;
use App\Helpers\Helper; use App\Helpers\Helper;
use App\Models\Actionlog; use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CustomField; use App\Models\CustomField;
use App\Models\Setting; use App\Models\Setting;
use App\Models\Company; use App\Models\Company;
@ -12,6 +13,7 @@ use App\Models\AssetModel;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Gate;
class ActionlogsTransformer class ActionlogsTransformer
{ {
@ -98,6 +100,13 @@ class ActionlogsTransformer
\Log::debug('custom fields do not match'); \Log::debug('custom fields do not match');
$clean_meta[$fieldname]['old'] = "************"; $clean_meta[$fieldname]['old'] = "************";
$clean_meta[$fieldname]['new'] = "************"; $clean_meta[$fieldname]['new'] = "************";
// Display the changes if the user is an admin or superadmin
if (Gate::allows('admin')) {
$clean_meta[$fieldname]['old'] = ($enc_old) ? unserialize($enc_old): '';
$clean_meta[$fieldname]['new'] = ($enc_new) ? unserialize($enc_new): '';
}
} }

View file

@ -7,6 +7,7 @@ use App\Models\Asset;
use App\Models\Setting; use App\Models\Setting;
use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Collection;
use Carbon\Carbon;
use Auth; use Auth;
class AssetsTransformer class AssetsTransformer
@ -38,7 +39,7 @@ class AssetsTransformer
'byod' => ($asset->byod ? true : false), 'byod' => ($asset->byod ? true : false),
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null, 'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'eol' => (($asset->model) && ($asset->model->eol != '')) ? $asset->model->eol : null, 'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date).' months' : null,
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null, 'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
'status_label' => ($asset->assetstatus) ? [ 'status_label' => ($asset->assetstatus) ? [
'id' => (int) $asset->assetstatus->id, 'id' => (int) $asset->assetstatus->id,

View file

@ -5,6 +5,9 @@ namespace App\Importer;
use App\Models\Asset; use App\Models\Asset;
use App\Models\AssetModel; use App\Models\AssetModel;
use App\Models\Statuslabel; use App\Models\Statuslabel;
use App\Models\User;
use App\Events\CheckoutableCheckedIn;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon; use Carbon\Carbon;
class AssetImporter extends ItemImporter class AssetImporter extends ItemImporter
@ -142,6 +145,12 @@ class AssetImporter extends ItemImporter
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by //-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
//-- the class that needs to use it (command importer or GUI importer inside the project). //-- the class that needs to use it (command importer or GUI importer inside the project).
if (isset($target)) { if (isset($target)) {
if (!is_null($asset->assigned_to)){
if ($asset->assigned_to != $target->id){
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
}
}
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name); $asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name);
} }

View file

@ -11,7 +11,7 @@ use Carbon\Carbon;
class AssetObserver class AssetObserver
{ {
/** /**
* Listen to the User created event. * Listen to the Asset updating event. This fires automatically every time an existing asset is saved.
* *
* @param Asset $asset * @param Asset $asset
* @return void * @return void
@ -137,14 +137,14 @@ class AssetObserver
public function saving(Asset $asset) public function saving(Asset $asset)
{ {
// determine if calculated eol and then calculate it - this should only happen on a new asset // determine if calculated eol and then calculate it - this should only happen on a new asset
if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && !is_null($asset->model->eol)){ if (is_null($asset->asset_eol_date) && !is_null($asset->purchase_date) && ($asset->model->eol > 0)){
$asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d'); $asset->asset_eol_date = $asset->purchase_date->addMonths($asset->model->eol)->format('Y-m-d');
$asset->eol_explicit = false; $asset->eol_explicit = false;
} }
// determine if explicit and set eol_explicit to true // determine if explicit and set eol_explicit to true
if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) { if (!is_null($asset->asset_eol_date) && !is_null($asset->purchase_date)) {
if($asset->model->eol) { if($asset->model->eol > 0) {
$months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date); $months = Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date);
if($months != $asset->model->eol) { if($months != $asset->model->eol) {
$asset->eol_explicit = true; $asset->eol_explicit = true;
@ -153,7 +153,7 @@ class AssetObserver
} elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) { } elseif (!is_null($asset->asset_eol_date) && is_null($asset->purchase_date)) {
$asset->eol_explicit = true; $asset->eol_explicit = true;
} }
if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol))) { if ((!is_null($asset->asset_eol_date)) && (!is_null($asset->purchase_date)) && (is_null($asset->model->eol) || ($asset->model->eol == 0))) {
$asset->eol_explicit = true; $asset->eol_explicit = true;
} }

View file

@ -104,7 +104,7 @@ class AssetModelPresenter extends Presenter
'searchable' => false, 'searchable' => false,
'sortable' => true, 'sortable' => true,
'switchable' => true, 'switchable' => true,
'title' => trans('general.eol'), 'title' => trans('admin/hardware/form.eol_rate'),
'visible' => true, 'visible' => true,
], ],
[ [

View file

@ -173,7 +173,7 @@ class AssetPresenter extends Presenter
'searchable' => false, 'searchable' => false,
'sortable' => true, 'sortable' => true,
'visible' => false, 'visible' => false,
'title' => trans('general.eol'), 'title' => trans('admin/hardware/form.eol_rate'),
], ],
[ [
'field' => 'asset_eol_date', 'field' => 'asset_eol_date',

View file

@ -38,7 +38,7 @@ class ActionlogFactory extends Factory
{ {
return $this->state(function () { return $this->state(function () {
$target = User::inRandomOrder()->first(); $target = User::inRandomOrder()->first();
$asset = Asset::RTD()->inRandomOrder()->first(); $asset = Asset::inRandomOrder()->RTD()->first();
$asset->update( $asset->update(
[ [

View file

@ -26,6 +26,7 @@ class CustomFieldFactory extends Factory
'format' => '', 'format' => '',
'element' => 'text', 'element' => 'text',
'auto_add_to_fieldsets' => '0', 'auto_add_to_fieldsets' => '0',
'show_in_requestable_list' => '0',
]; ];
} }
@ -66,6 +67,7 @@ class CustomFieldFactory extends Factory
return [ return [
'name' => 'CPU', 'name' => 'CPU',
'help_text' => 'The speed of the processor on this device.', 'help_text' => 'The speed of the processor on this device.',
'show_in_requestable_list' => '1',
]; ];
}); });
} }
@ -79,4 +81,37 @@ class CustomFieldFactory extends Factory
]; ];
}); });
} }
public function testEncrypted()
{
return $this->state(function () {
return [
'name' => 'Test Encrypted',
'field_encrypted' => '1',
'help_text' => 'This is a sample encrypted field.',
];
});
}
public function testCheckbox()
{
return $this->state(function () {
return [
'name' => 'Test Checkbox',
'help_text' => 'This is a sample checkbox.',
'field_values' => "One\nTwo\nThree",
'element' => 'checkbox',
];
});
}
public function testRequired()
{
return $this->state(function () {
return [
'name' => 'Test Required',
'help_text' => 'This is a sample required field.',
];
});
}
} }

View file

@ -33,6 +33,10 @@ class CustomFieldSeeder extends Seeder
CustomField::factory()->count(1)->ram()->create(); CustomField::factory()->count(1)->ram()->create();
CustomField::factory()->count(1)->cpu()->create(); CustomField::factory()->count(1)->cpu()->create();
CustomField::factory()->count(1)->macAddress()->create(); CustomField::factory()->count(1)->macAddress()->create();
CustomField::factory()->count(1)->testEncrypted()->create();
CustomField::factory()->count(1)->testCheckbox()->create();
CustomField::factory()->count(1)->testRequired()->create();
DB::table('custom_field_custom_fieldset')->insert([ DB::table('custom_field_custom_fieldset')->insert([
[ [
@ -66,6 +70,40 @@ class CustomFieldSeeder extends Seeder
'required' => 0, 'required' => 0,
], ],
[
'custom_field_id' => '6',
'custom_fieldset_id' => '2',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '6',
'custom_fieldset_id' => '1',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '7',
'custom_fieldset_id' => '2',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '7',
'custom_fieldset_id' => '1',
'order' => 0,
'required' => 0,
],
[
'custom_field_id' => '8',
'custom_fieldset_id' => '1',
'order' => 0,
'required' => 1,
],
]); ]);
} }
} }

View file

@ -38,12 +38,13 @@ class DatabaseSeeder extends Seeder
$this->call(DepreciationSeeder::class); $this->call(DepreciationSeeder::class);
$this->call(StatuslabelSeeder::class); $this->call(StatuslabelSeeder::class);
$this->call(AccessorySeeder::class); $this->call(AccessorySeeder::class);
$this->call(CustomFieldSeeder::class);
$this->call(AssetSeeder::class); $this->call(AssetSeeder::class);
$this->call(LicenseSeeder::class); $this->call(LicenseSeeder::class);
$this->call(ComponentSeeder::class); $this->call(ComponentSeeder::class);
$this->call(ConsumableSeeder::class); $this->call(ConsumableSeeder::class);
$this->call(ActionlogSeeder::class); $this->call(ActionlogSeeder::class);
$this->call(CustomFieldSeeder::class);
Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']); Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']);
$output = Artisan::output(); $output = Artisan::output();

View file

@ -368,7 +368,7 @@ return [
'consumables_count' => 'Consumables Count', 'consumables_count' => 'Consumables Count',
'components_count' => 'Components Count', 'components_count' => 'Components Count',
'licenses_count' => 'Licenses Count', 'licenses_count' => 'Licenses Count',
'notification_error' => 'Error:', 'notification_error' => 'Error',
'notification_error_hint' => 'Please check the form below for errors', 'notification_error_hint' => 'Please check the form below for errors',
'notification_bulk_error_hint' => 'The following fields had validation errors and were not edited:', 'notification_bulk_error_hint' => 'The following fields had validation errors and were not edited:',
'notification_success' => 'Success', 'notification_success' => 'Success',

View file

@ -151,6 +151,7 @@
<th data-visible="false" data-sortable="true" class="text-center"><i class="fa fa-eye" aria-hidden="true"><span class="sr-only">Visible to User</span></i></th> <th data-visible="false" data-sortable="true" class="text-center"><i class="fa fa-eye" aria-hidden="true"><span class="sr-only">Visible to User</span></i></th>
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-envelope" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_email_short') }}</span></i></th> <th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-envelope" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_email_short') }}</span></i></th>
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-laptop fa-fw" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_requestable_list_short') }}</span></i></th> <th data-sortable="true" data-searchable="true" class="text-center"><i class="fa fa-laptop fa-fw" aria-hidden="true"><span class="sr-only">{{ trans('admin/custom_fields/general.show_in_requestable_list_short') }}</span></i></th>
<th data-sortable="true" data-searchable="true" class="text-center"><i class="fa-solid fa-fingerprint"><span class="sr-only">{{ trans('admin/custom_fields/general.unique') }}</span></i></th>
<th data-sortable="true" data-searchable="true" class="text-center">{{ trans('admin/custom_fields/general.field_element_short') }}</th> <th data-sortable="true" data-searchable="true" class="text-center">{{ trans('admin/custom_fields/general.field_element_short') }}</th>
<th data-searchable="true">{{ trans('admin/custom_fields/general.fieldsets') }}</th> <th data-searchable="true">{{ trans('admin/custom_fields/general.fieldsets') }}</th>
<th>{{ trans('button.actions') }}</th> <th>{{ trans('button.actions') }}</th>
@ -176,6 +177,7 @@
<td class="text-center">{!! ($field->display_in_user_view=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td> <td class="text-center">{!! ($field->display_in_user_view=='1' ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>') !!}</td>
<td class="text-center">{!! ($field->show_in_email=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td> <td class="text-center">{!! ($field->show_in_email=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
<td class="text-center">{!! ($field->show_in_requestable_list=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td> <td class="text-center">{!! ($field->show_in_requestable_list=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
<td class="text-center">{!! ($field->is_unique=='1') ? '<i class="fas fa-check text-success" aria-hidden="true"><span class="sr-only">'.trans('general.yes').'</span></i>' : '<i class="fas fa-times text-danger" aria-hidden="true"><span class="sr-only">'.trans('general.no').'</span></i>' !!}</td>
<td>{{ $field->element }}</td> <td>{{ $field->element }}</td>
<td> <td>
@foreach($field->fieldset as $fieldset) @foreach($field->fieldset as $fieldset)

View file

@ -62,7 +62,7 @@
</div> </div>
<div class="col-md-5"> <div class="col-md-5">
<label class="form-control"> <label class="form-control">
{{ Form::checkbox('null_expected_checkin_date', '1', false, ['checked' => 'false']) }} {{ Form::checkbox('null_expected_checkin_date', '1', false) }}
{{ trans_choice('general.set_to_null', count($assets), ['asset_count' => count($assets)]) }} {{ trans_choice('general.set_to_null', count($assets), ['asset_count' => count($assets)]) }}
</label> </label>
</div> </div>

View file

@ -631,7 +631,7 @@
</div> </div>
@endif @endif
@if (($asset->model) && ($asset->model->eol)) @if (($asset->asset_eol_date) && ($asset->purchase_date))
<div class="row"> <div class="row">
<div class="col-md-2"> <div class="col-md-2">
<strong> <strong>
@ -639,7 +639,7 @@
</strong> </strong>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
{{ $asset->model->eol }} {{ Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date) }}
{{ trans('admin/hardware/form.months') }} {{ trans('admin/hardware/form.months') }}
</div> </div>
@ -650,6 +650,9 @@
<div class="col-md-2"> <div class="col-md-2">
<strong> <strong>
{{ trans('admin/hardware/form.eol_date') }} {{ trans('admin/hardware/form.eol_date') }}
@if ($asset->purchase_date)
{!! $asset->asset_eol_date < date("Y-m-d") ? '<i class="fas fa-exclamation-triangle text-orange" aria-hidden="true"></i>' : '' !!}
@endif
</strong> </strong>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">

View file

@ -37,21 +37,20 @@
@elseif ($field->element=='checkbox') @elseif ($field->element=='checkbox')
<!-- Checkboxes --> <!-- Checkboxes -->
@foreach ($field->formatFieldValuesAsArray() as $key => $value) @foreach ($field->formatFieldValuesAsArray() as $key => $value)
<div> <label class="form-control">
<label> <input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
<input type="checkbox" value="{{ $value }}" name="{{ $field->db_column_name() }}[]" class="minimal" {{ isset($item) ? (in_array($value, array_map('trim', explode(',', $item->{$field->db_column_name()}))) ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($key, array_map('trim', explode(',', $field->defaultValue($model->id)))) ? ' checked="checked"' : '')) }}>
{{ $value }} {{ $value }}
</label> </label>
</div>
@endforeach @endforeach
@elseif ($field->element=='radio') @elseif ($field->element=='radio')
@foreach ($field->formatFieldValuesAsArray() as $value) @foreach ($field->formatFieldValuesAsArray() as $value)
<div>
<label> <label class="form-control">
<input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" class="minimal" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}> <input type="radio" value="{{ $value }}" name="{{ $field->db_column_name() }}" {{ isset($item) ? ($item->{$field->db_column_name()} == $value ? ' checked="checked"' : '') : (Request::old($field->db_column_name()) != '' ? ' checked="checked"' : (in_array($value, explode(', ', $field->defaultValue($model->id))) ? ' checked="checked"' : '')) }}>
{{ $value }} {{ $value }}
</label> </label>
</div>
@endforeach @endforeach
@endif @endif

View file

@ -115,17 +115,19 @@
@endif @endif
@if ($messages = Session::get('bulk_errors')) @if ($messages = Session::get('bulk_asset_errors'))
<div class="col-md-12"> <div class="col-md-12">
<div class="alert alert alert-danger fade in"> <div class="alert alert alert-danger fade in">
<button type="button" class="close" data-dismiss="alert">&times;</button> <button type="button" class="close" data-dismiss="alert">&times;</button>
<i class="fas fa-exclamation-triangle faa-pulse animated"></i> <i class="fas fa-exclamation-triangle faa-pulse animated"></i>
<strong>{{ trans('general.notification_error') }}: </strong> <strong>{{ trans('general.notification_error') }}: </strong>
{{ trans('general.notification_bulk_error_hint') }} {{ trans('general.notification_bulk_error_hint') }}
@foreach($messages as $message) @foreach($messages as $key => $message)
@for ($x = 0; $x < count($message); $x++)
<ul> <ul>
<li>{{ $message }}</li> <li>{{ $message[$x] }}</li>
</ul> </ul>
@endfor
@endforeach @endforeach
</div> </div>
</div> </div>

View file

@ -530,15 +530,37 @@
function changeLogFormatter(value) { function changeLogFormatter(value) {
var result = ''; var result = '';
var pretty_index = '';
for (var index in value) { for (var index in value) {
result += index + ': <del>' + value[index].old + '</del> <i class="fas fa-long-arrow-alt-right" aria-hidden="true"></i> ' + value[index].new + '<br>'
// Check if it's a custom field
if (index.startsWith('_snipeit_')) {
pretty_index = index.replace("_snipeit_", "Custom:_");
} else {
pretty_index = index;
}
extra_pretty_index = prettyLog(pretty_index);
result += extra_pretty_index + ': <del>' + value[index].old + '</del> <i class="fas fa-long-arrow-alt-right" aria-hidden="true"></i> ' + value[index].new + '<br>'
} }
return result; return result;
} }
function prettyLog(str) {
let frags = str.split('_');
for (let i = 0; i < frags.length; i++) {
frags[i] = frags[i].charAt(0).toUpperCase() + frags[i].slice(1);
}
return frags.join(' ');
}
// Create a linked phone number in the table list // Create a linked phone number in the table list
function phoneFormatter(value) { function phoneFormatter(value) {

View file

@ -1,9 +1,9 @@
<!-- Purchase Date --> <!-- EOL Date -->
<div class="form-group {{ $errors->has('asset_eol_date') ? ' has-error' : '' }}"> <div class="form-group {{ $errors->has('asset_eol_date') ? ' has-error' : '' }}">
<label for="asset_eol_date" class="col-md-3 control-label">{{ trans('admin/hardware/form.eol_date') }}</label> <label for="asset_eol_date" class="col-md-3 control-label">{{ trans('admin/hardware/form.eol_date') }}</label>
<div class="input-group col-md-4"> <div class="input-group col-md-4">
<div class="input-group date" data-provide="datepicker" data-date-clear-btn="true" data-date-format="yyyy-mm-dd" data-autoclose="true"> <div class="input-group date" data-provide="datepicker" data-date-clear-btn="true" data-date-format="yyyy-mm-dd" data-autoclose="true">
<input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="asset_eol_date" id="asset_eol_date" readonly value="{{ old('asset_eol_date', optional($item->asset_eol_date)->format('Y-m-d') ?? $item->present()->eol_date() ?? '') }}" style="background-color:inherit"> <input type="text" class="form-control" placeholder="{{ trans('general.select_date') }}" name="asset_eol_date" id="asset_eol_date" readonly value="{{ old('asset_eol_date', optional($item->asset_eol_date)->format('Y-m-d') ?? $item->asset_eol_date ?? '') }}" style="background-color:inherit" />
<span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span> <span class="input-group-addon"><i class="fas fa-calendar" aria-hidden="true"></i></span>
</div> </div>
{!! $errors->first('asset_eol_date', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!} {!! $errors->first('asset_eol_date', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}