Fixed and optimized some things related to #421 (& some more cleanup)

This commit is contained in:
Bernd Bestel 2020-01-21 17:30:09 +01:00
parent 17e5c04bf9
commit f543a3a472
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
11 changed files with 213 additions and 429 deletions

View File

@ -49,9 +49,7 @@ class StockController extends BaseController
'locations' => $this->Database->locations()->orderBy('name'),
'currentStockDetail' => $this->Database->stock()->orderBy('product_id'),
'currentStockLocations' => $this->StockService->GetCurrentStockLocations(),
'missingProducts' => $this->StockService->GetMissingProducts(),
'nextXDays' => $nextXDays,
'productGroups' => $this->Database->product_groups()->orderBy('name'),
'userfields' => $this->UserfieldsService->GetFields('products'),
'userfieldValues' => $this->UserfieldsService->GetAllValues('products')
]);

View File

@ -1615,3 +1615,6 @@ msgstr ""
msgid "Keep screen on while displaying a \"fullscreen-card\""
msgstr ""
msgid "A purchased date is required"
msgstr ""

View File

@ -614,10 +614,10 @@ $(document).on("click", ".show-as-dialog-link", function(e)
backdrop: true,
closeButton: false,
buttons: {
ok: {
label: __t('OK'),
className: 'btn-success responsive-button',
callback: function()
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function ()
{
bootbox.hideAll();
}

View File

@ -1,24 +1,4 @@
$(document).ready(function() {
if (GetUriParam("embedded") !== undefined)
{
var locationId = GetUriParam('locationId');
if (typeof locationId === 'undefined')
{
Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetInputElement().focus();
} else {
$("#location_id").val(locationId);
$("#location_id").trigger('change');
$("#use_specific_stock_entry").click();
$("#use_specific_stock_entry").trigger('change');
}
}
});
$('#save-consume-button').on('click', function(e)
$('#save-consume-button').on('click', function(e)
{
e.preventDefault();
@ -497,3 +477,21 @@ function UndoStockTransaction(transactionId)
}
);
};
if (GetUriParam("embedded") !== undefined)
{
var locationId = GetUriParam('locationId');
if (typeof locationId === 'undefined')
{
Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetInputElement().focus();
}
else
{
$("#location_id").val(locationId);
$("#location_id").trigger('change');
$("#use_specific_stock_entry").click();
$("#use_specific_stock_entry").trigger('change');
}
}

View File

@ -7,45 +7,19 @@
});
$('#stock-detail-table tbody').removeClass("d-none");
function bootBoxModal(message) {
bootbox.dialog({
message: message,
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
}
$.fn.dataTable.ext.search.push(
function( settings, data, dataIndex ) {
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex)
{
var productId = Grocy.Components.ProductPicker.GetValue();
if ( ( isNaN( productId ) ||
productId == "" ||
//assume productId is in the first column
productId == data[1] ) )
if ((isNaN(productId) || productId == "" || productId == data[1]))
{
return true;
}
return false;
}
);
$(document).ready(function() {
Grocy.Components.ProductPicker.GetPicker().trigger('change');
} );
return false;
});
Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
{
@ -114,29 +88,17 @@ $(document).on('click', '.product-open-button', function(e)
var productId = $(e.currentTarget).attr('data-product-id');
var productName = $(e.currentTarget).attr('data-product-name');
var productQuName = $(e.currentTarget).attr('data-product-qu-name');
var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
var stockRowId = $(e.currentTarget).attr('data-stockrow-id');
var button = $(e.currentTarget);
Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': 1 },
Grocy.Api.Post('stock/products/' + productId + '/open', { 'amount': 1, 'stock_entry_id': specificStockEntryId },
function(bookingResponse)
{
Grocy.Api.Get('stock/products/' + productId,
function(result)
{
if (result.stock_amount == result.stock_amount_opened)
{
button.addClass("disabled");
}
Grocy.FrontendHelpers.EndUiBusy();
toastr.success(__t('Marked %1$s of %2$s as opened', 1 + " " + productQuName, productName) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBooking(' + bookingResponse.id + ')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>');
RefreshProductRow(productId);
},
function(xhr)
{
Grocy.FrontendHelpers.EndUiBusy();
console.error(xhr);
}
);
toastr.success(__t('Marked %1$s of %2$s as opened', 1 + " " + productQuName, productName) + '<br><a class="btn btn-secondary btn-sm mt-2" href="#" onclick="UndoStockBookingEntry(' + bookingResponse.id + ',' + stockRowId + ')"><i class="fas fa-undo"></i> ' + __t("Undo") + '</a>');
RefreshStockDetailRow(stockRowId);
},
function(xhr)
{
@ -152,91 +114,40 @@ $(document).on("click", ".stock-name-cell", function(e)
$("#stockdetail-productcard-modal").modal("show");
});
$(document).on("click", ".product-purchase-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/purchase?embedded&product=") + productId.toString() + '"></iframe>');
});
$(document).on("click", ".product-transfer-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
var locationId = $(e.currentTarget).attr('data-location-id');
var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/transfer?embedded&product=") + productId.toString() + '&locationId=' + locationId.toString() + '&stockId=' + specificStockEntryId.toString() + '"></iframe>');
});
$(document).on("click", ".product-consume-custom-amount-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
var locationId = $(e.currentTarget).attr('data-location-id');
var specificStockEntryId = $(e.currentTarget).attr('data-stock-id');
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/consume?embedded&product=") + productId.toString() + '&locationId=' + locationId.toString() + '&stockId=' + specificStockEntryId.toString() + '"></iframe>');
});
$(document).on("click", ".product-inventory-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/inventory?embedded&product=") + productId.toString() + '"></iframe>');
});
$(document).on("click", ".product-stockedit-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
var stockRowId = $(e.currentTarget).attr("data-id");
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/stockedit?embedded&product=") + productId.toString() + '&stockRowId=' + stockRowId.toString() + '"></iframe>');
});
$(document).on("click", ".product-add-to-shopping-list-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootBoxModal('<iframe height="650px" class="embed-responsive" src="' + U("/shoppinglistitem/new?embedded&updateexistingproduct&product=") + productId.toString() + '"></iframe>');
});
function RefreshStockDetailRow(stockRowId)
{
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function(result)
{
var stockRow = $('#stock-' + stockRowId + '-row');
if (result == null || result.amount == 0)
{
stockRow.fadeOut(500, function()
{
$(this).addClass("d-none");
});
}
else
{
var expiringThreshold = moment().add(Grocy.UserSettings.stock_expring_soon_days, "days");
var now = moment();
var bestBeforeDate = moment(result.best_before_date);
stockRow.removeClass("table-warning");
stockRow.removeClass("table-danger");
stockRow.removeClass("table-info");
stockRow.removeClass("d-none");
stockRow.removeAttr("style");
if (result == null || result.amount == 0)
if (now.isAfter(bestBeforeDate))
{
stockRow.fadeOut(500, function()
{
//$(this).tooltip("hide");
$(this).addClass("d-none");
});
stockRow.addClass("table-danger");
}
else
else if (bestBeforeDate.isBefore(expiringThreshold))
{
stockRow.addClass("table-warning");
}
$('#stock-' + stockRowId + '-amount').parent().effect('highlight', { }, 500);
$('#stock-' + stockRowId + '-amount').fadeOut(500, function ()
{
@ -248,6 +159,7 @@ function RefreshStockDetailRow(stockRowId)
{
$(this).text(result.best_before_date).fadeIn(500);
});
$('#stock-' + stockRowId + '-best-before-date-timeago').attr('datetime', result.best_before_date + ' 23:59:59');
var locationName = "";
Grocy.Api.Get("objects/locations/" + result.location_id,
@ -258,7 +170,8 @@ function RefreshStockDetailRow(stockRowId)
function(xhr)
{
console.error(xhr);
});
}
);
$('#stock-' + stockRowId + '-location').parent().effect('highlight', { }, 500);
$('#stock-' + stockRowId + '-location').fadeOut(500, function()
{
@ -276,8 +189,24 @@ function RefreshStockDetailRow(stockRowId)
{
$(this).text(result.purchased_date).fadeIn(500);
});
$('#stock-' + stockRowId + '-purchased-date-timeago').attr('datetime', result.purchased_date + ' 23:59:59');
$('#stock-' + stockRowId + '-opened-amount').parent().effect('highlight', {}, 500);
$('#stock-' + stockRowId + '-opened-amount').fadeOut(500, function ()
{
if (result.open == 1)
{
$(this).text(__t('Opened')).fadeIn(500);
}
else
{
$(this).text("").fadeIn(500);
$(".product-open-button[data-stockrow-id='" + stockRowId + "']").removeClass("disabled");
}
});
}
// Needs to be delayed because of the animation above the date-text would be wrong if fired immediately...
setTimeout(function()
{
RefreshContextualTimeago();
@ -316,3 +245,9 @@ function UndoStockBookingEntry(bookingId, stockRowId)
}
);
};
$(document).on("click", ".product-name-cell", function(e)
{
Grocy.Components.ProductCard.Refresh($(e.currentTarget).attr("data-product-id"));
$("#productcard-modal").modal("show");
});

View File

@ -1,57 +1,4 @@
$(document).ready(function() {
var stockRowId = GetUriParam('stockRowId');
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function(stockEntry)
{
Grocy.Components.LocationPicker.SetId(stockEntry.location_id);
$('#amount').val(stockEntry.amount);
$('#price').val(stockEntry.price);
Grocy.Components.DateTimePicker.SetValue(stockEntry.best_before_date);
Grocy.Api.Get('stock/products/' + stockEntry.product_id,
function(productDetails)
{
$('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
if (productDetails.product.allow_partial_units_in_stock == 1)
{
$("#amount").attr("min", "0.01");
$("#amount").attr("step", "0.01");
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', 0.01.toLocaleString()));
}
else
{
$("#amount").attr("min", "1");
$("#amount").attr("step", "1");
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', '1'));
}
if (productDetails.product.enable_tare_weight_handling == 1)
{
$("#amount").attr("min", productDetails.product.tare_weight);
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', parseFloat(productDetails.product.tare_weight).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: 2 })));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
$("#tare-weight-handling-info").addClass("d-none");
}
},
function(xhr)
{
console.error(xhr);
}
);
},
function(xhr)
{
console.error(xhr);
}
);
} );
$('#save-stockedit-button').on('click', function(e)
$('#save-stockedit-button').on('click', function(e)
{
e.preventDefault();
@ -76,8 +23,6 @@ $('#save-stockedit-button').on('click', function(e)
}
jsonData.price = price;
var bookingResponse = null;
var stockRowId = GetUriParam('stockRowId');
jsonData.id = stockRowId;
@ -135,3 +80,54 @@ if (Grocy.Components.DateTimePicker)
Grocy.FrontendHelpers.ValidateForm('stockedit-form');
});
}
var stockRowId = GetUriParam('stockRowId');
Grocy.Api.Get("stock/" + stockRowId + "/entry",
function (stockEntry)
{
Grocy.Components.LocationPicker.SetId(stockEntry.location_id);
$('#amount').val(stockEntry.amount);
$('#price').val(stockEntry.price);
Grocy.Components.DateTimePicker.SetValue(stockEntry.best_before_date);
Grocy.Api.Get('stock/products/' + stockEntry.product_id,
function (productDetails)
{
$('#amount_qu_unit').text(productDetails.quantity_unit_stock.name);
if (productDetails.product.allow_partial_units_in_stock == 1)
{
$("#amount").attr("min", "0.01");
$("#amount").attr("step", "0.01");
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', 0.01.toLocaleString()));
}
else
{
$("#amount").attr("min", "1");
$("#amount").attr("step", "1");
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', '1'));
}
if (productDetails.product.enable_tare_weight_handling == 1)
{
$("#amount").attr("min", productDetails.product.tare_weight);
$("#amount").parent().find(".invalid-feedback").text(__t('The amount cannot be lower than %1$s', parseFloat(productDetails.product.tare_weight).toLocaleString({ minimumFractionDigits: 0, maximumFractionDigits: 2 })));
$("#tare-weight-handling-info").removeClass("d-none");
}
else
{
$("#tare-weight-handling-info").addClass("d-none");
}
},
function (xhr)
{
console.error(xhr);
}
);
},
function (xhr)
{
console.error(xhr);
}
);

View File

@ -196,126 +196,6 @@ function RefreshStatistics()
}
RefreshStatistics();
$(document).on("click", ".product-purchase-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootbox.dialog({
message: '<iframe height="650px" class="embed-responsive" src="' + U("/purchase?embedded&product=") + productId.toString() + '"></iframe>',
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
});
$(document).on("click", ".product-transfer-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootbox.dialog({
message: '<iframe height="650px" class="embed-responsive" src="' + U("/transfer?embedded&product=") + productId.toString() + '"></iframe>',
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
});
$(document).on("click", ".product-consume-custom-amount-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootbox.dialog({
message: '<iframe height="650px" class="embed-responsive" src="' + U("/consume?embedded&product=") + productId.toString() + '"></iframe>',
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
});
$(document).on("click", ".product-inventory-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootbox.dialog({
message: '<iframe height="650px" class="embed-responsive" src="' + U("/inventory?embedded&product=") + productId.toString() + '"></iframe>',
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
});
$(document).on("click", ".product-add-to-shopping-list-button", function(e)
{
e.preventDefault();
var productId = $(e.currentTarget).attr("data-product-id");
bootbox.dialog({
message: '<iframe height="650px" class="embed-responsive" src="' + U("/shoppinglistitem/new?embedded&updateexistingproduct&product=") + productId.toString() + '"></iframe>',
size: 'large',
backdrop: true,
closeButton: false,
buttons: {
cancel: {
label: __t('Cancel'),
className: 'btn-secondary responsive-button',
callback: function()
{
bootbox.hideAll();
}
}
}
});
});
function RefreshProductRow(productId)
{
productId = productId.toString();
@ -398,7 +278,7 @@ function RefreshProductRow(productId)
{
$(this).text(result.next_best_before_date).fadeIn(500);
});
$('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date);
$('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date + ' 23:59:59');
if (result.stock_amount_opened > 0)
{

View File

@ -1,23 +1,4 @@
$(document).ready(function() {
if (GetUriParam("embedded") !== undefined)
{
var locationId = GetUriParam('locationId');
if (typeof locationId === 'undefined')
{
Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetInputElement().focus();
} else {
$("#location_id_from").val(locationId);
$("#location_id_from").trigger('change');
$("#use_specific_stock_entry").click();
$("#use_specific_stock_entry").trigger('change');
}
}
});
$('#save-transfer-button').on('click', function(e)
$('#save-transfer-button').on('click', function(e)
{
e.preventDefault();
@ -440,3 +421,22 @@ function UndoStockTransaction(transactionId)
}
);
};
if (GetUriParam("embedded") !== undefined)
{
var locationId = GetUriParam('locationId');
if (typeof locationId === 'undefined')
{
Grocy.Components.ProductPicker.GetPicker().trigger('change');
Grocy.Components.ProductPicker.GetInputElement().focus();
}
else
{
$("#location_id_from").val(locationId);
$("#location_id_from").trigger('change');
$("#use_specific_stock_entry").click();
$("#use_specific_stock_entry").trigger('change');
}
}

View File

@ -9,21 +9,16 @@
<script src="{{ $U('/viewjs/purchase.js?v=', true) }}{{ $version }}"></script>
@endpush
@push('pageStyles')
<style>
.product-name-cell[data-product-has-picture='true'] {
cursor: pointer;
}
</style>
@endpush
@section('content')
<div class="row">
<div class="col">
<h1>@yield('title')</h1>
</div>
<div class="col">
@include('components.productpicker', array('products' => $products,'disallowAddProductWorkflows' => true))
@include('components.productpicker', array(
'products' => $products,
'disallowAllProductWorkflows' => true
))
</div>
</div>
@ -48,19 +43,9 @@
</thead>
<tbody class="d-none">
@foreach($currentStockDetail as $currentStockEntry)
<tr id="stock-{{ $currentStockEntry->id }}-row" class="@if(GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING && $currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime('-1 days')) && $currentStockEntry->amount > 0) table-danger @elseif(GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING && $currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) table-warning @elseif (FindObjectInArrayByPropertyValue($missingProducts, 'id', $currentStockEntry->product_id) !== null) table-info @endif">
<tr id="stock-{{ $currentStockEntry->id }}-row" class="@if(GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING && $currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime('-1 days')) && $currentStockEntry->amount > 0) table-danger @elseif(GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING && $currentStockEntry->best_before_date < date('Y-m-d 23:59:59', strtotime("+$nextXDays days")) && $currentStockEntry->amount > 0) table-warning @endif">
<td class="fit-content border-right">
<a class="btn btn-success btn-sm stock-consume-button @if($currentStockEntry->amount < 1) disabled @endif" href="#" data-toggle="tooltip" data-placement="left" title="{{ $__t('Consume %1$s of %2$s', '1 ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
data-product-id="{{ $currentStockEntry->product_id }}"
data-stock-id="{{ $currentStockEntry->stock_id }}"
data-stockrow-id="{{ $currentStockEntry->id }}"
data-location-id="{{ $currentStockEntry->location_id }}"
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-consume-amount="1">
<i class="fas fa-utensils"></i> 1
</a>
<a id="stock-{{ $currentStockEntry->id }}-consume-all-button" class="btn btn-danger btn-sm stock-consume-button @if($currentStockEntry->amount == 0) disabled @endif" href="#" data-toggle="tooltip" data-placement="right" title="{{ $__t('Consume all %s for this stock entry', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
<a class="btn btn-success btn-sm stock-consume-button" href="#" data-toggle="tooltip" data-placement="left" title="{{ $__t('Consume %1$s of %2$s', '1 ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
data-product-id="{{ $currentStockEntry->product_id }}"
data-stock-id="{{ $currentStockEntry->stock_id }}"
data-stockrow-id="{{ $currentStockEntry->id }}"
@ -68,14 +53,19 @@
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-consume-amount="{{ $currentStockEntry->amount }}">
<i class="fas fa-utensils"></i> {{ $__t('All') }}
<i class="fas fa-utensils"></i>
</a>
@if(GROCY_FEATURE_FLAG_STOCK_PRODUCT_OPENED_TRACKING)
<a class="btn btn-success btn-sm product-open-button @if($currentStockEntry->amount < 1 || $currentStockEntry->amount == $currentStockEntry->amount_opened) disabled @endif" href="#" data-toggle="tooltip" data-placement="left" title="{{ $__t('Mark %1$s of %2$s as open', '1 ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
<a class="btn btn-success btn-sm product-open-button @if($currentStockEntry->open == 1) disabled @endif" href="#" data-toggle="tooltip" data-placement="left" title="{{ $__t('Mark %1$s of %2$s as open', '1 ' . FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name) }}"
data-product-id="{{ $currentStockEntry->product_id }}"
data-product-name="{{ FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->name }}"
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}">
<i class="fas fa-box-open"></i> 1
data-product-qu-name="{{ FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name }}"
data-stock-id="{{ $currentStockEntry->stock_id }}"
data-stockrow-id="{{ $currentStockEntry->id }}">
<i class="fas fa-box-open"></i>
</a>
<a class="btn btn-info btn-sm show-as-dialog-link" href="{{ $U('/stockedit?embedded&product=' . $currentStockEntry->product_id . '&stockRowId=' . $currentStockEntry->id) }}" data-toggle="tooltip" data-placement="left" title="{{ $__t('Edit stock entry') }}">
<i class="fas fa-edit"></i>
</a>
@endif
<div class="dropdown d-inline-block">
@ -83,39 +73,24 @@
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item product-add-to-shopping-list-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/shoppinglistitem/new?embedded&updateexistingproduct&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-shopping-cart"></i> {{ $__t('Add to shopping list') }}
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item product-purchase-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/purchase?embedded&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-shopping-cart"></i> {{ $__t('Purchase') }}
</a>
<a class="dropdown-item product-consume-custom-amount-button @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}"
data-location-id="{{ $currentStockEntry->location_id }}"
data-stock-id="{{ $currentStockEntry->stock_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/consume?embedded&product=' . $currentStockEntry->product_id . '&locationId=' . $currentStockEntry->location_id . '&stockId=' . $currentStockEntry->stock_id) }}">
<i class="fas fa-utensils"></i> {{ $__t('Consume') }}
</a>
@if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
<a class="dropdown-item product-transfer-button @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}"
data-location-id="{{ $currentStockEntry->location_id }}"
data-stock-id="{{ $currentStockEntry->stock_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/transfer?embedded&product=' . $currentStockEntry->product_id . '&locationId=' . $currentStockEntry->location_id . '&stockId=' . $currentStockEntry->stock_id) }}">
<i class="fas fa-exchange-alt"></i> {{ $__t('Transfer') }}
</a>
@endif
<a class="dropdown-item product-inventory-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/inventory?embedded&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-list"></i> {{ $__t('Inventory') }}
</a>
<a class="dropdown-item product-stockedit-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}"
data-location-id="{{ $currentStockEntry->location_id }}"
data-id="{{ $currentStockEntry->id }}">
<i class="fas fa-boxes"></i> {{ $__t('Edit stock entry') }}
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item product-name-cell" data-product-id="{{ $currentStockEntry->product_id }}" type="button" href="#">
<i class="fas fa-info"></i> {{ $__t('Show product details') }}
@ -153,30 +128,25 @@
</td>
<td>
<span id="stock-{{ $currentStockEntry->id }}-amount" class="locale-number locale-number-quantity-amount">{{ $currentStockEntry->amount }}</span> <span id="product-{{ $currentStockEntry->product_id }}-qu-name">{{ $__n($currentStockEntry->amount, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }}</span>
<span id="stock-{{ $currentStockEntry->id }}-opened-amount" class="small font-italic">@if($currentStockEntry->amount_opened > 0){{ $__t('%s opened', $currentStockEntry->amount_opened) }}@endif</span>
@if($currentStockEntry->is_aggregated_amount == 1)
<span class="pl-1 text-secondary">
<i class="fas fa-custom-sigma-sign"></i> <span id="product-{{ $currentStockEntry->product_id }}-amount-aggregated" class="locale-number locale-number-quantity-amount">{{ $currentStockEntry->amount_aggregated }}</span> {{ $__n($currentStockEntry->amount_aggregated, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name, FindObjectInArrayByPropertyValue($quantityunits, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->qu_id_stock)->name_plural) }}
@if($currentStockEntry->amount_opened_aggregated > 0)<span id="product-{{ $currentStockEntry->product_id }}-opened-amount-aggregated" class="small font-italic">{{ $__t('%s opened', $currentStockEntry->amount_opened_aggregated) }}</span>@endif
</span>
@endif
<span id="stock-{{ $currentStockEntry->id }}-opened-amount" class="small font-italic">@if($currentStockEntry->open == 1){{ $__t('Opened') }}@endif</span>
</td>
<td>
<span id="stock-{{ $currentStockEntry->id }}-best-before-date">{{ $currentStockEntry->best_before_date }}</span>
<time id="stock-{{ $currentStockEntry->id }}-best-before-date-timeago" class="timeago timeago-contextual" datetime="{{ $currentStockEntry->best_before_date }} 23:59:59"></time>
</td>
@if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
<td id="stock-{{ $currentStockEntry->id }}-location" class="location-name-cell cursor-link" data-location-id="{{ $currentStockEntry->location_id }}">
<td id="stock-{{ $currentStockEntry->id }}-location" data-location-id="{{ $currentStockEntry->location_id }}">
{{ FindObjectInArrayByPropertyValue($locations, 'id', $currentStockEntry->location_id)->name }}
</td>
@endif
@if(GROCY_FEATURE_FLAG_STOCK_PRICE_TRACKING)
<td id="stock-{{ $currentStockEntry->id }}-price" class="price-name-cell cursor-link" data-price-id="{{ $currentStockEntry->price }}">
<td id="stock-{{ $currentStockEntry->id }}-price" class="locale-number locale-number-currency" data-price-id="{{ $currentStockEntry->price }}">
{{ $currentStockEntry->price }}
</td>
@endif
<td>
<span id="stock-{{ $currentStockEntry->id }}-purchased-date">{{ $currentStockEntry->purchased_date }}</span>
<time id="stock-{{ $currentStockEntry->id }}-purchased-date-timeago" class="timeago timeago-contextual" datetime="{{ $currentStockEntry->purchased_date }} 23:59:59"></time>
</td>
</tr>
@endforeach
@ -185,7 +155,7 @@
</div>
</div>
<div class="modal fade" id="stockdetail-productcard-modal" tabindex="-1">
<div class="modal fade" id="productcard-modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content text-center">
<div class="modal-body">

View File

@ -69,13 +69,27 @@
<input type="hidden" name="price" id="price" value="0">
@endif
@php /*@include('components.datetimepicker', array(
'id' => 'purchase_date',
'label' => 'Purchased date',
'format' => 'YYYY-MM-DD',
'initWithNow' => false,
'limitEndToNow' => false,
'limitStartToNow' => false,
'invalidFeedback' => $__t('A purchased date is required'),
'nextInputSelector' => '#save-stockedit-button',
'additionalGroupCssClasses' => 'date-only-datetimepicker'
))*/ @endphp
<div class="checkbox">
<label for="open">
<input type="checkbox" id="open" name="open"> {{ $__t('Opened') }}
</label>
</div>
<button id="save-stockedit-button" class="btn btn-success">{{ $__t('OK') }}</button>
</form>
</div>
<div class="col-xs-12 col-md-6 col-xl-4 hide-when-embedded">
@include('components.productcard')
</div>
</div>
@stop

View File

@ -9,14 +9,6 @@
<script src="{{ $U('/viewjs/purchase.js?v=', true) }}{{ $version }}"></script>
@endpush
@push('pageStyles')
<style>
.product-name-cell[data-product-has-picture='true'] {
cursor: pointer;
}
</style>
@endpush
@section('content')
<div class="row">
<div class="col">
@ -25,6 +17,9 @@
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/stockjournal') }}">
<i class="fas fa-file-alt"></i> {{ $__t('Journal') }}
</a>
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/stockdetail') }}">
<i class="fas fa-boxes"></i> {{ $__t('Stock entries') }}
</a>
@if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
<a class="btn btn-outline-dark responsive-button" href="{{ $U('/locationcontentsheet') }}">
<i class="fas fa-print"></i> {{ $__t('Location Content Sheet') }}
@ -127,27 +122,22 @@
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item product-add-to-shopping-list-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/shoppinglistitem/new?embedded&updateexistingproduct&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-shopping-cart"></i> {{ $__t('Add to shopping list') }}
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item product-purchase-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/purchase?embedded&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-shopping-cart"></i> {{ $__t('Purchase') }}
</a>
<a class="dropdown-item product-consume-custom-amount-button @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/consume?embedded&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-utensils"></i> {{ $__t('Consume') }}
</a>
@if(GROCY_FEATURE_FLAG_STOCK_LOCATION_TRACKING)
<a class="dropdown-item product-transfer-button @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link @if($currentStockEntry->amount < 1) disabled @endif" type="button" href="{{ $U('/transfer?embedded&product=' . $currentStockEntry->product_id) }}">
<i class="fas fa-exchange-alt"></i> {{ $__t('Transfer') }}
</a>
@endif
<a class="dropdown-item product-inventory-button" type="button" href="#"
data-product-id="{{ $currentStockEntry->product_id }}">
<a class="dropdown-item show-as-dialog-link" type="button" href="{{ $U('/inventory?embedded&product=' . $currentStockEntry->product_id ) }}">
<i class="fas fa-list"></i> {{ $__t('Inventory') }}
</a>
<div class="dropdown-divider"></div>