Add location support to equipment

This commit is contained in:
oliversum-ch 2025-12-29 16:36:42 +01:00
parent 68b4abfac4
commit 8d07311ae5
6 changed files with 112 additions and 70 deletions

View File

@ -11,29 +11,32 @@ class EquipmentController extends BaseController
public function EditForm(Request $request, Response $response, array $args) public function EditForm(Request $request, Response $response, array $args)
{ {
if ($args['equipmentId'] == 'new') if ($args['equipmentId'] == 'new')
{ {
return $this->renderPage($response, 'equipmentform', [ return $this->renderPage($response, 'equipmentform', [
'mode' => 'create', 'mode' => 'create',
'userfields' => $this->getUserfieldsService()->GetFields('equipment') 'userfields' => $this->getUserfieldsService()->GetFields('equipment'),
]); 'locations' => $this->getDatabase()->locations()->orderBy('name', 'COLLATE NOCASE')
} ]);
else }
{ else
return $this->renderPage($response, 'equipmentform', [ {
'equipment' => $this->getDatabase()->equipment($args['equipmentId']), return $this->renderPage($response, 'equipmentform', [
'mode' => 'edit', 'equipment' => $this->getDatabase()->equipment($args['equipmentId']),
'userfields' => $this->getUserfieldsService()->GetFields('equipment') 'mode' => 'edit',
]); 'userfields' => $this->getUserfieldsService()->GetFields('equipment'),
} 'locations' => $this->getDatabase()->locations()->orderBy('name', 'COLLATE NOCASE')
} ]);
}
}
public function Overview(Request $request, Response $response, array $args) public function Overview(Request $request, Response $response, array $args)
{ {
return $this->renderPage($response, 'equipment', [ return $this->renderPage($response, 'equipment', [
'equipment' => $this->getDatabase()->equipment()->orderBy('name', 'COLLATE NOCASE'), 'equipment' => $this->getDatabase()->equipment()->orderBy('name', 'COLLATE NOCASE'),
'userfields' => $this->getUserfieldsService()->GetFields('equipment'), 'userfields' => $this->getUserfieldsService()->GetFields('equipment'),
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('equipment') 'userfieldValues' => $this->getUserfieldsService()->GetAllValues('equipment'),
]); 'locations' => $this->getDatabase()->locations()->orderBy('name', 'COLLATE NOCASE')
} ]);
}
} }

1
migrations/0255.sql Normal file
View File

@ -0,0 +1 @@
ALTER TABLE equipment ADD location_id INTEGER;

View File

