Merge remote-tracking branch 'origin/develop'

This commit is contained in:
snipe
2026-03-23 08:59:36 +00:00
6 changed files with 57 additions and 0 deletions
@@ -3,6 +3,7 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\AssetModel;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Gate;
@@ -58,6 +59,7 @@ class AssetModelsTransformer
'assets_assigned_count' => (int) $assetmodel->assets_assigned_count,
'assets_archived_count' => (int) $assetmodel->assets_archived_count,
'remaining' => (int) ($assetmodel->assets_count - (int) $assetmodel->assets_assigned_count) - (int) $assetmodel->assets_archived_count,
'percent_remaining' => round($assetmodel->percentRemaining()),
'category' => ($assetmodel->category) ? [
'id' => (int) $assetmodel->category->id,
'name' => e($assetmodel->category->name),
@@ -83,6 +85,7 @@ class AssetModelsTransformer
];
$permissions_array['available_actions'] = [
'create_asset' => (Gate::allows('create', Asset::class) && ($assetmodel->deleted_at == '')),
'update' => (Gate::allows('update', AssetModel::class) && ($assetmodel->deleted_at == '')),
'delete' => $assetmodel->isDeletable(),
'clone' => (Gate::allows('create', AssetModel::class) && ($assetmodel->deleted_at == '')),
+8
View File
@@ -142,6 +142,14 @@ class AssetModel extends SnipeModel
return $this->hasMany(Asset::class, 'model_id')->Archived();
}
public function percentRemaining()
{
if ($this->availableAssets()->count() == 0) {
return 0;
}
return $this->availableAssets()->count() / $this->assets()->count() * 100;
}
/**
* Establishes the model -> category relationship
*
+9
View File
@@ -110,6 +110,15 @@ class AssetModelPresenter extends Presenter
'class' => 'text-right text-padding-number-cell',
'footerFormatter' => 'qtySumFormatter',
],
[
'field' => 'percent_remaining',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => '% ' . trans('general.remaining'),
'visible' => true,
'formatter' => 'progressBarFormatter',
],
[
'field' => 'assets_archived_count',
'searchable' => false,
@@ -0,0 +1,17 @@
@props([
'item' => null,
'route' => null,
'wide' => false,
'tooltip' => trans('general.create'),
])
@can('create', $item)
<!-- start add button component -->
<a href="{{ $route }}" class="btn btn-sm btn-info hidden-print{{ ($wide=='true') ?? ' btn-block btn-social' }}" data-tooltip="true" data-placement="top" data-title="{{ $tooltip }}">
<x-icon type="create" class="fa-fw" />
@if ($wide=='true')
{{ trans('general.create') }}
@endif
<!-- end add button component -->
</a>
@endcan
+1
View File
@@ -53,6 +53,7 @@
<x-box.info-panel :infoPanelObj="$model" img_path="{{ app('models_upload_url') }}">
<x-slot:buttons>
<x-button.edit :item="$model" :route="route('models.edit', $model->id)" />
<x-button.add :item="\App\Models\Asset::class" :tooltip="trans('general.new_asset')" :route="route('hardware.create', ['model_id' => $model->id])"/>
<x-button.restore :item="$model" :route="route('models.restore.store', $model->id)" />
<x-button.clone :item="$model" :route="route('models.clone.create', $model->id)" />
<x-button.delete :item="$model" />
@@ -960,6 +960,21 @@
}
function progressBarFormatter(value) {
var bar_color = 'danger';
if (value <= 25) {
bar_color = 'danger';
}
else if (value <= 75) {
bar_color = 'warning';
}
else if (value <= 100) {
bar_color = 'success';
}
return '<div class="progress progress-sm" data-tooltip="true" title="' + value + '%"><div class="progress-bar progress-bar-' + bar_color + '" role="progressbar" aria-valuenow="' + value + '" aria-valuemin="0" aria-valuemax="100" style="width: ' + value + '%; min-width: 1em;"></div></div>';
}
// Use this when we're introspecting into a column object and need to link
function genericColumnObjLinkFormatter(destination) {
return function (value,row) {
@@ -1071,6 +1086,10 @@
dest = dest + '/' + row.owner_id + '/' + element_name;
}
if ((row.available_actions) && (row.available_actions.create_asset === true)) {
actions += '<a href="{{ config('app.url') }}/hardware/create?model_id=' + row.id + '" class="actions btn btn-sm btn-info hidden-print" data-tooltip="true" title="{{ trans('general.new_asset') }}"><x-icon type="plus" class="fa-fw" /><span class="sr-only">{{ trans('general.new_asset') }}</span></a>&nbsp;';
}
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 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;';
}