From 9ef55f1f01a792227210237fa6608cc20e05968e Mon Sep 17 00:00:00 2001 From: Bernd Bestel Date: Sat, 4 May 2019 16:13:05 +0200 Subject: [PATCH] Make it possible to track a chore execution without the time part, only the day --- changelog/47_UNRELEASED_xxxx-xx-xx.md | 1 + grocy.openapi.json | 3 + localization/strings.pot | 6 ++ migrations/0069.sql | 2 + public/viewjs/choreform.js | 2 +- public/viewjs/choresoverview.js | 97 +++++++++++++--------- public/viewjs/choretracking.js | 20 +++++ public/viewjs/components/datetimepicker.js | 7 ++ services/ChoresService.php | 6 ++ views/choreform.blade.php | 10 +++ 10 files changed, 112 insertions(+), 42 deletions(-) create mode 100644 migrations/0069.sql diff --git a/changelog/47_UNRELEASED_xxxx-xx-xx.md b/changelog/47_UNRELEASED_xxxx-xx-xx.md index 3af1b79e..e1f542df 100644 --- a/changelog/47_UNRELEASED_xxxx-xx-xx.md +++ b/changelog/47_UNRELEASED_xxxx-xx-xx.md @@ -14,6 +14,7 @@ - It's now possible to customize the default amount for purchase/consume (see stock settings under the settings icon on the top right) - Chores improvements - New recurrence patterns - chores can now also be "scheduled" to repat daily/weekly/monthly + - It's now possible to track the day of a chore execution only (without the time, option per chore) - Recipe improvements - It's now possible to enter a "variable amount" (e. g. if a recipe needs "1 - 2 cups"), the original amount is still used for stock fulfillment checking (if enabled for that recipe ingredient) - New translations: (thanks all the translators) diff --git a/grocy.openapi.json b/grocy.openapi.json index 4d14c5e4..7610cad7 100644 --- a/grocy.openapi.json +++ b/grocy.openapi.json @@ -2780,6 +2780,9 @@ "period_days": { "type": "integer" }, + "track_date_only": { + "type": "boolean" + }, "row_created_timestamp": { "type": "string", "format": "date-time" diff --git a/localization/strings.pot b/localization/strings.pot index ced2fd83..d4e3d725 100644 --- a/localization/strings.pot +++ b/localization/strings.pot @@ -1227,3 +1227,9 @@ msgstr "" msgid "When this is not empty, it will be shown instead of the amount entered above while the amount there will still be used for stock fulfillment checking" msgstr "" + +msgid "Track date only" +msgstr "" + +msgid "When enabled only the day of an execution is tracked, not the time" +msgstr "" diff --git a/migrations/0069.sql b/migrations/0069.sql new file mode 100644 index 00000000..ccdec713 --- /dev/null +++ b/migrations/0069.sql @@ -0,0 +1,2 @@ +ALTER TABLE chores +ADD track_date_only TINYINT DEFAULT 0; diff --git a/public/viewjs/choreform.js b/public/viewjs/choreform.js index 8d029124..917c7c26 100644 --- a/public/viewjs/choreform.js +++ b/public/viewjs/choreform.js @@ -2,7 +2,7 @@ { e.preventDefault(); - var jsonData = $('#chore-form').serializeJSON(); + var jsonData = $('#chore-form').serializeJSON({ checkboxUncheckedValue: "0" }); Grocy.FrontendHelpers.BeginUiBusy("chore-form"); if (Grocy.EditMode === 'create') diff --git a/public/viewjs/choresoverview.js b/public/viewjs/choresoverview.js index 931adade..dfd55701 100644 --- a/public/viewjs/choresoverview.js +++ b/public/viewjs/choresoverview.js @@ -65,51 +65,66 @@ $(document).on('click', '.track-chore-button', function(e) var choreId = $(e.currentTarget).attr('data-chore-id'); var choreName = $(e.currentTarget).attr('data-chore-name'); - var trackedTime = moment().format('YYYY-MM-DD HH:mm:ss'); - Grocy.Api.Post('chores/' + choreId + '/execute', { 'tracked_time': trackedTime }, - function() + Grocy.Api.Get('objects/chores/' + choreId, + function(chore) { - Grocy.Api.Get('chores/' + choreId, - function(result) + var trackedTime = moment().format('YYYY-MM-DD HH:mm:ss'); + if (chore.track_date_only == 1) + { + trackedTime = moment().format('YYYY-MM-DD'); + } + + Grocy.Api.Post('chores/' + choreId + '/execute', { 'tracked_time': trackedTime }, + function() { - var choreRow = $('#chore-' + choreId + '-row'); - var nextXDaysThreshold = moment().add($("#info-due-chores").data("next-x-days"), "days"); - var now = moment(); - var nextExecutionTime = moment(result.next_estimated_execution_time); - - choreRow.removeClass("table-warning"); - choreRow.removeClass("table-danger"); - if (nextExecutionTime.isBefore(now)) - { - choreRow.addClass("table-danger"); - } - else if (nextExecutionTime.isBefore(nextXDaysThreshold)) - { - choreRow.addClass("table-warning"); - } - - $('#chore-' + choreId + '-last-tracked-time').parent().effect('highlight', { }, 500); - $('#chore-' + choreId + '-last-tracked-time').fadeOut(500, function() - { - $(this).text(trackedTime).fadeIn(500); - }); - $('#chore-' + choreId + '-last-tracked-time-timeago').attr('datetime', trackedTime); - - if (result.chore.period_type == "dynamic-regular") - { - $('#chore-' + choreId + '-next-execution-time').parent().effect('highlight', { }, 500); - $('#chore-' + choreId + '-next-execution-time').fadeOut(500, function() + Grocy.Api.Get('chores/' + choreId, + function(result) { - $(this).text(result.next_estimated_execution_time).fadeIn(500); - }); - $('#chore-' + choreId + '-next-execution-time-timeago').attr('datetime', result.next_estimated_execution_time); - } + var choreRow = $('#chore-' + choreId + '-row'); + var nextXDaysThreshold = moment().add($("#info-due-chores").data("next-x-days"), "days"); + var now = moment(); + var nextExecutionTime = moment(result.next_estimated_execution_time); - Grocy.FrontendHelpers.EndUiBusy(); - toastr.success(__t('Tracked execution of chore %s on %s', choreName, trackedTime)); - RefreshContextualTimeago(); - RefreshStatistics(); + choreRow.removeClass("table-warning"); + choreRow.removeClass("table-danger"); + if (nextExecutionTime.isBefore(now)) + { + choreRow.addClass("table-danger"); + } + else if (nextExecutionTime.isBefore(nextXDaysThreshold)) + { + choreRow.addClass("table-warning"); + } + + $('#chore-' + choreId + '-last-tracked-time').parent().effect('highlight', { }, 500); + $('#chore-' + choreId + '-last-tracked-time').fadeOut(500, function() + { + $(this).text(trackedTime).fadeIn(500); + }); + $('#chore-' + choreId + '-last-tracked-time-timeago').attr('datetime', trackedTime); + + if (result.chore.period_type == "dynamic-regular") + { + $('#chore-' + choreId + '-next-execution-time').parent().effect('highlight', { }, 500); + $('#chore-' + choreId + '-next-execution-time').fadeOut(500, function() + { + $(this).text(result.next_estimated_execution_time).fadeIn(500); + }); + $('#chore-' + choreId + '-next-execution-time-timeago').attr('datetime', result.next_estimated_execution_time); + } + + Grocy.FrontendHelpers.EndUiBusy(); + toastr.success(__t('Tracked execution of chore %s on %s', choreName, trackedTime)); + RefreshContextualTimeago(); + RefreshStatistics(); + }, + function(xhr) + { + Grocy.FrontendHelpers.EndUiBusy(); + console.error(xhr); + } + ); }, function(xhr) { @@ -120,7 +135,7 @@ $(document).on('click', '.track-chore-button', function(e) }, function(xhr) { - Grocy.FrontendHelpers.EndUiBusy(); + Grocy.FrontendHelpers.EndUiBusy("choretracking-form"); console.error(xhr); } ); diff --git a/public/viewjs/choretracking.js b/public/viewjs/choretracking.js index 92fbccae..2adefaa8 100644 --- a/public/viewjs/choretracking.js +++ b/public/viewjs/choretracking.js @@ -45,6 +45,26 @@ $('#chore_id').on('change', function(e) var choreId = $(e.target).val(); if (choreId) { + Grocy.Api.Get('objects/chores/' + choreId, + function(chore) + { + if (chore.track_date_only == 1) + { + Grocy.Components.DateTimePicker.ChangeFormat("YYYY-MM-DD"); + Grocy.Components.DateTimePicker.SetValue(moment().format("YYYY-MM-DD")); + } + else + { + Grocy.Components.DateTimePicker.ChangeFormat("YYYY-MM-DD HH:mm:ss"); + Grocy.Components.DateTimePicker.SetValue(moment().format("YYYY-MM-DD HH:mm:ss")); + } + }, + function(xhr) + { + console.error(xhr); + } + ); + Grocy.Components.ChoreCard.Refresh(choreId); Grocy.Components.DateTimePicker.GetInputElement().focus(); Grocy.FrontendHelpers.ValidateForm('choretracking-form'); diff --git a/public/viewjs/components/datetimepicker.js b/public/viewjs/components/datetimepicker.js index 8b866e7c..c6fc63a6 100644 --- a/public/viewjs/components/datetimepicker.js +++ b/public/viewjs/components/datetimepicker.js @@ -43,6 +43,13 @@ Grocy.Components.DateTimePicker.Clear = function() $('#datetimepicker-timeago').text(''); } +Grocy.Components.DateTimePicker.ChangeFormat = function(format) +{ + $(".datetimepicker").datetimepicker("destroy"); + Grocy.Components.DateTimePicker.GetInputElement().data("format", format); + Grocy.Components.DateTimePicker.Init(); +} + var startDate = null; if (Grocy.Components.DateTimePicker.GetInputElement().data('init-with-now') === true) { diff --git a/services/ChoresService.php b/services/ChoresService.php index c18bb921..1599e35e 100644 --- a/services/ChoresService.php +++ b/services/ChoresService.php @@ -58,6 +58,12 @@ class ChoresService extends BaseService { throw new \Exception('User does not exist'); } + + $chore = $this->Database->chores($choreId); + if ($chore->track_date_only == 1) + { + $trackedTime = substr($trackedTime, 0, 10) . ' 00:00:00'; + } $logRow = $this->Database->chores_log()->createRow(array( 'chore_id' => $choreId, diff --git a/views/choreform.blade.php b/views/choreform.blade.php index 6e547fe6..93216262 100644 --- a/views/choreform.blade.php +++ b/views/choreform.blade.php @@ -87,6 +87,16 @@ +
+
+ + track_date_only == 1) checked @endif class="form-check-input" type="checkbox" id="track_date_only" name="track_date_only" value="1"> + +
+
+ @include('components.userfieldsform', array( 'userfields' => $userfields, 'entity' => 'chores'