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)
- 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)
- 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)

View File

@ -80,9 +80,30 @@ class BatteriesController extends BaseController
$usersService = $this->getUsersService();
$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', [
'batteries' => $this->getDatabase()->batteries()->where('active = 1')->orderBy('name', 'COLLATE NOCASE'),
'current' => $this->getBatteriesService()->GetCurrent(),
'batteries' => $batteries,
'current' => $currentBatteries,
'nextXDays' => $nextXDays,
'userfields' => $this->getUserfieldsService()->GetFields('batteries'),
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('batteries')

View File

@ -94,9 +94,30 @@ class ChoresController extends BaseController
$usersService = $this->getUsersService();
$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', [
'chores' => $this->getDatabase()->chores()->orderBy('name', 'COLLATE NOCASE'),
'currentChores' => $this->getChoresService()->GetCurrent(),
'chores' => $chores,
'currentChores' => $currentChores,
'nextXDays' => $nextXDays,
'userfields' => $this->getUserfieldsService()->GetFields('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)
{
$usersService = $this->getUsersService();
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['tasks_due_soon_days'];
if (isset($request->getQueryParams()['include_done']))
{
$tasks = $this->getDatabase()->tasks()->orderBy('name', 'COLLATE NOCASE');
@ -15,8 +18,21 @@ class TasksController extends BaseController
$tasks = $this->getTasksService()->GetCurrent();
}
$usersService = $this->getUsersService();
$nextXDays = $usersService->GetUserSettings(GROCY_USER_ID)['tasks_due_soon_days'];
foreach ($tasks as $task)
{
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', [
'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)"
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)
{
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 nextExecutionTime = moment(result.next_estimated_charge_time);
@ -139,28 +139,38 @@ $(document).on('click', '.battery-grocycode-label-print', function(e)
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',
function(result)
{
var dueCount = 0;
var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0;
var now = moment();
var overdueThreshold = moment();
var nextXDaysThreshold = moment().add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element =>
{
var date = moment(element.next_estimated_charge_time);
if (date.isBefore(now))
if (date.isBefore(overdueThreshold))
{
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'));
},
function(xhr)

View File

@ -109,7 +109,7 @@ $(document).on('click', '.track-chore-button', function(e)
function(result)
{
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 nextExecutionTime = moment(result.next_estimated_execution_time);
@ -202,25 +202,34 @@ $(document).on('click', '.chore-grocycode-label-print', function(e)
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',
function(result)
{
var dueCount = 0;
var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0;
var assignedToMeCount = 0;
var now = moment();
var overdueThreshold = moment();
var nextXDaysThreshold = moment().add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element =>
{
var date = moment(element.next_estimated_execution_time);
if (date.isBefore(now))
if (date.isBefore(overdueThreshold))
{
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)
@ -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-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()
{
var nextXDays = $("#info-due-tasks").data("next-x-days");
var nextXDays = $("#info-due-soon-tasks").data("next-x-days");
Grocy.Api.Get('tasks',
function(result)
{
var dueCount = 0;
var dueTodayCount = 0;
var dueSoonCount = 0;
var overdueCount = 0;
var now = moment();
var nextXDaysThreshold = moment().add(nextXDays, "days");
var overdueThreshold = moment().subtract(1, "days").endOf("day");
var nextXDaysThreshold = moment().endOf("day").add(nextXDays, "days");
var todayThreshold = moment().endOf("day");
result.forEach(element =>
{
var date = moment(element.due_date);
if (date.isBefore(now))
var date = moment(element.due_date + " 23:59:59").endOf("day");
if (date.isSameOrBefore(overdueThreshold))
{
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'));
},
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, 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, 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
@ -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('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('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);
@ -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('-10 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 H:i:s', strtotime('-20 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('-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(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(6, date('Y-m-d H:i:s', strtotime('-10 days')));
$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('-150 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('-50 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('-540 days')));
$batteriesService->TrackChargeCycle(1, date('Y-m-d H:i:s', strtotime('-360 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('-150 days')));
$batteriesService->TrackChargeCycle(2, date('Y-m-d H:i:s', strtotime('-100 days')));

View File

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

View File

@ -29,17 +29,20 @@
</div>
</div>
<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"
data-status-filter="overdue"
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)
<div id="info-assigned-to-me-chores"
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
<div class="float-right">
<a class="btn btn-sm btn-outline-info d-md-none mt-1"
@ -79,8 +82,9 @@
<select class="custom-control custom-select"
id="status-filter">
<option value="all">{{ $__t('All') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
<option value="overdue">{{ $__t('Overdue') }}</option>
<option value="duetoday">{{ $__t('Due today') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
</select>
</div>
</div>
@ -132,9 +136,7 @@
<tbody class="d-none">
@foreach($currentChores as $curentChoreEntry)
<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')))
table-warning
@endif">
class="@if($curentChoreEntry->due_type == 'overdue') table-danger @elseif($curentChoreEntry->due_type == 'duetoday') table-info @elseif($curentChoreEntry->due_type == 'duesoon') table-warning @endif">
<td class="fit-content border-right">
<a class="btn btn-success btn-sm track-chore-button permission-CHORE_TRACK_EXECUTION"
href="#"
@ -217,25 +219,14 @@
</td>
<td id="chore-{{ $curentChoreEntry->chore_id }}-due-filter-column"
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
H:i:s'))
overdue
@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'
)))
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
{{ $curentChoreEntry->due_type }}
@if($curentChoreEntry->due_type == 'duetoday')
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>
@endif

View File

@ -50,16 +50,16 @@
</div>
<div class="border-top border-bottom my-2 py-1">
@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"
data-next-x-days="{{ $nextXDays }}"
data-status-filter="duesoon"
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
<div id="info-missing-products"
data-status-filter="belowminstockamount"

View File

@ -29,13 +29,16 @@
</div>
</div>
<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-next-x-days="{{ $nextXDays }}"
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">
<a class="btn btn-sm btn-outline-info d-md-none mt-1"
data-toggle="collapse"
@ -74,8 +77,9 @@
<select class="custom-control custom-select"
id="status-filter">
<option value="all">{{ $__t('All') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
<option value="overdue">{{ $__t('Overdue') }}</option>
<option value="duetoday">{{ $__t('Due today') }}</option>
<option value="duesoon">{{ $__t('Due soon') }}</option>
</select>
</div>
</div>
@ -121,9 +125,7 @@
<tbody class="d-none">
@foreach($tasks as $task)
<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')))
table-warning
@endif">
class="@if($task->due_type == 'overdue') table-danger @elseif($task->due_type == 'duetoday') table-info @elseif($task->due_type == 'duesoon') table-warning @endif">
<td class="fit-content border-right">
@if($task->done == 0)
<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
</td>
<td class="d-none">
@if($task->done == 1) text-muted @endif @if(!empty($task->due_date) && $task->due_date < date('Y-m-d'))
overdue
@elseif(!empty($task->due_date) && $task->due_date < date('Y-m-d',
strtotime('+'
.
$nextXDays
. ' days'
)))
duesoon
@endif
</td>
<td
class="d-none">
@if($task->category_id != null) {{ FindObjectInArrayByPropertyValue($taskCategories, 'id', $task->category_id)->name }} @else {{ $__t('Uncategorized') }} @endif
{{ $task->due_type }}
@if($task->due_type == 'duetoday')
duesoon
@endif
</td>
<td class="d-none">
@if($task->category_id != null) {{ FindObjectInArrayByPropertyValue($taskCategories, 'id', $task->category_id)->name }} @else {{ $__t('Uncategorized') }} @endif
</td>
@include('components.userfields_tbody',
array( 'userfields'=> $userfields,