diff --git a/app/Http/Controllers/AssetsController.php b/app/Http/Controllers/AssetsController.php index 84d891d969..056df24aa4 100755 --- a/app/Http/Controllers/AssetsController.php +++ b/app/Http/Controllers/AssetsController.php @@ -666,20 +666,23 @@ class AssetsController extends Controller if ($settings->qr_code == '1') { $asset = Asset::withTrashed()->find($assetId); - $size = Helper::barcodeDimensions($settings->barcode_type); - $qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png'; + if ($asset) { + $size = Helper::barcodeDimensions($settings->barcode_type); + $qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png'; - if (isset($asset->id, $asset->asset_tag)) { - if (file_exists($qr_file)) { - $header = ['Content-type' => 'image/png']; - return response()->file($qr_file, $header); - } else { - $barcode = new \Com\Tecnick\Barcode\Barcode(); - $barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2)); - file_put_contents($qr_file, $barcode_obj->getPngData()); - return response($barcode_obj->getPngData())->header('Content-type', 'image/png'); + if (isset($asset->id, $asset->asset_tag)) { + if (file_exists($qr_file)) { + $header = ['Content-type' => 'image/png']; + return response()->file($qr_file, $header); + } else { + $barcode = new \Com\Tecnick\Barcode\Barcode(); + $barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', array(-2, -2, -2, -2)); + file_put_contents($qr_file, $barcode_obj->getPngData()); + return response($barcode_obj->getPngData())->header('Content-type', 'image/png'); + } } } + return 'That asset is invalid'; } } diff --git a/app/Http/Controllers/ComponentsController.php b/app/Http/Controllers/ComponentsController.php index 01574ea794..0d4d6f0768 100644 --- a/app/Http/Controllers/ComponentsController.php +++ b/app/Http/Controllers/ComponentsController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Helpers\Helper; use App\Http\Requests\ImageUploadRequest; +use App\Models\Actionlog; use App\Models\Company; use App\Models\Component; use App\Models\CustomField; @@ -313,5 +314,97 @@ class ComponentsController extends Controller return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success')); } + /** + * Returns a view that allows the checkin of a component from an asset. + * + * @author [A. Gianotto] [] + * @see ComponentsController::postCheckout() method that stores the data. + * @since [v4.1.4] + * @param int $componentId + * @return \Illuminate\Contracts\View\View + */ + public function getCheckin($component_asset_id) + { + + // This could probably be done more cleanly but I am very tired. - @snipe + if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { + if (is_null($component = Component::find($component_assets->component_id))) { + return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); + } + if (is_null($asset = Asset::find($component_assets->asset_id))) { + return redirect()->route('components.index')->with('error', + trans('admin/components/message.not_found')); + } + $this->authorize('checkin', $component_assets); + return view('components/checkin', compact('component_assets','component','asset')); + } + + return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found')); + + } + + /** + * Validate and store checkin data. + * + * @author [A. Gianotto] [] + * @see ComponentsController::getCheckout() method that returns the form. + * @since [v4.1.4] + * @param Request $request + * @param int $componentId + * @return \Illuminate\Http\RedirectResponse + */ + public function postCheckin(Request $request, $component_asset_id) + { + if ($component_assets = DB::table('components_assets')->find($component_asset_id)) { + if (is_null($component = Component::find($component_assets->component_id))) { + return redirect()->route('components.index')->with('error', + trans('admin/components/message.not_found')); + } + + + $this->authorize('checkin', $component); + + $max_to_checkin = $component_assets->assigned_qty; + $validator = Validator::make($request->all(), [ + "checkin_qty" => "required|numeric|between:1,$max_to_checkin" + ]); + + if ($validator->fails()) { + return redirect()->back() + ->withErrors($validator) + ->withInput(); + } + + // Validation passed, so let's figure out what we have to do here. + $qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty')); + + // We have to modify the record to reflect the new qty that's + // actually checked out. + $component_assets->assigned_qty = $qty_remaining_in_checkout; + DB::table('components_assets')->where('id', + $component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]); + + $log = new Actionlog(); + $log->user_id = Auth::user()->id; + $log->action_type = 'checkin from'; + $log->target_type = Asset::class; + $log->target_id = $component_assets->asset_id; + $log->item_id = $component_assets->component_id; + $log->item_type = Component::class; + $log->note = $request->input('note'); + $log->save(); + + // If the checked-in qty is exactly the same as the assigned_qty, + // we can simply delete the associated components_assets record + if ($qty_remaining_in_checkout == 0) { + DB::table('components_assets')->where('id', '=', $component_asset_id)->delete(); + } + + return redirect()->route('components.index')->with('success', + trans('admin/components/message.checkout.success')); + } + return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found')); + } + } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 4223ea02cf..810d610d67 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -552,6 +552,7 @@ class SettingsController extends Controller $setting->alert_threshold = $request->input('alert_threshold'); $setting->audit_interval = $request->input('audit_interval'); $setting->audit_warning_days = $request->input('audit_warning_days'); + $setting->show_alerts_in_menu = $request->input('show_alerts_in_menu', '0'); if ($setting->save()) { return redirect()->route('settings.index') diff --git a/config/app.php b/config/app.php index 5b89f57818..f30388b596 100755 --- a/config/app.php +++ b/config/app.php @@ -121,7 +121,7 @@ return [ | */ - 'log' => env('APP_LOG', 'daily'), + 'log' => env('APP_LOG', 'single'), /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2017_11_08_025918_add_alert_menu_setting.php b/database/migrations/2017_11_08_025918_add_alert_menu_setting.php new file mode 100644 index 0000000000..5833f157c3 --- /dev/null +++ b/database/migrations/2017_11_08_025918_add_alert_menu_setting.php @@ -0,0 +1,32 @@ +boolean('show_alerts_in_menu')->default(1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('show_alerts_in_menu'); + }); + } +} diff --git a/package.json b/package.json index c6878348f9..ee56a6406d 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "bootstrap-less": "^3.3.8", "ekko-lightbox": "^5.1.1", "font-awesome": "^4.7.0", + "icheck": "^1.0.2", "jquery-slimscroll": "^1.3.8", "jquery-ui": "^1.12.1", "jquery-ui-bundle": "^1.12.1", diff --git a/public/js/build/all.js b/public/js/build/all.js index e33831514c..3bd9f1d7ad 100644 Binary files a/public/js/build/all.js and b/public/js/build/all.js differ diff --git a/public/js/dist/all.js b/public/js/dist/all.js index e33831514c..3bd9f1d7ad 100644 Binary files a/public/js/dist/all.js and b/public/js/dist/all.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 0ae079e6c9..790b857a50 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -8,7 +8,7 @@ "/css/app.css.map": "/css/app.css.map?id=bdbe05e6ecd70ccfac72", "/css/overrides.css.map": "/css/overrides.css.map?id=898c91d4a425b01b589b", "/css/dist/all.css": "/css/dist/all.css?id=7c3842d2639193ac7e88", - "/js/dist/all.js": "/js/dist/all.js?id=991cd06c975979f6f067", + "/js/dist/all.js": "/js/dist/all.js?id=0d558c3ed637f4c81a77", "/css/build/all.css": "/css/build/all.css?id=7c3842d2639193ac7e88", - "/js/build/all.js": "/js/build/all.js?id=991cd06c975979f6f067" + "/js/build/all.js": "/js/build/all.js?id=0d558c3ed637f4c81a77" } \ No newline at end of file diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index 63c3d473f0..d6b6abbc23 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -6,7 +6,7 @@ return array( 'ad_domain_help' => 'This is sometimes the same as your email domain, but not always.', 'is_ad' => 'This is an Active Directory server', 'alert_email' => 'Send alerts to', - 'alerts_enabled' => 'Alerts Enabled', + 'alerts_enabled' => 'Email Alerts Enabled', 'alert_interval' => 'Expiring Alerts Threshold (in days)', 'alert_inv_threshold' => 'Inventory Alert Threshold', 'asset_ids' => 'Asset IDs', @@ -27,7 +27,7 @@ return array( 'custom_forgot_pass_url_help' => 'This replaces the built-in forgotten password URL on the login screen, useful to direct people to internal or hosted LDAP password reset functionality. It will effectively disable local user forgotten password functionality.', 'default_currency' => 'Default Currency', 'default_eula_text' => 'Default EULA', - 'default_language' => 'Default Language', + 'default_language' => 'Default Language', 'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.', 'display_asset_name' => 'Display Asset Name', 'display_checkout_date' => 'Display Checkout Date', @@ -91,6 +91,7 @@ return array( 'qr_text' => 'QR Code Text', 'setting' => 'Setting', 'settings' => 'Settings', + 'show_alerts_in_menu' => 'Show alerts in top menu', 'site_name' => 'Site Name', 'slack_botname' => 'Slack Botname', 'slack_channel' => 'Slack Channel', diff --git a/resources/views/components/checkin.blade.php b/resources/views/components/checkin.blade.php new file mode 100644 index 0000000000..96c2181172 --- /dev/null +++ b/resources/views/components/checkin.blade.php @@ -0,0 +1,69 @@ +@extends('layouts/default') + +{{-- Page title --}} +@section('title') + {{ trans('admin/licenses/general.checkin') }} + @parent +@stop + + +@section('header_right') + + {{ trans('general.back') }} +@stop + +{{-- Page content --}} +@section('content') +
+ +
+
+ {{csrf_field()}} + +
+
+

{{ $component->name }}

+
+
+ + +
+ +
+

{{ $asset->present()->fullName }}

+
+
+ + + +
+ +
+ +
+
+

Must be {{ $component_assets->assigned_qty }} or less.

+ {!! $errors->first('checkin_qty', ' + :message') !!} +
+
+ + +
+ +
+ + {!! $errors->first('note', ' :message') !!} +
+
+ +
+ +
+
+ + +@stop diff --git a/resources/views/components/view.blade.php b/resources/views/components/view.blade.php index 57f2eb7141..b7b08232c9 100644 --- a/resources/views/components/view.blade.php +++ b/resources/views/components/view.blade.php @@ -58,6 +58,7 @@ {{ trans('general.asset') }} {{ trans('general.qty') }} {{ trans('general.date') }} + Checkin/Checkout diff --git a/resources/views/groups/edit.blade.php b/resources/views/groups/edit.blade.php index 735163400f..0d94a77031 100755 --- a/resources/views/groups/edit.blade.php +++ b/resources/views/groups/edit.blade.php @@ -35,7 +35,7 @@ $permission_name = $permission[$i]['permission']; ?> @if ($permission[$i]['display']) -
+

{{ $area }}: {{ $permission[$i]['label'] }}

{{ $permission[$i]['note'] }}

diff --git a/resources/views/hardware/labels.blade.php b/resources/views/hardware/labels.blade.php index 77ad1f4331..9e3994037b 100644 --- a/resources/views/hardware/labels.blade.php +++ b/resources/views/hardware/labels.blade.php @@ -10,8 +10,10 @@ labels_width = $settings->labels_width - $settings->labels_display_sgutter; $settings->labels_height = $settings->labels_height - $settings->labels_display_bgutter; - $qr_size = ($settings->labels_height - .25); - $qr_txt_size = $settings->labels_width - $qr_size - $settings->labels_display_sgutter - .1; + // Leave space on bottom for 1D barcode if necessary + $qr_size = ($settings->alt_barcode_enabled=='1') && ($settings->alt_barcode!='') ? $settings->labels_height - .25 : $settings->labels_height; + // Leave space on left for QR code if necessary + $qr_txt_size = ($settings->qr_code=='1' ? $settings->labels_width - $qr_size - .1: $settings->labels_width); ?>