@ -29,16 +29,28 @@ equipmentTable.on('select', function(e, dt, type, indexes)
function DisplayEquipment(id) function DisplayEquipment(id)
{ {
Grocy.Api.Get('objects/equipment/' + id, Grocy.Api.Get('objects/equipment/' + id,
function(equipmentItem) function(equipmentItem)
{ {
$(".selected-equipment-name").text(equipmentItem.name); $(".selected-equipment-name").text(equipmentItem.name);
$("#description-tab-content").html(equipmentItem.description); $("#description-tab-content").html(equipmentItem.description);
$(".equipment-edit-button").attr("href", U("/equipment/" + equipmentItem.id.toString())); $(".equipment-edit-button").attr("href", U("/equipment/" + equipmentItem.id.toString()));
if (equipmentItem.instruction_manual_file_name) var equipmentLocation = FindObjectInArrayByPropertyValue(Grocy.Locations, 'id', equipmentItem.location_id);
{ if (equipmentLocation)
var pdfUrl = U('/api/files/equipmentmanuals/' + btoa(equipmentItem.instruction_manual_file_name)); {
$("#selected-equipment-instruction-manual").attr("src", pdfUrl); $("#selected-equipment-location-name").text(equipmentLocation.name);
$("#selected-equipment-location").removeClass("d-none");
}
else
{
$("#selected-equipment-location-name").text("");
$("#selected-equipment-location").addClass("d-none");
}
if (equipmentItem.instruction_manual_file_name)
{
var pdfUrl = U('/api/files/equipmentmanuals/' + btoa(equipmentItem.instruction_manual_file_name));
$("#selected-equipment-instruction-manual").attr("src", pdfUrl);
$("#selectedEquipmentInstructionManualDownloadButton").attr("href", pdfUrl); $("#selectedEquipmentInstructionManualDownloadButton").attr("href", pdfUrl);
$("#selected-equipment-instruction-manual").removeClass("d-none"); $("#selected-equipment-instruction-manual").removeClass("d-none");
$("#selectedEquipmentInstructionManualDownloadButton").removeClass("d-none"); $("#selectedEquipmentInstructionManualDownloadButton").removeClass("d-none");

View File

@ -12,7 +12,11 @@
return; return;
} }
var jsonData = $('#equipment-form').serializeJSON(); var jsonData = $('#equipment-form').serializeJSON();
if (jsonData.location_id == "")
{
jsonData.location_id = null;
}
Grocy.FrontendHelpers.BeginUiBusy("equipment-form"); Grocy.FrontendHelpers.BeginUiBusy("equipment-form");
if ($("#instruction-manual")[0].files.length > 0) if ($("#instruction-manual")[0].files.length > 0)

View File

@ -5,10 +5,14 @@
@section('title', $__t('Equipment')) @section('title', $__t('Equipment'))
@section('content') @section('content')
<script>
Grocy.Locations = @json($locations);
</script>
<div class="row"> <div class="row">
<div class="col-12 col-md-4 pb-3"> <div class="col-12 col-md-4 pb-3">
<div class="title-related-links border-bottom mb-2 py-1"> <div class="title-related-links border-bottom mb-2 py-1">
<h2 class="title">@yield('title')</h2> <h2 class="title">@yield('title')</h2>
<div class="float-right @if($embedded) pr-5 @endif"> <div class="float-right @if($embedded) pr-5 @endif">
<button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3" <button class="btn btn-outline-dark d-md-none mt-2 order-1 order-md-3"
type="button" type="button"
@ -65,14 +69,15 @@
data-toggle="tooltip" data-toggle="tooltip"
title="{{ $__t('Table options') }}" title="{{ $__t('Table options') }}"
data-table-selector="#equipment-table" data-table-selector="#equipment-table"
href="#"><i class="fa-solid fa-eye"></i></a> href="#"><i class="fa-solid fa-eye"></i></a>
</th> </th>
<th>{{ $__t('Name') }}</th> <th>{{ $__t('Name') }}</th>
<th>{{ $__t('Location') }}</th>
@include('components.userfields_thead', array( @include('components.userfields_thead', array(
'userfields' => $userfields, 'userfields' => $userfields,
'excludeFieldTypes' => [\Grocy\Services\UserfieldsService::USERFIELD_TYPE_FILE] 'excludeFieldTypes' => [\Grocy\Services\UserfieldsService::USERFIELD_TYPE_FILE]
)) ))
</tr> </tr>
</thead> </thead>
@ -102,15 +107,21 @@
</a> </a>
</div> </div>
</div> </div>
</td> </td>
<td> <td>
{{ $equipmentItem->name }} {{ $equipmentItem->name }}
</td> </td>
<td>
@php $location = FindObjectInArrayByPropertyValue($locations, 'id', $equipmentItem->location_id); @endphp
@if(!empty($location))
{{ $location->name }}
@endif
</td>
@include('components.userfields_tbody', array( @include('components.userfields_tbody', array(
'userfields' => $userfields, 'userfields' => $userfields,
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $equipmentItem->id), 'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $equipmentItem->id),
'excludeFieldTypes' => [\Grocy\Services\UserfieldsService::USERFIELD_TYPE_FILE] 'excludeFieldTypes' => [\Grocy\Services\UserfieldsService::USERFIELD_TYPE_FILE]
)) ))
</tr> </tr>
@ -119,10 +130,15 @@
</table> </table>
</div> </div>
<div class="col-12 col-md-8"> <div class="col-12 col-md-8">
<ul class="nav nav-tabs grocy-tabs mb-1"> <p id="selected-equipment-location"
<li class="nav-item"> class="text-muted d-none">
<a class="nav-link active" <i class="fa-solid fa-location-dot"></i>
<span id="selected-equipment-location-name"></span>
</p>
<ul class="nav nav-tabs grocy-tabs mb-1">
<li class="nav-item">
<a class="nav-link active"
data-toggle="tab" data-toggle="tab"
href="#instruction-manual-tab">{{ $__t('Instruction manual') }}</a> href="#instruction-manual-tab">{{ $__t('Instruction manual') }}</a>
</li> </li>

View File

@ -38,21 +38,27 @@
<form id="equipment-form" <form id="equipment-form"
novalidate> novalidate>
<div class="form-group"> <div class="form-group">
<label for="name">{{ $__t('Name') }}</label> <label for="name">{{ $__t('Name') }}</label>
<input type="text" <input type="text"
class="form-control" class="form-control"
required required
id="name" id="name"
name="name" name="name"
value="@if($mode == 'edit'){{ $equipment->name }}@endif"> value="@if($mode == 'edit'){{ $equipment->name }}@endif">
<div class="invalid-feedback">{{ $__t('A name is required') }}</div> <div class="invalid-feedback">{{ $__t('A name is required') }}</div>
</div> </div>
<div class="form-group"> @include('components.locationpicker', array(
<label for="description">{{ $__t('Notes') }}</label> 'locations' => $locations,
<textarea class="form-control wysiwyg-editor" 'isRequired' => false,
id="description" 'prefillById' => $mode == 'edit' ? $equipment->location_id : ''
))
<div class="form-group">
<label for="description">{{ $__t('Notes') }}</label>
<textarea class="form-control wysiwyg-editor"
id="description"
name="description">@if($mode == 'edit'){{ $equipment->description }}@endif</textarea> name="description">@if($mode == 'edit'){{ $equipment->description }}@endif</textarea>
</div> </div>