mirror of
https://github.com/grocy/grocy.git
synced 2025-04-28 17:23:56 +00:00
Implemented that chores can be assigned to users (closes #253)
This commit is contained in:
parent
3dcd513094
commit
74f9470769
12
.tx/config
12
.tx/config
@ -1,9 +1,15 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[grocy.chore_types]
|
||||
file_filter = localization/<lang>/chore_types.po
|
||||
source_file = localization/chore_types.pot
|
||||
[grocy.chore_period_types]
|
||||
file_filter = localization/<lang>/chore_period_types.po
|
||||
source_file = localization/chore_period_types.pot
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
[grocy.chore_assignment_types]
|
||||
file_filter = localization/<lang>/chore_assignment_types.po
|
||||
source_file = localization/chore_assignment_types.pot
|
||||
source_lang = en
|
||||
type = PO
|
||||
|
||||
|
@ -12,6 +12,9 @@
|
||||
- Recipe improvements
|
||||
- Based on the new linked quantity units, recipe ingredients can now use any product related unit, the amount is calculated according to the cnoversion factor of the unit relation
|
||||
- Chores improvements
|
||||
- Chores can now be assigned to users
|
||||
- Option per chore, different "assignment types" like "Random", "Who least did first", etc.
|
||||
- On the chores overview page the list can be filterd to only show chores assigned to the currently logged in user
|
||||
- New option "Due date rollover" per chore which means the chore can never be overdue, the due date will shift forward each day when due
|
||||
- Equipment improvements/fixes
|
||||
- Fixed that the delete button not always deleted the currently selected equipment item
|
||||
|
@ -70,4 +70,37 @@ class ChoresApiController extends BaseApiController
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function CalculateNextExecutionAssignments(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
try
|
||||
{
|
||||
$requestBody = $request->getParsedBody();
|
||||
|
||||
$choreId = null;
|
||||
if (array_key_exists('chore_id', $requestBody) && !empty($requestBody['chore_id']) && is_numeric($requestBody['chore_id']))
|
||||
{
|
||||
$choreId = intval($requestBody['chore_id']);
|
||||
}
|
||||
|
||||
if ($choreId === null)
|
||||
{
|
||||
$chores = $this->Database->chores();
|
||||
foreach ($chores as $chore)
|
||||
{
|
||||
$this->ChoresService->CalculateNextExecutionAssignment($chore->id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->ChoresService->CalculateNextExecutionAssignment($choreId);
|
||||
}
|
||||
|
||||
return $this->EmptyApiResponse($response);
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
return $this->GenericErrorResponse($response, $ex->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ class ChoresController extends BaseController
|
||||
'currentChores' => $this->ChoresService->GetCurrent(),
|
||||
'nextXDays' => $nextXDays,
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores'),
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('chores')
|
||||
'userfieldValues' => $this->UserfieldsService->GetAllValues('chores'),
|
||||
'users' => $usersService->GetUsersAsDto()
|
||||
]);
|
||||
}
|
||||
|
||||
@ -60,21 +61,28 @@ class ChoresController extends BaseController
|
||||
|
||||
public function ChoreEditForm(\Slim\Http\Request $request, \Slim\Http\Response $response, array $args)
|
||||
{
|
||||
$usersService = new UsersService();
|
||||
$users = $usersService->GetUsersAsDto();
|
||||
|
||||
if ($args['choreId'] == 'new')
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'choreform', [
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService'),
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService', 'CHORE_PERIOD_TYPE_'),
|
||||
'mode' => 'create',
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores')
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores'),
|
||||
'assignmentTypes' => GetClassConstants('\Grocy\Services\ChoresService', 'CHORE_ASSIGNMENT_TYPE_'),
|
||||
'users' => $users
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return $this->AppContainer->view->render($response, 'choreform', [
|
||||
'chore' => $this->Database->chores($args['choreId']),
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService'),
|
||||
'periodTypes' => GetClassConstants('\Grocy\Services\ChoresService', 'CHORE_PERIOD_TYPE_'),
|
||||
'mode' => 'edit',
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores')
|
||||
'userfields' => $this->UserfieldsService->GetFields('chores'),
|
||||
'assignmentTypes' => GetClassConstants('\Grocy\Services\ChoresService', 'CHORE_ASSIGNMENT_TYPE_'),
|
||||
'users' => $users
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -2100,6 +2100,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/chores/executions/calculate-next-assignments": {
|
||||
"post": {
|
||||
"summary": "(Re)calculates all next user assignments of all chores",
|
||||
"tags": [
|
||||
"Chores"
|
||||
],
|
||||
"requestBody": {
|
||||
"required": false,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chore_id": {
|
||||
"type": "integer",
|
||||
"description": "The chore id of the chore which next user assignment should be (re)calculated, when omitted, the next user assignments of all chores will (re)caluclated"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"chore_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "The operation was successful"
|
||||
},
|
||||
"400": {
|
||||
"description": "The operation was not successful",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/GenericErrorResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/batteries": {
|
||||
"get": {
|
||||
"summary": "Returns all batteries incl. the next estimated charge time per battery",
|
||||
@ -2853,6 +2895,9 @@
|
||||
"next_estimated_execution_time": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
},
|
||||
"next_execution_assigned_user": {
|
||||
"$ref": "#/components/schemas/UserDto"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
@ -3091,15 +3136,39 @@
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"manually",
|
||||
"dynamic-regular"
|
||||
"dynamic-regular",
|
||||
"daily",
|
||||
"weekly",
|
||||
"monthly"
|
||||
]
|
||||
},
|
||||
"period_config": {
|
||||
"type": "string"
|
||||
},
|
||||
"period_days": {
|
||||
"type": "integer"
|
||||
},
|
||||
"track_date_only": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"rollover": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"assignment_type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"no-assignment",
|
||||
"who-least-did-first",
|
||||
"random",
|
||||
"in-alphabetical-order"
|
||||
]
|
||||
},
|
||||
"assignment_config": {
|
||||
"type": "string"
|
||||
},
|
||||
"next_execution_assigned_to_user_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"row_created_timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time"
|
||||
|
@ -88,10 +88,20 @@ function SumArrayValue($array, $propertyName)
|
||||
return $sum;
|
||||
}
|
||||
|
||||
function GetClassConstants($className)
|
||||
function GetClassConstants($className, $prefix = null)
|
||||
{
|
||||
$r = new ReflectionClass($className);
|
||||
return $r->getConstants();
|
||||
$constants = $r->getConstants();
|
||||
|
||||
if ($prefix === null)
|
||||
{
|
||||
return $constants;
|
||||
}
|
||||
else
|
||||
{
|
||||
$matchingKeys = preg_grep('!^' . $prefix . '!', array_keys($constants));
|
||||
return array_intersect_key($constants, array_flip($matchingKeys));
|
||||
}
|
||||
}
|
||||
|
||||
function RandomString($length, $allowedChars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||
|
25
localization/chore_assignment_types.pot
Normal file
25
localization/chore_assignment_types.pot
Normal file
@ -0,0 +1,25 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Translation migration from old PHP array files\n"
|
||||
"Language-Team: http://www.transifex.com/grocy/grocy/language/en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"Language: en\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -29,3 +29,6 @@ msgstr ""
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr ""
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr ""
|
||||
|
26
localization/da/chore_assignment_types.po
Normal file
26
localization/da/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/grocy/teams/93189/da/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: da\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -1,5 +1,5 @@
|
||||
# Translators:
|
||||
# Bernd Bestel <bernd@berrnd.de>, 2019
|
||||
# Troels Siggaard <troels@siggaard.com>, 2019
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
@ -7,7 +7,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01 17:42+0000\n"
|
||||
"Last-Translator: Bernd Bestel <bernd@berrnd.de>, 2019\n"
|
||||
"Last-Translator: Troels Siggaard <troels@siggaard.com>, 2019\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/grocy/teams/93189/da/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -17,16 +17,16 @@ msgstr ""
|
||||
"X-Domain: grocy/chore_types\n"
|
||||
|
||||
msgid "manually"
|
||||
msgstr "Manuelt"
|
||||
msgstr "manuelt"
|
||||
|
||||
msgid "dynamic-regular"
|
||||
msgstr ""
|
||||
msgstr "gentagende-dynamisk"
|
||||
|
||||
msgid "daily"
|
||||
msgstr ""
|
||||
msgstr "daglig"
|
||||
|
||||
msgid "weekly"
|
||||
msgstr ""
|
||||
msgstr "ugentlig"
|
||||
|
||||
msgid "monthly"
|
||||
msgstr ""
|
||||
msgstr "månedlig"
|
@ -1,3 +1,6 @@
|
||||
# Translators:
|
||||
# Troels Siggaard <troels@siggaard.com>, 2019
|
||||
# Bernd Bestel <bernd@berrnd.de>, 2019
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
@ -5,6 +8,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01 17:42+0000\n"
|
||||
"Last-Translator: Bernd Bestel <bernd@berrnd.de>, 2019\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/grocy/teams/93189/da/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -14,19 +18,22 @@ msgstr ""
|
||||
"X-Domain: grocy/component_translations\n"
|
||||
|
||||
msgid "timeago_locale"
|
||||
msgstr ""
|
||||
msgstr "timdsiden_lokal"
|
||||
|
||||
msgid "timeago_nan"
|
||||
msgstr ""
|
||||
msgstr "tidsiden_ien"
|
||||
|
||||
msgid "moment_locale"
|
||||
msgstr ""
|
||||
msgstr "tidspunkt_lokal"
|
||||
|
||||
msgid "datatables_localization"
|
||||
msgstr ""
|
||||
msgstr "datatabeller_lokalisering"
|
||||
|
||||
msgid "summernote_locale"
|
||||
msgstr ""
|
||||
msgstr "summernote_lokal"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr ""
|
||||
msgstr "fuldkalender_lokal"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "da_DK"
|
||||
|
26
localization/de/chore_assignment_types.po
Normal file
26
localization/de/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: German (https://www.transifex.com/grocy/teams/93189/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -52,3 +52,6 @@ msgstr "de-DE"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "de"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "de_DE"
|
||||
|
25
localization/en/chore_assignment_types.po
Normal file
25
localization/en/chore_assignment_types.po
Normal file
@ -0,0 +1,25 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"Last-Translator: Translation migration from old PHP array files\n"
|
||||
"Language-Team: http://www.transifex.com/grocy/grocy/language/en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"Language: en\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr "No assignment"
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr "Who least did first"
|
||||
|
||||
msgid "random"
|
||||
msgstr "Random"
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr "In alphabetical order"
|
@ -1,14 +1,15 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"Last-Translator: Translation migration from old PHP array files\n"
|
||||
"Language-Team: http://www.transifex.com/grocy/grocy/language/en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"Language: en\n"
|
||||
"X-Domain: grocy/chore_types\n"
|
||||
|
@ -29,3 +29,6 @@ msgstr "x"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "x"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "x"
|
||||
|
26
localization/en_GB/chore_assignment_types.po
Normal file
26
localization/en_GB/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: English (United Kingdom) (https://www.transifex.com/grocy/teams/93189/en_GB/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: en_GB\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -17,19 +17,32 @@ msgstr ""
|
||||
"X-Domain: grocy/component_translations\n"
|
||||
|
||||
msgid "timeago_locale"
|
||||
msgstr ""
|
||||
msgstr "en"
|
||||
|
||||
msgid "timeago_nan"
|
||||
msgstr ""
|
||||
msgstr "NaN years ago"
|
||||
|
||||
msgid "moment_locale"
|
||||
msgstr "en-gb"
|
||||
|
||||
msgid "datatables_localization"
|
||||
msgstr ""
|
||||
"{\"sEmptyTable\":\"No data available in table\",\"sInfo\":\"Showing _START_ "
|
||||
"to _END_ of _TOTAL_ entries\",\"sInfoEmpty\":\"Showing 0 to 0 of 0 "
|
||||
"entries\",\"sInfoFiltered\":\"(filtered from _MAX_ total "
|
||||
"entries)\",\"sInfoPostFix\":\"\",\"sInfoThousands\":\",\",\"sLengthMenu\":\"Show"
|
||||
" _MENU_ "
|
||||
"entries\",\"sLoadingRecords\":\"Loading...\",\"sProcessing\":\"Processing...\",\"sSearch\":\"Search:\",\"sZeroRecords\":\"No"
|
||||
" matching records "
|
||||
"found\",\"oPaginate\":{\"sFirst\":\"First\",\"sLast\":\"Last\",\"sNext\":\"Next\",\"sPrevious\":\"Previous\"},\"oAria\":{\"sSortAscending\":\":"
|
||||
" activate to sort column ascending\",\"sSortDescending\":\": activate to "
|
||||
"sort column descending\"}}"
|
||||
|
||||
msgid "summernote_locale"
|
||||
msgstr "en-gb"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "en-gb"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "x"
|
||||
|
26
localization/es/chore_assignment_types.po
Normal file
26
localization/es/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/grocy/teams/93189/es/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -43,3 +43,6 @@ msgstr "es-ES"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "es"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "es_ES"
|
||||
|
26
localization/fr/chore_assignment_types.po
Normal file
26
localization/fr/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: French (https://www.transifex.com/grocy/teams/93189/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -47,3 +47,6 @@ msgstr "fr-FR"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "fr"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "fr_FR"
|
||||
|
26
localization/it/chore_assignment_types.po
Normal file
26
localization/it/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Italian (https://www.transifex.com/grocy/teams/93189/it/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: it\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -1,4 +1,5 @@
|
||||
# Translators:
|
||||
# Antonino Ursino <ninus_@libero.it>, 2019
|
||||
# Bernd Bestel <bernd@berrnd.de>, 2019
|
||||
#
|
||||
msgid ""
|
||||
@ -17,28 +18,22 @@ msgstr ""
|
||||
"X-Domain: grocy/component_translations\n"
|
||||
|
||||
msgid "timeago_locale"
|
||||
msgstr "it"
|
||||
msgstr "tempofa_locale"
|
||||
|
||||
msgid "timeago_nan"
|
||||
msgstr "NaN anni fa"
|
||||
msgstr "tempofa_nan"
|
||||
|
||||
msgid "moment_locale"
|
||||
msgstr "it"
|
||||
msgstr "istante_locale"
|
||||
|
||||
msgid "datatables_localization"
|
||||
msgstr ""
|
||||
"{\"sEmptyTable\":\"Nessun dato disponibile\",\"sInfo\":\"Mostrando da "
|
||||
"_START_ a _END_ di _TOTAL_ voci\",\"sInfoEmpty\":\"Mostrando da 0 a 0 di 0 "
|
||||
"voci\",\"sInfoFiltered\":\"(Filtrato da _MAX_ voci "
|
||||
"totali)\",\"sInfoPostFix\":\"\",\"sInfoThousands\":\",\",\"sLengthMenu\":\"Mostra"
|
||||
" _MENU_ "
|
||||
"voci\",\"sLoadingRecords\":\"Caricando...\",\"sProcessing\":\"Calcolando...\",\"sSearch\":\"Cerca:\",\"sZeroRecords\":\"Nessun"
|
||||
" risultato "
|
||||
"trovato\",\"oPaginate\":{\"sFirst\":\"Prima\",\"sLast\":\"Ultima\",\"sNext\":\"Prossima\",\"sPrevious\":\"Precedente\"},\"oAria\":{\"sSortAscending\":\":"
|
||||
" ordine crescente\",\"sSortDescending\":\": ordine decrescente\"}}"
|
||||
msgstr "datitabelle_localizzazione"
|
||||
|
||||
msgid "summernote_locale"
|
||||
msgstr "it-IT"
|
||||
msgstr "summernote_locale"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "fr"
|
||||
msgstr "calendariocompleto_locale"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "it_IT"
|
||||
|
26
localization/nl/chore_assignment_types.po
Normal file
26
localization/nl/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Dutch (https://www.transifex.com/grocy/teams/93189/nl/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: nl\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -45,3 +45,6 @@ msgstr "nl-NL"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "nl"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "nl_NL"
|
||||
|
26
localization/no/chore_assignment_types.po
Normal file
26
localization/no/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Norwegian (https://www.transifex.com/grocy/teams/93189/no/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: no\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -1,5 +1,6 @@
|
||||
# Translators:
|
||||
# Bernd Bestel <bernd@berrnd.de>, 2019
|
||||
# Andreas Henden <chairman2s.ah@gmail.com>, 2019
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
@ -7,7 +8,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-05-01 17:42+0000\n"
|
||||
"Last-Translator: Bernd Bestel <bernd@berrnd.de>, 2019\n"
|
||||
"Last-Translator: Andreas Henden <chairman2s.ah@gmail.com>, 2019\n"
|
||||
"Language-Team: Norwegian (https://www.transifex.com/grocy/teams/93189/no/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -17,7 +18,7 @@ msgstr ""
|
||||
"X-Domain: grocy/chore_types\n"
|
||||
|
||||
msgid "manually"
|
||||
msgstr "Manuel"
|
||||
msgstr "manuelt"
|
||||
|
||||
msgid "dynamic-regular"
|
||||
msgstr "Automatisk"
|
@ -48,3 +48,6 @@ msgstr "nb-NO"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "nb"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "nb_NO"
|
||||
|
26
localization/pl/chore_assignment_types.po
Normal file
26
localization/pl/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Polish (https://www.transifex.com/grocy/teams/93189/pl/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: pl\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -43,3 +43,6 @@ msgstr "pl-PL"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "pl"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "pl_PL"
|
||||
|
26
localization/ru/chore_assignment_types.po
Normal file
26
localization/ru/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Russian (https://www.transifex.com/grocy/teams/93189/ru/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ru\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -33,3 +33,6 @@ msgstr "ru-RU"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "ru"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "ru_RU"
|
||||
|
@ -349,7 +349,7 @@ msgstr ""
|
||||
msgid "This means %s will be removed from stock"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means it is estimated that a new execution of this chore is tracked %s days after the last was tracked"
|
||||
msgid "This means the next execution of this chore is scheduled %s days after the last execution"
|
||||
msgstr ""
|
||||
|
||||
msgid "Removed %1$s of %2$s from stock"
|
||||
@ -1367,3 +1367,47 @@ msgstr ""
|
||||
|
||||
msgid "Edit QU conversion"
|
||||
msgstr ""
|
||||
|
||||
msgid "An assignment type is required"
|
||||
msgstr ""
|
||||
|
||||
msgid "Assignment type"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore is scheduled 1 day after the last execution"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore is scheduled 1 day after the last execution, but only for the weekdays selected below"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore is not scheduled"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore is scheduled on the below selected day of each month"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore will not be assigned to anyone"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore will be assigned to the one who executed it least"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore will be assigned randomly"
|
||||
msgstr ""
|
||||
|
||||
msgid "This means the next execution of this chore will be assigned to the next one in alphabetical order"
|
||||
msgstr ""
|
||||
|
||||
msgid "Assign to"
|
||||
msgstr ""
|
||||
|
||||
msgid "This assignment type requires that at least one is assigned"
|
||||
msgstr ""
|
||||
|
||||
msgid "%s chore is assigned to me"
|
||||
msgid_plural "%s chores are assigned to me"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "Assigned to me"
|
||||
msgstr ""
|
||||
|
26
localization/sv_SE/chore_assignment_types.po
Normal file
26
localization/sv_SE/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Swedish (Sweden) (https://www.transifex.com/grocy/teams/93189/sv_SE/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: sv_SE\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -43,3 +43,6 @@ msgstr "sv-SE"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "sv"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "sv_SE"
|
||||
|
26
localization/ta/chore_assignment_types.po
Normal file
26
localization/ta/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Tamil (https://www.transifex.com/grocy/teams/93189/ta/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: ta\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -30,3 +30,6 @@ msgstr ""
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr ""
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr ""
|
||||
|
26
localization/tr/chore_assignment_types.po
Normal file
26
localization/tr/chore_assignment_types.po
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2019-05-01T17:59:17+00:00\n"
|
||||
"PO-Revision-Date: 2019-09-17 10:45+0000\n"
|
||||
"Language-Team: Turkish (https://www.transifex.com/grocy/teams/93189/tr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: tr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Domain: grocy/chore_assignment_types\n"
|
||||
|
||||
msgid "no-assignment"
|
||||
msgstr ""
|
||||
|
||||
msgid "who-least-did-first"
|
||||
msgstr ""
|
||||
|
||||
msgid "random"
|
||||
msgstr ""
|
||||
|
||||
msgid "in-alphabetical-order"
|
||||
msgstr ""
|
@ -44,3 +44,6 @@ msgstr "tr-TR"
|
||||
|
||||
msgid "fullcalendar_locale"
|
||||
msgstr "tr"
|
||||
|
||||
msgid "bootstrap-select_locale"
|
||||
msgstr "tr_TR"
|
||||
|
@ -67,7 +67,7 @@ UNION
|
||||
|
||||
-- Second: Product specific overrides
|
||||
SELECT
|
||||
p.id AS id, -- Dummy, LessQL needs an id column
|
||||
p.id AS id, -- Dummy, LessQL needs an id column
|
||||
p.id AS product_id,
|
||||
quc.from_qu_id AS from_qu_id,
|
||||
qu_from.name AS from_qu_name,
|
||||
@ -87,7 +87,7 @@ UNION
|
||||
|
||||
-- Third: Default quantity unit conversion factors
|
||||
SELECT
|
||||
p.id AS id, -- Dummy, LessQL needs an id column
|
||||
p.id AS id, -- Dummy, LessQL needs an id column
|
||||
p.id AS product_id,
|
||||
p.qu_id_stock AS from_qu_id,
|
||||
qu_from.name AS from_qu_name,
|
||||
|
74
migrations/0083.sql
Normal file
74
migrations/0083.sql
Normal file
@ -0,0 +1,74 @@
|
||||
ALTER TABLE chores
|
||||
ADD assignment_type TEXT;
|
||||
|
||||
ALTER TABLE chores
|
||||
ADD assignment_config TEXT;
|
||||
|
||||
ALTER TABLE chores
|
||||
ADD next_execution_assigned_to_user_id INT;
|
||||
|
||||
DROP VIEW chores_current;
|
||||
CREATE VIEW chores_current
|
||||
AS
|
||||
SELECT
|
||||
x.chore_id,
|
||||
x.last_tracked_time,
|
||||
CASE WHEN x.rollover = 1 AND DATETIME('now', 'localtime') > x.next_estimated_execution_time THEN
|
||||
DATETIME(STRFTIME('%Y-%m-%d', DATETIME('now', 'localtime')) || ' ' || STRFTIME('%H:%M:%S', x.next_estimated_execution_time))
|
||||
ELSE
|
||||
x.next_estimated_execution_time
|
||||
END AS next_estimated_execution_time,
|
||||
x.track_date_only,
|
||||
x.next_execution_assigned_to_user_id
|
||||
FROM (
|
||||
|
||||
SELECT
|
||||
h.id AS chore_id,
|
||||
MAX(l.tracked_time) AS last_tracked_time,
|
||||
CASE h.period_type
|
||||
WHEN 'manually' THEN '2999-12-31 23:59:59'
|
||||
WHEN 'dynamic-regular' THEN DATETIME(MAX(l.tracked_time), '+' || CAST(h.period_days AS TEXT) || ' day')
|
||||
WHEN 'daily' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+1 day')
|
||||
WHEN 'weekly' THEN
|
||||
CASE
|
||||
WHEN period_config LIKE '%sunday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 0')
|
||||
WHEN period_config LIKE '%monday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 1')
|
||||
WHEN period_config LIKE '%tuesday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 2')
|
||||
WHEN period_config LIKE '%wednesday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 3')
|
||||
WHEN period_config LIKE '%thursday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 4')
|
||||
WHEN period_config LIKE '%friday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 5')
|
||||
WHEN period_config LIKE '%saturday%' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '1 days', 'weekday 6')
|
||||
END
|
||||
WHEN 'monthly' THEN DATETIME(IFNULL(MAX(l.tracked_time), DATETIME('now', 'localtime')), '+1 month', 'start of month', '+' || CAST(h.period_days - 1 AS TEXT) || ' day')
|
||||
END AS next_estimated_execution_time,
|
||||
h.track_date_only,
|
||||
h.rollover,
|
||||
h.next_execution_assigned_to_user_id
|
||||
FROM chores h
|
||||
LEFT JOIN chores_log l
|
||||
ON h.id = l.chore_id
|
||||
AND l.undone = 0
|
||||
GROUP BY h.id, h.period_days
|
||||
|
||||
) x;
|
||||
|
||||
CREATE VIEW chores_assigned_users_resolved
|
||||
AS
|
||||
SELECT
|
||||
c.id AS chore_id,
|
||||
u.id AS user_id
|
||||
FROM chores c
|
||||
JOIN users u
|
||||
ON ',' || c.assignment_config || ',' LIKE '%,' || CAST(u.id AS TEXT) || ',%';
|
||||
|
||||
CREATE VIEW chores_execution_users_statistics
|
||||
AS
|
||||
SELECT
|
||||
c.id AS id, -- Dummy, LessQL needs an id column
|
||||
c.id AS chore_id,
|
||||
caur.user_id AS user_id,
|
||||
(SELECT COUNT(1) FROM chores_log WHERE chore_id = c.id AND done_by_user_id = caur.user_id AND undone = 0) AS execution_count
|
||||
FROM chores c
|
||||
JOIN chores_assigned_users_resolved caur
|
||||
ON c.id = caur.chore_id
|
||||
GROUP BY c.id, caur.user_id;
|
@ -30,6 +30,7 @@
|
||||
"swagger-ui-dist": "^3.22.1",
|
||||
"tempusdominus-bootstrap-4": "https://github.com/berrnd/tempusdominus-bootstrap-4.git#master",
|
||||
"timeago": "^1.6.7",
|
||||
"toastr": "^2.1.4"
|
||||
"toastr": "^2.1.4",
|
||||
"bootstrap-select": "^1.13.10"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
e.preventDefault();
|
||||
|
||||
var jsonData = $('#chore-form').serializeJSON({ checkboxUncheckedValue: "0" });
|
||||
jsonData.assignment_config = $("#assignment_config").val().join(",");
|
||||
Grocy.FrontendHelpers.BeginUiBusy("chore-form");
|
||||
|
||||
if (Grocy.EditMode === 'create')
|
||||
@ -13,7 +14,17 @@
|
||||
Grocy.EditObjectId = result.created_object_id;
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
Grocy.Api.Post('chores/executions/calculate-next-assignments', { "chore_id": Grocy.EditObjectId },
|
||||
function (result)
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
},
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
@ -30,7 +41,17 @@
|
||||
{
|
||||
Grocy.Components.UserfieldsForm.Save(function()
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
Grocy.Api.Post('chores/executions/calculate-next-assignments', { "chore_id": Grocy.EditObjectId },
|
||||
function (result)
|
||||
{
|
||||
window.location.href = U('/chores');
|
||||
},
|
||||
function (xhr)
|
||||
{
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
console.error(xhr);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
function(xhr)
|
||||
@ -80,6 +101,7 @@ Grocy.FrontendHelpers.ValidateForm('chore-form');
|
||||
setTimeout(function()
|
||||
{
|
||||
$(".input-group-chore-period-type").trigger("change");
|
||||
$(".input-group-chore-assignment-type").trigger("change");
|
||||
}, 100);
|
||||
|
||||
$('.input-group-chore-period-type').on('change', function(e)
|
||||
@ -94,7 +116,7 @@ $('.input-group-chore-period-type').on('change', function(e)
|
||||
|
||||
if (periodType === 'manually')
|
||||
{
|
||||
//
|
||||
$('#chore-period-type-info').text(__t('This means the next execution of this chore is not scheduled'));
|
||||
}
|
||||
else if (periodType === 'dynamic-regular')
|
||||
{
|
||||
@ -102,21 +124,59 @@ $('.input-group-chore-period-type').on('change', function(e)
|
||||
$("#period_days").attr("min", "0");
|
||||
$("#period_days").attr("max", "9999");
|
||||
$("#period_days").parent().find(".invalid-feedback").text(__t('This cannot be negative'));
|
||||
$('#chore-period-type-info').text(__t('This means it is estimated that a new execution of this chore is tracked %s days after the last was tracked', periodDays.toString()));
|
||||
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled %s days after the last execution', periodDays.toString()));
|
||||
}
|
||||
else if (periodType === 'daily')
|
||||
{
|
||||
//
|
||||
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled 1 day after the last execution'));
|
||||
}
|
||||
else if (periodType === 'weekly')
|
||||
{
|
||||
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled 1 day after the last execution, but only for the weekdays selected below'));
|
||||
$("#period_config").val($(".period-type-weekly input:checkbox:checked").map(function () { return this.value; }).get().join(","));
|
||||
}
|
||||
else if (periodType === 'monthly')
|
||||
{
|
||||
$('#chore-period-type-info').text(__t('This means the next execution of this chore is scheduled on the below selected day of each month'));
|
||||
$("label[for='period_days']").text(__t("Day of month"));
|
||||
$("#period_days").attr("min", "1");
|
||||
$("#period_days").attr("max", "31");
|
||||
$("#period_days").parent().find(".invalid-feedback").text(__t('The amount must be between %1$s and %2$s', "1", "31"));
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('chore-form');
|
||||
});
|
||||
|
||||
$('.input-group-chore-assignment-type').on('change', function(e)
|
||||
{
|
||||
var assignmentType = $('#assignment_type').val();
|
||||
|
||||
$('#chore-period-assignment-info').text("");
|
||||
$("#assignment_config").removeAttr("required");
|
||||
$("#assignment_config").attr("disabled", "");
|
||||
|
||||
if (assignmentType === 'no-assignment')
|
||||
{
|
||||
$('#chore-assignment-type-info').text(__t('This means the next execution of this chore will not be assigned to anyone'));
|
||||
}
|
||||
else if (assignmentType === 'who-least-did-first')
|
||||
{
|
||||
$('#chore-assignment-type-info').text(__t('This means the next execution of this chore will be assigned to the one who executed it least'));
|
||||
$("#assignment_config").attr("required", "");
|
||||
$("#assignment_config").removeAttr("disabled");
|
||||
}
|
||||
else if (assignmentType === 'random')
|
||||
{
|
||||
$('#chore-assignment-type-info').text(__t('This means the next execution of this chore will be assigned randomly'));
|
||||
$("#assignment_config").attr("required", "");
|
||||
$("#assignment_config").removeAttr("disabled");
|
||||
}
|
||||
else if (assignmentType === 'in-alphabetical-order')
|
||||
{
|
||||
$('#chore-assignment-type-info').text(__t('This means the next execution of this chore will be assigned to the next one in alphabetical order'));
|
||||
$("#assignment_config").attr("required", "");
|
||||
$("#assignment_config").removeAttr("disabled");
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.ValidateForm('chore-form');
|
||||
});
|
||||
|
@ -43,7 +43,7 @@ $("#status-filter").on("change", function()
|
||||
// Transfer CSS classes of selected element to dropdown element (for background)
|
||||
$(this).attr("class", $("#" + $(this).attr("id") + " option[value='" + value + "']").attr("class") + " form-control");
|
||||
|
||||
choresOverviewTable.column(4).search(value).draw();
|
||||
choresOverviewTable.column(5).search(value).draw();
|
||||
});
|
||||
|
||||
$(".status-filter-button").on("click", function()
|
||||
@ -114,6 +114,15 @@ $(document).on('click', '.track-chore-button', function(e)
|
||||
$('#chore-' + choreId + '-next-execution-time-timeago').attr('datetime', result.next_estimated_execution_time);
|
||||
}
|
||||
|
||||
if (result.chore.next_execution_assigned_to_user_id != null)
|
||||
{
|
||||
$('#chore-' + choreId + '-next-execution-assigned-user').parent().effect('highlight', {}, 500);
|
||||
$('#chore-' + choreId + '-next-execution-assigned-user').fadeOut(500, function ()
|
||||
{
|
||||
$(this).text(result.next_execution_assigned_user.display_name).fadeIn(500);
|
||||
});
|
||||
}
|
||||
|
||||
Grocy.FrontendHelpers.EndUiBusy();
|
||||
toastr.success(__t('Tracked execution of chore %1$s on %2$s', choreName, trackedTime));
|
||||
RefreshStatistics();
|
||||
@ -160,6 +169,7 @@ function RefreshStatistics()
|
||||
{
|
||||
var dueCount = 0;
|
||||
var overdueCount = 0;
|
||||
var assignedToMeCount = 0;
|
||||
var now = moment();
|
||||
var nextXDaysThreshold = moment().add(nextXDays, "days");
|
||||
result.forEach(element => {
|
||||
@ -172,10 +182,16 @@ function RefreshStatistics()
|
||||
{
|
||||
dueCount++;
|
||||
}
|
||||
|
||||
if (parseInt(element.next_execution_assigned_to_user_id) == Grocy.UserId)
|
||||
{
|
||||
assignedToMeCount++;
|
||||
}
|
||||
});
|
||||
|
||||
$("#info-due-chores").text(__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-overdue-chores").text(__n(overdueCount, '%s chore is overdue to be done', '%s chores are overdue to be done'));
|
||||
$("#info-assigned-to-me-chores").text(__n(assignedToMeCount, '%s chore is assigned to me', '%s chores are assigned to me'));
|
||||
},
|
||||
function(xhr)
|
||||
{
|
||||
|
@ -190,6 +190,7 @@ $app->group('/api', function()
|
||||
$this->get('/chores/{choreId}', '\Grocy\Controllers\ChoresApiController:ChoreDetails');
|
||||
$this->post('/chores/{choreId}/execute', '\Grocy\Controllers\ChoresApiController:TrackChoreExecution');
|
||||
$this->post('/chores/executions/{executionId}/undo', '\Grocy\Controllers\ChoresApiController:UndoChoreExecution');
|
||||
$this->post('/chores/executions/calculate-next-assignments', '\Grocy\Controllers\ChoresApiController:CalculateNextExecutionAssignments');
|
||||
}
|
||||
|
||||
// Batteries
|
||||
|
@ -4,11 +4,16 @@ namespace Grocy\Services;
|
||||
|
||||
class ChoresService extends BaseService
|
||||
{
|
||||
const CHORE_TYPE_MANUALLY = 'manually';
|
||||
const CHORE_TYPE_DYNAMIC_REGULAR = 'dynamic-regular';
|
||||
const CHORE_TYPE_DAILY = 'daily';
|
||||
const CHORE_TYPE_weekly = 'weekly';
|
||||
const CHORE_TYPE_monthly = 'monthly';
|
||||
const CHORE_PERIOD_TYPE_MANUALLY = 'manually';
|
||||
const CHORE_PERIOD_TYPE_DYNAMIC_REGULAR = 'dynamic-regular';
|
||||
const CHORE_PERIOD_TYPE_DAILY = 'daily';
|
||||
const CHORE_PERIOD_TYPE_WEEKLY = 'weekly';
|
||||
const CHORE_PERIOD_TYPE_MONTHLY = 'monthly';
|
||||
|
||||
const CHORE_ASSIGNMENT_TYPE_NO_ASSIGNMENT = 'no-assignment';
|
||||
const CHORE_ASSIGNMENT_TYPE_WHO_LEAST_DID_FIRST = 'who-least-did-first';
|
||||
const CHORE_ASSIGNMENT_TYPE_RANDOM = 'random';
|
||||
const CHORE_ASSIGNMENT_TYPE_IN_ALPHABETICAL_ORDER = 'in-alphabetical-order';
|
||||
|
||||
public function GetCurrent()
|
||||
{
|
||||
@ -23,26 +28,34 @@ class ChoresService extends BaseService
|
||||
throw new \Exception('Chore does not exist');
|
||||
}
|
||||
|
||||
$usersService = new UsersService();
|
||||
$users = $usersService->GetUsersAsDto();
|
||||
|
||||
$chore = $this->Database->chores($choreId);
|
||||
$choreTrackedCount = $this->Database->chores_log()->where('chore_id = :1 AND undone = 0', $choreId)->count();
|
||||
$choreLastTrackedTime = $this->Database->chores_log()->where('chore_id = :1 AND undone = 0', $choreId)->max('tracked_time');
|
||||
$nextExeuctionTime = $this->Database->chores_current()->where('chore_id', $choreId)->min('next_estimated_execution_time');
|
||||
$nextExecutionTime = $this->Database->chores_current()->where('chore_id', $choreId)->min('next_estimated_execution_time');
|
||||
|
||||
$lastChoreLogRow = $this->Database->chores_log()->where('chore_id = :1 AND tracked_time = :2 AND undone = 0', $choreId, $choreLastTrackedTime)->fetch();
|
||||
$lastDoneByUser = null;
|
||||
if ($lastChoreLogRow !== null && !empty($lastChoreLogRow))
|
||||
{
|
||||
$usersService = new UsersService();
|
||||
$users = $usersService->GetUsersAsDto();
|
||||
$lastDoneByUser = FindObjectInArrayByPropertyValue($users, 'id', $lastChoreLogRow->done_by_user_id);
|
||||
}
|
||||
|
||||
$nextExecutionAssignedUser = null;
|
||||
if (!empty($chore->next_execution_assigned_to_user_id))
|
||||
{
|
||||
$nextExecutionAssignedUser = FindObjectInArrayByPropertyValue($users, 'id', $chore->next_execution_assigned_to_user_id);
|
||||
}
|
||||
|
||||
return array(
|
||||
'chore' => $chore,
|
||||
'last_tracked' => $choreLastTrackedTime,
|
||||
'tracked_count' => $choreTrackedCount,
|
||||
'last_done_by' => $lastDoneByUser,
|
||||
'next_estimated_execution_time' => $nextExeuctionTime
|
||||
'next_estimated_execution_time' => $nextExecutionTime,
|
||||
'next_execution_assigned_user' => $nextExecutionAssignedUser
|
||||
);
|
||||
}
|
||||
|
||||
@ -72,7 +85,9 @@ class ChoresService extends BaseService
|
||||
));
|
||||
$logRow->save();
|
||||
|
||||
return $this->Database->lastInsertId();
|
||||
$lastInsertId = $this->Database->lastInsertId();
|
||||
$this->CalculateNextExecutionAssignment($choreId);
|
||||
return $lastInsertId;
|
||||
}
|
||||
|
||||
private function ChoreExists($choreId)
|
||||
@ -95,4 +110,86 @@ class ChoresService extends BaseService
|
||||
'undone_timestamp' => date('Y-m-d H:i:s')
|
||||
));
|
||||
}
|
||||
|
||||
public function CalculateNextExecutionAssignment($choreId)
|
||||
{
|
||||
if (!$this->ChoreExists($choreId))
|
||||
{
|
||||
throw new \Exception('Chore does not exist');
|
||||
}
|
||||
|
||||
$chore = $this->Database->chores($choreId);
|
||||
$choreLastTrackedTime = $this->Database->chores_log()->where('chore_id = :1 AND undone = 0', $choreId)->max('tracked_time');
|
||||
$lastChoreLogRow = $this->Database->chores_log()->where('chore_id = :1 AND tracked_time = :2 AND undone = 0', $choreId, $choreLastTrackedTime)->fetch();
|
||||
$lastDoneByUserId = $lastChoreLogRow->done_by_user_id;
|
||||
|
||||
$usersService = new UsersService();
|
||||
$users = $usersService->GetUsersAsDto();
|
||||
$assignedUsers = array();
|
||||
foreach ($users as $user)
|
||||
{
|
||||
if (in_array($user->id, explode(',', $chore->assignment_config)))
|
||||
{
|
||||
$assignedUsers[] = $user;
|
||||
}
|
||||
}
|
||||
|
||||
$nextExecutionUserId = null;
|
||||
if ($chore->assignment_type == self::CHORE_ASSIGNMENT_TYPE_RANDOM)
|
||||
{
|
||||
// Random assignment and only 1 user in the group? Well, ok - will be hard to guess the next one...
|
||||
if (count($assignedUsers) == 1)
|
||||
{
|
||||
$nextExecutionUserId = array_shift($assignedUsers)->id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Randomness in small groups will likely often result in the same user, so try it as long as this is the case
|
||||
while ($nextExecutionUserId == null || $nextExecutionUserId == $lastDoneByUserId)
|
||||
{
|
||||
$nextExecutionUserId = $assignedUsers[array_rand($assignedUsers)]->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($chore->assignment_type == self::CHORE_ASSIGNMENT_TYPE_IN_ALPHABETICAL_ORDER)
|
||||
{
|
||||
usort($assignedUsers, function($a, $b)
|
||||
{
|
||||
return strcmp($a->display_name, $b->display_name);
|
||||
});
|
||||
|
||||
$nextRoundMatches = false;
|
||||
foreach ($assignedUsers as $user)
|
||||
{
|
||||
if ($nextRoundMatches)
|
||||
{
|
||||
$nextExecutionUserId = $user->id;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($user->id == $lastDoneByUserId)
|
||||
{
|
||||
$nextRoundMatches = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing has matched, probably it was the last user in the sorted list -> the first one is the next one
|
||||
if ($nextExecutionUserId == null)
|
||||
{
|
||||
$nextExecutionUserId = array_shift($assignedUsers)->id;
|
||||
}
|
||||
}
|
||||
else if ($chore->assignment_type == self::CHORE_ASSIGNMENT_TYPE_WHO_LEAST_DID_FIRST)
|
||||
{
|
||||
$row = $this->Database->chores_execution_users_statistics()->where('chore_id = :1', $choreId)->orderBy('execution_count')->limit(1)->fetch();
|
||||
if ($row != null)
|
||||
{
|
||||
$nextExecutionUserId = $row->user_id;
|
||||
}
|
||||
}
|
||||
|
||||
$chore->update(array(
|
||||
'next_execution_assigned_to_user_id' => $nextExecutionUserId
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -125,8 +125,8 @@ class DemoDataGeneratorService extends BaseService
|
||||
INSERt INTO meal_plan(day, recipe_id) VALUES ('{$sundayThisWeek}', 4);
|
||||
|
||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$this->__t_sql('Changed towels in the bathroom')}', 'manually', 5); --1
|
||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$this->__t_sql('Cleaned the kitchen floor')}', 'dynamic-regular', 7); --2
|
||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$this->__t_sql('Lawn mowed in the garden')}', 'dynamic-regular', 21); --3
|
||||
INSERT INTO chores (name, period_type, period_days, assignment_type, assignment_config, next_execution_assigned_to_user_id) VALUES ('{$this->__t_sql('Cleaned the kitchen floor')}', 'dynamic-regular', 7, 'random', '1,2,3,4', 1); --2
|
||||
INSERT INTO chores (name, period_type, period_days, assignment_type, assignment_config, next_execution_assigned_to_user_id) VALUES ('{$this->__t_sql('Lawn mowed in the garden')}', 'dynamic-regular', 21, 'random', '1,2,3,4', 1); --3
|
||||
INSERT INTO chores (name, period_type, period_days) VALUES ('{$this->__t_sql('The thing which happens on the 5th of every month')}', 'monthly', 5); --4
|
||||
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
|
||||
|
@ -34,7 +34,8 @@ class LocalizationService
|
||||
{
|
||||
$this->PotMain = Translations::fromPoFile(__DIR__ . '/../localization/strings.pot');
|
||||
|
||||
$this->Pot = Translations::fromPoFile(__DIR__ . '/../localization/chore_types.pot');
|
||||
$this->Pot = Translations::fromPoFile(__DIR__ . '/../localization/chore_period_types.pot');
|
||||
$this->Pot = $this->Pot->mergeWith(Translations::fromPoFile(__DIR__ . '/../localization/chore_assignment_types.pot'));
|
||||
$this->Pot = $this->Pot->mergeWith(Translations::fromPoFile(__DIR__ . '/../localization/component_translations.pot'));
|
||||
$this->Pot = $this->Pot->mergeWith(Translations::fromPoFile(__DIR__ . '/../localization/demo_data.pot'));
|
||||
$this->Pot = $this->Pot->mergeWith(Translations::fromPoFile(__DIR__ . '/../localization/stock_transaction_types.pot'));
|
||||
@ -45,7 +46,8 @@ class LocalizationService
|
||||
$this->PoUserStrings = new Translations();
|
||||
$this->PoUserStrings->setDomain('grocy/userstrings');
|
||||
|
||||
$this->Po = Translations::fromPoFile(__DIR__ . "/../localization/$culture/chore_types.po");
|
||||
$this->Po = Translations::fromPoFile(__DIR__ . "/../localization/$culture/chore_period_types.po");
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/chore_assignment_types.po"));
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/component_translations.po"));
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/demo_data.po"));
|
||||
$this->Po = $this->Po->mergeWith(Translations::fromPoFile(__DIR__ . "/../localization/$culture/stock_transaction_types.po"));
|
||||
|
@ -8,6 +8,15 @@
|
||||
|
||||
@section('viewJsName', 'choreform')
|
||||
|
||||
@push('pageScripts')
|
||||
<script src="{{ $U('/node_modules/bootstrap-select/dist/js/bootstrap-select.min.js?v=', true) }}{{ $version }}"></script>
|
||||
@if(!empty($__t('bootstrap-select_locale') && $__t('bootstrap-select_locale') != 'x'))<script src="{{ $U('/node_modules', true) }}/bootstrap-select/dist/js/i18n/defaults-{{ $__t('bootstrap-select_locale') }}.js?v={{ $version }}"></script>@endif
|
||||
@endpush
|
||||
|
||||
@push('pageStyles')
|
||||
<link href="{{ $U('/node_modules/bootstrap-select/dist/css/bootstrap-select.min.css?v=', true) }}{{ $version }}" rel="stylesheet">
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-xs-12">
|
||||
@ -33,7 +42,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="period_type">{{ $__t('Period type') }}</label>
|
||||
<label for="period_type">{{ $__t('Period type') }} <span id="chore-period-type-info" class="small text-muted"></span></label>
|
||||
<select required class="form-control input-group-chore-period-type" id="period_type" name="period_type">
|
||||
@foreach($periodTypes as $periodType)
|
||||
<option @if($mode == 'edit' && $periodType == $chore->period_type) selected="selected" @endif value="{{ $periodType }}">{{ $__t($periodType) }}</option>
|
||||
@ -50,7 +59,6 @@
|
||||
'min' => '0',
|
||||
'additionalCssClasses' => 'input-group-chore-period-type',
|
||||
'invalidFeedback' => $__t('This cannot be negative'),
|
||||
'additionalHtmlElements' => '<span id="chore-period-type-info" class="small text-muted"></span>',
|
||||
'additionalGroupCssClasses' => 'period-type-input period-type-dynamic-regular period-type-monthly'
|
||||
))
|
||||
|
||||
@ -87,6 +95,26 @@
|
||||
|
||||
<input type="hidden" id="period_config" name="period_config" value="@if($mode == 'edit'){{ $chore->period_config }}@endif">
|
||||
|
||||
<div class="form-group">
|
||||
<label for="assignment_type">{{ $__t('Assignment type') }} <span id="chore-assignment-type-info" class="small text-muted"></span></label>
|
||||
<select required class="form-control input-group-chore-assignment-type" id="assignment_type" name="assignment_type">
|
||||
@foreach($assignmentTypes as $assignmentType)
|
||||
<option @if($mode == 'edit' && $assignmentType == $chore->assignment_type) selected="selected" @endif value="{{ $assignmentType }}">{{ $__t($assignmentType) }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $__t('An assignment type is required') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="assignment_config">{{ $__t('Assign to') }}</label>
|
||||
<select required multiple class="form-control input-group-chore-assignment-type selectpicker" id="assignment_config" name="assignment_config" data-actions-Box="true" data-live-search="true">
|
||||
@foreach($users as $user)
|
||||
<option @if($mode == 'edit' && in_array($user->id, explode(',', $chore->assignment_config))) selected="selected" @endif value="{{ $user->id }}">{{ $user->display_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="invalid-feedback">{{ $__t('This assignment type requires that at least one is assigned') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input type="hidden" name="track_date_only" value="0">
|
||||
|
@ -17,7 +17,8 @@
|
||||
</a>
|
||||
</h1>
|
||||
<p id="info-due-chores" data-status-filter="duesoon" data-next-x-days="{{ $nextXDays }}" class="btn btn-lg btn-warning status-filter-button responsive-button mr-2"></p>
|
||||
<p id="info-overdue-chores" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button"></p>
|
||||
<p id="info-overdue-chores" data-status-filter="overdue" class="btn btn-lg btn-danger status-filter-button responsive-button mr-2"></p>
|
||||
<p id="info-assigned-to-me-chores" data-status-filter="assigned-to-me" class="btn btn-lg btn-secondary status-filter-button responsive-button"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -32,6 +33,7 @@
|
||||
<option class="bg-white" value="all">{{ $__t('All') }}</option>
|
||||
<option class="bg-warning" value="duesoon">{{ $__t('Due soon') }}</option>
|
||||
<option class="bg-danger" value="overdue">{{ $__t('Overdue') }}</option>
|
||||
<option class="bg-secondary text-white" value="assigned-to-me">{{ $__t('Assigned to me') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -45,6 +47,7 @@
|
||||
<th>{{ $__t('Chore') }}</th>
|
||||
<th>{{ $__t('Next estimated tracking') }}</th>
|
||||
<th>{{ $__t('Last tracked') }}</th>
|
||||
<th>{{ $__t('Assigned to') }}</th>
|
||||
<th class="d-none">Hidden status</th>
|
||||
|
||||
@include('components.userfields_thead', array(
|
||||
@ -55,7 +58,7 @@
|
||||
</thead>
|
||||
<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_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_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s', strtotime("+$nextXDays days"))) table-warning @endif">
|
||||
<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">
|
||||
<td class="fit-content border-right">
|
||||
<a class="btn btn-success btn-sm track-chore-button" href="#" data-toggle="tooltip" data-placement="left" title="{{ $__t('Track execution of chore %s', FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->name) }}"
|
||||
data-chore-id="{{ $curentChoreEntry->chore_id }}"
|
||||
@ -83,7 +86,7 @@
|
||||
{{ FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->name }}
|
||||
</td>
|
||||
<td>
|
||||
@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_TYPE_MANUALLY)
|
||||
@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_PERIOD_TYPE_MANUALLY)
|
||||
<span id="chore-{{ $curentChoreEntry->chore_id }}-next-execution-time">{{ $curentChoreEntry->next_estimated_execution_time }}</span>
|
||||
<time id="chore-{{ $curentChoreEntry->chore_id }}-next-execution-time-timeago" class="timeago timeago-contextual @if($curentChoreEntry->track_date_only == 1) timeago-date-only @endif" datetime="{{ $curentChoreEntry->next_estimated_execution_time }}"></time>
|
||||
@else
|
||||
@ -94,8 +97,18 @@
|
||||
<span id="chore-{{ $curentChoreEntry->chore_id }}-last-tracked-time">{{ $curentChoreEntry->last_tracked_time }}</span>
|
||||
<time id="chore-{{ $curentChoreEntry->chore_id }}-last-tracked-time-timeago" class="timeago timeago-contextual @if($curentChoreEntry->track_date_only == 1) timeago-date-only @endif" datetime="{{ $curentChoreEntry->last_tracked_time }}"></time>
|
||||
</td>
|
||||
<td>
|
||||
<span id="chore-{{ $curentChoreEntry->chore_id }}-next-execution-assigned-user">
|
||||
@if(!empty($curentChoreEntry->next_execution_assigned_to_user_id))
|
||||
{{ FindObjectInArrayByPropertyValue($users, 'id', $curentChoreEntry->next_execution_assigned_to_user_id)->display_name }}
|
||||
@else
|
||||
...
|
||||
@endif
|
||||
</span>
|
||||
</td>
|
||||
<td class="d-none">
|
||||
@if(FindObjectInArrayByPropertyValue($chores, 'id', $curentChoreEntry->chore_id)->period_type !== \Grocy\Services\ChoresService::CHORE_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_TYPE_MANUALLY && $curentChoreEntry->next_estimated_execution_time < date('Y-m-d H:i:s', strtotime("+$nextXDays days"))) duesoon @endif
|
||||
@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
|
||||
@if($curentChoreEntry->next_execution_assigned_to_user_id == GROCY_USER_ID) assigned-to-me @endif
|
||||
</td>
|
||||
|
||||
@include('components.userfields_tbody', array(
|
||||
|
@ -57,6 +57,7 @@
|
||||
Grocy.GettextPo = {!! $GettextPo !!};
|
||||
Grocy.UserSettings = {!! json_encode($userSettings) !!};
|
||||
Grocy.FeatureFlags = {!! json_encode($featureFlags) !!};
|
||||
Grocy.UserId = {{ GROCY_USER_ID }};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
|
@ -25,6 +25,11 @@ bootbox@^5.1.3:
|
||||
bootstrap ">=3.0.0"
|
||||
jquery ">=1.9.1"
|
||||
|
||||
bootstrap-select@^1.13.10:
|
||||
version "1.13.10"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap-select/-/bootstrap-select-1.13.10.tgz#b0cf57f8d448bc0488faba04ecaa2f4c5216e144"
|
||||
integrity sha512-mwfyd+VWHY8wDN4je4Y8PPEaOAzDPUz95z5F5zxzlIqebqxtbrujclFWLrhkVOyETpsgZCL1rsfyEnHpAugtGg==
|
||||
|
||||
bootstrap@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.0.0.tgz#ceb03842c145fcc1b9b4e15da2a05656ba68469a"
|
||||
|
Loading…
x
Reference in New Issue
Block a user