2020-08-30 12:18:16 +02:00
Grocy . Api = { } ;
2018-04-18 19:03:39 +02:00
Grocy . Api . Get = function ( apiFunction , success , error )
2017-04-15 23:16:20 +02:00
{
var xhr = new XMLHttpRequest ( ) ;
2018-04-18 19:03:39 +02:00
var url = U ( '/api/' + apiFunction ) ;
2017-04-15 23:16:20 +02:00
xhr . onreadystatechange = function ( )
{
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2017-04-15 23:16:20 +02:00
{
if ( success )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-19 14:51:51 +01:00
}
2017-04-15 23:16:20 +02:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
xhr . open ( 'GET' , url , true ) ;
xhr . send ( ) ;
2017-04-16 23:11:03 +02:00
} ;
2017-04-15 23:16:20 +02:00
2018-04-18 19:03:39 +02:00
Grocy . Api . Post = function ( apiFunction , jsonData , success , error )
2017-04-15 23:16:20 +02:00
{
var xhr = new XMLHttpRequest ( ) ;
2018-04-18 19:03:39 +02:00
var url = U ( '/api/' + apiFunction ) ;
2017-04-15 23:16:20 +02:00
xhr . onreadystatechange = function ( )
{
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2017-04-15 23:16:20 +02:00
{
if ( success )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-19 14:51:51 +01:00
}
2017-04-15 23:16:20 +02:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
xhr . open ( 'POST' , url , true ) ;
xhr . setRequestHeader ( 'Content-type' , 'application/json' ) ;
xhr . send ( JSON . stringify ( jsonData ) ) ;
2017-04-16 23:11:03 +02:00
} ;
2018-07-11 19:43:05 +02:00
2019-01-19 00:37:21 -07:00
Grocy . Api . Put = function ( apiFunction , jsonData , success , error )
{
var xhr = new XMLHttpRequest ( ) ;
var url = U ( '/api/' + apiFunction ) ;
xhr . onreadystatechange = function ( )
{
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2019-01-19 00:37:21 -07:00
{
if ( success )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-19 14:51:51 +01:00
}
2019-01-19 00:37:21 -07:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
xhr . open ( 'PUT' , url , true ) ;
xhr . setRequestHeader ( 'Content-type' , 'application/json' ) ;
xhr . send ( JSON . stringify ( jsonData ) ) ;
} ;
Grocy . Api . Delete = function ( apiFunction , jsonData , success , error )
{
var xhr = new XMLHttpRequest ( ) ;
var url = U ( '/api/' + apiFunction ) ;
xhr . onreadystatechange = function ( )
{
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2019-01-19 00:37:21 -07:00
{
if ( success )
{
2019-01-19 14:51:51 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-19 14:51:51 +01:00
}
2019-01-19 00:37:21 -07:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
xhr . open ( 'DELETE' , url , true ) ;
xhr . setRequestHeader ( 'Content-type' , 'application/json' ) ;
xhr . send ( JSON . stringify ( jsonData ) ) ;
} ;
2018-10-01 20:20:50 +02:00
Grocy . Api . UploadFile = function ( file , group , fileName , success , error )
2018-09-30 23:22:17 +02:00
{
2018-10-01 20:20:50 +02:00
var xhr = new XMLHttpRequest ( ) ;
2019-01-21 22:13:42 +01:00
var url = U ( '/api/files/' + group + '/' + btoa ( fileName ) ) ;
2018-10-01 20:20:50 +02:00
xhr . onreadystatechange = function ( )
2018-09-30 23:22:17 +02:00
{
2018-10-01 20:20:50 +02:00
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-21 22:13:42 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2018-10-01 20:20:50 +02:00
{
if ( success )
{
2019-01-21 22:13:42 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-21 22:13:42 +01:00
}
2018-10-01 20:20:50 +02:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
2018-09-30 23:22:17 +02:00
2018-10-01 20:20:50 +02:00
xhr . open ( 'PUT' , url , true ) ;
xhr . setRequestHeader ( 'Content-type' , 'application/octet-stream' ) ;
xhr . send ( file ) ;
} ;
Grocy . Api . DeleteFile = function ( fileName , group , success , error )
{
2018-09-30 23:22:17 +02:00
var xhr = new XMLHttpRequest ( ) ;
2019-01-21 22:13:42 +01:00
var url = U ( '/api/files/' + group + '/' + btoa ( fileName ) ) ;
2018-09-30 23:22:17 +02:00
xhr . onreadystatechange = function ( )
{
if ( xhr . readyState === XMLHttpRequest . DONE )
{
2019-01-21 22:13:42 +01:00
if ( xhr . status === 200 || xhr . status === 204 )
2018-09-30 23:22:17 +02:00
{
if ( success )
{
2019-01-21 22:13:42 +01:00
if ( xhr . status === 200 )
{
success ( JSON . parse ( xhr . responseText ) ) ;
}
else
{
2020-08-30 12:18:16 +02:00
success ( { } ) ;
2019-01-21 22:13:42 +01:00
}
2018-09-30 23:22:17 +02:00
}
}
else
{
if ( error )
{
error ( xhr ) ;
}
}
}
} ;
2018-10-01 20:20:50 +02:00
xhr . open ( 'DELETE' , url , true ) ;
xhr . setRequestHeader ( 'Content-type' , 'application/json' ) ;
xhr . send ( ) ;
2018-09-30 23:22:17 +02:00
} ;
2021-06-29 20:24:02 +02:00
U = function ( relativePath )
{
return Grocy . BaseUrl . replace ( /\/$/ , '' ) + relativePath ;
}
2021-07-12 21:20:39 +02:00
Grocy . Translator = new Translator ( Grocy . LocalizationStrings ) ;
2022-02-06 21:09:34 +01:00
Grocy . TranslatorQu = new Translator ( Grocy . LocalizationStringsQu ) ;
2019-07-06 15:43:54 +02:00
_ _t = function ( text , ... placeholderValues )
{
if ( Grocy . Mode === "dev" )
{
var text2 = text ;
2021-07-12 21:20:39 +02:00
if ( Grocy . LocalizationStrings && ! Grocy . LocalizationStrings . messages [ "" ] . hasOwnProperty ( text2 ) )
2021-07-12 19:10:07 +02:00
{
Grocy . Api . Post ( 'system/log-missing-localization' , { "text" : text2 } ) ;
}
2019-07-06 15:43:54 +02:00
}
2020-08-29 16:41:27 +02:00
2021-07-04 21:47:55 +02:00
return Grocy . Translator . _ _ ( text , ... placeholderValues )
2019-07-06 15:43:54 +02:00
}
2022-02-06 21:09:34 +01:00
_ _n = function ( number , singularForm , pluralForm , isQu = false )
2019-07-06 15:43:54 +02:00
{
if ( Grocy . Mode === "dev" )
{
var singularForm2 = singularForm ;
2021-07-12 21:20:39 +02:00
if ( Grocy . LocalizationStrings && ! Grocy . LocalizationStrings . messages [ "" ] . hasOwnProperty ( singularForm2 ) )
2021-07-12 19:10:07 +02:00
{
Grocy . Api . Post ( 'system/log-missing-localization' , { "text" : singularForm2 } ) ;
}
2019-07-06 15:43:54 +02:00
}
2022-02-06 21:09:34 +01:00
if ( isQu )
{
return Grocy . TranslatorQu . n _ _ ( singularForm , pluralForm , Math . abs ( number ) , Math . abs ( number ) )
}
else
{
return Grocy . Translator . n _ _ ( singularForm , pluralForm , Math . abs ( number ) , Math . abs ( number ) )
}
2019-07-06 15:43:54 +02:00
}
if ( ! Grocy . ActiveNav . isEmpty ( ) )
{
var menuItem = $ ( '#sidebarResponsive' ) . find ( "[data-nav-for-page='" + Grocy . ActiveNav + "']" ) ;
menuItem . addClass ( 'active-page' ) ;
2020-01-27 19:00:49 +01:00
if ( menuItem . length )
2019-07-06 15:43:54 +02:00
{
2020-01-27 19:00:49 +01:00
var parentMenuSelector = menuItem . data ( "sub-menu-of" ) ;
if ( typeof parentMenuSelector !== "undefined" )
{
$ ( parentMenuSelector ) . collapse ( "show" ) ;
$ ( parentMenuSelector ) . prev ( ".nav-link-collapse" ) . addClass ( "active-page" ) ;
2020-08-30 12:18:16 +02:00
$ ( parentMenuSelector ) . on ( "shown.bs.collapse" , function ( e )
2020-01-27 19:00:49 +01:00
{
if ( ! menuItem . isVisibleInViewport ( 75 ) )
{
menuItem [ 0 ] . scrollIntoView ( ) ;
}
} )
}
else
{
if ( ! menuItem . isVisibleInViewport ( 75 ) )
{
menuItem [ 0 ] . scrollIntoView ( ) ;
}
}
2019-07-06 15:43:54 +02:00
}
}
var observer = new MutationObserver ( function ( mutations )
{
mutations . forEach ( function ( mutation )
{
if ( mutation . attributeName === "class" )
{
var attributeValue = $ ( mutation . target ) . prop ( mutation . attributeName ) ;
if ( attributeValue . contains ( "sidenav-toggled" ) )
{
window . localStorage . setItem ( "sidebar_state" , "collapsed" ) ;
}
else
{
window . localStorage . setItem ( "sidebar_state" , "expanded" ) ;
}
}
} ) ;
} ) ;
observer . observe ( document . body , {
attributes : true
} ) ;
if ( window . localStorage . getItem ( "sidebar_state" ) === "collapsed" )
{
$ ( "#sidenavToggler" ) . click ( ) ;
}
2020-01-27 19:00:49 +01:00
RefreshContextualTimeago = function ( rootSelector = "#page-content" )
2019-07-06 15:43:54 +02:00
{
2020-01-27 19:00:49 +01:00
$ ( rootSelector + " time.timeago" ) . each ( function ( )
2019-07-06 15:43:54 +02:00
{
var element = $ ( this ) ;
2019-09-26 13:55:42 +02:00
if ( ! element . hasAttr ( "datetime" ) )
{
element . text ( "" )
return
}
2019-07-06 15:43:54 +02:00
var timestamp = element . attr ( "datetime" ) ;
2019-07-07 09:04:40 +02:00
2022-03-07 17:57:14 +01:00
if ( timestamp . isEmpty ( ) || timestamp . length < 10 )
2019-09-26 13:55:42 +02:00
{
element . text ( "" )
return
}
2019-07-06 15:43:54 +02:00
var isNever = timestamp && timestamp . substring ( 0 , 10 ) == "2999-12-31" ;
2019-09-14 13:05:36 +02:00
var isToday = timestamp && timestamp . substring ( 0 , 10 ) == moment ( ) . format ( "YYYY-MM-DD" ) ;
2019-07-07 19:38:57 +02:00
var isDateWithoutTime = element . hasClass ( "timeago-date-only" ) ;
2019-07-07 09:04:40 +02:00
2019-07-06 15:43:54 +02:00
if ( isNever )
{
element . prev ( ) . text ( _ _t ( "Never" ) ) ;
2019-09-21 13:40:31 +02:00
element . text ( "" ) ;
2019-07-06 15:43:54 +02:00
}
2019-07-07 09:04:40 +02:00
else if ( isToday )
2019-07-06 17:19:28 +02:00
{
element . text ( _ _t ( "Today" ) ) ;
}
2019-07-06 15:43:54 +02:00
else
{
2021-11-15 20:05:10 +01:00
element . text ( moment ( timestamp ) . fromNow ( ) ) ;
2019-07-06 15:43:54 +02:00
}
2019-07-07 19:38:57 +02:00
if ( isDateWithoutTime )
{
element . prev ( ) . text ( element . prev ( ) . text ( ) . substring ( 0 , 10 ) ) ;
}
2019-07-06 15:43:54 +02:00
} ) ;
}
RefreshContextualTimeago ( ) ;
toastr . options = {
toastClass : 'alert' ,
closeButton : true ,
timeOut : 20000 ,
extendedTimeOut : 5000
} ;
window . FontAwesomeConfig = {
searchPseudoElements : true
}
2020-08-30 12:18:16 +02:00
Grocy . FrontendHelpers = { } ;
2022-03-26 10:34:00 +01:00
Grocy . FrontendHelpers . ValidateForm = function ( formId , reportValidity = false )
2018-07-11 19:43:05 +02:00
{
var form = document . getElementById ( formId ) ;
2019-09-20 13:37:53 +02:00
if ( form === null || form === undefined )
{
return ;
}
2022-03-26 10:34:00 +01:00
$ ( form ) . addClass ( 'was-validated' ) ;
if ( reportValidity )
2018-07-11 19:43:05 +02:00
{
2022-03-26 10:34:00 +01:00
form . reportValidity ( ) ;
2018-07-11 19:43:05 +02:00
}
2022-03-26 10:34:00 +01:00
return form . checkValidity ( ) ;
2018-07-11 19:43:05 +02:00
}
2018-09-08 09:26:12 +02:00
2018-11-24 19:40:50 +01:00
Grocy . FrontendHelpers . BeginUiBusy = function ( formId = null )
{
$ ( "body" ) . addClass ( "cursor-busy" ) ;
if ( formId !== null )
{
$ ( "#" + formId + " :input" ) . attr ( "disabled" , true ) ;
}
}
Grocy . FrontendHelpers . EndUiBusy = function ( formId = null )
{
$ ( "body" ) . removeClass ( "cursor-busy" ) ;
if ( formId !== null )
{
$ ( "#" + formId + " :input" ) . attr ( "disabled" , false ) ;
}
}
2018-09-08 09:26:12 +02:00
Grocy . FrontendHelpers . ShowGenericError = function ( message , exception )
{
2019-05-01 20:19:18 +02:00
toastr . error ( _ _t ( message ) + '<br><br>' + _ _t ( 'Click to show technical details' ) , '' , {
2018-09-08 09:26:12 +02:00
onclick : function ( )
{
bootbox . alert ( {
2019-05-01 20:19:18 +02:00
title : _ _t ( 'Error details' ) ,
2020-11-17 19:11:02 +01:00
message : '<pre class="my-0"><code>' + JSON . stringify ( exception , null , 4 ) + '</code></pre>' ,
2019-09-24 10:24:47 +02:00
closeButton : false
2018-09-08 09:26:12 +02:00
} ) ;
}
} ) ;
2019-01-19 00:37:21 -07:00
2018-09-08 09:26:12 +02:00
console . error ( exception ) ;
}
2018-09-30 09:57:42 +02:00
2022-04-02 19:26:55 +02:00
Grocy . FrontendHelpers . SaveUserSetting = function ( settingsKey , value , force = false )
2020-12-16 18:18:03 +01:00
{
2022-04-02 19:26:55 +02:00
if ( Grocy . UserSettings [ settingsKey ] == value && ! force )
2022-01-16 14:58:42 +01:00
{
return ;
}
2020-12-16 18:18:03 +01:00
Grocy . UserSettings [ settingsKey ] = value ;
jsonData = { } ;
jsonData . value = value ;
Grocy . Api . Put ( 'user/settings/' + settingsKey , jsonData ,
function ( result )
{
// Nothing to do...
} ,
function ( xhr )
{
2022-01-16 14:58:42 +01:00
console . error ( xhr ) ;
2020-12-16 18:18:03 +01:00
}
) ;
}
Grocy . FrontendHelpers . DeleteUserSetting = function ( settingsKey , reloadPageOnSuccess = false )
{
delete Grocy . UserSettings [ settingsKey ] ;
Grocy . Api . Delete ( 'user/settings/' + settingsKey , { } ,
function ( result )
{
if ( reloadPageOnSuccess )
{
location . reload ( ) ;
}
} ,
function ( xhr )
{
if ( ! xhr . statusText . isEmpty ( ) )
{
Grocy . FrontendHelpers . ShowGenericError ( 'Error while deleting, please retry' , xhr . response )
}
}
) ;
}
2021-06-12 17:21:12 +02:00
Grocy . FrontendHelpers . RunWebhook = function ( webhook , data , repetitions = 1 )
{
Object . assign ( data , webhook . extra _data ) ;
var hasAlreadyFailed = false ;
for ( i = 0 ; i < repetitions ; i ++ )
{
$ . post ( webhook . hook , data ) . fail ( function ( req , status , errorThrown )
{
if ( ! hasAlreadyFailed )
{
hasAlreadyFailed = true ;
Grocy . FrontendHelpers . ShowGenericError ( _ _t ( "Error while executing WebHook" , { "status" : status , "errorThrown" : errorThrown } ) ) ;
}
} ) ;
}
}
2019-06-09 08:58:46 +02:00
$ ( document ) . on ( "keyup paste change" , "input, textarea" , function ( )
2018-09-30 09:57:42 +02:00
{
$ ( this ) . closest ( "form" ) . addClass ( "is-dirty" ) ;
} ) ;
2019-06-09 08:58:46 +02:00
$ ( document ) . on ( "click" , "select" , function ( )
2018-09-30 09:57:42 +02:00
{
$ ( this ) . closest ( "form" ) . addClass ( "is-dirty" ) ;
} ) ;
2018-09-30 17:14:04 +02:00
// Auto saving user setting controls
2020-01-26 15:35:01 +01:00
$ ( document ) . on ( "change" , ".user-setting-control" , function ( )
2018-09-30 17:14:04 +02:00
{
var element = $ ( this ) ;
var settingKey = element . attr ( "data-setting-key" ) ;
2018-10-20 14:55:49 +02:00
2020-11-17 19:11:02 +01:00
if ( ! element [ 0 ] . checkValidity ( ) )
{
return ;
}
2018-10-20 14:55:49 +02:00
var inputType = "unknown" ;
if ( typeof element . attr ( "type" ) !== typeof undefined && element . attr ( "type" ) !== false )
{
inputType = element . attr ( "type" ) . toLowerCase ( ) ;
}
2019-01-19 00:37:21 -07:00
2018-09-30 17:14:04 +02:00
if ( inputType === "checkbox" )
{
value = element . is ( ":checked" ) ;
}
else
{
var value = element . val ( ) ;
}
2019-01-19 00:37:21 -07:00
2020-12-16 18:18:03 +01:00
Grocy . FrontendHelpers . SaveUserSetting ( settingKey , value ) ;
2018-09-30 17:14:04 +02:00
} ) ;
2018-10-01 20:20:50 +02:00
// Show file name Bootstrap custom file input
$ ( 'input.custom-file-input' ) . on ( 'change' , function ( )
{
$ ( this ) . next ( '.custom-file-label' ) . html ( GetFileNameFromPath ( $ ( this ) . val ( ) ) ) ;
} ) ;
// Translation of "Browse"-button of Bootstrap custom file input
if ( $ ( ".custom-file-label" ) . length > 0 )
{
2019-05-01 20:19:18 +02:00
$ ( "<style>" ) . html ( '.custom-file-label::after { content: "' + _ _t ( "Select file" ) + '"; }' ) . appendTo ( "head" ) ;
2018-10-01 20:20:50 +02:00
}
2018-10-03 19:05:00 +02:00
ResizeResponsiveEmbeds = function ( fillEntireViewport = false )
{
if ( ! fillEntireViewport )
{
var maxHeight = $ ( "body" ) . height ( ) - $ ( "#mainNav" ) . outerHeight ( ) - 62 ;
}
else
{
var maxHeight = $ ( "body" ) . height ( ) ;
}
2019-01-19 00:37:21 -07:00
2019-01-26 19:31:41 +01:00
$ ( "embed.embed-responsive" ) . attr ( "height" , maxHeight . toString ( ) + "px" ) ;
$ ( "iframe.embed-responsive" ) . each ( function ( )
{
$ ( this ) . attr ( "height" , $ ( this ) [ 0 ] . contentWindow . document . body . scrollHeight . toString ( ) + "px" ) ;
} ) ;
2018-10-03 19:05:00 +02:00
}
$ ( window ) . on ( 'resize' , function ( )
{
2018-10-13 09:18:16 +02:00
ResizeResponsiveEmbeds ( $ ( "body" ) . hasClass ( "fullscreen-card" ) ) ;
2018-10-03 19:05:00 +02:00
} ) ;
2018-11-17 14:50:52 +01:00
$ ( "iframe" ) . on ( "load" , function ( )
{
ResizeResponsiveEmbeds ( $ ( "body" ) . hasClass ( "fullscreen-card" ) ) ;
} ) ;
function WindowMessageBag ( message , payload = null )
{
2020-08-30 12:18:16 +02:00
var obj = { } ;
2018-11-17 14:50:52 +01:00
obj . Message = message ;
obj . Payload = payload ;
return obj ;
}
2018-11-21 19:08:36 +01:00
// Add border around anchor link section
if ( window . location . hash )
{
$ ( window . location . hash ) . addClass ( "p-2 border border-info rounded" ) ;
}
2019-02-09 13:41:40 +01:00
$ ( "#about-dialog-link" ) . on ( "click" , function ( )
{
bootbox . alert ( {
message : '<iframe height="400px" class="embed-responsive" src="' + U ( "/about?embedded" ) + '"></iframe>' ,
2019-03-09 15:54:16 +01:00
closeButton : false ,
size : "large"
2019-02-09 13:41:40 +01:00
} ) ;
} ) ;
2019-03-03 16:33:48 +01:00
2020-01-27 19:00:49 +01:00
function RefreshLocaleNumberDisplay ( rootSelector = "#page-content" )
2019-03-03 16:33:48 +01:00
{
2020-01-27 19:00:49 +01:00
$ ( rootSelector + " .locale-number.locale-number-currency" ) . each ( function ( )
2019-05-07 19:48:14 +02:00
{
2020-11-16 19:10:29 +01:00
var text = $ ( this ) . text ( ) ;
if ( isNaN ( text ) || text . isEmpty ( ) )
2019-09-26 15:25:30 +02:00
{
return ;
}
2020-11-16 19:10:29 +01:00
var value = parseFloat ( text ) ;
$ ( this ) . text ( value . toLocaleString ( undefined , { style : "currency" , currency : Grocy . Currency , minimumFractionDigits : Grocy . UserSettings . stock _decimal _places _prices , maximumFractionDigits : Grocy . UserSettings . stock _decimal _places _prices } ) ) ;
2019-05-07 19:48:14 +02:00
} ) ;
2019-03-05 19:36:14 +01:00
2020-01-27 19:00:49 +01:00
$ ( rootSelector + " .locale-number.locale-number-quantity-amount" ) . each ( function ( )
2019-05-07 19:48:14 +02:00
{
2020-11-16 19:10:29 +01:00
var text = $ ( this ) . text ( ) ;
if ( isNaN ( text ) || text . isEmpty ( ) )
2019-09-26 15:25:30 +02:00
{
return ;
}
2020-11-16 19:10:29 +01:00
var value = parseFloat ( text ) ;
$ ( this ) . text ( value . toLocaleString ( undefined , { minimumFractionDigits : 0 , maximumFractionDigits : Grocy . UserSettings . stock _decimal _places _amounts } ) ) ;
2019-05-07 19:48:14 +02:00
} ) ;
2019-09-20 20:06:24 +02:00
2020-08-30 12:18:16 +02:00
$ ( rootSelector + " .locale-number.locale-number-generic" ) . each ( function ( )
2019-09-20 20:06:24 +02:00
{
2020-11-16 19:10:29 +01:00
var text = $ ( this ) . text ( ) ;
if ( isNaN ( text ) || text . isEmpty ( ) )
2019-09-26 15:25:30 +02:00
{
return ;
}
2020-08-29 16:41:27 +02:00
2020-11-16 19:10:29 +01:00
var value = parseFloat ( text ) ;
2022-02-28 20:59:58 +01:00
$ ( this ) . text ( value . toLocaleString ( undefined , { minimumFractionDigits : 0 , maximumFractionDigits : 0 } ) ) ;
2019-09-20 20:06:24 +02:00
} ) ;
2019-05-07 19:48:14 +02:00
}
RefreshLocaleNumberDisplay ( ) ;
2019-05-03 19:36:27 +02:00
2020-11-15 14:15:09 +01:00
function RefreshLocaleNumberInput ( rootSelector = "#page-content" )
{
$ ( rootSelector + " .locale-number-input.locale-number-currency" ) . each ( function ( )
{
2020-11-15 22:29:47 +01:00
var value = $ ( this ) . val ( ) ;
2020-11-16 19:10:29 +01:00
if ( isNaN ( value ) || value . toString ( ) . isEmpty ( ) )
2020-11-15 14:15:09 +01:00
{
return ;
}
2020-11-16 19:10:29 +01:00
$ ( this ) . val ( parseFloat ( value ) . toLocaleString ( "en" , { minimumFractionDigits : Grocy . UserSettings . stock _decimal _places _prices , maximumFractionDigits : Grocy . UserSettings . stock _decimal _places _prices , useGrouping : false } ) ) ;
2020-11-15 14:15:09 +01:00
} ) ;
$ ( rootSelector + " .locale-number-input.locale-number-quantity-amount" ) . each ( function ( )
{
2020-11-15 22:29:47 +01:00
var value = $ ( this ) . val ( ) ;
2020-11-16 19:10:29 +01:00
if ( isNaN ( value ) || value . toString ( ) . isEmpty ( ) )
2020-11-15 14:15:09 +01:00
{
return ;
}
2020-11-15 23:03:12 +01:00
$ ( this ) . val ( parseFloat ( value ) . toLocaleString ( "en" , { minimumFractionDigits : 0 , maximumFractionDigits : Grocy . UserSettings . stock _decimal _places _amounts , useGrouping : false } ) ) ;
2020-11-15 14:15:09 +01:00
} ) ;
$ ( rootSelector + " .locale-number-input.locale-number-generic" ) . each ( function ( )
{
2020-11-15 22:29:47 +01:00
var value = $ ( this ) . val ( ) ;
2020-11-16 19:10:29 +01:00
if ( isNaN ( value ) || value . toString ( ) . isEmpty ( ) )
2020-11-15 14:15:09 +01:00
{
return ;
}
2020-11-15 23:03:12 +01:00
$ ( this ) . val ( value . toLocaleString ( "en" , { minimumFractionDigits : 0 , maximumFractionDigits : 2 , useGrouping : false } ) ) ;
2020-11-15 14:15:09 +01:00
} ) ;
}
RefreshLocaleNumberInput ( ) ;
2019-03-05 19:36:14 +01:00
$ ( document ) . on ( "click" , ".easy-link-copy-textbox" , function ( )
{
$ ( this ) . select ( ) ;
} ) ;
2019-08-15 14:35:28 +02:00
$ ( "textarea.wysiwyg-editor" ) . summernote ( {
minHeight : "300px" ,
2022-01-23 18:28:28 +01:00
lang : _ _t ( "summernote_locale" ) ,
callbacks : {
onImageLinkInsert : function ( url )
{
// Summernote workaround: Make images responsive
// By adding the "img-fluid" class to the img tag
$img = $ ( '<img>' ) . attr ( { src : url , class : "img-fluid" } )
$ ( this ) . summernote ( "insertNode" , $img [ 0 ] ) ;
}
}
} ) ;
// Summernote workaround: Make embeds responsive
// By wrapping any embeded video in a container with class "embed-responsive"
$ ( ".note-video-clip" ) . each ( function ( )
{
$ ( this ) . parent ( ) . html ( '<div class="embed-responsive embed-responsive-16by9">' + $ ( this ) . wrap ( "<p/>" ) . parent ( ) . html ( ) + "</div>" ) ;
2019-08-15 14:35:28 +02:00
} ) ;
2019-09-18 13:59:37 +02:00
function LoadImagesLazy ( )
{
2021-07-13 19:29:23 +02:00
$ ( ".lazy:visible" ) . Lazy ( {
2019-09-18 13:59:37 +02:00
enableThrottle : true ,
throttle : 500
} ) ;
}
LoadImagesLazy ( ) ;
2019-09-18 18:46:07 +02:00
if ( ! Grocy . CalendarFirstDayOfWeek . isEmpty ( ) )
{
moment . updateLocale ( moment . locale ( ) , {
week : {
dow : Grocy . CalendarFirstDayOfWeek
}
} ) ;
}
2019-09-20 13:37:53 +02:00
$ ( window ) . on ( "message" , function ( e )
{
var data = e . originalEvent . data ;
if ( data . Message === "ShowSuccessMessage" )
{
toastr . success ( data . Payload ) ;
}
else if ( data . Message === "CloseAllModals" )
{
bootbox . hideAll ( ) ;
}
} ) ;
2019-09-27 16:54:40 +02:00
$ ( document ) . on ( "click" , ".show-as-dialog-link" , function ( e )
{
e . preventDefault ( ) ;
var link = $ ( e . currentTarget ) . attr ( "href" ) ;
2020-08-29 16:41:27 +02:00
2019-09-27 16:54:40 +02:00
bootbox . dialog ( {
message : '<iframe height="650px" class="embed-responsive" src="' + link + '"></iframe>' ,
size : 'large' ,
backdrop : true ,
closeButton : false ,
buttons : {
2020-01-21 17:30:09 +01:00
cancel : {
2020-11-15 15:28:50 +01:00
label : _ _t ( 'Close' ) ,
2020-01-21 17:30:09 +01:00
className : 'btn-secondary responsive-button' ,
2020-08-30 12:18:16 +02:00
callback : function ( )
2019-09-27 16:54:40 +02:00
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
2019-10-15 19:38:51 +02:00
// Default DataTables initialisation settings
2020-12-17 17:41:31 +01:00
var collapsedGroups = { } ;
2019-10-15 19:38:51 +02:00
$ . extend ( true , $ . fn . dataTable . defaults , {
'paginate' : false ,
'deferRender' : true ,
2020-08-30 12:18:16 +02:00
'language' : IsJsonString ( _ _t ( 'datatables_localization' ) ) ? JSON . parse ( _ _t ( 'datatables_localization' ) ) : { } ,
2019-10-15 19:38:51 +02:00
'scrollY' : false ,
2020-11-07 14:53:45 +01:00
'scrollX' : true ,
2019-10-15 19:38:51 +02:00
'colReorder' : true ,
'stateSave' : true ,
2020-08-30 12:18:16 +02:00
'stateSaveParams' : function ( settings , data )
2019-10-15 19:38:51 +02:00
{
data . search . search = "" ;
data . columns . forEach ( column =>
{
column . search . search = "" ;
} ) ;
2020-11-11 21:11:17 +01:00
} ,
'stateSaveCallback' : function ( settings , data )
{
2020-11-15 14:58:35 +01:00
var settingKey = 'datatables_state_' + settings . sTableId ;
2020-12-16 18:18:03 +01:00
if ( $ . isEmptyObject ( data ) )
{
//state.clear was called and unfortunately the table is not refresh, so we are reloading the page
Grocy . FrontendHelpers . DeleteUserSetting ( settingKey , true ) ;
} else
{
var stateData = JSON . stringify ( data ) ;
Grocy . FrontendHelpers . SaveUserSetting ( settingKey , stateData ) ;
}
2020-11-11 21:11:17 +01:00
} ,
'stateLoadCallback' : function ( settings , data )
{
2020-11-15 14:58:35 +01:00
var settingKey = 'datatables_state_' + settings . sTableId ;
2020-11-15 15:20:50 +01:00
if ( Grocy . UserSettings [ settingKey ] == undefined )
{
return null ;
}
else
{
return JSON . parse ( Grocy . UserSettings [ settingKey ] ) ;
}
2020-12-07 19:48:33 +01:00
} ,
2020-12-16 18:18:03 +01:00
'preDrawCallback' : function ( settings )
{
// Currently it is not possible to save the state of rowGroup via saveState events
var api = new $ . fn . dataTable . Api ( settings ) ;
if ( typeof api . rowGroup === "function" )
{
var settingKey = 'datatables_rowGroup_' + settings . sTableId ;
if ( Grocy . UserSettings [ settingKey ] !== undefined )
{
var rowGroup = JSON . parse ( Grocy . UserSettings [ settingKey ] ) ;
// Check if there way changed. the draw event is called often therefore we have to check if it's really necessary
if ( rowGroup . enable !== api . rowGroup ( ) . enabled ( )
|| ( "dataSrc" in rowGroup && rowGroup . dataSrc !== api . rowGroup ( ) . dataSrc ( ) ) )
{
api . rowGroup ( ) . enable ( rowGroup . enable ) ;
if ( "dataSrc" in rowGroup )
{
api . rowGroup ( ) . dataSrc ( rowGroup . dataSrc ) ;
2021-08-04 17:41:20 +02:00
// Apply fixed order for group column
var fixedOrder = {
pre : [ rowGroup . dataSrc , 'asc' ]
} ;
api . order . fixed ( fixedOrder ) ;
2020-12-16 18:18:03 +01:00
}
}
}
}
} ,
2020-12-07 19:48:33 +01:00
'columnDefs' : [
{ type : 'chinese-string' , targets : '_all' }
2020-12-16 18:18:03 +01:00
] ,
'rowGroup' : {
2020-12-17 17:41:31 +01:00
enable : false ,
startRender : function ( rows , group )
{
var collapsed = ! ! collapsedGroups [ group ] ;
var toggleClass = collapsed ? "fa-caret-right" : "fa-caret-down" ;
rows . nodes ( ) . each ( function ( row )
{
row . style . display = collapsed ? "none" : "" ;
} ) ;
return $ ( "<tr/>" )
2020-12-19 23:57:33 +01:00
. append ( '<td colspan="' + rows . columns ( ) [ 0 ] . length + '">' + group + ' <span class="fa fa-fw d-print-none ' + toggleClass + '"/></td>' )
2020-12-17 17:41:31 +01:00
. attr ( "data-name" , group )
. toggleClass ( "collapsed" , collapsed ) ;
}
2020-12-16 18:18:03 +01:00
}
2019-10-15 19:38:51 +02:00
} ) ;
2020-12-17 17:41:31 +01:00
$ ( document ) . on ( "click" , "tr.dtrg-group" , function ( )
{
var name = $ ( this ) . data ( 'name' ) ;
collapsedGroups [ name ] = ! collapsedGroups [ name ] ;
$ ( "table" ) . DataTable ( ) . draw ( ) ;
} ) ;
2020-08-29 12:05:32 +02:00
2020-11-11 17:34:37 +01:00
// serializeJSON defaults
$ . serializeJSON . defaultOptions . checkboxUncheckedValue = "0" ;
2020-08-30 12:18:16 +02:00
$ ( Grocy . UserPermissions ) . each ( function ( index , item )
2020-08-29 12:05:32 +02:00
{
2020-08-30 12:18:16 +02:00
if ( item . has _permission == 0 )
2020-08-29 12:05:32 +02:00
{
2020-08-30 12:18:16 +02:00
$ ( '.permission-' + item . permission _name ) . addClass ( 'disabled' ) . addClass ( 'not-allowed' ) ;
2020-08-29 12:05:32 +02:00
}
} ) ;
2020-09-14 11:20:29 +02:00
$ ( 'a.link-return' ) . not ( ".btn" ) . each ( function ( )
{
var base = $ ( this ) . data ( 'href' ) ;
if ( base . contains ( '?' ) )
2020-08-31 19:11:51 +02:00
{
2022-02-13 20:07:29 +01:00
$ ( this ) . attr ( 'href' , base + '&returnto' + encodeURIComponent ( Grocy . CurrentUrlRelative ) ) ;
2020-08-31 19:11:51 +02:00
}
2020-09-14 11:20:29 +02:00
else
{
2022-02-13 20:07:29 +01:00
$ ( this ) . attr ( 'href' , base + '?returnto=' + encodeURIComponent ( Grocy . CurrentUrlRelative ) ) ;
2020-08-31 19:11:51 +02:00
}
} )
$ ( document ) . on ( "click" , "a.btn.link-return" , function ( e )
{
e . preventDefault ( ) ;
var link = GetUriParam ( "returnto" ) ;
if ( ! link || ! link . length > 0 )
{
location . href = $ ( e . currentTarget ) . attr ( "href" ) ;
}
else
{
location . href = U ( link ) ;
}
} ) ;
2020-09-14 11:15:11 +02:00
2020-09-14 11:20:29 +02:00
$ ( '.dropdown-item' ) . has ( '.form-check input[type=checkbox]' ) . on ( 'click' , function ( e )
{
if ( $ ( e . target ) . is ( 'div.form-check' ) || $ ( e . target ) . is ( 'div.dropdown-item' ) )
2020-09-14 11:15:11 +02:00
{
$ ( e . target ) . find ( 'input[type=checkbox]' ) . click ( ) ;
}
} )
2020-11-08 15:09:10 +01:00
$ ( '.table' ) . on ( 'column-sizing.dt' , function ( e , settings )
{
var dtScrollWidth = $ ( '.dataTables_scroll' ) . width ( ) ;
2021-07-04 15:34:39 +02:00
var tableWidth = $ ( '.table' ) . width ( ) + 100 ; // Some extra padding, otherwise the scrollbar maybe only appears after a column is already completely out of the viewport
2020-11-08 15:09:10 +01:00
if ( dtScrollWidth < tableWidth )
{
2020-11-17 20:50:04 +01:00
$ ( '.dataTables_scrollBody' ) . addClass ( "no-force-overflow-visible" ) ;
2020-11-11 20:14:16 +01:00
$ ( '.dataTables_scrollBody' ) . removeClass ( "force-overflow-visible" ) ;
}
else
2020-11-08 15:09:10 +01:00
{
2020-11-17 20:50:04 +01:00
$ ( '.dataTables_scrollBody' ) . removeClass ( "no-force-overflow-visible" ) ;
2020-11-11 20:14:16 +01:00
$ ( '.dataTables_scrollBody' ) . addClass ( "force-overflow-visible" ) ;
}
} ) ;
$ ( 'td .dropdown' ) . on ( 'show.bs.dropdown' , function ( e )
{
2020-11-17 20:50:04 +01:00
if ( $ ( '.dataTables_scrollBody' ) . hasClass ( "no-force-overflow-visible" ) )
2020-11-11 20:14:16 +01:00
{
$ ( '.dataTables_scrollBody' ) . addClass ( "force-overflow-visible" ) ;
2020-11-08 15:09:10 +01:00
}
} ) ;
2020-11-11 20:14:16 +01:00
$ ( "td .dropdown" ) . on ( 'hide.bs.dropdown' , function ( e )
{
2020-11-17 20:50:04 +01:00
if ( $ ( '.dataTables_scrollBody' ) . hasClass ( "no-force-overflow-visible" ) )
2020-11-11 20:14:16 +01:00
{
$ ( '.dataTables_scrollBody' ) . removeClass ( "force-overflow-visible" ) ;
}
} )
2020-11-08 15:09:10 +01:00
$ ( window ) . on ( "message" , function ( e )
{
var data = e . originalEvent . data ;
if ( data . Message === "Reload" )
{
window . location . reload ( ) ;
}
} ) ;
2020-11-11 21:11:17 +01:00
2020-11-11 22:28:05 +01:00
$ ( ".change-table-columns-visibility-button" ) . on ( "click" , function ( e )
2020-11-11 21:11:17 +01:00
{
2020-11-12 21:35:10 +01:00
e . preventDefault ( ) ;
2020-11-11 21:11:17 +01:00
var dataTableSelector = $ ( e . currentTarget ) . attr ( "data-table-selector" ) ;
var dataTable = $ ( dataTableSelector ) . DataTable ( ) ;
var columnCheckBoxesHtml = "" ;
2020-12-16 18:18:03 +01:00
var rowGroupRadioBoxesHtml = "" ;
var rowGroupDefined = typeof dataTable . rowGroup === "function" ;
if ( rowGroupDefined )
{
var rowGroupChecked = ( dataTable . rowGroup ( ) . enabled ( ) ) ? "" : "checked" ;
rowGroupRadioBoxesHtml = ' \
< div class = "custom-control custom-radio custom-control-inline" > \
< input ' + rowGroupChecked + ' class = "custom-control-input change-table-columns-rowgroup-toggle" \
type = "radio" \
name = "column-rowgroup" \
id = "column-rowgroup-none" \
data - table - selector = "' + dataTableSelector + '" \
data - column - index = "-1" \
> \
2020-12-19 14:03:28 +01:00
< label class = "custom-control-label font-italic" \
2020-12-16 18:18:03 +01:00
for = "column-rowgroup-none" > ' + __t("None") + ' \
< / l a b e l > \
< / d i v > ' ;
}
2020-11-11 21:11:17 +01:00
dataTable . columns ( ) . every ( function ( )
{
var index = this . index ( ) ;
2022-02-15 18:40:42 +01:00
var headerCell = $ ( this . header ( ) ) ;
var title = headerCell . text ( ) ;
2020-11-11 21:11:17 +01:00
var visible = this . visible ( ) ;
if ( title . isEmpty ( ) || title . startsWith ( "Hidden" ) )
{
return ;
}
2022-02-15 18:40:42 +01:00
var shadowColumnIndex = headerCell . attr ( "data-shadow-rowgroup-column" ) ;
2021-06-28 19:14:15 +02:00
if ( shadowColumnIndex )
{
index = shadowColumnIndex ;
}
2020-11-11 21:11:17 +01:00
var checked = "checked" ;
if ( ! visible )
{
checked = "" ;
}
2020-12-16 18:18:03 +01:00
columnCheckBoxesHtml += ' \
2020-11-11 21:11:17 +01:00
< div class = "custom-control custom-checkbox" > \
< input ' + checked + ' class = "form-check-input custom-control-input change-table-columns-visibility-toggle" \
type = "checkbox" \
id = "column-' + index.toString() + '" \
data - table - selector = "' + dataTableSelector + '" \
data - column - index = "' + index.toString() + '" \
value = "1" > \
< label class = "form-check-label custom-control-label" \
for = "column-' + index.toString() + '" > ' + title + ' \
< / l a b e l > \
2020-12-16 18:18:03 +01:00
< / d i v > ' ;
2022-02-15 18:40:42 +01:00
if ( rowGroupDefined && headerCell . hasClass ( "allow-grouping" ) )
2020-12-16 18:18:03 +01:00
{
var rowGroupChecked = "" ;
if ( dataTable . rowGroup ( ) . enabled ( ) && dataTable . rowGroup ( ) . dataSrc ( ) == index )
{
rowGroupChecked = "checked" ;
}
rowGroupRadioBoxesHtml += ' \
< div class = "custom-control custom-radio" > \
< input ' + rowGroupChecked + ' class = "custom-control-input change-table-columns-rowgroup-toggle" \
type = "radio" \
name = "column-rowgroup" \
id = "column-rowgroup-' + index.toString() + '" \
data - table - selector = "' + dataTableSelector + '" \
data - column - index = "' + index.toString() + '" \
> \
< label class = "custom-control-label" \
for = "column-rowgroup-' + index.toString() + '" > ' + title + ' \
< / l a b e l > \
< / d i v > ' ;
}
2020-11-11 21:11:17 +01:00
} ) ;
2022-02-15 18:40:42 +01:00
var message = ' \
< div class = "text-center" > \
< h5 > ' + __t(' Table options ') + ' < / h 5 > \
< hr > \
< h5 class = "mb-0" > ' + __t(' Hide / view columns ') + ' < / h 5 > \
< div class = "text-left form-group" > \
' + columnCheckBoxesHtml + ' \
< / d i v > \
< / d i v > ' ;
2020-12-16 18:18:03 +01:00
if ( rowGroupDefined )
{
2022-02-15 18:40:42 +01:00
message += ' \
< div class = "text-center mt-1" > \
< h5 class = "pt-3 mb-0" > ' + __t(' Group by ') + ' < / h 5 > \
< div class = "text-left form-group" > \
' + rowGroupRadioBoxesHtml + ' \
< / d i v > \
< / d i v > ' ;
2020-12-16 18:18:03 +01:00
}
2020-11-11 21:11:17 +01:00
bootbox . dialog ( {
2020-12-16 18:18:03 +01:00
message : message ,
2020-11-11 21:11:17 +01:00
size : 'small' ,
backdrop : true ,
closeButton : false ,
buttons : {
2020-12-16 18:18:03 +01:00
reset : {
label : _ _t ( 'Reset' ) ,
className : 'btn-outline-danger float-left responsive-button' ,
callback : function ( )
{
bootbox . confirm ( {
message : _ _t ( "Are you sure to reset the table options?" ) ,
buttons : {
cancel : {
label : 'No' ,
2020-12-19 14:03:28 +01:00
className : 'btn-danger'
} ,
confirm : {
label : 'Yes' ,
className : 'btn-success'
2020-12-16 18:18:03 +01:00
}
} ,
callback : function ( result )
{
if ( result )
{
var dataTable = $ ( dataTableSelector ) . DataTable ( ) ;
var tableId = dataTable . settings ( ) [ 0 ] . sTableId ;
// Delete rowgroup settings
Grocy . FrontendHelpers . DeleteUserSetting ( 'datatables_rowGroup_' + tableId ) ;
// Delete state settings
dataTable . state . clear ( ) ;
}
bootbox . hideAll ( ) ;
}
} ) ;
}
} ,
ok : {
2020-11-11 21:11:17 +01:00
label : _ _t ( 'OK' ) ,
className : 'btn-primary responsive-button' ,
callback : function ( )
{
bootbox . hideAll ( ) ;
}
}
}
} ) ;
} ) ;
2020-12-16 18:18:03 +01:00
2020-11-11 21:11:17 +01:00
$ ( document ) . on ( "click" , ".change-table-columns-visibility-toggle" , function ( )
{
var dataTableSelector = $ ( this ) . attr ( "data-table-selector" ) ;
var columnIndex = $ ( this ) . attr ( "data-column-index" ) ;
var dataTable = $ ( dataTableSelector ) . DataTable ( ) ;
dataTable . columns ( columnIndex ) . visible ( this . checked ) ;
2022-03-14 22:39:35 +01:00
LoadImagesLazy ( ) ;
2020-11-11 21:11:17 +01:00
} ) ;
2020-12-16 18:18:03 +01:00
$ ( document ) . on ( "click" , ".change-table-columns-rowgroup-toggle" , function ( )
{
var dataTableSelector = $ ( this ) . attr ( "data-table-selector" ) ;
var columnIndex = $ ( this ) . attr ( "data-column-index" ) ;
var dataTable = $ ( dataTableSelector ) . DataTable ( ) ;
var rowGroup ;
if ( columnIndex == - 1 )
{
rowGroup = {
enable : false
} ;
dataTable . rowGroup ( ) . enable ( false ) ;
2021-08-04 17:41:20 +02:00
// Remove fixed order
dataTable . order . fixed ( { } ) ;
2020-12-16 18:18:03 +01:00
}
else
{
rowGroup = {
enable : true ,
dataSrc : columnIndex
}
dataTable . rowGroup ( ) . enable ( true ) ;
dataTable . rowGroup ( ) . dataSrc ( columnIndex ) ;
2021-08-04 17:41:20 +02:00
// Apply fixed order for group column
var fixedOrder = {
pre : [ columnIndex , 'asc' ]
} ;
dataTable . order . fixed ( fixedOrder ) ;
2020-12-16 18:18:03 +01:00
}
var settingKey = 'datatables_rowGroup_' + dataTable . settings ( ) [ 0 ] . sTableId ;
Grocy . FrontendHelpers . SaveUserSetting ( settingKey , JSON . stringify ( rowGroup ) ) ;
dataTable . draw ( ) ;
} ) ;
2021-07-15 17:54:48 +02:00
2021-07-15 20:17:58 +02:00
if ( Grocy . FeatureFlags . GROCY _FEATURE _FLAG _RECIPES )
{
2021-07-16 17:32:08 +02:00
if ( $ ( window ) . width ( ) < 768 )
{
$ ( "#meal-plan-nav-link" ) . attr ( "href" , $ ( "#meal-plan-nav-link" ) . attr ( "href" ) + "?start=" + moment ( ) . format ( "YYYY-MM-DD" ) + "&days=0" ) ;
}
else
{
$ ( "#meal-plan-nav-link" ) . attr ( "href" , $ ( "#meal-plan-nav-link" ) . attr ( "href" ) + "?start=" + moment ( ) . startOf ( "week" ) . format ( "YYYY-MM-DD" ) ) ;
}
2021-07-15 20:17:58 +02:00
}
2022-04-02 17:49:35 +02:00
$ ( '[data-toggle="tooltip"][data-html="true"]' ) . on ( "shown.bs.tooltip" , function ( )
{
RefreshLocaleNumberDisplay ( ".tooltip" ) ;
} )