mirror of
https://github.com/grocy/grocy.git
synced 2025-08-20 12:20:22 +00:00
Squashed commit
Make it possible to actively not-check a mandatory checkbox Userfield (closes #2601) Pluralize the "opened" localization string (closes #2280) Added a trendline to the price history chart (closes #2237) Various minor style/code refinements
This commit is contained in:
@@ -209,21 +209,16 @@ a:not([href]) {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Barcodescanner Quagga2 */
|
||||
#barcodescanner-container {
|
||||
max-height: 90vw;
|
||||
/* Camera Barcodescanner Quagga2 */
|
||||
#camerabarcodescanner-container {
|
||||
max-height: 90vh;
|
||||
}
|
||||
|
||||
#livestream-container {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
#barcodescanner-livestream video {
|
||||
#camerabarcodescanner-livestream video {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
#barcodescanner-livestream canvas {
|
||||
#camerabarcodescanner-livestream canvas {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -304,6 +299,14 @@ a:not([href]) {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.btn.dropdown-toggle:after {
|
||||
vertical-align: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
content: '\f107';
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
}
|
||||
|
||||
/* Third party component customizations - DataTables */
|
||||
.dataTable td {
|
||||
vertical-align: middle !important;
|
||||
@@ -362,14 +365,6 @@ html {
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
.dropdown-toggle:after {
|
||||
vertical-align: 0;
|
||||
margin: 0;
|
||||
border: none;
|
||||
content: '\f107';
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
}
|
||||
|
||||
/* Third party component customizations - Tempus Dominus */
|
||||
.bootstrap-datetimepicker-widget.dropdown-menu {
|
||||
width: auto !important;
|
||||
|
@@ -874,3 +874,9 @@ $(document).on("click", "#clear-filter-button", function(e)
|
||||
{
|
||||
$(".tooltip").tooltip("hide");
|
||||
});
|
||||
|
||||
$(document).on("click", '.btn, a, button', function(e)
|
||||
{
|
||||
// Remove focus after click
|
||||
document.activeElement.blur();
|
||||
});
|
||||
|
@@ -20,21 +20,21 @@ $("#expected_barcode").on("keyup", function(e)
|
||||
if ($("#expected_barcode").val().length > 1)
|
||||
{
|
||||
$("#scanned_barcode").removeAttr("disabled");
|
||||
$("#barcodescanner-start-button").removeAttr("disabled");
|
||||
$("#barcodescanner-start-button").removeClass("disabled");
|
||||
$("#camerabarcodescanner-start-button").removeAttr("disabled");
|
||||
$("#camerabarcodescanner-start-button").removeClass("disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#scanned_barcode").attr("disabled", "");
|
||||
$("#barcodescanner-start-button").attr("disabled", "");
|
||||
$("#barcodescanner-start-button").addClass("disabled");
|
||||
$("#camerabarcodescanner-start-button").attr("disabled", "");
|
||||
$("#camerabarcodescanner-start-button").addClass("disabled");
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function()
|
||||
{
|
||||
$("#barcodescanner-start-button").attr("disabled", "");
|
||||
$("#barcodescanner-start-button").addClass("disabled");
|
||||
$("#camerabarcodescanner-start-button").attr("disabled", "");
|
||||
$("#camerabarcodescanner-start-button").addClass("disabled");
|
||||
$("#expected_barcode").focus();
|
||||
}, 500);
|
||||
|
||||
|
@@ -117,7 +117,6 @@ $(document).on('click', '.track-charge-cycle-button', function(e)
|
||||
$(document).on('click', '.battery-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var batteryId = $(e.currentTarget).attr('data-battery-id');
|
||||
Grocy.Api.Get('batteries/' + batteryId + '/printlabel', function(labelData)
|
||||
|
@@ -91,7 +91,6 @@ $('#battery-form input').keydown(function(event)
|
||||
$(document).on('click', '.battery-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var batteryId = $(e.currentTarget).attr('data-battery-id');
|
||||
Grocy.Api.Get('batteries/' + batteryId + '/printlabel', function(labelData)
|
||||
|
@@ -271,7 +271,6 @@ Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
||||
$(document).on('click', '.chore-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var choreId = $(e.currentTarget).attr('data-chore-id');
|
||||
Grocy.Api.Get('chores/' + choreId + '/printlabel', function(labelData)
|
||||
|
@@ -213,7 +213,6 @@ $(document).on('click', '.track-chore-button', function(e)
|
||||
$(document).on('click', '.chore-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var choreId = $(e.currentTarget).attr('data-chore-id');
|
||||
Grocy.Api.Get('chores/' + choreId + '/printlabel', function(labelData)
|
||||
|
@@ -37,30 +37,29 @@ Grocy.Components.CameraBarcodeScanner.CheckCapabilities = async function()
|
||||
var hasTorch = typeof capabilities.torch === 'boolean' && capabilities.torch;
|
||||
|
||||
// Remove the torch button if the select camera doesn't have a torch
|
||||
var button = document.querySelector('.torch');
|
||||
if (!hasTorch)
|
||||
{
|
||||
button.classList.add('disabled');
|
||||
document.querySelector('.camerabarcodescanner-modal .modal-footer').setAttribute('style', 'display:none !important;');
|
||||
}
|
||||
else
|
||||
{
|
||||
button.classList.remove('disabled');
|
||||
document.querySelector('.camerabarcodescanner-modal .modal-footer').setAttribute('style', 'flex;');
|
||||
}
|
||||
|
||||
// Reduce the height of the video, if it's higher than then the viewport
|
||||
if (!Grocy.Components.CameraBarcodeScanner.LiveVideoSizeAdjusted)
|
||||
{
|
||||
var bc = document.getElementById('barcodescanner-container');
|
||||
var bc = document.getElementById('camerabarcodescanner-container');
|
||||
if (bc)
|
||||
{
|
||||
var bcAspectRatio = bc.offsetWidth / bc.offsetHeight;
|
||||
var settings = track.getSettings();
|
||||
if (bcAspectRatio > settings.aspectRatio)
|
||||
{
|
||||
var v = document.querySelector('#barcodescanner-livestream video');
|
||||
var v = document.querySelector('#camerabarcodescanner-livestream video');
|
||||
if (v)
|
||||
{
|
||||
var c = document.querySelector('#barcodescanner-livestream canvas')
|
||||
var c = document.querySelector('#camerabarcodescanner-livestream canvas')
|
||||
var newWidth = v.clientWidth / bcAspectRatio * settings.aspectRatio + 'px';
|
||||
v.style.width = newWidth;
|
||||
c.style.width = newWidth;
|
||||
@@ -81,7 +80,7 @@ Grocy.Components.CameraBarcodeScanner.StartScanning = function()
|
||||
inputStream: {
|
||||
name: "Live",
|
||||
type: "LiveStream",
|
||||
target: document.querySelector("#barcodescanner-livestream"),
|
||||
target: document.querySelector("#camerabarcodescanner-livestream"),
|
||||
constraints: {
|
||||
facingMode: "environment",
|
||||
...(window.localStorage.getItem('cameraId') && { deviceId: window.localStorage.getItem('cameraId') }), // If preferred cameraId is set, request to use that specific camera
|
||||
@@ -234,7 +233,7 @@ Quagga.onProcessed(function(result)
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
$(document).on("click", "#camerabarcodescanner-start-button", async function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
var inputElement = $(e.currentTarget).prev();
|
||||
@@ -248,12 +247,12 @@ $(document).on("click", "#barcodescanner-start-button", async function(e)
|
||||
Grocy.Components.CameraBarcodeScanner.CurrentTarget = inputElement.attr("data-target");
|
||||
|
||||
var dialog = bootbox.dialog({
|
||||
message: '<div id="barcodescanner-container" class="col"><div id="barcodescanner-livestream"></div></div>',
|
||||
message: '<div id="camerabarcodescanner-container" class="col"><div id="camerabarcodescanner-livestream"></div></div>',
|
||||
title: __t('Scan a barcode'),
|
||||
size: 'large',
|
||||
backdrop: true,
|
||||
closeButton: true,
|
||||
className: "form",
|
||||
className: "form camerabarcodescanner-modal",
|
||||
buttons: {
|
||||
torch: {
|
||||
label: '<i class="fa-solid fa-lightbulb"></i>',
|
||||
@@ -296,11 +295,11 @@ Grocy.Components.CameraBarcodeScanner.Init = function()
|
||||
{
|
||||
if ($(this).hasAttr("disabled"))
|
||||
{
|
||||
$(this).after('<a id="barcodescanner-start-button" class="btn btn-sm btn-primary text-white disabled" data-target="' + $(this).attr("data-target") + '"><i class="fa-solid fa-camera"></i></a>');
|
||||
$(this).after('<a id="camerabarcodescanner-start-button" class="btn btn-sm btn-primary text-white disabled" data-target="' + $(this).attr("data-target") + '"><i class="fa-solid fa-camera"></i></a>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$(this).after('<a id="barcodescanner-start-button" class="btn btn-sm btn-primary text-white" data-target="' + $(this).attr("data-target") + '"><i class="fa-solid fa-camera"></i></a>');
|
||||
$(this).after('<a id="camerabarcodescanner-start-button" class="btn btn-sm btn-primary text-white" data-target="' + $(this).attr("data-target") + '"><i class="fa-solid fa-camera"></i></a>');
|
||||
}
|
||||
|
||||
Grocy.Components.CameraBarcodeScanner.InitDone = true;
|
||||
|
@@ -136,7 +136,10 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
||||
$("#productcard-no-price-data-hint").addClass("d-none");
|
||||
|
||||
Grocy.Components.ProductCard.ReInitPriceHistoryChart();
|
||||
|
||||
var datasets = {};
|
||||
datasets["_TrendlineDataset"] = []
|
||||
|
||||
var chart = Grocy.Components.ProductCard.PriceHistoryChart.data;
|
||||
priceHistoryDataPoints.forEach((dataPoint) =>
|
||||
{
|
||||
@@ -150,18 +153,41 @@ Grocy.Components.ProductCard.Refresh = function(productId)
|
||||
{
|
||||
datasets[key] = []
|
||||
}
|
||||
|
||||
chart.labels.push(moment(dataPoint.date).toDate());
|
||||
datasets[key].push({ x: moment(dataPoint.date).toDate(), y: dataPoint.price * productDetails.qu_conversion_factor_price_to_stock });
|
||||
|
||||
datasets["_TrendlineDataset"].push({ x: moment(dataPoint.date).toDate(), y: dataPoint.price * productDetails.qu_conversion_factor_price_to_stock });
|
||||
});
|
||||
|
||||
Object.keys(datasets).forEach((key) =>
|
||||
{
|
||||
chart.datasets.push({
|
||||
data: datasets[key],
|
||||
fill: false,
|
||||
borderColor: "HSL(" + (129 * chart.datasets.length) + ",100%,50%)",
|
||||
label: key,
|
||||
});
|
||||
if (key != "_TrendlineDataset")
|
||||
{
|
||||
chart.datasets.push({
|
||||
data: datasets[key],
|
||||
fill: false,
|
||||
borderColor: "HSL(" + (129 * chart.datasets.length) + ",100%,50%)",
|
||||
label: key
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
chart.datasets.push({
|
||||
data: datasets[key],
|
||||
fill: false,
|
||||
borderColor: "HSL(" + (129 * chart.datasets.length) + ",100%,50%)",
|
||||
label: key,
|
||||
hidden: true,
|
||||
alwaysShowTrendline: true,
|
||||
trendlineLinear: {
|
||||
colorMin: "rgba(0, 0, 0, 0.3)",
|
||||
colorMax: "rgba(0, 0, 0, 0.3)",
|
||||
lineStyle: "dotted",
|
||||
width: 3
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Grocy.Components.ProductCard.PriceHistoryChart.update();
|
||||
@@ -234,7 +260,13 @@ Grocy.Components.ProductCard.ReInitPriceHistoryChart = function()
|
||||
}]
|
||||
},
|
||||
legend: {
|
||||
display: true
|
||||
display: true,
|
||||
labels: {
|
||||
filter: function(item, chart)
|
||||
{
|
||||
return item.text != "_TrendlineDataset";
|
||||
}
|
||||
}
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
|
@@ -76,15 +76,15 @@ Grocy.Components.ProductPicker.HideCustomError = function()
|
||||
Grocy.Components.ProductPicker.Disable = function()
|
||||
{
|
||||
Grocy.Components.ProductPicker.GetInputElement().attr("disabled", "");
|
||||
$("#barcodescanner-start-button").attr("disabled", "");
|
||||
$("#barcodescanner-start-button").addClass("disabled");
|
||||
$("#camerabarcodescanner-start-button").attr("disabled", "");
|
||||
$("#camerabarcodescanner-start-button").addClass("disabled");
|
||||
}
|
||||
|
||||
Grocy.Components.ProductPicker.Enable = function()
|
||||
{
|
||||
Grocy.Components.ProductPicker.GetInputElement().removeAttr("disabled");
|
||||
$("#barcodescanner-start-button").removeAttr("disabled");
|
||||
$("#barcodescanner-start-button").removeClass("disabled");
|
||||
$("#camerabarcodescanner-start-button").removeAttr("disabled");
|
||||
$("#camerabarcodescanner-start-button").removeClass("disabled");
|
||||
}
|
||||
|
||||
$('.product-combobox').combobox({
|
||||
@@ -295,7 +295,7 @@ $('#product_id_text_input').on('blur', function(e)
|
||||
{
|
||||
Grocy.Components.ProductPicker.PopupOpen = false;
|
||||
Grocy.Components.ProductPicker.SetValue('');
|
||||
$("#barcodescanner-start-button").click();
|
||||
$("#camerabarcodescanner-start-button").click();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -182,11 +182,19 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
|
||||
if (userfield.type == "datetime" && userfield.default_value == "now")
|
||||
{
|
||||
input.val(moment().format("YYYY-MM-DD HH:mm:ss"))
|
||||
input.val(moment().format("YYYY-MM-DD HH:mm:ss"));
|
||||
}
|
||||
else if (userfield.type == "date" && userfield.default_value == "now")
|
||||
{
|
||||
input.val(moment().format("YYYY-MM-DD"))
|
||||
input.val(moment().format("YYYY-MM-DD"));
|
||||
}
|
||||
else if (userfield.type == "checkbox" && userfield.input_required == 1)
|
||||
{
|
||||
input.prop("indeterminate", true);
|
||||
input.on("change", function()
|
||||
{
|
||||
input.removeAttr("required");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -212,6 +220,12 @@ Grocy.Components.UserfieldsForm.Load = function()
|
||||
{
|
||||
var input = $(".userfield-input[data-userfield-name='" + key + "']");
|
||||
|
||||
if (input.attr("type") == "checkbox")
|
||||
{
|
||||
// The required attribute for checkboxes is only relevant when creating objects
|
||||
input.removeAttr("required");
|
||||
}
|
||||
|
||||
if (input.attr("type") == "checkbox" && value == 1)
|
||||
{
|
||||
input.prop("checked", true);
|
||||
|
@@ -287,7 +287,7 @@ function OnLocationChange(locationId, stockId)
|
||||
var openTxt = __t("Not opened");
|
||||
if (stockEntry.open == 1)
|
||||
{
|
||||
openTxt = __t("Opened");
|
||||
openTxt = __n(stockEntry.amount, "Opened", "Opened");
|
||||
}
|
||||
|
||||
if (stockEntry.location_id == locationId)
|
||||
@@ -672,7 +672,6 @@ $(document).on("change", "#scan-mode", function(e)
|
||||
|
||||
$("#scan-mode-button").on("click", function(e)
|
||||
{
|
||||
document.activeElement.blur();
|
||||
$("#scan-mode").click();
|
||||
$("#scan-mode-button").toggleClass("btn-success").toggleClass("btn-danger");
|
||||
if ($("#scan-mode").prop("checked"))
|
||||
|
@@ -267,7 +267,6 @@ setTimeout(function()
|
||||
$(document).on('click', '.product-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var productId = $(e.currentTarget).attr('data-product-id');
|
||||
Grocy.Api.Get('stock/products/' + productId + '/printlabel', function(labelData)
|
||||
|
@@ -689,7 +689,6 @@ $("#scan-mode").on("change", function(e)
|
||||
|
||||
$("#scan-mode-button").on("click", function(e)
|
||||
{
|
||||
document.activeElement.blur();
|
||||
$("#scan-mode").click();
|
||||
$("#scan-mode-button").toggleClass("btn-success").toggleClass("btn-danger");
|
||||
if ($("#scan-mode").prop("checked"))
|
||||
|
@@ -379,7 +379,6 @@ $(window).on("message", function(e)
|
||||
$(document).on('click', '.recipe-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var recipeId = $(e.currentTarget).attr('data-recipe-id');
|
||||
Grocy.Api.Get('recipes/' + recipeId + '/printlabel', function(labelData)
|
||||
|
@@ -429,7 +429,6 @@ if (window.location.hash === "#fullscreen")
|
||||
$(document).on('click', '.recipe-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var recipeId = $(e.currentTarget).attr('data-recipe-id');
|
||||
Grocy.Api.Get('recipes/' + recipeId + '/printlabel', function(labelData)
|
||||
|
@@ -559,7 +559,6 @@ $("#description").on("summernote.change", function()
|
||||
$(document).on("click", "#save-description-button", function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
Grocy.Api.Put('objects/shopping_lists/' + $("#selected-shopping-list").val(), { description: $("#description").val() },
|
||||
function(result)
|
||||
@@ -576,7 +575,6 @@ $(document).on("click", "#save-description-button", function(e)
|
||||
$(document).on("click", "#clear-description-button", function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
$("#description").summernote("reset");
|
||||
$("#save-description-button").click();
|
||||
|
@@ -161,7 +161,6 @@ $(document).on('click', '.product-open-button', function(e)
|
||||
$(document).on('click', '.stockentry-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var stockId = $(e.currentTarget).attr('data-stock-id');
|
||||
Grocy.Api.Get('stock/entry/' + stockId + '/printlabel', function(labelData)
|
||||
@@ -288,7 +287,7 @@ function RefreshStockEntryRow(stockRowId)
|
||||
|
||||
if (result.open == 1)
|
||||
{
|
||||
$('#stock-' + stockRowId + '-opened-amount').text(__t('Opened'));
|
||||
$('#stock-' + stockRowId + '-opened-amount').text(__n(result.amount, 'Opened', 'Opened'));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -137,7 +137,6 @@ $(document).on('click', '.undo-stock-booking-button', function(e)
|
||||
$(document).on('click', '.product-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var productId = $(e.currentTarget).attr('data-product-id');
|
||||
Grocy.Api.Get('stock/products/' + productId + '/printlabel', function(labelData)
|
||||
|
@@ -113,7 +113,6 @@ $("#search").on("keyup", Delay(function()
|
||||
$(document).on('click', '.product-grocycode-label-print', function(e)
|
||||
{
|
||||
e.preventDefault();
|
||||
document.activeElement.blur();
|
||||
|
||||
var productId = $(e.currentTarget).attr('data-product-id');
|
||||
Grocy.Api.Get('stock/products/' + productId + '/printlabel', function(labelData)
|
||||
|
@@ -340,7 +340,7 @@ $("#location_id_from").on('change', function(e)
|
||||
var openTxt = __t("Not opened");
|
||||
if (stockEntry.open == 1)
|
||||
{
|
||||
openTxt = __t("Opened");
|
||||
openTxt = __n(stockEntry.amount, "Opened", "Opened");
|
||||
}
|
||||
|
||||
if (stockEntry.location_id == locationId)
|
||||
|
Reference in New Issue
Block a user