Highlight chores/tasks/batteries due today in a separate color + status filter (closes #1740)

This commit is contained in:
Bernd Bestel 2022-01-23 17:29:25 +01:00
parent dfd6262f4a
commit aef646e9df
No known key found for this signature in database
GPG Key ID: 71BD34C0D4891300
13 changed files with 198 additions and 123 deletions

View File

@ -1,4 +1,5 @@
- Stock entry labels get now also printed on inventory (only when adding products, same option "Stock entry label" like on the purchase page) - Stock entry labels get now also printed on inventory (only when adding products, same option "Stock entry label" like on the purchase page)
- Added a separate status filter and table row highlighting (blue) on the chores, tasks and batteries overview pages for items due today
- Optimized relative time display (also fixed a phrasing problem for some languages, e.g. Hungarian) (thanks @Tallyrald) - Optimized relative time display (also fixed a phrasing problem for some languages, e.g. Hungarian) (thanks @Tallyrald)
- When using LDAP authentication, the configured `LDAP_UID_ATTR` is now used to compare if the user already exists instead of the username entered on the login page (that prevents creating multiple users if you entere the username in different notations) (thanks @FloSet) - When using LDAP authentication, the configured `LDAP_UID_ATTR` is now used to compare if the user already exists instead of the username entered on the login page (that prevents creating multiple users if you entere the username in different notations) (thanks @FloSet)
- When using reverse proxy authentication (`ReverseProxyAuthMiddleware`), it's now also possible to pass the username in an environment variable instead of an HTTP header (new `config.php` option `REVERSE_PROXY_AUTH_USE_ENV`) (thanks @Forceu) - When using reverse proxy authentication (`ReverseProxyAuthMiddleware`), it's now also possible to pass the username in an environment variable instead of an HTTP header (new `config.php` option `REVERSE_PROXY_AUTH_USE_ENV`) (thanks @Forceu)

View File

@ -80,9 +80,30 @@ class BatteriesController extends BaseController
$usersService = $this->getUsersService(); $usersService = $this->getUsersService();
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['batteries_due_soon_days']; $nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['batteries_due_soon_days'];
$batteries = $this->getDatabase()->batteries()->where('active = 1')->orderBy('name', 'COLLATE NOCASE');
$currentBatteries = $this->getBatteriesService()->GetCurrent();
foreach ($currentBatteries as $currentBattery)
{
if (FindObjectInArrayByPropertyValue($batteries, 'id', $currentBattery->battery_id)->charge_interval_days > 0)
{
if ($currentBattery->next_estimated_charge_time < date('Y-m-d H:i:s'))
{
$currentBattery->due_type = 'overdue';
}
elseif ($currentBattery->next_estimated_charge_time <= date('Y-m-d 23:59:59'))
{
$currentBattery->due_type = 'duetoday';
}
elseif ($currentBattery->next_estimated_charge_time <= date('Y-m-d H:i:s', strtotime('+' . $nextXDays . ' days')))
{
$currentBattery->due_type = 'duesoon';
}
}
}
return $this->renderPage($response, 'batteriesoverview', [ return $this->renderPage($response, 'batteriesoverview', [
'batteries' => $this->getDatabase()->batteries()->where('active = 1')->orderBy('name', 'COLLATE NOCASE'), 'batteries' => $batteries,
'current' => $this->getBatteriesService()->GetCurrent(), 'current' => $currentBatteries,
'nextXDays' => $nextXDays, 'nextXDays' => $nextXDays,
'userfields' => $this->getUserfieldsService()->GetFields('batteries'), 'userfields' => $this->getUserfieldsService()->GetFields('batteries'),
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('batteries') 'userfieldValues' => $this->getUserfieldsService()->GetAllValues('batteries')

View File

@ -94,9 +94,30 @@ class ChoresController extends BaseController
$usersService = $this->getUsersService(); $usersService = $this->getUsersService();
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['chores_due_soon_days']; $nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['chores_due_soon_days'];
$chores = $this->getDatabase()->chores()->orderBy('name', 'COLLATE NOCASE');
$currentChores = $this->getChoresService()->GetCurrent();
foreach ($currentChores as $currentChore)
{
if (FindObjectInArrayByPropertyValue($chores, 'id', $currentChore->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY)
{
if ($currentChore->next_estimated_execution_time < date('Y-m-d H:i:s'))
{
$currentChore->due_type = 'overdue';
}
elseif ($currentChore->next_estimated_execution_time <= date('Y-m-d 23:59:59'))
{
$currentChore->due_type = 'duetoday';
}
elseif ($currentChore->next_estimated_execution_time <= date('Y-m-d H:i:s', strtotime('+' . $nextXDays . ' days')))
{
$currentChore->due_type = 'duesoon';
}
}
}
return $this->renderPage($response, 'choresoverview', [ return $this->renderPage($response, 'choresoverview', [
'chores' => $this->getDatabase()->chores()->orderBy('name', 'COLLATE NOCASE'), 'chores' => $chores,
'currentChores' => $this->getChoresService()->GetCurrent(), 'currentChores' => $currentChores,
'nextXDays' => $nextXDays, 'nextXDays' => $nextXDays,
'userfields' => $this->getUserfieldsService()->GetFields('chores'), 'userfields' => $this->getUserfieldsService()->GetFields('chores'),
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('chores'), 'userfieldValues' => $this->getUserfieldsService()->GetAllValues('chores'),

View File

@ -6,6 +6,9 @@ class TasksController extends BaseController
{ {
public function Overview(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args) public function Overview(\Psr\Http\Message\ServerRequestInterface $request, \Psr\Http\Message\ResponseInterface $response, array $args)
{ {
$usersService = $this->getUsersService();
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['tasks_due_soon_days'];
if (isset($request->getQueryParams()['include_done'])) if (isset($request->getQueryParams()['include_done']))
{ {
$tasks = $this->getDatabase()->tasks()->orderBy('name', 'COLLATE NOCASE'); $tasks = $this->getDatabase()->tasks()->orderBy('name', 'COLLATE NOCASE');
@ -15,8 +18,21 @@ class TasksController extends BaseController
$tasks = $this->getTasksService()->GetCurrent(); $tasks = $this->getTasksService()->GetCurrent();
} }
$usersService = $this->getUsersService(); foreach ($tasks as $task)
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['tasks_due_soon_days']; {
if ($task->due_date < date('Y-m-d 23:59:59', strtotime('-1 days')))
{
$task->due_type = 'overdue';
}
elseif ($task->due_date <= date('Y-m-d 23:59:59'))
{
$task->due_type = 'duetoday';
}
elseif ($task->due_date <= date('Y-m-d 23:59:59', strtotime('+' . $nextXDays . ' days')))
{
$task->due_type = 'duesoon';
}
}
return $this->renderPage($response, 'tasks', [ return $this->renderPage($response, 'tasks', [
'tasks' => $tasks, 'tasks' => $tasks,

View File

@ -2259,3 +2259,15 @@ msgstr ""
msgid "After merging, all occurences of this chore will be replaced by the kept chore (means this chore will not exist anymore)" msgid "After merging, all occurences of this chore will be replaced by the kept chore (means this chore will not exist anymore)"
msgstr "" msgstr ""
msgid "Due today"
msgstr ""
msgid "%s chore is due to be done today"
msgstr ""
msgid "%s task is due to be done today"
msgstr ""
msgid "%s battery is due to be charged today"
msgstr ""

View File

@ -71,7 +71,7 @@ $(document).on('click', '.track-charge-cycle-button', function(e)
function(result) function(result)
{ {
var batteryRow = $('#battery-' + batteryId + '-row'); var batteryRow = $('#battery-' + batteryId + '-row');
var nextXDaysThreshold = moment().add($("#info-due-batteries").data("next-x-days"), "days"); var nextXDaysThreshold = moment().add($("#info-due-soon-batteries").data("next-x-days"), "days");
var now = moment(); var now = moment();
var nextExecutionTime = moment(result.next_estimated_charge_time); var nextExecutionTime = moment(result.next_estimated_charge_time);
@ -139,28 +139,38 @@ $(document).on('click', '.battery-grocycode-label-print', function(e)
function RefreshStatistics() function RefreshStatistics()
{ {
var nextXDays = $("#info-due-batteries").data("next-x-days"); var nextXDays = $("#info-due-soon-batteries").data("next-x-days");
Grocy.Api.Get('batteries', Grocy.Api.Get('batteries',
function(result) function(result)
{ {
var dueCount = 0; var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0; var overdueCount = 0;
var now = moment(); var overdueThreshold = moment();
var nextXDaysThreshold = moment().add(nextXDays, "days"); var nextXDaysThreshold = moment().add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element => result.forEach(element =>
{ {
var date = moment(element.next_estimated_charge_time); var date = moment(element.next_estimated_charge_time);
if (date.isBefore(now))
if (date.isBefore(overdueThreshold))
{ {
overdueCount++; overdueCount++;
} }
else if (date.isBefore(nextXDaysThreshold)) else if (date.isSameOrBefore(todayThreshold))
{ {
dueCount++; dueTodayCount++;
dueSoonCount++;
}
else if (date.isSameOrBefore(nextXDaysThreshold))
{
dueSoonCount++;
} }
}); });
$("#info-due-batteries").html('<span class="d-block d-md-none">' + dueCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueCount, '%s battery is due to be charged', '%s batteries are due to be charged') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days')); $("#info-due-today-batteries").html('<span class="d-block d-md-none">' + dueTodayCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueTodayCount, '%s battery is due to be charged today', '%s batteries are due to be charged today'));
$("#info-due-soon-batteries").html('<span class="d-block d-md-none">' + dueSoonCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueSoonCount, '%s battery is due to be charged', '%s batteries are due to be charged') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days'));
$("#info-overdue-batteries").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s battery is overdue to be charged', '%s batteries are overdue to be charged')); $("#info-overdue-batteries").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s battery is overdue to be charged', '%s batteries are overdue to be charged'));
}, },
function(xhr) function(xhr)

View File

@ -109,7 +109,7 @@ $(document).on('click', '.track-chore-button', function(e)
function(result) function(result)
{ {
var choreRow = $('#chore-' + choreId + '-row'); var choreRow = $('#chore-' + choreId + '-row');
var nextXDaysThreshold = moment().add($("#info-due-chores").data("next-x-days"), "days"); var nextXDaysThreshold = moment().add($("#info-due-soon-chores").data("next-x-days"), "days");
var now = moment(); var now = moment();
var nextExecutionTime = moment(result.next_estimated_execution_time); var nextExecutionTime = moment(result.next_estimated_execution_time);
@ -202,25 +202,34 @@ $(document).on('click', '.chore-grocycode-label-print', function(e)
function RefreshStatistics() function RefreshStatistics()
{ {
var nextXDays = $("#info-due-chores").data("next-x-days"); var nextXDays = $("#info-due-soon-chores").data("next-x-days");
Grocy.Api.Get('chores', Grocy.Api.Get('chores',
function(result) function(result)
{ {
var dueCount = 0; var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0; var overdueCount = 0;
var assignedToMeCount = 0; var assignedToMeCount = 0;
var now = moment(); var overdueThreshold = moment();
var nextXDaysThreshold = moment().add(nextXDays, "days"); var nextXDaysThreshold = moment().add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element => result.forEach(element =>
{ {
var date = moment(element.next_estimated_execution_time); var date = moment(element.next_estimated_execution_time);
if (date.isBefore(now))
if (date.isBefore(overdueThreshold))
{ {
overdueCount++; overdueCount++;
} }
else if (date.isBefore(nextXDaysThreshold)) else if (date.isSameOrBefore(todayThreshold))
{ {
dueCount++; dueTodayCount++;
dueSoonCount++;
}
else if (date.isSameOrBefore(nextXDaysThreshold))
{
dueSoonCount++;
} }
if (parseInt(element.next_execution_assigned_to_user_id) == Grocy.UserId) if (parseInt(element.next_execution_assigned_to_user_id) == Grocy.UserId)
@ -229,7 +238,8 @@ function RefreshStatistics()
} }
}); });
$("#info-due-chores").html('<span class="d-block d-md-none">' + dueCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueCount, '%s chore is due to be done', '%s chores are due to be done') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days')); $("#info-due-today-chores").html('<span class="d-block d-md-none">' + dueTodayCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueTodayCount, '%s chore is due to be done today', '%s chores are due to be done today'));
$("#info-due-soon-chores").html('<span class="d-block d-md-none">' + dueSoonCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueSoonCount, '%s chore is due to be done', '%s chores are due to be done') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days'));
$("#info-overdue-chores").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s chore is overdue to be done', '%s chores are overdue to be done')); $("#info-overdue-chores").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s chore is overdue to be done', '%s chores are overdue to be done'));
$("#info-assigned-to-me-chores").html('<span class="d-block d-md-none">' + assignedToMeCount + ' <i class="fas fa-exclamation-circle"></i></span><span class="d-none d-md-block">' + __n(assignedToMeCount, '%s chore is assigned to me', '%s chores are assigned to me')); $("#info-assigned-to-me-chores").html('<span class="d-block d-md-none">' + assignedToMeCount + ' <i class="fas fa-exclamation-circle"></i></span><span class="d-none d-md-block">' + __n(assignedToMeCount, '%s chore is assigned to me', '%s chores are assigned to me'));
}, },

View File

@ -183,28 +183,38 @@ if (GetUriParam('include_done'))
function RefreshStatistics() function RefreshStatistics()
{ {
var nextXDays = $("#info-due-tasks").data("next-x-days"); var nextXDays = $("#info-due-soon-tasks").data("next-x-days");
Grocy.Api.Get('tasks', Grocy.Api.Get('tasks',
function(result) function(result)
{ {
var dueCount = 0; var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0; var overdueCount = 0;
var now = moment(); var overdueThreshold = moment().subtract(1, "days").endOf("day");
var nextXDaysThreshold = moment().add(nextXDays, "days"); var nextXDaysThreshold = moment().endOf("day").add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element => result.forEach(element =>
{ {
var date = moment(element.due_date); var date = moment(element.due_date + " 23:59:59").endOf("day");
if (date.isBefore(now))
if (date.isSameOrBefore(overdueThreshold))
{ {
overdueCount++; overdueCount++;
} }
else if (date.isBefore(nextXDaysThreshold)) else if (date.isSameOrBefore(todayThreshold))
{ {
dueCount++; dueTodayCount++;
dueSoonCount++;
}
else if (date.isSameOrBefore(nextXDaysThreshold))
{
dueSoonCount++;
} }
}); });
$("#info-due-tasks").html('<span class="d-block d-md-none">' + dueCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueCount, '%s task is due to be done', '%s tasks are due to be done') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days')); $("#info-due-today-tasks").html('<span class="d-block d-md-none">' + dueTodayCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueTodayCount, '%s task is due to be done today', '%s tasks are due to be done today'));
$("#info-due-soon-tasks").html('<span class="d-block d-md-none">' + dueSoonCount + ' <i class="fas fa-clock"></i></span><span class="d-none d-md-block">' + __n(dueSoonCount, '%s task is due to be done', '%s tasks are due to be done') + ' ' + __n(nextXDays, 'within the next day', 'within the next %s days'));
$("#info-overdue-tasks").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s task is overdue to be done', '%s tasks are overdue to be done')); $("#info-overdue-tasks").html('<span class="d-block d-md-none">' + overdueCount + ' <i class="fas fa-times-circle"></i></span><span class="d-none d-md-block">' + __n(overdueCount, '%s task is overdue to be done', '%s tasks are overdue to be done'));
}, },
function(xhr) function(xhr)

View File

@ -169,7 +169,7 @@ class DemoDataGeneratorService extends BaseService
INSERT INTO chores (name, period_type) VALUES ('{$this->__t_sql('The thing which happens daily')}', 'daily'); --5 INSERT INTO chores (name, period_type) VALUES ('{$this->__t_sql('The thing which happens daily')}', 'daily'); --5
INSERT INTO chores (name, period_type, period_config) VALUES ('{$this->__t_sql('The thing which happens on Mondays and Wednesdays')}', 'weekly', 'monday,wednesday'); --6 INSERT INTO chores (name, period_type, period_config) VALUES ('{$this->__t_sql('The thing which happens on Mondays and Wednesdays')}', 'weekly', 'monday,wednesday'); --6
INSERT INTO batteries (name, description, used_in) VALUES ('{$this->__t_sql('Battery')}1', '{$this->__t_sql('Warranty ends')} 2023', '{$this->__t_sql('TV remote control')}'); --1 INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('{$this->__t_sql('Battery')}1', '{$this->__t_sql('Warranty ends')} 2023', '{$this->__t_sql('TV remote control')}', 180); --1
INSERT INTO batteries (name, description, used_in) VALUES ('{$this->__t_sql('Battery')}2', '{$this->__t_sql('Warranty ends')} 2022', '{$this->__t_sql('Alarm clock')}'); --2 INSERT INTO batteries (name, description, used_in) VALUES ('{$this->__t_sql('Battery')}2', '{$this->__t_sql('Warranty ends')} 2022', '{$this->__t_sql('Alarm clock')}'); --2
INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('{$this->__t_sql('Battery')}3', '{$this->__t_sql('Warranty ends')} 2022', '{$this->__t_sql('Heat remote control')}', 60); --3 INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('{$this->__t_sql('Battery')}3', '{$this->__t_sql('Warranty ends')} 2022', '{$this->__t_sql('Heat remote control')}', 60); --3
INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('{$this->__t_sql('Battery')}4', '{$this->__t_sql('Warranty ends')} 2028', '{$this->__t_sql('Heat remote control')}', 60); --4 INSERT INTO batteries (name, description, used_in, charge_interval_days) VALUES ('{$this->__t_sql('Battery')}4', '{$this->__t_sql('Warranty ends')} 2028', '{$this->__t_sql('Heat remote control')}', 60); --4
@ -178,7 +178,7 @@ class DemoDataGeneratorService extends BaseService
INSERT INTO task_categories (name) VALUES ('{$this->__t_sql('Life')}'); --2 INSERT INTO task_categories (name) VALUES ('{$this->__t_sql('Life')}'); --2
INSERT INTO task_categories (name) VALUES ('{$this->__t_sql('Projects')}'); --3 INSERT INTO task_categories (name) VALUES ('{$this->__t_sql('Projects')}'); --3
INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Repair the garage door')}', 1, date(datetime('now', 'localtime'), '+14 day'), 1); INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Repair the garage door')}', 1, date(datetime('now', 'localtime')), 1);
INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Fork and improve grocy')}', 3, date(datetime('now', 'localtime'), '+30 day'), 1); INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Fork and improve grocy')}', 3, date(datetime('now', 'localtime'), '+30 day'), 1);
INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Task')}1', 2, date(datetime('now', 'localtime'), '-1 day'), 1); INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Task')}1', 2, date(datetime('now', 'localtime'), '-1 day'), 1);
INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Task')}2', 2, date(datetime('now', 'localtime'), '-1 day'), 1); INSERT INTO tasks (name, category_id, due_date, assigned_to_user_id) VALUES ('{$this->__t_sql('Task')}2', 2, date(datetime('now', 'localtime'), '-1 day'), 1);
@ -293,18 +293,19 @@ class DemoDataGeneratorService extends BaseService
$choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-5 days'))); $choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-5 days')));
$choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-10 days'))); $choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-10 days')));
$choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-15 days'))); $choresService->TrackChore(1, date('Y-m-d H:i:s', strtotime('-15 days')));
$choresService->TrackChore(2, date('Y-m-d H:i:s', strtotime('-10 days'))); $choresService->TrackChore(2, date('Y-m-d 23:59:59', strtotime('-7 days')));
$choresService->TrackChore(2, date('Y-m-d H:i:s', strtotime('-20 days'))); $choresService->TrackChore(2, date('Y-m-d H:i:s', strtotime('-14 days')));
$choresService->TrackChore(2, date('Y-m-d H:i:s', strtotime('-21 days')));
$choresService->TrackChore(3, date('Y-m-d H:i:s', strtotime('-17 days'))); $choresService->TrackChore(3, date('Y-m-d H:i:s', strtotime('-17 days')));
$choresService->TrackChore(4, date('Y-m-d H:i:s', strtotime('-10 days'))); $choresService->TrackChore(4, date('Y-m-d H:i:s', strtotime('-10 days')));
$choresService->TrackChore(5, date('Y-m-d H:i:s', strtotime('+0 days'))); $choresService->TrackChore(5, date('Y-m-d H:i:s', strtotime('+0 days')));
$choresService->TrackChore(6, date('Y-m-d H:i:s', strtotime('-10 days'))); $choresService->TrackChore(6, date('Y-m-d H:i:s', strtotime('-10 days')));
$batteriesService = new BatteriesService(); $batteriesService = new BatteriesService();
$batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-200 days'))); $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-720 days')));
$batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-150 days'))); $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-540 days')));
$batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-100 days'))); $batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-360 days')));
$batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-50 days'))); $batteriesService->TrackChargeCycle(1, date('Y-m-d 23:59:59', strtotime('-180 days')));
$batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-200 days'))); $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-200 days')));
$batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-150 days'))); $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-150 days')));
$batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days'))); $batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days')));

