From e1907e30b1f9b2601c76d00d809a3a4be6c625cd Mon Sep 17 00:00:00 2001 From: Steffen Date: Sat, 2 Mar 2019 00:25:42 +0100 Subject: [PATCH] Allow multiple upload fields and add logo option to labels (#6736) * Change upload js to work with multiple upload elements on a single page * Change uploadFile in upload modal and form partial * Change uploadFile to js-uploadFile to avoid potential issues in the future * Remove duplicate style attribute causing webpack to fail * Missed a css class in rename to js- prefix * - Move logo uploads to partial for eaiser usage - Add label logo - Add css classes to label elements - Change label prefix text (M: S: ...) to css::before content for easy removal in config * Add more css classes to labels * Allow unescaped " (quot) in css ouput * Add max size param to partial, set defaults for allowedType and size --- app/Http/Controllers/SettingsController.php | 41 +++++-- app/Models/Setting.php | 9 +- ...2_17_205048_add_label_logo_to_settings.php | 32 +++++ .../js/components/importer/importer-file.vue | 3 +- resources/assets/js/snipeit.js | 34 ++--- resources/lang/en/admin/settings/general.php | 52 ++++---- resources/views/hardware/labels.blade.php | 57 ++++++--- resources/views/modals/upload-file.blade.php | 6 +- .../forms/edit/image-upload.blade.php | 8 +- .../partials/forms/edit/uploadLogo.blade.php | 29 +++++ resources/views/settings/branding.blade.php | 116 +++++------------- 11 files changed, 226 insertions(+), 161 deletions(-) create mode 100644 database/migrations/2019_02_17_205048_add_label_logo_to_settings.php create mode 100644 resources/views/partials/forms/edit/uploadLogo.blade.php diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index f96f4dc0bd..3c86bcca40 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -412,13 +412,13 @@ class SettingsController extends Controller $setting->brand = 1; // If they are uploading an image, validate it and upload it - } elseif ($request->hasFile('image')) { - $image = $request->file('image'); + } elseif ($request->hasFile('logo')) { + $image = $request->file('logo'); $ext = $image->getClientOriginalExtension(); $setting->logo = $file_name = 'logo.' . $ext; if ('svg' != $image->getClientOriginalExtension()) { - $upload = Image::make($image->getRealPath())->resize(null, 150, function($constraint) { + $upload = Image::make($image->getRealPath())->resize(null, 150, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); @@ -438,14 +438,14 @@ class SettingsController extends Controller Storage::disk('public')->delete($setting->email_logo); $setting->email_logo = null; - // If they are uploading an image, validate it and upload it + // If they are uploading an image, validate it and upload it } elseif ($request->hasFile('email_logo')) { $email_image = $email_upload = $request->file('email_logo'); $email_ext = $email_image->getClientOriginalExtension(); $setting->email_logo = $email_file_name = 'email_logo.' . $email_ext; if ('svg' != $email_image->getClientOriginalExtension()) { - $email_upload = Image::make($email_image->getRealPath())->resize(null, 100, function($constraint) { + $email_upload = Image::make($email_image->getRealPath())->resize(null, 100, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); @@ -460,21 +460,46 @@ class SettingsController extends Controller } } + // If the user wants to clear the label logo... + if ('1' == $request->input('clear_label_logo')) { + Storage::disk('public')->delete($setting->label_logo); + $setting->label_logo = null; + + // If they are uploading an image, validate it and upload it + } elseif ($request->hasFile('label_logo')) { + $image = $request->file('label_logo'); + $ext = $image->getClientOriginalExtension(); + $setting->label_logo = $label_file_name = 'label_logo.' . $ext; + + if ('svg' != $image->getClientOriginalExtension()) { + $upload = Image::make($image->getRealPath())->resize(null, 100, function ($constraint) { + $constraint->aspectRatio(); + $constraint->upsize(); + }); + } + + // This requires a string instead of an object, so we use ($string) + Storage::disk('public')->put($label_file_name, (string) $upload->encode()); + + // Remove Current image if exists + if (($setting->label_logo) && (file_exists($label_file_name))) { + Storage::disk('public')->delete($label_file_name); + } + } // If the user wants to clear the favicon... if ('1' == $request->input('clear_favicon')) { Storage::disk('public')->delete($setting->clear_favicon); $setting->favicon = null; - // If they are uploading an image, validate it and upload it + // If they are uploading an image, validate it and upload it } elseif ($request->hasFile('favicon')) { - $favicon_image = $favicon_upload = $request->file('favicon'); $favicon_ext = $favicon_image->getClientOriginalExtension(); $setting->favicon = $favicon_file_name = 'favicon-uploaded.' . $favicon_ext; if (('ico' != $favicon_image->getClientOriginalExtension()) && ('svg' != $favicon_image->getClientOriginalExtension())) { - $favicon_upload = Image::make($favicon_image->getRealPath())->resize(null, 36, function($constraint) { + $favicon_upload = Image::make($favicon_image->getRealPath())->resize(null, 36, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); }); diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 3d26cd9d88..25ddbb6978 100755 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -215,6 +215,8 @@ class Setting extends Model // Needed for modifying the bootstrap nav :( $custom_css = str_ireplace('script', 'SCRIPTS-NOT-ALLOWED-HERE', $custom_css); $custom_css = str_replace('>', '>', $custom_css); + // Allow String output (needs quotes) + $custom_css = str_replace('"', '"', $custom_css); return $custom_css; } @@ -320,9 +322,9 @@ class Setting extends Model /** * Get the specific LDAP settings - * + * * @author Wes Hulette - * + * * @since 5.0.0 * * @return Collection @@ -330,7 +332,7 @@ class Setting extends Model public static function getLdapSettings(): Collection { $ldapSettings = self::select([ - 'ldap_enabled', + 'ldap_enabled', 'ldap_server', 'ldap_uname', 'ldap_pword', @@ -354,5 +356,4 @@ class Setting extends Model return collect($ldapSettings); } - } diff --git a/database/migrations/2019_02_17_205048_add_label_logo_to_settings.php b/database/migrations/2019_02_17_205048_add_label_logo_to_settings.php new file mode 100644 index 0000000000..591a32d095 --- /dev/null +++ b/database/migrations/2019_02_17_205048_add_label_logo_to_settings.php @@ -0,0 +1,32 @@ +char('label_logo')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('email_logo'); + }); + } +} diff --git a/resources/assets/js/components/importer/importer-file.vue b/resources/assets/js/components/importer/importer-file.vue index 7c18dba0c6..afcd151ee5 100644 --- a/resources/assets/js/components/importer/importer-file.vue +++ b/resources/assets/js/components/importer/importer-file.vue @@ -82,9 +82,8 @@

-
{{ this.statusText }}
diff --git a/resources/assets/js/snipeit.js b/resources/assets/js/snipeit.js index 5c067c2538..1fb74cfc82 100755 --- a/resources/assets/js/snipeit.js +++ b/resources/assets/js/snipeit.js @@ -418,11 +418,11 @@ $(document).ready(function () { // Image preview - function readURL(input) { + function readURL(input, $preview) { if (input.files && input.files[0]) { var reader = new FileReader(); reader.onload = function(e) { - $('#imagePreview').attr('src', e.target.result); + $preview.attr('src', e.target.result); }; reader.readAsDataURL(input.files[0]); } @@ -436,28 +436,32 @@ $(document).ready(function () { } // File size validation - $('#uploadFile').bind('change', function() { - $('#upload-file-status').removeClass('text-success').removeClass('text-danger'); - $('.goodfile').remove(); - $('.badfile').remove(); - $('.badfile').remove(); - $('.previewSize').hide(); - $('#upload-file-info').html(''); + $('.js-uploadFile').bind('change', function() { + let $this = $(this); + let id = '#' + $this.attr('id'); + let status = id + '-status'; + let $status = $(status); + $status.removeClass('text-success').removeClass('text-danger'); + $(status + ' .goodfile').remove(); + $(status + ' .badfile').remove(); + $(status + ' .previewSize').hide(); + $(id + '-info').html(''); - var max_size = $('#uploadFile').data('maxsize'); + var max_size = $this.data('maxsize'); var total_size = 0; for (var i = 0; i < this.files.length; i++) { total_size += this.files[i].size; - $('#upload-file-info').append('' + this.files[i].name + ' (' + formatBytes(this.files[i].size) + ') '); + $(id + '-info').append('' + this.files[i].name + ' (' + formatBytes(this.files[i].size) + ') '); } if (total_size > max_size) { - $('#upload-file-status').addClass('text-danger').removeClass('help-block').prepend(' ').append(' Upload is ' + formatBytes(total_size) + '.'); + $status.addClass('text-danger').removeClass('help-block').prepend(' ').append(' Upload is ' + formatBytes(total_size) + '.'); } else { - $('#upload-file-status').addClass('text-success').removeClass('help-block').prepend(' '); - readURL(this); - $('#imagePreview').fadeIn(); + $status.addClass('text-success').removeClass('help-block').prepend(' '); + let $preview = $(id + '-imagePreview'); + readURL(this, $preview); + $preview.fadeIn(); } diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index 6df5fc4ba1..613200d673 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -7,41 +7,41 @@ return array( 'admin_cc_email' => 'CC Email', 'admin_cc_email_help' => 'If you would like to send a copy of checkin/checkout emails that are sent to users to an additional email account, enter it here. Otherwise leave this field blank.', 'is_ad' => 'This is an Active Directory server', - 'alert_email' => 'Send alerts to', - 'alerts_enabled' => 'Email Alerts Enabled', - 'alert_interval' => 'Expiring Alerts Threshold (in days)', - 'alert_inv_threshold' => 'Inventory Alert Threshold', - 'asset_ids' => 'Asset IDs', - 'audit_interval' => 'Audit Interval', + 'alert_email' => 'Send alerts to', + 'alerts_enabled' => 'Email Alerts Enabled', + 'alert_interval' => 'Expiring Alerts Threshold (in days)', + 'alert_inv_threshold' => 'Inventory Alert Threshold', + 'asset_ids' => 'Asset IDs', + 'audit_interval' => 'Audit Interval', 'audit_interval_help' => 'If you are required to regularly physically audit your assets, enter the interval in months.', - 'audit_warning_days' => 'Audit Warning Threshold', + 'audit_warning_days' => 'Audit Warning Threshold', 'audit_warning_days_help' => 'How many days in advance should we warn you when assets are due for auditing?', - 'auto_increment_assets' => 'Generate auto-incrementing asset IDs', - 'auto_increment_prefix' => 'Prefix (optional)', - 'auto_incrementing_help' => 'Enable auto-incrementing asset IDs first to set this', - 'backups' => 'Backups', - 'barcode_settings' => 'Barcode Settings', + 'auto_increment_assets' => 'Generate auto-incrementing asset IDs', + 'auto_increment_prefix' => 'Prefix (optional)', + 'auto_incrementing_help' => 'Enable auto-incrementing asset IDs first to set this', + 'backups' => 'Backups', + 'barcode_settings' => 'Barcode Settings', 'confirm_purge' => 'Confirm Purge', 'confirm_purge_help' => 'Enter the text "DELETE" in the box below to purge your deleted records. This action cannot be undone.', - 'custom_css' => 'Custom CSS', - 'custom_css_help' => 'Enter any custom CSS overrides you would like to use. Do not include the <style></style> tags.', + 'custom_css' => 'Custom CSS', + 'custom_css_help' => 'Enter any custom CSS overrides you would like to use. Do not include the <style></style> tags.', 'custom_forgot_pass_url' => 'Custom Password Reset URL', '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.', 'dashboard_message' => 'Dashboard Message', 'dashboard_message_help' => 'This text will appear on the dashboard for anyone with permission to view the dashboard.', - 'default_currency' => 'Default Currency', - 'default_eula_text' => 'Default EULA', + 'default_currency' => 'Default Currency', + 'default_eula_text' => 'Default EULA', 'default_language' => 'Default Language', - 'default_eula_help_text' => 'You can also associate custom EULAs to specific asset categories.', + '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', 'display_eol' => 'Display EOL in table view', 'display_qr' => 'Display Square Codes', - 'display_alt_barcode' => 'Display 1D barcode', + 'display_alt_barcode' => 'Display 1D barcode', 'email_logo' => 'Email Logo', - 'barcode_type' => '2D Barcode Type', - 'alt_barcode_type' => '1D barcode type', - 'email_logo_size' => 'Square logos in email look best.', + 'barcode_type' => '2D Barcode Type', + 'alt_barcode_type' => '1D barcode type', + 'email_logo_size' => 'Square logos in email look best. ', 'eula_settings' => 'EULA Settings', 'eula_markdown' => 'This EULA allows Github flavored markdown.', 'favicon' => 'Favicon', @@ -50,9 +50,11 @@ return array( 'footer_text' => 'Additional Footer Text ', 'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using Github flavored markdown. Line breaks, headers, images, etc may result in unpredictable results.', 'general_settings' => 'General Settings', - 'generate_backup' => 'Generate Backup', + 'generate_backup' => 'Generate Backup', 'header_color' => 'Header Color', 'info' => 'These settings let you customize certain aspects of your installation.', + 'label_logo' => 'Label Logo', + 'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ', 'laravel' => 'Laravel Version', 'ldap_enabled' => 'LDAP enabled', 'ldap_integration' => 'LDAP Integration', @@ -61,9 +63,9 @@ return array( 'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.', 'ldap_server' => 'LDAP Server', 'ldap_server_help' => 'This should start with ldap:// (for unencrypted or TLS) or ldaps:// (for SSL)', - 'ldap_server_cert' => 'LDAP SSL certificate validation', - 'ldap_server_cert_ignore' => 'Allow invalid SSL Certificate', - 'ldap_server_cert_help' => 'Select this checkbox if you are using a self signed SSL cert and would like to accept an invalid SSL certificate.', + 'ldap_server_cert' => 'LDAP SSL certificate validation', + 'ldap_server_cert_ignore' => 'Allow invalid SSL Certificate', + 'ldap_server_cert_help' => 'Select this checkbox if you are using a self signed SSL cert and would like to accept an invalid SSL certificate.', 'ldap_tls' => 'Use TLS', 'ldap_tls_help' => 'This should be checked only if you are running STARTTLS on your LDAP server. ', 'ldap_uname' => 'LDAP Bind Username', diff --git a/resources/views/hardware/labels.blade.php b/resources/views/hardware/labels.blade.php index d5fef3942f..d5b2317e35 100644 --- a/resources/views/hardware/labels.blade.php +++ b/resources/views/hardware/labels.blade.php @@ -56,6 +56,13 @@ margin-left: auto; margin-right: auto; } + div.label-logo { + float: right; + display: inline-block; + } + img.label-logo { + height: 0.5in; + } .qr_text { width: {{ $qr_txt_size }}in; @@ -80,7 +87,21 @@ margin: {{ $settings->labels_pmargin_top }}in {{ $settings->labels_pmargin_right }}in {{ $settings->labels_pmargin_bottom }}in {{ $settings->labels_pmargin_left }}in; } - + .label-model::before { + content: "M: " + } + .label-company::before { + content: "C: " + } + .label-asset_tag::before { + content: "T: " + } + .label-serial::before { + content: "S: " + } + .label-name::before { + content: "N: " + } @media print { .noprint { @@ -103,7 +124,7 @@ } @if ($snipeSettings->custom_css) - {{ $snipeSettings->show_custom_css() }} + {!! $snipeSettings->show_custom_css() !!} @endif @@ -113,48 +134,54 @@
@if ($settings->qr_code=='1') -
+
@endif
+ @if ($settings->label_logo) + + @endif + @if ($settings->qr_text!='') -
+
{{ $settings->qr_text }}
@endif @if (($settings->labels_display_company_name=='1') && ($asset->company)) -
- C: {{ $asset->company->name }} +
+ {{ $asset->company->name }}
@endif @if (($settings->labels_display_name=='1') && ($asset->name!='')) -
- N: {{ $asset->name }} +
+ {{ $asset->name }}
@endif @if (($settings->labels_display_tag=='1') && ($asset->asset_tag!='')) -
- T: {{ $asset->asset_tag }} +
+ {{ $asset->asset_tag }}
@endif @if (($settings->labels_display_serial=='1') && ($asset->serial!='')) -
- S: {{ $asset->serial }} +
+ {{ $asset->serial }}
@endif @if (($settings->labels_display_model=='1') && ($asset->model->name!='')) -
- M: {{ $asset->model->name }} {{ $asset->model->model_number }} +
+ {{ $asset->model->name }} {{ $asset->model->model_number }}
@endif
@if ((($settings->alt_barcode_enabled=='1') && $settings->alt_barcode!='')) -
+
@endif diff --git a/resources/views/modals/upload-file.blade.php b/resources/views/modals/upload-file.blade.php index cf40f04e28..9c12032311 100644 --- a/resources/views/modals/upload-file.blade.php +++ b/resources/views/modals/upload-file.blade.php @@ -19,15 +19,15 @@
- +
-

{{ trans('general.upload_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}

+

{{ trans('general.upload_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}

diff --git a/resources/views/partials/forms/edit/image-upload.blade.php b/resources/views/partials/forms/edit/image-upload.blade.php index b0c7819b6e..518e98bf3c 100644 --- a/resources/views/partials/forms/edit/image-upload.blade.php +++ b/resources/views/partials/forms/edit/image-upload.blade.php @@ -3,15 +3,15 @@
- + -

{{ trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}

+

{{ trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}

{!! $errors->first('image', ':message') !!}
- +
diff --git a/resources/views/partials/forms/edit/uploadLogo.blade.php b/resources/views/partials/forms/edit/uploadLogo.blade.php new file mode 100644 index 0000000000..454de6f58a --- /dev/null +++ b/resources/views/partials/forms/edit/uploadLogo.blade.php @@ -0,0 +1,29 @@ +
+ + +
+ + + +

+ {{ $helpBlock }} +

+ {!! $errors->first($logoVariable, ':message') !!} + +
+
+ +
+ + @if ($setting->$logoVariable!='') +
+ {{ Form::checkbox($logoClearVariable, '1', Input::old($logoClearVariable),array('class' => 'minimal')) }} Remove current image +
+ @endif +
\ No newline at end of file diff --git a/resources/views/settings/branding.blade.php b/resources/views/settings/branding.blade.php index a478824212..914568f28d 100644 --- a/resources/views/settings/branding.blade.php +++ b/resources/views/settings/branding.blade.php @@ -56,8 +56,6 @@
- -
@@ -70,94 +68,42 @@
- -
- - -
- - - -

- {{ trans('general.logo_size') }} - {{ trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }} -

- {!! $errors->first('image', ':message') !!} - -
-
- -
- - @if ($setting->logo!='') -
- - {{ Form::checkbox('clear_logo', '1', Input::old('clear_logo'),array('class' => 'minimal')) }} Remove current image - -
- @endif -
+ @include('partials/forms/edit/uploadLogo', [ + "logoVariable" => "logo", + "logoId" => "uploadLogo", + "logoLabel" => trans('admin/settings/general.logo'), + "logoClearVariable" => "clear_logo", + "helpBlock" => trans('general.logo_size') . trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]), + ]) -
- + @include('partials/forms/edit/uploadLogo', [ + "logoVariable" => "email_logo", + "logoId" => "uploadEmailLogo", + "logoLabel" => trans('admin/settings/general.email_logo'), + "logoClearVariable" => "clear_email_logo", + "helpBlock" => trans('admin/settings/general.email_logo_size') . trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]), + ]) -
- - - -

- {{ trans('admin/settings/general.email_logo_size') }} - {{ trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]) }}

- {!! $errors->first('image', ':message') !!} - -
- - @if ($setting->email_logo!='') -
- - {{ Form::checkbox('clear_email_logo', '1', Input::old('clear_email_logo'),array('class' => 'minimal')) }} Remove current image - -
- @endif -
+ + @include('partials/forms/edit/uploadLogo', [ + "logoVariable" => "label_logo", + "logoId" => "uploadLabelLogo", + "logoLabel" => trans('admin/settings/general.label_logo'), + "logoClearVariable" => "clear_label_logo", + "helpBlock" => trans('admin/settings/general.label_logo_size') . trans('general.image_filetypes_help', ['size' => \App\Helpers\Helper::file_upload_max_size_readable()]), + ]) -
- - -
- - - -

{{ trans('admin/settings/general.favicon_size') }} - {{ trans('admin/settings/general.favicon_format') }}

- {!! $errors->first('favicon', ':message') !!} - -
- - @if ($setting->email_logo!='') -
- - {{ Form::checkbox('clear_favicon', '1', Input::old('clear_favicon'),array('class' => 'minimal')) }} Remove current favicon - -
- @endif -
- - + @include('partials/forms/edit/uploadLogo', [ + "logoVariable" => "favicon", + "logoId" => "uploadFavicon", + "logoLabel" => trans('admin/settings/general.favicon'), + "logoClearVariable" => "clear_favicon", + "helpBlock" => trans('admin/settings/general.favicon_size') . trans('admin/settings/general.favicon_format'), + "allowedTypes" => "image/x-icon,image/gif,image/jpeg,image/png,image/svg", + "maxSize" => 1000 + ])