From c4b0ef4d49903b2ea763efed5744be67586fab64 Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Tue, 7 Aug 2018 20:11:08 +0200 Subject: [PATCH] Refresh the complete row on all overview pages on changes, including the background color (closes #39) --- grocy.openapi.json | 16 +++++++ public/viewjs/batteriesoverview.js | 54 ++++++++++++++++++---- public/viewjs/habitsoverview.js | 54 ++++++++++++++++++---- public/viewjs/stockoverview.js | 73 ++++++++++++++++++++++-------- services/BatteriesService.php | 4 +- services/HabitsService.php | 4 +- services/StockService.php | 4 +- views/batteriesoverview.blade.php | 6 +-- views/habitsoverview.blade.php | 6 +-- views/stockoverview.blade.php | 4 +- 10 files changed, 176 insertions(+), 49 deletions(-) diff --git a/grocy.openapi.json b/grocy.openapi.json index 3524e85f..63c7f28d 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -1410,6 +1410,14 @@ }, "stock_amount": { "type": "integer" + }, + "next_best_before_date": { + "type": "string", + "format": "date-time" + }, + "last_price": { + "type": "number", + "format": "double" } } }, @@ -1472,6 +1480,10 @@ }, "last_done_by": { "$ref": "#/components/schemas/UserDto" + }, + "next_estimated_execution_time": { + "type": "string", + "format": "date-time" } } }, @@ -1489,6 +1501,10 @@ "charge_cycles_count": { "type": "integer", "description": "How often this battery was charged so far" + }, + "next_estimated_charge_time": { + "type": "string", + "format": "date-time" } } }, diff --git a/public/viewjs/batteriesoverview.js b/public/viewjs/batteriesoverview.js index 814e7436..b06a6de9 100644 --- a/public/viewjs/batteriesoverview.js +++ b/public/viewjs/batteriesoverview.js @@ -28,17 +28,53 @@ $(document).on('click', '.track-charge-cycle-button', function(e) var trackedTime = moment().format('YYYY-MM-DD HH:mm:ss'); Grocy.Api.Get('batteries/track-charge-cycle/' + batteryId + '?tracked_time=' + trackedTime, - function(result) + function() { - $('#battery-' + batteryId + '-last-tracked-time').parent().effect('highlight', {}, 500); - $('#battery-' + batteryId + '-last-tracked-time').fadeOut(500, function () { - $(this).text(trackedTime).fadeIn(500); - }); - $('#battery-' + batteryId + '-last-tracked-time-timeago').attr('datetime', trackedTime); - RefreshContextualTimeago(); + Grocy.Api.Get('batteries/get-battery-details/' + batteryId, + function(result) + { + var batteryRow = $('#battery-' + batteryId + '-row'); + var nextXDaysThreshold = moment().add($("#info-due-batteries").data("next-x-days"), "days"); + var now = moment(); + var nextExecutionTime = moment(result.next_estimated_charge_time); - toastr.success(L('Tracked charge cylce of battery #1 on #2', batteryName, trackedTime)); - RefreshStatistics(); + batteryRow.removeClass("table-warning"); + batteryRow.removeClass("table-danger"); + if (nextExecutionTime.isBefore(now)) + { + batteryRow.addClass("table-danger"); + } + else if (nextExecutionTime.isBefore(nextXDaysThreshold)) + { + batteryRow.addClass("table-warning"); + } + + $('#battery-' + batteryId + '-last-tracked-time').parent().effect('highlight', { }, 500); + $('#battery-' + batteryId + '-last-tracked-time').fadeOut(500, function() + { + $(this).text(trackedTime).fadeIn(500); + }); + $('#battery-' + batteryId + '-last-tracked-time-timeago').attr('datetime', trackedTime); + + if (result.battery.charge_interval_days != 0) + { + $('#battery-' + batteryId + '-next-charge-time').parent().effect('highlight', { }, 500); + $('#battery-' + batteryId + '-next-charge-time').fadeOut(500, function() + { + $(this).text(result.next_estimated_charge_time).fadeIn(500); + }); + $('#battery-' + batteryId + '-next-charge-time-timeago').attr('datetime', result.next_estimated_charge_time); + } + + toastr.success(L('Tracked charge cylce of battery #1 on #2', batteryName, trackedTime)); + RefreshContextualTimeago(); + RefreshStatistics(); + }, + function(xhr) + { + console.error(xhr); + } + ); }, function(xhr) { diff --git a/public/viewjs/habitsoverview.js b/public/viewjs/habitsoverview.js index 1f140fcf..750ce965 100644 --- a/public/viewjs/habitsoverview.js +++ b/public/viewjs/habitsoverview.js @@ -28,17 +28,53 @@ $(document).on('click', '.track-habit-button', function(e) var trackedTime = moment().format('YYYY-MM-DD HH:mm:ss'); Grocy.Api.Get('habits/track-habit-execution/' + habitId + '?tracked_time=' + trackedTime, - function(result) + function() { - $('#habit-' + habitId + '-last-tracked-time').parent().effect('highlight', {}, 500); - $('#habit-' + habitId + '-last-tracked-time').fadeOut(500, function () { - $(this).text(trackedTime).fadeIn(500); - }); - $('#habit-' + habitId + '-last-tracked-time-timeago').attr('datetime', trackedTime); - RefreshContextualTimeago(); + Grocy.Api.Get('habits/get-habit-details/' + habitId, + function(result) + { + var habitRow = $('#habit-' + habitId + '-row'); + var nextXDaysThreshold = moment().add($("#info-due-habits").data("next-x-days"), "days"); + var now = moment(); + var nextExecutionTime = moment(result.next_estimated_execution_time); - toastr.success(L('Tracked execution of habit #1 on #2', habitName, trackedTime)); - RefreshStatistics(); + habitRow.removeClass("table-warning"); + habitRow.removeClass("table-danger"); + if (nextExecutionTime.isBefore(now)) + { + habitRow.addClass("table-danger"); + } + else if (nextExecutionTime.isBefore(nextXDaysThreshold)) + { + habitRow.addClass("table-warning"); + } + + $('#habit-' + habitId + '-last-tracked-time').parent().effect('highlight', { }, 500); + $('#habit-' + habitId + '-last-tracked-time').fadeOut(500, function() + { + $(this).text(trackedTime).fadeIn(500); + }); + $('#habit-' + habitId + '-last-tracked-time-timeago').attr('datetime', trackedTime); + + if (result.habit.period_type == "dynamic-regular") + { + $('#habit-' + habitId + '-next-execution-time').parent().effect('highlight', { }, 500); + $('#habit-' + habitId + '-next-execution-time').fadeOut(500, function() + { + $(this).text(result.next_estimated_execution_time).fadeIn(500); + }); + $('#habit-' + habitId + '-next-execution-time-timeago').attr('datetime', result.next_estimated_execution_time); + } + + toastr.success(L('Tracked execution of habit #1 on #2', habitName, trackedTime)); + RefreshContextualTimeago(); + RefreshStatistics(); + }, + function(xhr) + { + console.error(xhr); + } + ); }, function(xhr) { diff --git a/public/viewjs/stockoverview.js b/public/viewjs/stockoverview.js index 48a23fb2..4dfe21d0 100644 --- a/public/viewjs/stockoverview.js +++ b/public/viewjs/stockoverview.js @@ -41,29 +41,62 @@ $(document).on('click', '.product-consume-button', function(e) var consumeAmount = $(e.currentTarget).attr('data-consume-amount'); Grocy.Api.Get('stock/consume-product/' + productId + '/' + consumeAmount, - function(result) + function() { - var oldAmount = parseInt($('#product-' + productId + '-amount').text()); - var newAmount = oldAmount - consumeAmount; - if (newAmount === 0) - { - $('#product-' + productId + '-row').fadeOut(500, function() + Grocy.Api.Get('stock/get-product-details/' + productId, + function(result) { - $(this).remove(); - }); - } - else - { - $('#product-' + productId + '-amount').parent().effect('highlight', { }, 500); - $('#product-' + productId + '-amount').fadeOut(500, function() - { - $(this).text(newAmount).fadeIn(500); - }); - $('#product-' + productId + '-consume-all-button').attr('data-consume-amount', newAmount); - } + var productRow = $('#product-' + productId + '-row'); + var expiringThreshold = moment().add("-" + $("#info-expiring-products").data("next-x-days"), "days"); + var now = moment(); + var nextBestBeforeDate = moment(result.next_best_before_date); - toastr.success(L('Removed #1 #2 of #3 from stock', consumeAmount, productQuName, productName)); - RefreshStatistics(); + productRow.removeClass("table-warning"); + productRow.removeClass("table-danger"); + if (now.isAfter(nextBestBeforeDate)) + { + productRow.addClass("table-danger"); + } + if (expiringThreshold.isAfter(nextBestBeforeDate)) + { + productRow.addClass("table-warning"); + } + + var oldAmount = parseInt($('#product-' + productId + '-amount').text()); + var newAmount = oldAmount - consumeAmount; + if (newAmount === 0) + { + $('#product-' + productId + '-row').fadeOut(500, function() + { + $(this).remove(); + }); + } + else + { + $('#product-' + productId + '-amount').parent().effect('highlight', { }, 500); + $('#product-' + productId + '-amount').fadeOut(500, function() + { + $(this).text(newAmount).fadeIn(500); + }); + $('#product-' + productId + '-consume-all-button').attr('data-consume-amount', newAmount); + + $('#product-' + productId + '-next-best-before-date').parent().effect('highlight', { }, 500); + $('#product-' + productId + '-next-best-before-date').fadeOut(500, function() + { + $(this).text(result.next_best_before_date).fadeIn(500); + }); + $('#product-' + productId + '-next-best-before-date-timeago').attr('datetime', result.next_best_before_date); + } + + toastr.success(L('Removed #1 #2 of #3 from stock', consumeAmount, productQuName, productName)); + RefreshContextualTimeago(); + RefreshStatistics(); + }, + function(xhr) + { + console.error(xhr); + } + ); }, function(xhr) { diff --git a/services/BatteriesService.php b/services/BatteriesService.php index 8d3ec8fa..5075b8e5 100644 --- a/services/BatteriesService.php +++ b/services/BatteriesService.php @@ -20,11 +20,13 @@ class BatteriesService extends BaseService $battery = $this->Database->batteries($batteryId); $batteryChargeCylcesCount = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->count(); $batteryLastChargedTime = $this->Database->battery_charge_cycles()->where('battery_id', $batteryId)->max('tracked_time'); + $nextChargeTime = $this->Database->batteries_current()->where('battery_id', $batteryId)->min('next_estimated_charge_time'); return array( 'battery' => $battery, 'last_charged' => $batteryLastChargedTime, - 'charge_cycles_count' => $batteryChargeCylcesCount + 'charge_cycles_count' => $batteryChargeCylcesCount, + 'next_estimated_charge_time' => $nextChargeTime ); } diff --git a/services/HabitsService.php b/services/HabitsService.php index b2b4d7e4..e3fafb09 100644 --- a/services/HabitsService.php +++ b/services/HabitsService.php @@ -23,6 +23,7 @@ class HabitsService extends BaseService $habit = $this->Database->habits($habitId); $habitTrackedCount = $this->Database->habits_log()->where('habit_id', $habitId)->count(); $habitLastTrackedTime = $this->Database->habits_log()->where('habit_id', $habitId)->max('tracked_time'); + $nextExeuctionTime = $this->Database->habits_current()->where('habit_id', $habitId)->min('next_estimated_execution_time'); $lastHabitLogRow = $this->Database->habits_log()->where('habit_id = :1 AND tracked_time = :2', $habitId, $habitLastTrackedTime)->fetch(); $lastDoneByUser = null; @@ -37,7 +38,8 @@ class HabitsService extends BaseService 'habit' => $habit, 'last_tracked' => $habitLastTrackedTime, 'tracked_count' => $habitTrackedCount, - 'last_done_by' => $lastDoneByUser + 'last_done_by' => $lastDoneByUser, + 'next_estimated_execution_time' => $nextExeuctionTime ); } diff --git a/services/StockService.php b/services/StockService.php index d79b7a34..c6f81c90 100644 --- a/services/StockService.php +++ b/services/StockService.php @@ -37,6 +37,7 @@ class StockService extends BaseService $productStockAmount = $this->Database->stock()->where('product_id', $productId)->sum('amount'); $productLastPurchased = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_PURCHASE)->max('purchased_date'); $productLastUsed = $this->Database->stock_log()->where('product_id', $productId)->where('transaction_type', self::TRANSACTION_TYPE_CONSUME)->max('used_date'); + $nextBestBeforeDate = $this->Database->stock()->where('product_id', $productId)->min('best_before_date'); $quPurchase = $this->Database->quantity_units($product->qu_id_purchase); $quStock = $this->Database->quantity_units($product->qu_id_stock); @@ -54,7 +55,8 @@ class StockService extends BaseService 'stock_amount' => $productStockAmount, 'quantity_unit_purchase' => $quPurchase, 'quantity_unit_stock' => $quStock, - 'last_price' => $lastPrice + 'last_price' => $lastPrice, + 'next_best_before_date' => $nextBestBeforeDate ); } diff --git a/views/batteriesoverview.blade.php b/views/batteriesoverview.blade.php index b8cf29a7..d9668951 100644 --- a/views/batteriesoverview.blade.php +++ b/views/batteriesoverview.blade.php @@ -37,7 +37,7 @@ @foreach($current as $curentBatteryEntry) - + @if(FindObjectInArrayByPropertyValue($batteries, 'id', $curentBatteryEntry->battery_id)->charge_interval_days > 0) - {{ $curentBatteryEntry->next_estimated_charge_time }} - + {{ $curentBatteryEntry->next_estimated_charge_time }} + @else ... @endif diff --git a/views/habitsoverview.blade.php b/views/habitsoverview.blade.php index 6cd23abc..6585cab0 100644 --- a/views/habitsoverview.blade.php +++ b/views/habitsoverview.blade.php @@ -37,7 +37,7 @@ @foreach($currentHabits as $curentHabitEntry) - + @if(FindObjectInArrayByPropertyValue($habits, 'id', $curentHabitEntry->habit_id)->period_type === \Grocy\Services\HabitsService::HABIT_TYPE_DYNAMIC_REGULAR) - {{ $curentHabitEntry->next_estimated_execution_time }} - + {{ $curentHabitEntry->next_estimated_execution_time }} + @else ... @endif diff --git a/views/stockoverview.blade.php b/views/stockoverview.blade.php index 2996cbcf..f682d9f4 100644 --- a/views/stockoverview.blade.php +++ b/views/stockoverview.blade.php @@ -72,8 +72,8 @@ {{ $currentStockEntry->amount }} {{ Pluralize($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) }} - {{ $currentStockEntry->best_before_date }} - + {{ $currentStockEntry->best_before_date }} + {{ FindObjectInArrayByPropertyValue($locations, 'id', FindObjectInArrayByPropertyValue($products, 'id', $currentStockEntry->product_id)->location_id)->name }}