View File

@ -29,13 +29,16 @@
</div> </div>
</div> </div>
<div class="border-top border-bottom my-2 py-1"> <div class="border-top border-bottom my-2 py-1">
<div id="info-due-batteries"
data-status-filter="duesoon"
data-next-x-days="{{ $nextXDays }}"
class="warning-message status-filter-message responsive-button mr-2"></div>
<div id="info-overdue-batteries" <div id="info-overdue-batteries"
data-status-filter="overdue" data-status-filter="overdue"
class="error-message status-filter-message responsive-button"></div> class="error-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-today-batteries"
data-status-filter="duetoday"
class="normal-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-soon-batteries"
data-status-filter="duesoon"
data-next-x-days="{{ $nextXDays }}"
class="warning-message status-filter-message responsive-button"></div>
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-1" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
@ -74,8 +77,9 @@
<select class="custom-control custom-select" <select class="custom-control custom-select"
id="status-filter"> id="status-filter">
<option value="all">{{ $__t('All') }}</option> <option value="all">{{ $__t('All') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
<option value="overdue">{{ $__t('Overdue') }}</option> <option value="overdue">{{ $__t('Overdue') }}</option>
<option value="duetoday">{{ $__t('Due today') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
</select> </select>
</div> </div>
</div> </div>
@ -109,9 +113,7 @@
<tbody class="d-none"> <tbody class="d-none">
@foreach($current as $currentBatteryEntry) @foreach($current as $currentBatteryEntry)
<tr id="battery-{{ $currentBatteryEntry->battery_id }}-row" <tr id="battery-{{ $currentBatteryEntry->battery_id }}-row"
class="@if(FindObjectInArrayByPropertyValue($batteries, 'id', $currentBatteryEntry->battery_id)->charge_interval_days > 0 && $currentBatteryEntry->next_estimated_charge_time < date('Y-m-d H:i:s')) table-danger @elseif(FindObjectInArrayByPropertyValue($batteries, 'id', $currentBatteryEntry->battery_id)->charge_interval_days > 0 && $currentBatteryEntry->next_estimated_charge_time < date('Y-m-d H:i:s', strtotime('+' . $nextXDays . ' days'))) class="@if($currentBatteryEntry->due_type == 'overdue') table-danger @elseif($currentBatteryEntry->due_type == 'duetoday') table-info @elseif($currentBatteryEntry->due_type == 'duesoon') table-warning @endif">
table-warning
@endif">
<td class="fit-content border-right"> <td class="fit-content border-right">
<a class="btn btn-success btn-sm track-charge-cycle-button permission-BATTERIES_TRACK_CHARGE_CYCLE" <a class="btn btn-success btn-sm track-charge-cycle-button permission-BATTERIES_TRACK_CHARGE_CYCLE"
href="#" href="#"
@ -186,25 +188,10 @@
@endif @endif
</td> </td>
<td class="d-none"> <td class="d-none">
"@if(FindObjectInArrayByPropertyValue($batteries, 'id', $currentBatteryEntry->battery_id)->charge_interval_days > 0 && $currentBatteryEntry->next_estimated_charge_time < date('Y-m-d {{ $currentBatteryEntry->due_type }}
H:i:s')) @if($currentBatteryEntry->due_type == 'duetoday')
overdue duesoon
@elseif(FindObjectInArrayByPropertyValue($batteries, 'id' @endif
,
$currentBatteryEntry->battery_id)->charge_interval_days > 0 && $currentBatteryEntry->next_estimated_charge_time < date('Y-m-d
H:i:s',
strtotime('+'
.
$nextXDays
. ' days'
)))
duesoon
@endif
</td>
@include('components.userfields_tbody',
array( 'userfields'=> $userfields,
'userfieldValues' => FindAllObjectsInArrayByPropertyValue($userfieldValues, 'object_id', $currentBatteryEntry->battery_id)
))
</tr> </tr>
@endforeach @endforeach

View File

@ -29,17 +29,20 @@
</div> </div>
</div> </div>
<div class="border-top border-bottom my-2 py-1"> <div class="border-top border-bottom my-2 py-1">
<div id="info-due-chores"
data-status-filter="duesoon"
data-next-x-days="{{ $nextXDays }}"
class="warning-message status-filter-message responsive-message mr-2"></div>
<div id="info-overdue-chores" <div id="info-overdue-chores"
data-status-filter="overdue" data-status-filter="overdue"
class="error-message status-filter-message responsive-button mr-2"></div> class="error-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-today-chores"
data-status-filter="duetoday"
class="normal-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-soon-chores"
data-status-filter="duesoon"
data-next-x-days="{{ $nextXDays }}"
class="warning-message status-filter-message responsive-message mr-2"></div>
@if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS) @if(GROCY_FEATURE_FLAG_CHORES_ASSIGNMENTS)
<div id="info-assigned-to-me-chores" <div id="info-assigned-to-me-chores"
data-user-filter="xx{{ GROCY_USER_ID }}xx" data-user-filter="xx{{ GROCY_USER_ID }}xx"
class="normal-message user-filter-message responsive-button"></div> class="secondary-message user-filter-message responsive-button"></div>
@endif @endif
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-1" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
@ -79,8 +82,9 @@
<select class="custom-control custom-select" <select class="custom-control custom-select"
id="status-filter"> id="status-filter">
<option value="all">{{ $__t('All') }}</option> <option value="all">{{ $__t('All') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
<option value="overdue">{{ $__t('Overdue') }}</option> <option value="overdue">{{ $__t('Overdue') }}</option>
<option value="duetoday">{{ $__t('Due today') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
</select> </select>
</div> </div>
</div> </div>
@ -132,9 +136,7 @@
<tbody class="d-none"> <tbody class="d-none">
@foreach($currentChores as $curentChoreEntry) @foreach($currentChores as $curentChoreEntry)
<tr id="chore-{{ $curentChoreEntry->chore_id }}-row" <tr id="chore-{{ $curentChoreEntry->chore_id }}-row"
class="@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s')) table-danger @elseif(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s', strtotime('+' . $nextXDays . ' days'))) class="@if($curentChoreEntry->due_type == 'overdue') table-danger @elseif($curentChoreEntry->due_type == 'duetoday') table-info @elseif($curentChoreEntry->due_type == 'duesoon') table-warning @endif">
table-warning
@endif">
<td class="fit-content border-right"> <td class="fit-content border-right">
<a class="btn btn-success btn-sm track-chore-button permission-CHORE_TRACK_EXECUTION" <a class="btn btn-success btn-sm track-chore-button permission-CHORE_TRACK_EXECUTION"
href="#" href="#"
@ -217,25 +219,14 @@
</td> </td>
<td id="chore-{{ $curentChoreEntry->chore_id }}-due-filter-column" <td id="chore-{{ $curentChoreEntry->chore_id }}-due-filter-column"
class="d-none"> class="d-none">
@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d {{ $curentChoreEntry->due_type }}
H:i:s')) @if($curentChoreEntry->due_type == 'duetoday')
overdue duesoon
@elseif(FindObjectInArrayByPropertyValue($chores, 'id' @endif
, </td>
$curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d <td class="d-none">
H:i:s', @if(!empty($curentChoreEntry->next_execution_assigned_to_user_id))
strtotime('+' xx{{ $curentChoreEntry->next_execution_assigned_to_user_id }}xx
.
$nextXDays
. ' days'
)))
duesoon
@endif
</td>
<td
class="d-none">
@if(!empty($curentChoreEntry->next_execution_assigned_to_user_id))
xx{{ $curentChoreEntry->next_execution_assigned_to_user_id }}xx
</td> </td>
@endif @endif

View File

@ -50,16 +50,16 @@
</div> </div>
<div class="border-top border-bottom my-2 py-1"> <div class="border-top border-bottom my-2 py-1">
@if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING) @if (GROCY_FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING)
<div id="info-expired-products"
data-status-filter="expired"
class="error-message status-filter-message responsive-button mr-2"></div>
<div id="info-overdue-products"
data-status-filter="overdue"
class="secondary-message status-filter-message responsive-button mr-2"></div>
<div id="info-duesoon-products" <div id="info-duesoon-products"
data-next-x-days="{{ $nextXDays }}" data-next-x-days="{{ $nextXDays }}"
data-status-filter="duesoon" data-status-filter="duesoon"
class="warning-message status-filter-message responsive-button mr-2"></div> class="warning-message status-filter-message responsive-button mr-2"></div>
<div id="info-overdue-products"
data-status-filter="overdue"
class="secondary-message status-filter-message responsive-button mr-2"></div>
<div id="info-expired-products"
data-status-filter="expired"
class="error-message status-filter-message responsive-button mr-2"></div>
@endif @endif
<div id="info-missing-products" <div id="info-missing-products"
data-status-filter="belowminstockamount" data-status-filter="belowminstockamount"

View File

@ -29,13 +29,16 @@
</div> </div>
</div> </div>
<div class="border-top border-bottom my-2 py-1"> <div class="border-top border-bottom my-2 py-1">
<div id="info-due-tasks" <div id="info-overdue-tasks"
data-status-filter="overdue"
class="error-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-today-tasks"
data-status-filter="duetoday"
class="normal-message status-filter-message responsive-button mr-2"></div>
<div id="info-due-soon-tasks"
data-status-filter="duesoon" data-status-filter="duesoon"
data-next-x-days="{{ $nextXDays }}" data-next-x-days="{{ $nextXDays }}"
class="warning-message status-filter-message responsive-button mr-2"></div> class="warning-message status-filter-message responsive-button mr-2"></div>
<div id="info-overdue-tasks"
data-status-filter="overdue"
class="error-message status-filter-message responsive-button"></div>
<div class="float-right"> <div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-1" <a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse" data-toggle="collapse"
@ -74,8 +77,9 @@
<select class="custom-control custom-select" <select class="custom-control custom-select"
id="status-filter"> id="status-filter">
<option value="all">{{ $__t('All') }}</option> <option value="all">{{ $__t('All') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
<option value="overdue">{{ $__t('Overdue') }}</option> <option value="overdue">{{ $__t('Overdue') }}</option>
<option value="duetoday">{{ $__t('Due today') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
</select> </select>
</div> </div>
</div> </div>
@ -121,9 +125,7 @@
<tbody class="d-none"> <tbody class="d-none">
@foreach($tasks as $task) @foreach($tasks as $task)
<tr id="task-{{ $task->id }}-row" <tr id="task-{{ $task->id }}-row"
class="@if($task->done == 1) text-muted @endif @if(!empty($task->due_date) && $task->due_date < date('Y-m-d')) table-danger @elseif(!empty($task->due_date) && $task->due_date < date('Y-m-d', strtotime('+' . $nextXDays . ' days'))) class="@if($task->due_type == 'overdue') table-danger @elseif($task->due_type == 'duetoday') table-info @elseif($task->due_type == 'duesoon') table-warning @endif">
table-warning
@endif">
<td class="fit-content border-right"> <td class="fit-content border-right">
@if($task->done == 0) @if($task->done == 0)
<a class="btn btn-success btn-sm do-task-button" <a class="btn btn-success btn-sm do-task-button"
@ -177,20 +179,13 @@
@if($task->assigned_to_user_id != null) <span>{{ GetUserDisplayName(FindObjectInArrayByPropertyValue($users, 'id', $task->assigned_to_user_id)) }}</span> @endif @if($task->assigned_to_user_id != null) <span>{{ GetUserDisplayName(FindObjectInArrayByPropertyValue($users, 'id', $task->assigned_to_user_id)) }}</span> @endif
</td> </td>
<td class="d-none"> <td class="d-none">
@if($task->done == 1) text-muted @endif @if(!empty($task->due_date) && $task->due_date < date('Y-m-d')) {{ $task->due_type }}
overdue @if($task->due_type == 'duetoday')
@elseif(!empty($task->due_date) && $task->due_date < date('Y-m-d', duesoon
strtotime('+' @endif
. </td>
$nextXDays <td class="d-none">
. ' days' @if($task->category_id != null) {{ FindObjectInArrayByPropertyValue($taskCategories, 'id', $task->category_id)->name }} @else {{ $__t('Uncategorized') }} @endif
)))
duesoon
@endif
</td>
<td
class="d-none">
@if($task->category_id != null) {{ FindObjectInArrayByPropertyValue($taskCategories, 'id', $task->category_id)->name }} @else {{ $__t('Uncategorized') }} @endif
</td> </td>
@include('components.userfields_tbody', @include('components.userfields_tbody',
array( 'userfields'=> $userfields, array( 'userfields'=> $userfields,