Merge pull request #18638 from grokability/experiments/compact-nav

Compacted nav UI, components for buttons
This commit is contained in:
snipe
2026-03-06 05:45:02 +01:00
committed by GitHub
56 changed files with 473 additions and 305 deletions

View File

@@ -12,6 +12,7 @@ class IconHelper
case 'checkin':
return 'fa-solid fa-rotate-right';
case 'edit':
case 'update':
return 'fas fa-pencil-alt';
case 'clone':
return 'far fa-clone';

View File

@@ -530,8 +530,6 @@ class UsersController extends Controller
*/
public function update(SaveUserRequest $request, User $user): JsonResponse
{
$this->authorize('update', User::class);
$this->authorize('update', $user);
/**
@@ -569,9 +567,6 @@ class UsersController extends Controller
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->filled('display_name')) {
$user->display_name = $request->input('display_name');
@@ -586,13 +581,29 @@ class UsersController extends Controller
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
\Log::error(print_r($permissions_array, true));
// Strip out the individual superuser permission if the API user isn't a superadmin
if (!auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
if (array_key_exists('superuser', $permissions_array)) {
unset($permissions_array['superuser']);
}
}
// Strip out the individual admin permission if the API user isn't an admin
if (!auth()->user()->isAdmin()) {
if ((is_array($permissions_array)) && (array_key_exists('admin', $permissions_array))) {
unset($permissions_array['admin']);
}
}
$user->permissions = $permissions_array;

View File

@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Session;
use Watson\Validating\ValidatingTrait;
@@ -158,6 +159,14 @@ class License extends Depreciable
);
}
public function isDeletable()
{
return Gate::allows('delete', $this)
&& ($this->free_seats_count == $this->seats)
&& ($this->deleted_at == '');
}
protected function terminatesFormattedDate(): Attribute
{
@@ -582,6 +591,23 @@ class License extends Depreciable
->whereNull('deleted_at');
}
/**
* This is really dumb - needs to be refactored, since we have ~3 diff methods that do almost the same thing
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function numRemaining()
{
return $this->licenseSeatsRelation()
->whereNull('asset_id')
->whereNull('assigned_to')
->where('unreassignable_seat', '=', false)
->whereNull('deleted_at')
->count();
}
/**
* Sets the available seats attribute
*

View File

@@ -181,6 +181,7 @@ class AccessoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
@@ -250,6 +251,7 @@ class AccessoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -268,6 +268,7 @@ class AssetAuditPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'hardwareAuditFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);

View File

@@ -17,6 +17,7 @@ class AssetModelPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -214,6 +215,7 @@ class AssetModelPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'modelsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);

View File

@@ -23,6 +23,7 @@ class AssetPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print'
], [
'field' => 'id',
'searchable' => false,
@@ -358,6 +359,7 @@ class AssetPresenter extends Presenter
'visible' => true,
'formatter' => 'hardwareInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
$layout[] = [
@@ -368,6 +370,7 @@ class AssetPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'hardwareActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);

View File

@@ -18,6 +18,8 @@ class CategoryPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -127,6 +129,7 @@ class CategoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'categoriesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -152,6 +152,7 @@ class CompanyPresenter extends Presenter
'visible' => true,
'formatter' => 'companiesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -186,6 +186,7 @@ class ComponentPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'componentsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
@@ -241,6 +242,7 @@ class ComponentPresenter extends Presenter
'visible' => true,
'formatter' => 'componentsInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -181,6 +181,7 @@ class ConsumablePresenter extends Presenter
'visible' => true,
'formatter' => 'consumablesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -111,6 +111,7 @@ class DepartmentPresenter extends Presenter
'visible' => true,
'formatter' => 'departmentsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -97,6 +97,7 @@ class DepreciationPresenter extends Presenter
'visible' => true,
'formatter' => 'depreciationsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -69,6 +69,7 @@ class GroupPresenter extends Presenter
'visible' => true,
'formatter' => 'groupsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -213,6 +213,7 @@ class LicensePresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'licensesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
@@ -307,6 +308,8 @@ class LicensePresenter extends Presenter
'title' => trans('general.checkin').'/'.trans('general.checkout'),
'visible' => true,
'formatter' => 'licenseSeatInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -20,6 +20,7 @@ class LocationPresenter extends Presenter
'formatter' => 'checkboxEnabledFormatter',
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
], [
'field' => 'id',
'searchable' => false,
@@ -266,6 +267,8 @@ class LocationPresenter extends Presenter
'title' => trans('table.actions'),
'visible' => true,
'formatter' => 'locationsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
@@ -334,6 +337,7 @@ class LocationPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -18,6 +18,8 @@ class ManufacturerPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -168,6 +170,7 @@ class ManufacturerPresenter extends Presenter
'visible' => true,
'formatter' => 'manufacturersActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -17,6 +17,8 @@ class SupplierPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print'
],
[
'field' => 'id',

View File

@@ -59,6 +59,8 @@ class UploadedFilesPresenter extends Presenter
'title' => trans('general.download'),
'visible' => true,
'formatter' => 'fileDownloadButtonsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'note',
@@ -93,6 +95,7 @@ class UploadedFilesPresenter extends Presenter
'visible' => true,
'formatter' => 'deleteUploadFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -26,6 +26,7 @@ class UserPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -432,6 +433,7 @@ class UserPresenter extends Presenter
'visible' => true,
'formatter' => 'usersActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];

View File

@@ -88,17 +88,14 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$accessory" img_path="{{ app('accessories_upload_url') }}">
<x-slot:before_list>
<x-button.wide-checkout :item="$accessory" :route="route('accessories.checkout.show', $accessory->id)" />
<x-button.wide-edit :item="$accessory" :route="route('accessories.edit', $accessory->id)" />
<x-button.wide-clone :item="$accessory" :route="route('clone/accessories', $accessory->id)" />
<x-button.wide-delete :item="$accessory" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.checkout permission="checkout" :item="$accessory" :route="route('accessories.checkout.show', $accessory->id)" />
<x-button.edit :item="$accessory" :route="route('accessories.edit', $accessory->id)" />
<x-button.clone :item="$accessory" :route="route('clone/accessories', $accessory->id)" />
<x-button.delete :item="$accessory" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -6,13 +6,16 @@
<!-- start side info-box -->
<div class="box-header with-border" style="padding-top: 0;">
<h3 class="box-title side-box-header" style="line-height: 20px">
{{ $infoPanelObj->display_name }}
</h3>
@if (isset($buttons))
<div class="row" style="padding-left: 10px">
{{ $buttons }}
</div>
@endif
</div>
<div class="box-body box-profile side-box expanded">
<div class="box-body box-profile">
@if (($infoPanelObj->image) && ($img_path))
<a href="{{ Storage::disk('public')->url($img_path.e($infoPanelObj->image)) }}" data-toggle="lightbox" data-type="image">
@@ -356,12 +359,12 @@
@if ((($infoPanelObj->address!='') && ($infoPanelObj->city!='')) || ($infoPanelObj->state!='') || ($infoPanelObj->country!=''))
<x-info-element>
<a class="btn btn-sm btn-theme" href="https://maps.google.com/?q={{ urlencode($infoPanelObj->address.','. $infoPanelObj->city.','.$infoPanelObj->state.','.$infoPanelObj->country.','.$infoPanelObj->zip) }}" target="_blank">
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-google" aria-hidden="true"></i>']) !!}
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-google hidden-print" aria-hidden="true"></i>']) !!}
<x-icon type="external-link"/>
</a>
<a class="btn btn-sm btn-theme" href="https://maps.apple.com/?q={{ urlencode($infoPanelObj->address.','. $infoPanelObj->city.','.$infoPanelObj->state.','.$infoPanelObj->country.','.$infoPanelObj->zip) }}" target="_blank">
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-apple" aria-hidden="true"></i>']) !!}
{!! trans('admin/locations/message.open_map', ['map_provider_icon' => '<i class="fa-brands fa-apple hidden-print" aria-hidden="true"></i>']) !!}
<x-icon type="external-link"/>
</a>
</x-info-element>

View File

@@ -0,0 +1,19 @@
@props([
'item' => null,
'permission' => null,
'route',
'wide' => false,
])
@can('checkout', $item)
@if ((method_exists($item, 'numRemaining')) && ($item->numRemaining() > 0))
<a href="{{ $route }}" class="btn btn-sm bg-maroon hidden-print" data-tooltip="true" data-placement="top" data-title="{{ trans('general.checkout') }}">
<x-icon type="checkout" class="fa-fw" />
@if ($wide=='true')
{{ trans('general.checkout') }}
@endif
</a>
@endif
@endcan

View File

@@ -0,0 +1,16 @@
@props([
'item' => null,
'route' => null,
'wide' => false,
])
@can('create', $item)
<!-- start clone button component -->
<a href="{{ $route }}" class="btn btn-sm btn-info hidden-print{{ ($wide=='true') ?? ' btn-block btn-social' }}">
<x-icon type="clone" class="fa-fw" />
@if ($wide=='true')
{{ trans('general.clone') }}
@endif
<!-- end clone button component -->
</a>
@endcan

View File

@@ -0,0 +1,24 @@
@props([
'item' => null,
'route' => null,
'count' => null,
'type' => 'item',
'wide' => false,
])
@can('delete', $item)
<!-- start delete button component -->
@if ((method_exists($item, 'isDeletable')) && ($item->deleted_at==''))
@if (!$item->isDeletable())
<button class="btn btn-sm btn-danger hidden-print disabled {{ ($wide=='true') ?? ' btn-block btn-social' }}" data-tooltip="true" data-placement="top" data-title="{{ trans('general.cannot_be_deleted') }}">
<x-icon type="delete" class="fa-fw" />
</button>
@else
<button class="btn btn-sm btn-danger delete-asset{{ ($wide=='true') ?? ' btn-block btn-social' }}" data-toggle="modal" title="{{ trans('general.delete_what', ['item'=> trans('general.'.$type)]) }}" data-content="{{ trans('general.sure_to_delete_var', ['item' => $item->name]) }}" data-target="#dataConfirmModal" data-tooltip="true" data-icon="fa fa-trash" data-placement="top" data-title="{{ trans('general.delete_what', ['item'=> trans('general.'.$type)]) }}" onClick="return false;">
<x-icon type="delete" class="fa-fw" />
</button>
@endif
@endif
<!-- end delete button component -->
@endif

View File

@@ -0,0 +1,21 @@
@props([
'item' => null,
'route' => null,
'wide' => false,
])
@can('update', $item)
<!-- start update button component -->
@if ($item->deleted_at=='')
<a href="{{ ($item->deleted_at == '') ? $route: '#' }}" class="btn btn-sm btn-warning hidden-print {{ ($wide=='true') ?? ' btn-block btn-social' }}{{ ($item->deleted_at!='') ? ' disabled' : '' }}">
<x-icon type="edit" class="fa-fw" />
@if ($wide=='true')
{{ trans('general.update') }}
@endif
</a>
@endif
<!-- end update button component -->
@endcan

View File

@@ -0,0 +1,11 @@
@props([
'item' => null,
'permission' => null,
'route',
])
@can($permission, $item)
<a href="{{ $route }}" {{ $attributes->merge(['class' => 'btn btn-sm hidden-print']) }} data-tooltip="true" data-placement="top" data-title="{{ trans('general.'.$permission) }}">
<x-icon type="{{ $permission }}" />
</a>
@endcan

View File

@@ -1,13 +0,0 @@
@props([
'item' => null,
'route' => null,
])
@can('create', $item)
<!-- start clone button component -->
<a href="{{ $route }}" class="btn btn-block btn-sm btn-info btn-social hidden-print">
<x-icon type="clone" />
{{ trans('general.clone') }}
<!-- end clone button component -->
</a>
@endcan

View File

@@ -1,25 +0,0 @@
@props([
'item' => null,
'route' => null,
'count' => null,
'type' => 'item',
])
@can('delete', $item)
<!-- start delete button component -->
@if ((method_exists($item, 'isDeletable')) && ($item->deleted_at==''))
@if (!$item->isDeletable())
<button class="btn btn-block btn-sm btn-danger btn-social hidden-print disabled" data-tooltip="true" data-placement="top" data-title="{{ trans('general.cannot_be_deleted') }}">
<x-icon type="delete" />
{{ trans('general.delete') }}
</button>
@else
<button class="btn btn-block btn-sm btn-danger btn-social delete-asset" data-toggle="modal" title="{{ trans('general.delete_what', ['item'=> trans('general.'.$type)]) }}" data-content="{{ trans('general.sure_to_delete_var', ['item' => $item->name]) }}" data-target="#dataConfirmModal" data-tooltip="true" data-icon="fa fa-trash" data-placement="top" data-title="{{ trans('general.delete_what', ['item'=> trans('general.'.$type)]) }}" onClick="return false;">
<x-icon type="delete" />
{{ trans('general.delete') }}
</button>
@endif
@endif
<!-- end delete button component -->
@endif

View File

@@ -1,15 +0,0 @@
@props([
'item' => null,
'route' => null,
])
@can('update', $item)
<!-- start update button component -->
@if ($item->deleted_at=='')
<a href="{{ ($item->deleted_at == '') ? $route: '#' }}" class="btn btn-block btn-sm btn-warning btn-social hidden-print{{ ($item->deleted_at!='') ? ' disabled' : '' }}">
<x-icon type="edit" />
{{ trans('general.update') }}
</a>
@endif
<!-- end update button component -->
@endcan

View File

@@ -10,7 +10,8 @@
<x-slot:content>
<x-table
show_column_search="true"
fixed_right_number="3"
fixed_right_number="2"
fixed_number="1"
show_advanced_search="true"
buttons="accessoryButtons"
api_url="{{ $route }}"

View File

@@ -4,7 +4,7 @@
])
@aware(['name'])
<div id="{{ Illuminate\Support\Str::camel($name) }}Form" style="min-width:400px">
<div id="{{ Illuminate\Support\Str::camel($name) }}Form" style="min-width:400px" class="hidden-print">
<form
method="POST"
action="{{ $action_route }}"

View File

@@ -9,15 +9,15 @@
>
@csrf
<div style="width:100% !important;">
<div style="width:100% !important;" class="hidden-print">
{{-- The sort and order will only be used if the cookie is actually empty (like on first-use) --}}
<input name="sort" type="hidden" value="assets.id">
<input name="order" type="hidden" value="asc">
<label for="bulk_actions">
<label>
<span class="sr-only">
{{ trans('button.bulk_actions') }}
</span>
</label>
<select name="bulk_actions" class="form-control select2" aria-label="bulk_actions" style="width: 350px !important;">
@if ((isset($status)) && ($status == 'Deleted'))
@can('delete', \App\Models\Asset::class)
@@ -45,5 +45,6 @@
</select>
<button class="btn btn-theme" id="{{ Illuminate\Support\Str::camel($name) }}Button" disabled>{{ trans('button.go') }}</button>
</label>
</div>
</form>

View File

@@ -11,7 +11,7 @@
@csrf
@if (request('status')!='deleted')
@can('view', \App\Models\AssetModel::class)
<div style="width:100% !important;">
<div style="width:100% !important;" class="hidden-print">
<label for="bulk_actions" class="sr-only">{{ trans('general.bulk_actions') }}</label>
<select name="bulk_actions" class="form-control select2" style="width: 200px;" aria-label="bulk_actions">
@can('delete', \App\Models\AssetModel::class)

View File

@@ -9,7 +9,7 @@
>
@csrf
<div style="width:100% !important;">
<div style="width:100% !important;" class="hidden-print">
{{-- The sort and order will only be used if the cookie is actually empty (like on first-use) --}}
<input name="sort" type="hidden" value="users.id">
<input name="order" type="hidden" value="asc">

View File

@@ -14,6 +14,8 @@
show_column_search="true"
show_advanced_search="true"
buttons="licenseButtons"
fixed_right_number="2"
fixed_number="1"
api_url="{{ $route }}"
:presenter="\App\Presenters\LicensePresenter::dataTableLayout()"
export_filename="export-{{ str_slug($name) }}-licenses-{{ date('Y-m-d') }}"

View File

@@ -0,0 +1,28 @@
@props([
'route' => null,
'name' => 'default',
])
<!-- start locations tab pane -->
@can('view', \App\Models\Location::class)
<x-slot:header>
{{ trans('general.locations') }}
</x-slot:header>
@include('partials.locations-bulk-actions')
<x-slot:content>
<x-table
show_column_search="true"
show_advanced_search="true"
fixed_right_number="2"
buttons="locationButtons"
api_url="{{ $route }}"
:presenter="\App\Presenters\LocationPresenter::dataTableLayout()"
export_filename="export-{{ str_slug($name) }}-locations-{{ date('Y-m-d') }}"
/>
</x-slot:content>
@endcan
<!-- end assets tab pane -->

View File

@@ -222,15 +222,14 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$category" img_path="{{ app('categories_upload_url') }}">
<x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$category" :route="route('categories.edit', $category->id)" />
<x-button.delete :item="$category" />
</x-slot:buttons>
<x-button.wide-edit :item="$category" :route="route('categories.edit', $category->id)" />
<x-button.wide-delete :item="$category" />
</x-slot:before_list>
</x-box.info-panel>
</x-box>
</x-page-column>

View File

@@ -227,13 +227,13 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$company" img_path="{{ app('companies_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$company" :route="route('companies.edit', $company->id)" />
<x-button.wide-delete :item="$company" />
<x-button.edit :item="$company" :route="route('companies.edit', $company->id)" />
<x-button.delete :item="$company" />
</x-slot:before_list>

View File

@@ -76,17 +76,15 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$snipe_component" img_path="{{ app('components_upload_url') }}">
<x-slot:before_list>
<x-button.wide-checkout :item="$snipe_component" :route="route('components.checkout.show', $snipe_component->id)" />
<x-button.wide-edit :item="$snipe_component" :route="route('components.edit', $snipe_component->id)" />
<x-button.wide-clone :item="$snipe_component" :route="route('components.clone.create', $snipe_component->id)" />
<x-button.wide-delete :item="$snipe_component" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.checkout :item="$snipe_component" :route="route('components.checkout.show', $snipe_component->id)" />
<x-button.edit :item="$snipe_component" :route="route('components.edit', $snipe_component->id)" />
<x-button.clone :item="$snipe_component" :route="route('components.clone.create', $snipe_component->id)" />
<x-button.delete :item="$snipe_component" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -80,17 +80,15 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$consumable" img_path="{{ app('consumables_upload_url') }}">
<x-slot:before_list>
<x-button.wide-checkout :item="$consumable" :route="route('consumables.checkout.show', $consumable->id)" />
<x-button.wide-edit :item="$consumable" :route="route('consumables.edit', $consumable->id)" />
<x-button.wide-clone :item="$consumable" :route="route('consumables.clone.create', $consumable->id)" />
<x-button.wide-delete :item="$consumable" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.checkout :item="$consumable" :route="route('consumables.checkout.show', $consumable->id)" />
<x-button.edit :item="$consumable" :route="route('consumables.edit', $consumable->id)" />
<x-button.clone :item="$consumable" :route="route('consumables.clone.create', $consumable->id)" />
<x-button.delete :item="$consumable" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -37,15 +37,13 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$department" img_path="{{ app('users_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$department" :route="route('departments.edit', $department->id)" />
<x-button.wide-delete :item="$department" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$department" :route="route('departments.edit', $department->id)" />
<x-button.delete :item="$department" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -127,15 +127,14 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$depreciation">
<x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$depreciation" :route="route('depreciations.edit', $depreciation->id)" />
<x-button.delete :item="$depreciation" />
</x-slot:buttons>
<x-button.wide-edit :item="$depreciation" :route="route('depreciations.edit', $depreciation->id)" />
<x-button.wide-delete :item="$depreciation" />
</x-slot:before_list>
</x-box.info-panel>
</x-box>

View File

@@ -41,6 +41,7 @@
<style>
:root {
color-scheme: light dark;
--btn-theme-hover-text-color: {{ $nav_link_color ?? 'light-dark(hsl(from var(--main-theme-color) h s calc(l - 10)),hsl(from var(--main-theme-color) h s calc(l - 10)))' }};
@@ -949,6 +950,59 @@
.bootstrap-table .fixed-table-container .table tbody tr.selected td {
background-color: light-dark(hsl(from var(--main-theme-color) h s calc(l + 40)),hsl(from var(--main-theme-color) h s calc(l - 40))) !important;
}
tr.success > td {
background-color: var(--text-success) !important;
}
tr.danger > td {
background-color: var(--text-danger) !important;
}
@media print {
body,
div.content-wrapper,
section.content,
.webui,
.main-panel,
.nav-tabs-custom,
.box,
.box-body,
.list-group,
.list-group-unbordered,
.list-group-item,
.row,
.tab-content
{
background: white !important;
color: black !important;
}
.fixed-table-toolbar,
.fixed-table-pagination,
#assetsToolBar,
.fixed-table-pagination
{
display: none !important;
}
.tab-pane.hidden-print {
display: none !important;
visibility: hidden !important;
}
h2, h3, h4 {
color: black !important;
}
.col-sm-9,
.main-panel
{
float: left;
width: 100% !important;
}
}
</style>
{{-- Custom CSS --}}
@@ -2154,27 +2208,54 @@
}
}
$(function () {
function checkInfoSidePanel() {
var side_panel_state = localStorage.getItem("side_panel_state");
// Open side info panel
if (side_panel_state == 'collapsed') {
collapseInfoSidePanel();
// Collapse side info panel
} else {
expandInfoSidePanel();
}
}
function toggleInfoSidePanel() {
var side_panel_state = localStorage.getItem("side_panel_state");
if (side_panel_state == 'expanded') {
localStorage.setItem("side_panel_state", 'collapsed');
} else {
localStorage.setItem("side_panel_state", 'expanded');
}
checkInfoSidePanel();
}
function collapseInfoSidePanel() {
$('.side-box').removeClass('expanded').hide();
$('.main-panel').removeClass('col-md-9').addClass('col-md-12');
$("#expand-info-panel-button").addClass('fa-square-caret-left').removeClass('fa-square-caret-right');
}
function expandInfoSidePanel() {
$('.side-box').fadeIn("fast").addClass('expanded');
$('.main-panel').removeClass('col-md-12').addClass('col-md-9');
$("#expand-info-panel-button").addClass('fa-square-caret-right').removeClass('fa-square-caret-left');
}
$(document).ready(function () {
checkInfoSidePanel();
// Handle the info-panel
$("#expand-info-panel-button").click(function () {
$('.side-box').parent('div').parent('div').parent('div').hide();
$(window).on('load', function() {
$('.side-box').parent('div').parent('div').parent('div').show();
});
if($('.side-box').hasClass('expanded')) {
$('.main-panel').removeClass('col-md-9').addClass('col-md-12');
$('.side-box').removeClass('expanded');
$("#expand-info-panel-button").addClass('fa-square-caret-left').removeClass('fa-square-caret-right');
} else {
$('.side-box').parent('div').parent('div').parent('div').fadeToggle("fast")
$('.side-box').addClass('expanded');
$('.main-panel').removeClass('col-md-12').addClass('col-md-9');
$("#expand-info-panel-button").addClass('fa-square-caret-right').removeClass('fa-square-caret-left');
}
toggleInfoSidePanel();
});

View File

@@ -123,30 +123,26 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$license" img_path="{{ app('licenses_upload_url') }}">
<x-slot:buttons>
<x-button.checkout permission="checkout" :item="$license" :route="route('licenses.freecheckout', $license->id)" />
<x-button.edit :item="$license" :route="route('licenses.edit', $license->id)" />
<x-button.clone :item="$license" :route="route('clone/license', $license->id)" />
<x-button.delete :item="$license" />
</x-slot:buttons>
<x-slot:before_list>
@can('update', $license)
<a href="{{ route('licenses.edit', $license->id) }}" class="btn btn-warning btn-sm btn-social btn-block hidden-print" style="margin-bottom: 5px;">
<x-icon type="edit" />
{{ trans('admin/licenses/general.edit') }}
</a>
<a href="{{ route('clone/license', $license->id) }}" class="btn btn-info btn-block btn-sm btn-social hidden-print" style="margin-bottom: 5px;">
<x-icon type="clone" />
{{ trans('admin/licenses/general.clone') }}</a>
@endcan
@can('checkout', $license)
@if (($license->availCount()->count() > 0) && (!$license->isInactive()))
<a href="{{ route('licenses.checkout', $license->id) }}" class="btn bg-maroon btn-sm btn-social btn-block hidden-print" style="margin-bottom: 5px;">
<x-icon type="checkout" />
{{ trans('general.checkout') }}
</a>
<a href="#" class="btn bg-maroon btn-sm btn-social btn-block hidden-print" style="margin-bottom: 5px;" data-toggle="modal" data-tooltip="true" title="{{ trans('admin/licenses/general.bulk.checkout_all.enabled_tooltip') }}" data-target="#checkoutFromAllModal">
<x-icon type="checkout-all" />
{{ trans('admin/licenses/general.bulk.checkout_all.button') }}
@@ -181,25 +177,6 @@
@endif
@endcan
@can('delete', $license)
@if ($license->availCount()->count() == $license->seats)
<a class="btn btn-block btn-danger btn-sm btn-social delete-asset" data-icon="fa fa-trash" data-toggle="modal" data-title="{{ trans('general.delete') }}" data-content="{{ trans('general.delete_confirm', ['item' => $license->name]) }}" data-target="#dataConfirmModal" onClick="return false;">
<x-icon type="delete" />
{{ trans('general.delete') }}
</a>
@else
<span data-tooltip="true" title=" {{ trans('admin/licenses/general.delete_disabled') }}">
<a href="#" class="btn btn-block btn-danger btn-sm btn-social delete-asset disabled" onClick="return false;">
<x-icon type="delete" />
{{ trans('general.delete') }}
</a>
</span>
@endif
@endcan
</x-slot:before_list>
</x-box.info-panel>
@@ -218,6 +195,15 @@
])
@endcan
@can('checkin', \App\Models\License::class)
@include ('modals.confirm-action',
[
'modal_name' => 'checkinFromAllModal',
'route' => route('licenses.bulkcheckin', $license->id),
'title' => trans('general.modal_confirm_generic'),
'body' => trans_choice('admin/licenses/general.bulk.checkin_all.modal', 2, ['checkedout_seats_count' => $checkedout_seats_count])
])
@endcan
@can('update', \App\Models\License::class)
@include ('modals.upload-file', ['item_type' => 'license', 'item_id' => $license->id])

View File

@@ -11,7 +11,7 @@
<x-container>
<x-box>
@include('partials.locations-bulk-actions')
<table
data-columns="{{ \App\Presenters\LocationPresenter::dataTableLayout() }}"
data-cookie-id-table="locationTable"

View File

@@ -384,32 +384,15 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$location" img_path="{{ app('locations_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$location" :route="route('locations.edit', $location->id)" />
<x-button.wide-restore :item="$location" :route="route('locations.restore', ['location' => $location->id])" />
@if ($location->deleted_at=='')
<a href="{{ route('locations.print_assigned', ['locationId' => $location->id]) }}" class="btn btn-block btn-sm btn-theme btn-social hidden-print">
<x-icon type="print" />
{{ trans('admin/locations/table.print_inventory') }}
</a>
<a href="{{ route('locations.print_all_assigned', ['locationId' => $location->id]) }}" class="btn btn-block btn-sm btn-theme btn-social hidden-print">
<x-icon type="print" />
{{ trans('admin/locations/table.print_all_assigned') }}
</a>
@endif
<x-button.wide-delete :item="$location" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$location" :route="route('locations.edit', $location->id)" />
<x-button.clone :item="$location" :route="route('clone/location', $location->id)" />
<x-button.delete :item="$location" />
<x-button.restore :item="$location" :route="route('locations.restore', ['location' => $location->id])" />
</x-slot:buttons>
@if ($location->ldap_ou)
<x-info-element icon_type="ldap">

View File

@@ -190,15 +190,13 @@ use Carbon\Carbon;
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$maintenance" img_path="{{ app('maintenances_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$maintenance" :route="route('maintenances.edit', $maintenance->id)" />
<x-button.wide-delete :item="$maintenance" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$maintenance" :route="route('maintenances.edit', $maintenance->id)" />
<x-button.delete :item="$maintenance" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -51,15 +51,13 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$manufacturer" img_path="{{ app('manufacturers_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$manufacturer" :route="route('manufacturers.edit', $manufacturer->id)" />
<x-button.wide-delete :item="$manufacturer" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$manufacturer" :route="route('manufacturers.edit', $manufacturer->id)" />
<x-button.delete :item="$manufacturer" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -49,15 +49,13 @@
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$model" img_path="{{ app('models_upload_url') }}">
<x-slot:before_list>
<x-button.wide-edit :item="$model" :route="route('models.edit', $model->id)" />
<x-button.wide-clone :item="$model" :route="route('models.clone.create', $model->id)" />
<x-button.wide-delete :item="$model" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$model" :route="route('models.edit', $model->id)" />
<x-button.clone :item="$model" :route="route('models.clone.create', $model->id)" />
<x-button.delete :item="$model" />
</x-slot:buttons>
</x-box.info-panel>
</x-box>

View File

@@ -1043,7 +1043,7 @@
function hardwareAuditFormatter(value, row) {
return '<a href="{{ config('app.url') }}/hardware/' + row.id + '/audit" class="actions btn btn-sm btn-primary" data-tooltip="true" title="{{ trans('general.audit') }}"><x-icon type="audit" /><span class="sr-only">{{ trans('general.audit') }}</span></a>&nbsp;';
return '<a href="{{ config('app.url') }}/hardware/' + row.id + '/audit" class="actions btn btn-sm btn-primary hidden-print" data-tooltip="true" title="{{ trans('general.audit') }}"><x-icon type="audit" /><span class="sr-only">{{ trans('general.audit') }}</span></a>&nbsp;';
}
@@ -1072,15 +1072,15 @@
}
if ((row.available_actions) && (row.available_actions.clone === true)) {
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/clone" class="actions btn btn-sm btn-info" data-tooltip="true" title="{{ trans('general.clone_item') }}"><x-icon type="clone" class="fa-fw" /><span class="sr-only">{{ trans('general.clone_item') }}</span></a>&nbsp;';
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/clone" class="actions btn btn-sm btn-info hidden-print" data-tooltip="true" title="{{ trans('general.clone_item') }}"><x-icon type="clone" class="fa-fw" /><span class="sr-only">{{ trans('general.clone_item') }}</span></a>&nbsp;';
}
if ((row.available_actions) && (row.available_actions.audit === true)) {
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/audit" class="actions btn btn-sm btn-primary" data-tooltip="true" title="{{ trans('general.audit') }}"><x-icon type="audit" class="fa-fw" /><span class="sr-only">{{ trans('general.audit') }}</span></a>&nbsp;';
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/audit" class="actions btn btn-sm btn-primary hidden-print" data-tooltip="true" title="{{ trans('general.audit') }}"><x-icon type="audit" class="fa-fw" /><span class="sr-only">{{ trans('general.audit') }}</span></a>&nbsp;';
}
if ((row.available_actions) && (row.available_actions.update === true)) {
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/edit" class="actions btn btn-sm btn-warning" data-tooltip="true" title="{{ trans('general.update') }}"><x-icon type="edit" class="fa-fw" /><span class="sr-only">{{ trans('general.update') }}</span></a>&nbsp;';
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '/edit" class="actions btn btn-sm btn-warning hidden-print" data-tooltip="true" title="{{ trans('general.update') }}"><x-icon type="edit" class="fa-fw" /><span class="sr-only">{{ trans('general.update') }}</span></a>&nbsp;';
} else {
if ((row.available_actions) && (row.available_actions.update != true)) {
actions += '<span data-tooltip="true" title="{{ trans('general.cannot_be_edited') }}"><a class="btn btn-warning btn-sm disabled" onClick="return false;"><x-icon type="edit" class="fa-fw" /></a></span>&nbsp;';
@@ -1100,7 +1100,7 @@
actions += '<a href="{{ config('app.url') }}/' + dest + '/' + row.id + '" '
+ ' class="actions btn btn-danger btn-sm delete-asset" data-tooltip="true" '
+ ' class="actions btn btn-danger btn-sm delete-asset hidden-print" data-tooltip="true" '
+ ' data-toggle="modal" data-icon="fa-trash"'
+ ' data-content="{{ trans('general.sure_to_delete') }}: ' + name_for_box + '?" '
+ ' data-title="{{ trans('general.delete') }}" onClick="return false;">'
@@ -1108,7 +1108,7 @@
} else {
// Do not show the delete button on things that are already deleted
if ((row.available_actions) && (row.available_actions.restore != true)) {
actions += '<span data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}"><a class="btn btn-danger btn-sm delete-asset disabled" onClick="return false;"><x-icon type="delete" class="fa-fw" /><span class="sr-only">{{ trans('general.cannot_be_deleted') }}</span></a></span>&nbsp;';
actions += '<span data-tooltip="true" title="{{ trans('general.cannot_be_deleted') }}"><a class="btn btn-danger btn-sm delete-asset disabled hidden-print" onClick="return false;"><x-icon type="delete" class="fa-fw" /><span class="sr-only">{{ trans('general.cannot_be_deleted') }}</span></a></span>&nbsp;';
}
}

View File

@@ -38,15 +38,13 @@
</x-box>
</x-page-column>
<x-page-column class="col-md-3">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$statuslabel">
<x-slot:before_list>
<x-button.wide-edit :item="$statuslabel" :route="route('statuslabels.edit', $statuslabel->id)" />
<x-button.wide-delete :item="$statuslabel" />
</x-slot:before_list>
<x-slot:buttons>
<x-button.edit :item="$statuslabel" :route="route('statuslabels.edit', $statuslabel->id)" />
<x-button.delete :item="$statuslabel" />
</x-slot:buttons>
</x-box.info-panel>

View File

@@ -20,8 +20,8 @@
<x-tabs>
<x-slot:tabnav>
<x-tabs.asset-tab count="{{ $supplier->assets()->AssetsForShow()->count() }}" class="active" />
<x-tabs.license-tab count="{{ $supplier->licenses->count() }}" class="active" />
<x-tabs.asset-tab count="{{ $supplier->assets()->AssetsForShow()->count() }}" />
<x-tabs.license-tab count="{{ $supplier->licenses->count() }}" />
<x-tabs.accessory-tab count="{{ $supplier->accessories->count() }}" />
<x-tabs.consumable-tab count="{{ $supplier->consumables->count() }}" />
<x-tabs.component-tab count="{{ $supplier->components->count() }}" />
@@ -54,68 +54,24 @@
<!-- start assets tab pane -->
@can('view', \App\Models\Asset::class)
<x-tabs.pane name="assets" class="in active">
<x-slot:header>
{{ trans('general.assets') }}
</x-slot:header>
<x-slot:bulkactions>
<x-table.bulk-assets />
</x-slot:bulkactions>
<x-slot:content>
<x-table
show_column_search="true"
show_advanced_search="true"
buttons="assetButtons"
api_url="{{ route('api.assets.index', ['supplier_id' => $supplier->id, 'itemtype' => 'assets']) }}"
:presenter="\App\Presenters\AssetPresenter::dataTableLayout()"
export_filename="export-{{ str_slug($supplier->name) }}-assets-{{ date('Y-m-d') }}"
/>
</x-slot:content>
<x-tabs.pane name="assets" count="{{ $supplier->assets()->AssetsForShow()->count() }}">
<x-table.assets name="assets" :route="route('api.assets.index', ['supplier_id' => $supplier->id, 'itemtype' => 'assets'])" />
</x-tabs.pane>
@endcan
<!-- end assets tab pane -->
<!-- start licenses tab pane -->
@can('view', \App\Models\License::class)
<x-tabs.pane name="licenses">
<x-slot:header>
{{ trans('general.licenses') }}
</x-slot:header>
<x-slot:content>
<x-table
show_advanced_search="true"
buttons="licenseButtons"
api_url="{{ route('api.licenses.index', ['supplier_id' => $supplier->id]) }}"
:presenter="\App\Presenters\LicensePresenter::dataTableLayout()"
export_filename="export-{{ str_slug($supplier->name) }}-licenses-{{ date('Y-m-d') }}"
/>
</x-slot:content>
<x-tabs.pane name="licenses" class="{{ $supplier->licenses->count() == 0 ? 'hidden-print' : '' }}">
<x-table.licenses name="licenses" :route="route('api.licenses.index', ['supplier_id' => $supplier->id])" />
</x-tabs.pane>
@endcan
<!-- end licenses tab pane -->
<!-- start accessories tab pane -->
@can('view', \App\Models\Accessory::class)
<x-tabs.pane name="accessories">
<x-slot:header>
{{ trans('general.accessories') }}
</x-slot:header>
<x-slot:content>
<x-table
show_column_search="true"
buttons="accessoryButtons"
api_url="{{ route('api.accessories.index', ['supplier_id' => $supplier->id]) }}"
:presenter="\App\Presenters\AccessoryPresenter::dataTableLayout()"
export_filename="export-{{ str_slug($supplier->name) }}-accessories-{{ date('Y-m-d') }}"
/>
</x-slot:content>
<x-tabs.pane name="accessories" class="{{ $supplier->accessories->count() == 0 ? 'hidden-print' : '' }}">
<x-table.accessories name="accessories" :route="route('api.accessories.index', ['supplier_id' => $supplier->id])" />
</x-tabs.pane>
@endcan
<!-- end accessories tab pane -->
@@ -123,12 +79,12 @@
<!-- start components tab pane -->
@can('view', \App\Models\Component::class)
<x-tabs.pane name="components">
<x-tabs.pane name="components" class="{{ $supplier->components->count() == 0 ? 'hidden-print' : '' }}">
<x-slot:header>
{{ trans('general.components') }}
</x-slot:header>
<x-slot:content>
<x-table
show_advanced_search="true"
buttons="componentButtons"
@@ -136,14 +92,14 @@
:presenter="\App\Presenters\ComponentPresenter::dataTableLayout()"
export_filename="export-{{ str_slug($supplier->name) }}-components-{{ date('Y-m-d') }}"
/>
</x-slot:content>
</x-tabs.pane>
@endcan
<!-- end components tab pane -->
<!-- start consumables tab pane -->
@can('view', \App\Models\Consumable::class)
<x-tabs.pane name="consumables">
<x-tabs.pane name="consumables" class="{{ $supplier->consumables->count() == 0 ? 'hidden-print' : '' }}">
<x-slot:header>
{{ trans('general.consumables') }}
</x-slot:header>
@@ -164,25 +120,24 @@
<!-- start consumables tab pane -->
@can('view', \App\Models\Asset::class)
<x-tabs.pane name="maintenances">
<x-tabs.pane name="maintenances" class="{{ $supplier->maintenances->count() == 0 ? 'hidden-print' : '' }}">
<x-slot:header>
{{ trans('admin/maintenances/general.maintenances') }}
</x-slot:header>
<x-slot:content>
<x-table
buttons="maintenanceButtons"
api_url="{{ route('api.maintenances.index', ['supplier_id' => $supplier->id]) }}"
:presenter="\App\Presenters\MaintenancesPresenter::dataTableLayout()"
export_filename="export-{{ str_slug($supplier->name) }}-maintenances-{{ date('Y-m-d') }}"
/>
</x-slot:content>
</x-tabs.pane>
@endcan
<!-- end consumables tab pane -->
<!-- start files tab pane -->
<x-tabs.pane name="files">
<x-tabs.pane name="files" class="{{ $supplier->uploads->count() == 0 ? 'hidden-print' : '' }}">
<x-slot:header>
{{ trans('general.files') }}
</x-slot:header>
@@ -196,17 +151,16 @@
</x-tabs>
</x-page-column>
<x-page-column class="col-md-3">
<x-page-column class="col-md-3 hidden-print">
<x-box>
<x-box class="side-box expanded">
<x-box.info-panel :infoPanelObj="$supplier" img_path="{{ app('suppliers_upload_url') }}">
<x-slot:before_list>
<x-slot:buttons>
<x-button :item="$supplier" permission="update" :route="route('suppliers.edit', $supplier->id)" class="btn-warning" />
<x-button.delete :item="$supplier" />
</x-slot:buttons>
<x-button.wide-edit :item="$supplier" :route="route('suppliers.edit', $supplier->id)" />
<x-button.wide-delete :item="$supplier" />
</x-slot:before_list>
</x-box.info-panel>
</x-box>
@@ -214,6 +168,36 @@
</x-container>
<div class="visible-print">
<table style="margin-top: 80px;" class="signature-boxes">
<tr>
<td style="padding-right: 10px; vertical-align: top; font-weight: bold;">{{ trans('general.signed_off_by') }}:</td>
<td style="padding-right: 10px; vertical-align: top;">______________________________________</td>
<td style="padding-right: 10px; vertical-align: top;">______________________________________</td>
<td>_____________</td>
</tr>
<tr style="height: 80px;">
<td></td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.name') }}</td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.signature') }}</td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.date') }}</td>
</tr>
<tr>
<td style="padding-right: 10px; vertical-align: top; font-weight: bold;">{{ trans('admin/users/table.manager') }}:</td>
<td style="padding-right: 10px; vertical-align: top;">______________________________________</td>
<td style="padding-right: 10px; vertical-align: top;">______________________________________</td>
<td>_____________</td>
</tr>
<tr>
<td></td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.name') }}</td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.signature') }}</td>
<td style="padding-right: 10px; vertical-align: top;">{{ trans('general.date') }}</td>
<td></td>
</tr>
</table>
</div>
@can('update', \App\Models\Supplier::class)
@include ('modals.upload-file', ['item_type' => 'supplier', 'item_id' => $supplier->id])

View File

@@ -33,7 +33,6 @@ Route::group([ 'prefix' => 'fields','middleware' => ['auth'] ], function () {
)->name('fieldsets.associate');
Route::resource('fieldsets', CustomFieldsetsController::class, [
'parameters' => [
'fieldset' => 'fieldset',
@@ -42,9 +41,17 @@ Route::group([ 'prefix' => 'fields','middleware' => ['auth'] ], function () {
'except' => ['show', 'view']
]);
// This is a shim to handle bootstrap tables
// @todo: normalize this in the JS
Route::get(
'fieldsets/{fieldset}/edit',
[CustomFieldsetsController::class, 'show']
)->name('fieldsets.edit.show');
Route::get(
'fieldsets/{fieldset}',
[CustomFieldsetsController::class, 'show']
)->name('fieldsets.show');
});

View File

@@ -110,7 +110,7 @@ class UpdateUserTest extends TestCase
'username' => 'mabel',
'password' => 'super-secret',
'password_confirmation' => 'super-secret',
'email' => 'mabel@onlymurderspod.com',
'email' => 'mabel@example.org',
'permissions' => '{"a.new.permission":"1"}',
'activated' => true,
'phone' => '619-555-5555',
@@ -138,7 +138,7 @@ class UpdateUserTest extends TestCase
$this->assertEquals('Mora', $user->last_name, 'Last name was not updated');
$this->assertEquals('mabel', $user->username, 'Username was not updated');
$this->assertTrue(Hash::check('super-secret', $user->password), 'Password was not updated');
$this->assertEquals('mabel@onlymurderspod.com', $user->email, 'Email was not updated');
$this->assertEquals('mabel@example.org', $user->email, 'Email was not updated');
$this->assertArrayHasKey('a.new.permission', $user->decodePermissions(), 'Permissions were not updated');
$this->assertTrue((bool) $user->activated, 'User not marked as activated');
$this->assertEquals('619-555-5555', $user->phone, 'Phone was not updated');