mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Improved user experience with part withdraw modal
Related to issue #201
This commit is contained in:
parent
ba4085d882
commit
436aff7533
6 changed files with 128 additions and 17 deletions
|
@ -31,6 +31,38 @@ export default class extends Controller
|
|||
this.element.querySelector('input[name="action"]').setAttribute('value', action);
|
||||
this.element.querySelector('input[name="lot_id"]').setAttribute('value', lotID);
|
||||
|
||||
//Set the title
|
||||
const titleElement = this.element.querySelector('.modal-title');
|
||||
switch (action) {
|
||||
case 'withdraw':
|
||||
titleElement.innerText = titleElement.getAttribute('data-withdraw');
|
||||
break;
|
||||
case 'add':
|
||||
titleElement.innerText = titleElement.getAttribute('data-add');
|
||||
break;
|
||||
case 'move':
|
||||
titleElement.innerText = titleElement.getAttribute('data-move');
|
||||
break;
|
||||
}
|
||||
|
||||
//Hide the move to lot select, if the action is not move (and unhide it, if it is)
|
||||
const moveToLotSelect = this.element.querySelector('#withdraw-modal-move-to');
|
||||
if (action === 'move') {
|
||||
moveToLotSelect.classList.remove('d-none');
|
||||
} else {
|
||||
moveToLotSelect.classList.add('d-none');
|
||||
}
|
||||
|
||||
//First unhide all move to lot options and then hide the currently selected lot
|
||||
const moveToLotOptions = moveToLotSelect.querySelectorAll('input[type="radio"]');
|
||||
moveToLotOptions.forEach(option => option.parentElement.classList.remove('d-none'));
|
||||
moveToLotOptions.forEach(option => {
|
||||
if (option.getAttribute('value') === lotID) {
|
||||
option.parentElement.classList.add('d-none');
|
||||
option.selected = false;
|
||||
}
|
||||
});
|
||||
|
||||
//For adding parts there is no limit on the amount to add
|
||||
if (action == 'add') {
|
||||
amountInput.removeAttribute('max');
|
||||
|
|
|
@ -81,7 +81,7 @@ class PartController extends AbstractController
|
|||
* @throws Exception
|
||||
*/
|
||||
public function show(Part $part, Request $request, TimeTravel $timeTravel, HistoryHelper $historyHelper,
|
||||
DataTableFactory $dataTable, ParameterExtractor $parameterExtractor, ?string $timestamp = null): Response
|
||||
DataTableFactory $dataTable, ParameterExtractor $parameterExtractor, PartLotWithdrawAddHelper $withdrawAddHelper, ?string $timestamp = null): Response
|
||||
{
|
||||
$this->denyAccessUnlessGranted('read', $part);
|
||||
|
||||
|
@ -122,6 +122,7 @@ class PartController extends AbstractController
|
|||
'timeTravel' => $timeTravel_timestamp,
|
||||
'description_params' => $parameterExtractor->extractParameters($part->getDescription()),
|
||||
'comment_params' => $parameterExtractor->extractParameters($part->getComment()),
|
||||
'withdraw_add_helper' => $withdrawAddHelper,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -330,6 +331,9 @@ class PartController extends AbstractController
|
|||
if ($this->isCsrfTokenValid('part_withraw' . $part->getID(), $request->request->get('_csfr'))) {
|
||||
//Retrieve partlot from the request
|
||||
$partLot = $em->find(PartLot::class, $request->request->get('lot_id'));
|
||||
if($partLot === null) {
|
||||
throw new \RuntimeException('Part lot not found!');
|
||||
}
|
||||
//Ensure that the partlot belongs to the part
|
||||
if($partLot->getPart() !== $part) {
|
||||
throw new \RuntimeException("The origin partlot does not belong to the part!");
|
||||
|
|
|
@ -39,6 +39,11 @@ class PartLotWithdrawAddHelper
|
|||
return false;
|
||||
}
|
||||
|
||||
//Part must contain more than 0 parts
|
||||
if ($partLot->getAmount() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,18 +63,23 @@
|
|||
<td>
|
||||
<div class="btn-group" role="group">
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
|
||||
data-action="add" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
|
||||
{% if lot.storageLocation and lot.storageLocation.full %}disabled{% endif %}
|
||||
>
|
||||
<i class="fa-solid fa-plus fa-fw"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
|
||||
data-action="remove" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
|
||||
data-action="withdraw" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
|
||||
title="{% trans %}part.info.withdraw_modal.title.withdraw{% endtrans %}"
|
||||
{% if not withdraw_add_helper.canWithdraw(lot) %}disabled{% endif %}
|
||||
>
|
||||
<i class="fa-solid fa-minus fa-fw"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
|
||||
data-action="add" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
|
||||
title="{% trans %}part.info.withdraw_modal.title.add{% endtrans %}"
|
||||
{% if not withdraw_add_helper.canAdd(lot) %}disabled{% endif %}
|
||||
>
|
||||
<i class="fa-solid fa-plus fa-fw"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#withdraw-modal"
|
||||
data-action="move" data-lot-id="{{ lot.id }}" data-lot-amount="{{ lot.amount }}"
|
||||
title="{% trans %}part.info.withdraw_modal.title.move{% endtrans %}"
|
||||
{% if not withdraw_add_helper.canWithdraw(lot) or part.partLots.count == 1 %}disabled{% endif %}
|
||||
>
|
||||
<i class="fa-solid fa-right-left fa-fw"></i>
|
||||
</button>
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
<div class="modal fade" id="withdraw-modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true" {{ stimulus_controller('pages/part_withdraw_modal') }}>
|
||||
<div class="modal fade" id="withdraw-modal" tabindex="-1" aria-labelledby="withdraw-modal-title" aria-hidden="true" {{ stimulus_controller('pages/part_withdraw_modal') }}>
|
||||
<form method="post" action="{{ path('part_add_withdraw', {"id": part.id}) }}">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
|
||||
<h1 class="modal-title fs-5" id="withdraw-modal-title"
|
||||
data-withdraw="{% trans %}part.info.withdraw_modal.title.withdraw{% endtrans %}"
|
||||
data-add="{% trans %}part.info.withdraw_modal.title.add{% endtrans %}"
|
||||
data-move="{% trans %}part.info.withdraw_modal.title.move{% endtrans %}"
|
||||
>Filled by JS Controller</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
@ -15,20 +19,20 @@
|
|||
|
||||
<div class="row mb-2">
|
||||
<label class="col-form-label col-sm-3">
|
||||
Amount
|
||||
{% trans %}part.info.withdraw_modal.amount{% endtrans %}
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="number" required class="form-control" min="0" step="{{ (part.partUnit and not part.partUnit.integer) ? 'any' : '1' }}" name="amount" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-2">
|
||||
<label class="col-form-label col-sm-3">Move to</label>
|
||||
<div class="row mb-2 d-none" id="withdraw-modal-move-to">
|
||||
<label class="col-form-label col-sm-3">{% trans %}part.info.withdraw_modal.move_to{% endtrans %}</label>
|
||||
<div class="col-sm-9">
|
||||
{% for lots in part.partLots|filter(l => l.instockUnknown == false) %}
|
||||
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="target_id" value="{{ lots.iD }}" id="modal_target_radio_{{ lots.iD }}" {% if lots.storageLocation and lots.storageLocation.full %}disabled{% endif %} required>
|
||||
<input class="form-check-input" type="radio" name="target_id" value="{{ lots.iD }}" id="modal_target_radio_{{ lots.iD }}" {% if not withdraw_add_helper.canAdd(lots) %}disabled{% endif %} required {% if loop.first %}checked{% endif %}>
|
||||
<label class="form-check-label" for="modal_target_radio_{{ lots.iD }}">
|
||||
{{ (lots.storageLocation) ? lots.storageLocation.fullPath : ("Lot " ~ loop.index) }}{% if lots.name is not empty %} ({{ lots.name }}){% endif %}: <b>{{ lots.amount | format_amount(part.partUnit) }}</b>
|
||||
</label>
|
||||
|
@ -39,16 +43,17 @@
|
|||
|
||||
<div class="row mb-2">
|
||||
<label class="col-form-label col-sm-3">
|
||||
Comment
|
||||
{% trans %}part.info.withdraw_modal.comment{% endtrans %}
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="comment" value="">
|
||||
<div id="emailHelp" class="form-text">{% trans %}part.info.withdraw_modal.comment.hint{% endtrans %}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary">Submit</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans %}modal.close{% endtrans %}</button>
|
||||
<button type="submit" class="btn btn-primary">{% trans %}modal.submit{% endtrans %}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -10133,5 +10133,65 @@ Element 3</target>
|
|||
<target>Price</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="hO.xnng" name="part.info.withdraw_modal.title.withdraw">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.title.withdraw</source>
|
||||
<target>Withdraw parts from lot</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ci6FaUj" name="part.info.withdraw_modal.title.add">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.title.add</source>
|
||||
<target>Add parts to lot</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="kGal3M_" name="part.info.withdraw_modal.title.move">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.title.move</source>
|
||||
<target>Move parts from lot to another lot</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="zxFeQRY" name="part.info.withdraw_modal.amount">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.amount</source>
|
||||
<target>Amount</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="iblpgc7" name="part.info.withdraw_modal.move_to">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.move_to</source>
|
||||
<target>Move to</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="pYCfHzw" name="part.info.withdraw_modal.comment">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.comment</source>
|
||||
<target>Comment</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="ARNLGgz" name="part.info.withdraw_modal.comment.hint">
|
||||
<segment>
|
||||
<source>part.info.withdraw_modal.comment.hint</source>
|
||||
<target>You can set a comment here describing why you are doing this operation (e.g. for what you need the parts). This info will be saved in the log.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="Sumeg5G" name="modal.close">
|
||||
<segment>
|
||||
<source>modal.close</source>
|
||||
<target>Close</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="sye5gxs" name="modal.submit">
|
||||
<segment>
|
||||
<source>modal.submit</source>
|
||||
<target>Submit</target>
|
||||
</segment>
|
||||
</unit>
|
||||
<unit id="jl7xM1O" name="part.withdraw.success">
|
||||
<segment>
|
||||
<source>part.withdraw.success</source>
|
||||
<target>Added/Moved/Withdrawn parts successfully.</target>
|
||||
</segment>
|
||||
</unit>
|
||||
</file>
|
||||
</xliff>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue