2018-09-22 13:26:58 +02:00
var choresOverviewTable = $ ( '#chores-overview-table' ) . DataTable ( {
2020-12-30 13:55:01 +01:00
'order' : [ [ 2 , 'asc' ] ] ,
2018-05-13 09:38:22 +02:00
'columnDefs' : [
2020-01-03 14:18:56 +01:00
{ 'orderable' : false , 'targets' : 0 } ,
2020-12-17 17:33:24 +01:00
{ 'searchable' : false , "targets" : 0 } ,
{ "type" : "html" , "targets" : 5 } ,
{ "type" : "html" , "targets" : 2 } ,
{ "type" : "html" , "targets" : 3 }
2020-12-07 19:48:33 +01:00
] . concat ( $ . fn . dataTable . defaults . columnDefs )
2017-07-25 20:03:31 +02:00
} ) ;
2019-01-05 20:06:35 +01:00
$ ( '#chores-overview-table tbody' ) . removeClass ( "d-none" ) ;
2019-03-04 17:43:12 +01:00
choresOverviewTable . columns . adjust ( ) . draw ( ) ;
2018-05-13 09:38:22 +02:00
2019-10-15 19:59:14 +02:00
$ ( "#search" ) . on ( "keyup" , Delay ( function ( )
2018-07-09 19:27:22 +02:00
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
2019-01-19 00:37:21 -07:00
2018-09-22 13:26:58 +02:00
choresOverviewTable . search ( value ) . draw ( ) ;
2019-10-15 19:59:14 +02:00
} , 200 ) ) ;
2018-07-09 19:27:22 +02:00
2018-09-24 19:13:53 +02:00
$ ( "#status-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
// Transfer CSS classes of selected element to dropdown element (for background)
$ ( this ) . attr ( "class" , $ ( "#" + $ ( this ) . attr ( "id" ) + " option[value='" + value + "']" ) . attr ( "class" ) + " form-control" ) ;
2019-01-19 00:37:21 -07:00
2021-11-12 18:26:19 +01:00
choresOverviewTable . column ( choresOverviewTable . colReorder . transpose ( 5 ) ) . search ( value ) . draw ( ) ;
2018-09-24 19:13:53 +02:00
} ) ;
2019-09-17 16:50:29 +02:00
$ ( "#user-filter" ) . on ( "change" , function ( )
{
var value = $ ( this ) . val ( ) ;
if ( value === "all" )
{
value = "" ;
}
// Transfer CSS classes of selected element to dropdown element (for background)
$ ( this ) . attr ( "class" , $ ( "#" + $ ( this ) . attr ( "id" ) + " option[value='" + value + "']" ) . attr ( "class" ) + " form-control" ) ;
2021-11-12 18:26:19 +01:00
choresOverviewTable . column ( choresOverviewTable . colReorder . transpose ( 6 ) ) . search ( value ) . draw ( ) ;
2019-09-17 16:50:29 +02:00
2023-02-06 20:22:10 +01:00
if ( value )
2019-09-17 16:50:29 +02:00
{
UpdateUriParam ( "user" , $ ( "#user-filter option:selected" ) . data ( "user-id" ) ) ;
}
} ) ;
2020-11-07 14:53:45 +01:00
$ ( "#clear-filter-button" ) . on ( "click" , function ( )
{
$ ( "#search" ) . val ( "" ) ;
$ ( "#status-filter" ) . val ( "all" ) ;
$ ( "#user-filter" ) . val ( "all" ) ;
2021-11-12 18:26:19 +01:00
choresOverviewTable . column ( choresOverviewTable . colReorder . transpose ( 5 ) ) . search ( "" ) . draw ( ) ;
choresOverviewTable . column ( choresOverviewTable . colReorder . transpose ( 6 ) ) . search ( "" ) . draw ( ) ;
2020-11-07 14:53:45 +01:00
choresOverviewTable . search ( "" ) . draw ( ) ;
2021-06-27 18:39:29 +02:00
RemoveUriParam ( "user" ) ;
2020-11-07 14:53:45 +01:00
} ) ;
2020-04-19 08:51:02 -04:00
$ ( ".status-filter-message" ) . on ( "click" , function ( )
2018-09-24 19:13:53 +02:00
{
var value = $ ( this ) . data ( "status-filter" ) ;
$ ( "#status-filter" ) . val ( value ) ;
$ ( "#status-filter" ) . trigger ( "change" ) ;
} ) ;
2020-04-19 08:51:02 -04:00
$ ( ".user-filter-message" ) . on ( "click" , function ( )
2019-09-17 16:50:29 +02:00
{
2019-09-17 16:58:42 +02:00
var value = $ ( this ) . data ( "user-filter" ) ;
2019-09-17 16:50:29 +02:00
$ ( "#user-filter" ) . val ( value ) ;
$ ( "#user-filter" ) . trigger ( "change" ) ;
} ) ;
2018-09-22 13:26:58 +02:00
$ ( document ) . on ( 'click' , '.track-chore-button' , function ( e )
2018-05-13 09:38:22 +02:00
{
2018-09-24 09:30:26 +02:00
e . preventDefault ( ) ;
2018-09-25 16:24:43 +02:00
2023-05-03 08:32:49 +02:00
$ ( ".tooltip" ) . tooltip ( "hide" ) ;
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy ( ) ;
2019-01-19 00:37:21 -07:00
2018-09-22 13:26:58 +02:00
var choreId = $ ( e . currentTarget ) . attr ( 'data-chore-id' ) ;
var choreName = $ ( e . currentTarget ) . attr ( 'data-chore-name' ) ;
2022-02-08 18:08:26 +01:00
var skipped = $ ( e . currentTarget ) . hasClass ( "skip" ) ;
2023-03-31 20:12:06 +02:00
var now = $ ( e . currentTarget ) . hasClass ( "now" ) ;
2018-05-13 09:38:22 +02:00
2022-03-23 18:22:50 +01:00
Grocy . Api . Get ( 'chores/' + choreId ,
function ( choreDetails )
2018-05-13 09:38:22 +02:00
{
2019-05-04 16:13:05 +02:00
var trackedTime = moment ( ) . format ( 'YYYY-MM-DD HH:mm:ss' ) ;
2023-03-31 20:12:06 +02:00
if ( ( skipped || ! now ) && choreDetails . next _estimated _execution _time != null )
2019-05-04 16:13:05 +02:00
{
2022-03-23 18:22:50 +01:00
trackedTime = moment ( choreDetails . next _estimated _execution _time ) . format ( 'YYYY-MM-DD HH:mm:ss' ) ;
}
if ( choreDetails . chore . track _date _only == 1 )
{
2023-03-31 20:12:06 +02:00
if ( ( skipped || ! now ) && choreDetails . next _estimated _execution _time != null )
2022-03-23 18:22:50 +01:00
{
trackedTime = moment ( choreDetails . next _estimated _execution _time ) . format ( 'YYYY-MM-DD' ) ;
}
else
{
trackedTime = moment ( ) . format ( 'YYYY-MM-DD' ) ;
}
2019-05-04 16:13:05 +02:00
}
2022-02-08 18:08:26 +01:00
Grocy . Api . Post ( 'chores/' + choreId + '/execute' , { 'tracked_time' : trackedTime , 'skipped' : skipped } ,
2019-05-04 16:13:05 +02:00
function ( )
2018-08-07 20:11:08 +02:00
{
2019-05-04 16:13:05 +02:00
Grocy . Api . Get ( 'chores/' + choreId ,
function ( result )
2018-08-07 20:11:08 +02:00
{
2019-05-04 16:13:05 +02:00
var choreRow = $ ( '#chore-' + choreId + '-row' ) ;
2022-01-23 17:29:25 +01:00
var nextXDaysThreshold = moment ( ) . add ( $ ( "#info-due-soon-chores" ) . data ( "next-x-days" ) , "days" ) ;
2022-03-31 22:52:38 +02:00
var todayThreshold = moment ( ) . endOf ( "day" ) ;
2019-05-04 16:13:05 +02:00
var now = moment ( ) ;
var nextExecutionTime = moment ( result . next _estimated _execution _time ) ;
choreRow . removeClass ( "table-warning" ) ;
choreRow . removeClass ( "table-danger" ) ;
2022-03-31 22:52:38 +02:00
choreRow . removeClass ( "table-info" ) ;
2019-09-17 17:17:33 +02:00
$ ( '#chore-' + choreId + '-due-filter-column' ) . html ( "" ) ;
2019-05-04 16:13:05 +02:00
if ( nextExecutionTime . isBefore ( now ) )
{
choreRow . addClass ( "table-danger" ) ;
2019-09-17 17:17:33 +02:00
$ ( '#chore-' + choreId + '-due-filter-column' ) . html ( "overdue" ) ;
2019-05-04 16:13:05 +02:00
}
2022-03-31 22:52:38 +02:00
else if ( nextExecutionTime . isSameOrBefore ( todayThreshold ) )
{
choreRow . addClass ( "table-info" ) ;
$ ( '#chore-' + choreId + '-due-filter-column' ) . html ( "duetoday" ) ;
}
2019-05-04 16:13:05 +02:00
else if ( nextExecutionTime . isBefore ( nextXDaysThreshold ) )
{
choreRow . addClass ( "table-warning" ) ;
2019-09-17 17:17:33 +02:00
$ ( '#chore-' + choreId + '-due-filter-column' ) . html ( "duesoon" ) ;
2019-05-04 16:13:05 +02:00
}
2020-01-28 19:27:18 +01:00
animateCSS ( "#chore-" + choreId + "-row td:not(:first)" , "shake" ) ;
$ ( '#chore-' + choreId + '-last-tracked-time' ) . text ( trackedTime ) ;
2019-05-04 16:13:05 +02:00
$ ( '#chore-' + choreId + '-last-tracked-time-timeago' ) . attr ( 'datetime' , trackedTime ) ;
2023-02-06 20:22:10 +01:00
if ( result . next _estimated _execution _time )
2019-05-04 16:13:05 +02:00
{
2020-01-28 19:27:18 +01:00
$ ( '#chore-' + choreId + '-next-execution-time' ) . text ( result . next _estimated _execution _time ) ;
2019-05-04 16:13:05 +02:00
$ ( '#chore-' + choreId + '-next-execution-time-timeago' ) . attr ( 'datetime' , result . next _estimated _execution _time ) ;
}
2022-04-03 13:56:14 +02:00
else
{
$ ( '#chore-' + choreId + '-next-execution-time' ) . text ( "-" ) ;
$ ( '#chore-' + choreId + '-next-execution-time-timeago' ) . removeAttr ( 'datetime' ) ;
}
2019-05-04 16:13:05 +02:00
2019-09-17 13:13:26 +02:00
if ( result . chore . next _execution _assigned _to _user _id != null )
{
2020-01-28 19:27:18 +01:00
$ ( '#chore-' + choreId + '-next-execution-assigned-user' ) . text ( result . next _execution _assigned _user . display _name ) ;
2019-09-17 13:13:26 +02:00
}
2022-04-03 13:56:14 +02:00
else
{
$ ( '#chore-' + choreId + '-next-execution-assigned-user' ) . text ( "-" ) ;
}
2019-09-17 13:13:26 +02:00
2022-04-03 13:56:14 +02:00
$ ( '#chore-' + choreId + '-rescheduled-icon' ) . remove ( ) ;
$ ( '#chore-' + choreId + '-reassigned-icon' ) . remove ( ) ;
2022-03-27 16:11:16 +02:00
2019-05-04 16:13:05 +02:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2019-05-05 14:13:50 +02:00
toastr . success ( _ _t ( 'Tracked execution of chore %1$s on %2$s' , choreName , trackedTime ) ) ;
2019-05-04 16:13:05 +02:00
RefreshStatistics ( ) ;
2019-09-14 13:05:36 +02:00
// Delay due to delayed/animated set of new timestamps above
setTimeout ( function ( )
{
2020-01-27 19:00:49 +01:00
RefreshContextualTimeago ( "#chore-" + choreId + "-row" ) ;
2019-09-17 17:17:33 +02:00
// Refresh the DataTable to re-apply filters
choresOverviewTable . rows ( ) . invalidate ( ) . draw ( false ) ;
$ ( ".input-group-filter" ) . trigger ( "change" ) ;
2019-09-14 13:05:36 +02:00
} , 550 ) ;
2019-05-04 16:13:05 +02:00
} ,
function ( xhr )
{
Grocy . FrontendHelpers . EndUiBusy ( ) ;
console . error ( xhr ) ;
}
) ;
2018-08-07 20:11:08 +02:00
} ,
function ( xhr )
{
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . EndUiBusy ( ) ;
2018-08-07 20:11:08 +02:00
console . error ( xhr ) ;
}
) ;
2018-05-13 09:38:22 +02:00
} ,
function ( xhr )
{
2019-05-04 16:13:05 +02:00
Grocy . FrontendHelpers . EndUiBusy ( "choretracking-form" ) ;
2018-05-13 09:38:22 +02:00
console . error ( xhr ) ;
}
) ;
} ) ;
2018-08-04 15:44:58 +02:00
2019-03-09 13:11:50 +01:00
$ ( document ) . on ( "click" , ".chore-name-cell" , function ( e )
{
Grocy . Components . ChoreCard . Refresh ( $ ( e . currentTarget ) . attr ( "data-chore-id" ) ) ;
$ ( "#choresoverview-chorecard-modal" ) . modal ( "show" ) ;
} ) ;
2021-07-13 19:29:23 +02:00
$ ( document ) . on ( 'click' , '.chore-grocycode-label-print' , function ( e )
{
e . preventDefault ( ) ;
document . activeElement . blur ( ) ;
var choreId = $ ( e . currentTarget ) . attr ( 'data-chore-id' ) ;
Grocy . Api . Get ( 'chores/' + choreId + '/printlabel' , function ( labelData )
{
if ( Grocy . Webhooks . labelprinter !== undefined )
{
Grocy . FrontendHelpers . RunWebhook ( Grocy . Webhooks . labelprinter , labelData ) ;
}
} ) ;
} ) ;
2018-08-04 15:44:58 +02:00
function RefreshStatistics ( )
{
2022-01-23 17:29:25 +01:00
var nextXDays = $ ( "#info-due-soon-chores" ) . data ( "next-x-days" ) ;
2019-01-19 00:37:21 -07:00
Grocy . Api . Get ( 'chores' ,
2018-08-04 15:44:58 +02:00
function ( result )
{
2022-01-23 17:29:25 +01:00
var dueTodayCount = 0 ;
var dueSoonCount = 0 ;
2018-08-04 15:44:58 +02:00
var overdueCount = 0 ;
2019-09-17 13:13:26 +02:00
var assignedToMeCount = 0 ;
2022-01-23 17:29:25 +01:00
var overdueThreshold = moment ( ) ;
2018-08-04 15:44:58 +02:00
var nextXDaysThreshold = moment ( ) . add ( nextXDays , "days" ) ;
2022-01-23 17:29:25 +01:00
var todayThreshold = moment ( ) . endOf ( "day" ) ;
2020-08-30 12:18:16 +02:00
result . forEach ( element =>
{
2018-08-04 15:44:58 +02:00
var date = moment ( element . next _estimated _execution _time ) ;
2022-01-23 17:29:25 +01:00
if ( date . isBefore ( overdueThreshold ) )
2018-08-04 15:44:58 +02:00
{
overdueCount ++ ;
}
2022-01-23 17:29:25 +01:00
else if ( date . isSameOrBefore ( todayThreshold ) )
{
dueTodayCount ++ ;
dueSoonCount ++ ;
}
else if ( date . isSameOrBefore ( nextXDaysThreshold ) )
2018-08-04 15:44:58 +02:00
{
2022-01-23 17:29:25 +01:00
dueSoonCount ++ ;
2018-08-04 15:44:58 +02:00
}
2019-09-17 13:13:26 +02:00
2023-02-06 20:22:10 +01:00
if ( element . next _execution _assigned _to _user _id == Grocy . UserId )
2019-09-17 13:13:26 +02:00
{
assignedToMeCount ++ ;
}
2018-08-04 15:44:58 +02:00
} ) ;
2019-01-19 00:37:21 -07:00
2022-04-04 20:10:29 +02:00
$ ( "#info-due-today-chores" ) . html ( '<span class="d-block d-md-none">' + dueTodayCount + ' <i class="fa-solid 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="fa-solid 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="fa-solid 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="fa-solid 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' ) ) ;
2018-08-04 15:44:58 +02:00
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
}
2022-03-26 18:30:26 +01:00
$ ( document ) . on ( "click" , ".reschedule-chore-button" , function ( e )
{
e . preventDefault ( ) ;
var choreId = $ ( e . currentTarget ) . attr ( "data-chore-id" ) ;
Grocy . EditObjectId = choreId ;
Grocy . Api . Get ( "chores/" + choreId , function ( choreDetails )
{
2022-04-03 13:56:14 +02:00
var prefillDate = choreDetails . next _estimated _execution _time || moment ( ) . format ( "YYYY-MM-DD HH:mm:ss" ) ;
2023-02-06 20:22:10 +01:00
if ( choreDetails . chore . rescheduled _date )
2022-03-26 18:30:26 +01:00
{
prefillDate = choreDetails . chore . rescheduled _date ;
}
if ( choreDetails . chore . track _date _only == 1 )
{
Grocy . Components . DateTimePicker . ChangeFormat ( "YYYY-MM-DD" ) ;
Grocy . Components . DateTimePicker . SetValue ( moment ( prefillDate ) . format ( "YYYY-MM-DD" ) ) ;
}
else
{
Grocy . Components . DateTimePicker . ChangeFormat ( "YYYY-MM-DD HH:mm:ss" ) ;
Grocy . Components . DateTimePicker . SetValue ( moment ( prefillDate ) . format ( "YYYY-MM-DD HH:mm:ss" ) ) ;
}
2022-07-09 09:00:15 +02:00
if ( typeof choreDetails . chore . next _execution _assigned _to _user _id != "string" )
{
choreDetails . chore . next _execution _assigned _to _user _id = "" ;
}
2023-02-06 20:22:10 +01:00
if ( choreDetails . chore . next _execution _assigned _to _user _id )
2022-04-03 13:56:14 +02:00
{
Grocy . Components . UserPicker . SetId ( choreDetails . chore . next _execution _assigned _to _user _id )
}
else
{
Grocy . Components . UserPicker . SetValue ( "" ) ;
Grocy . Components . UserPicker . SetId ( null ) ;
}
2022-03-26 18:30:26 +01:00
$ ( "#reschedule-chore-modal-title" ) . text ( choreDetails . chore . name ) ;
$ ( "#reschedule-chore-modal" ) . modal ( "show" ) ;
} ) ;
} ) ;
$ ( "#reschedule-chore-save-button" ) . on ( "click" , function ( e )
{
e . preventDefault ( ) ;
if ( ! Grocy . FrontendHelpers . ValidateForm ( "reschedule-chore-form" , true ) )
{
return ;
}
2022-04-03 13:56:14 +02:00
Grocy . Api . Put ( 'objects/chores/' + Grocy . EditObjectId , { "rescheduled_date" : Grocy . Components . DateTimePicker . GetValue ( ) , "rescheduled_next_execution_assigned_to_user_id" : Grocy . Components . UserPicker . GetValue ( ) } ,
2022-03-26 18:30:26 +01:00
function ( result )
{
2022-04-03 13:56:14 +02:00
Grocy . Api . Post ( 'chores/executions/calculate-next-assignments' , { "chore_id" : Grocy . EditObjectId } ,
function ( result )
{
window . location . reload ( ) ;
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
2022-03-26 18:30:26 +01:00
} ,
function ( xhr )
{
Grocy . FrontendHelpers . ShowGenericError ( 'Error while saving, probably this item already exists' , xhr . response )
}
) ;
} ) ;
$ ( "#reschedule-chore-clear-button" ) . on ( "click" , function ( e )
{
e . preventDefault ( ) ;
2022-04-03 13:56:14 +02:00
Grocy . Api . Put ( 'objects/chores/' + Grocy . EditObjectId , { "rescheduled_date" : null , "rescheduled_next_execution_assigned_to_user_id" : null } ,
2022-03-26 18:30:26 +01:00
function ( result )
{
2022-04-03 13:56:14 +02:00
Grocy . Api . Post ( 'chores/executions/calculate-next-assignments' , { "chore_id" : Grocy . EditObjectId } ,
function ( result )
{
window . location . reload ( ) ;
} ,
function ( xhr )
{
console . error ( xhr ) ;
}
) ;
2022-03-26 18:30:26 +01:00
} ,
function ( xhr )
{
Grocy . FrontendHelpers . ShowGenericError ( 'Error while saving, probably this item already exists' , xhr . response )
}
) ;
} ) ;
2019-09-17 16:50:29 +02:00
if ( GetUriParam ( "user" ) !== undefined )
{
$ ( "#user-filter" ) . val ( "xx" + GetUriParam ( "user" ) + "xx" ) ;
$ ( "#user-filter" ) . trigger ( "change" ) ;
}
2018-08-04 15:44:58 +02:00
RefreshStatistics ( ) ;