diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000000..006074f2ea --- /dev/null +++ b/.htaccess @@ -0,0 +1,14 @@ +# Optional: force HTTPS: +# +# RewriteEngine On +# RewriteCond %{HTTPS} off +# RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L] +# + +# To hide directory listing +Options All -Indexes + +# To prevent access to .env and other files + + Deny from all + diff --git a/.sandstorm/changelog.md b/.sandstorm/changelog.md index 7cef1b27c5..0e4e976f9a 100644 --- a/.sandstorm/changelog.md +++ b/.sandstorm/changelog.md @@ -1,3 +1,21 @@ +# 4.6.13 +- [Issue 1074](https://github.com/firefly-iii/firefly-iii/issues/1074), suggested by [MacPaille](https://github.com/MacPaille) +- [Issue 1077](https://github.com/firefly-iii/firefly-iii/issues/1077), suggested by [wtercato](https://github.com/wtercato) +- Bulk edit of transactions thanks to [vicmosin](https://github.com/vicmosin) ([issue 1078](https://github.com/firefly-iii/firefly-iii/issues/1078)) +- Support for Turkish. +- [Issue 1090](https://github.com/firefly-iii/firefly-iii/issues/1090), suggested by [Findus23](https://github.com/Findus23) +- [Issue 1097](https://github.com/firefly-iii/firefly-iii/issues/1097), suggested by [kelvinhammond](https://github.com/kelvinhammond) +- [Issue 1093](https://github.com/firefly-iii/firefly-iii/issues/1093), suggested by [jinformatique](https://github.com/jinformatique) +- [Issue 1098](https://github.com/firefly-iii/firefly-iii/issues/1098), suggested by [Nik-vr](https://github.com/Nik-vr) +- [Issue 972](https://github.com/firefly-iii/firefly-iii/issues/972), reported by [pjotrvdh](https://github.com/pjotrvdh) +- [Issue 1079](https://github.com/firefly-iii/firefly-iii/issues/1079), reported by [gavu](https://github.com/gavu) +- [Issue 1080](https://github.com/firefly-iii/firefly-iii/issues/1080), reported by [zjean](https://github.com/zjean) +- [Issue 1083](https://github.com/firefly-iii/firefly-iii/issues/1083), reported by [skuzzle](https://github.com/skuzzle) +- [Issue 1085](https://github.com/firefly-iii/firefly-iii/issues/1085), reported by [nicoschreiner](https://github.com/nicoschreiner) +- [Issue 1087](https://github.com/firefly-iii/firefly-iii/issues/1087), reported by [4oo4](https://github.com/4oo4) +- [Issue 1089](https://github.com/firefly-iii/firefly-iii/issues/1089), reported by [robin5210](https://github.com/robin5210) +- [Issue 1092](https://github.com/firefly-iii/firefly-iii/issues/1092), reported by [kelvinhammond](https://github.com/kelvinhammond) +- [Issue 1096](https://github.com/firefly-iii/firefly-iii/issues/1096), reported by [wtercato](https://github.com/wtercato) # 4.6.12 - Support for Indonesian. diff --git a/.sandstorm/sandstorm-files.list b/.sandstorm/sandstorm-files.list index 04910192cc..36bb69887a 100644 --- a/.sandstorm/sandstorm-files.list +++ b/.sandstorm/sandstorm-files.list @@ -200,14 +200,22 @@ lib/x86_64-linux-gnu/libwrap.so.0.7.6 lib/x86_64-linux-gnu/libz.so.1 lib/x86_64-linux-gnu/libz.so.1.2.8 lib64/ld-linux-x86-64.so.2 -opt/app/.dockerignore opt/app/.env opt/app/.env.docker opt/app/.env.example opt/app/.env.heroku opt/app/.env.sandstorm opt/app/.gitattributes +opt/app/.htaccess opt/app/.sandstorm/.gitattributes +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/action_provision +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/action_set_name +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/creator_uid +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/id +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/index_uuid +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/private_key +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/synced_folders +opt/app/.sandstorm/.vagrant/machines/default/virtualbox/vagrant_cwd opt/app/.sandstorm/Vagrantfile opt/app/.sandstorm/app-graphics/firefly-iii-128.png opt/app/.sandstorm/app-graphics/firefly-iii-150.png @@ -231,9 +239,7 @@ opt/app/.sandstorm/setup.sh opt/app/.sandstorm/stack opt/app/CHANGELOG.md opt/app/CODE_OF_CONDUCT.md -opt/app/Dockerfile opt/app/LICENSE -opt/app/Procfile opt/app/README.md opt/app/app.json opt/app/app/Console/Commands/CreateExport.php @@ -359,6 +365,7 @@ opt/app/app/Http/Controllers/Chart/ReportController.php opt/app/app/Http/Controllers/Chart/TagReportController.php opt/app/app/Http/Controllers/Controller.php opt/app/app/Http/Controllers/CurrencyController.php +opt/app/app/Http/Controllers/DebugController.php opt/app/app/Http/Controllers/ExportController.php opt/app/app/Http/Controllers/HelpController.php opt/app/app/Http/Controllers/HomeController.php @@ -389,6 +396,7 @@ opt/app/app/Http/Controllers/RuleController.php opt/app/app/Http/Controllers/RuleGroupController.php opt/app/app/Http/Controllers/SearchController.php opt/app/app/Http/Controllers/TagController.php +opt/app/app/Http/Controllers/Transaction/BulkController.php opt/app/app/Http/Controllers/Transaction/ConvertController.php opt/app/app/Http/Controllers/Transaction/LinkController.php opt/app/app/Http/Controllers/Transaction/MassController.php @@ -416,6 +424,7 @@ opt/app/app/Http/Requests/AttachmentFormRequest.php opt/app/app/Http/Requests/BillFormRequest.php opt/app/app/Http/Requests/BudgetFormRequest.php opt/app/app/Http/Requests/BudgetIncomeRequest.php +opt/app/app/Http/Requests/BulkEditJournalRequest.php opt/app/app/Http/Requests/CategoryFormRequest.php opt/app/app/Http/Requests/ConfigurationRequest.php opt/app/app/Http/Requests/CurrencyFormRequest.php @@ -625,10 +634,21 @@ opt/app/app/Services/Github/Request/GithubRequest.php opt/app/app/Services/Github/Request/UpdateRequest.php opt/app/app/Services/Password/PwndVerifier.php opt/app/app/Services/Password/Verifier.php +opt/app/app/Services/Spectre/Exception/DuplicatedCustomerException.php +opt/app/app/Services/Spectre/Exception/SpectreException.php +opt/app/app/Services/Spectre/Object/Account.php +opt/app/app/Services/Spectre/Object/Attempt.php opt/app/app/Services/Spectre/Object/Customer.php +opt/app/app/Services/Spectre/Object/Holder.php +opt/app/app/Services/Spectre/Object/Login.php opt/app/app/Services/Spectre/Object/SpectreObject.php opt/app/app/Services/Spectre/Object/Token.php +opt/app/app/Services/Spectre/Object/Transaction.php opt/app/app/Services/Spectre/Request/CreateTokenRequest.php +opt/app/app/Services/Spectre/Request/ListAccountsRequest.php +opt/app/app/Services/Spectre/Request/ListCustomersRequest.php +opt/app/app/Services/Spectre/Request/ListLoginsRequest.php +opt/app/app/Services/Spectre/Request/ListTransactionsRequest.php opt/app/app/Services/Spectre/Request/NewCustomerRequest.php opt/app/app/Services/Spectre/Request/SpectreRequest.php opt/app/app/Support/Amount.php @@ -657,7 +677,8 @@ opt/app/app/Support/Import/Configuration/ConfigurationInterface.php opt/app/app/Support/Import/Configuration/File/Initial.php opt/app/app/Support/Import/Configuration/File/Map.php opt/app/app/Support/Import/Configuration/File/Roles.php -opt/app/app/Support/Import/Configuration/File/Upload.php +opt/app/app/Support/Import/Configuration/File/UploadConfig.php +opt/app/app/Support/Import/Configuration/Spectre/HaveAccounts.php opt/app/app/Support/Import/Information/BunqInformation.php opt/app/app/Support/Import/Information/InformationInterface.php opt/app/app/Support/Models/TransactionJournalTrait.php @@ -763,7 +784,6 @@ opt/app/config/session.php opt/app/config/twigbridge.php opt/app/config/upgrade.php opt/app/config/view.php -opt/app/crowdin.yml opt/app/database/factories/ModelFactory.php opt/app/database/migrations/2016_06_16_000000_create_support_tables.php opt/app/database/migrations/2016_06_16_000001_create_users_table.php @@ -786,8 +806,7 @@ opt/app/database/seeds/PermissionSeeder.php opt/app/database/seeds/TransactionCurrencySeeder.php opt/app/database/seeds/TransactionTypeSeeder.php opt/app/docker-compose.yml -opt/app/nginx_app.conf -opt/app/phpunit.coverage.xml +opt/app/index.php opt/app/public/.htaccess opt/app/public/android-chrome-192x192.png opt/app/public/android-chrome-512x512.png @@ -920,6 +939,7 @@ opt/app/public/js/ff/tags/create-edit.js opt/app/public/js/ff/tags/index.js opt/app/public/js/ff/tags/show.js opt/app/public/js/ff/transactions/list.js +opt/app/public/js/ff/transactions/mass/edit-bulk.js opt/app/public/js/ff/transactions/mass/edit.js opt/app/public/js/ff/transactions/show.js opt/app/public/js/ff/transactions/single/common.js @@ -935,8 +955,6 @@ opt/app/public/js/lib/bootstrap-tagsinput.min.js.map opt/app/public/js/lib/bootstrap3-typeahead.min.js opt/app/public/js/lib/daterangepicker.js opt/app/public/js/lib/html5shiv.min.js -opt/app/public/js/lib/jquery-3.1.1.min.js -opt/app/public/js/lib/jquery-3.1.1.min.map opt/app/public/js/lib/jquery-3.2.1.min.js opt/app/public/js/lib/jquery-3.2.1.min.map opt/app/public/js/lib/jquery-ui.min.js @@ -1074,6 +1092,20 @@ opt/app/resources/lang/pl_PL/list.php opt/app/resources/lang/pl_PL/pagination.php opt/app/resources/lang/pl_PL/passwords.php opt/app/resources/lang/pl_PL/validation.php +opt/app/resources/lang/tr_TR/auth.php +opt/app/resources/lang/tr_TR/bank.php +opt/app/resources/lang/tr_TR/breadcrumbs.php +opt/app/resources/lang/tr_TR/config.php +opt/app/resources/lang/tr_TR/csv.php +opt/app/resources/lang/tr_TR/demo.php +opt/app/resources/lang/tr_TR/firefly.php +opt/app/resources/lang/tr_TR/form.php +opt/app/resources/lang/tr_TR/import.php +opt/app/resources/lang/tr_TR/intro.php +opt/app/resources/lang/tr_TR/list.php +opt/app/resources/lang/tr_TR/pagination.php +opt/app/resources/lang/tr_TR/passwords.php +opt/app/resources/lang/tr_TR/validation.php opt/app/resources/stubs/binary.bin opt/app/resources/stubs/csv.csv opt/app/resources/stubs/demo-configuration.json @@ -1194,13 +1226,11 @@ opt/app/resources/views/import/bunq/prerequisites.twig opt/app/resources/views/import/file/initial.twig opt/app/resources/views/import/file/map.twig opt/app/resources/views/import/file/roles.twig -opt/app/resources/views/import/file/upload.twig +opt/app/resources/views/import/file/upload-config.twig opt/app/resources/views/import/index.twig -opt/app/resources/views/import/spectre/input-fields.twig +opt/app/resources/views/import/spectre/accounts.twig opt/app/resources/views/import/spectre/prerequisites.twig opt/app/resources/views/import/spectre/redirect.twig -opt/app/resources/views/import/spectre/select-country.twig -opt/app/resources/views/import/spectre/select-provider.twig opt/app/resources/views/import/status.twig opt/app/resources/views/index.twig opt/app/resources/views/javascript/accounts.twig @@ -1219,6 +1249,7 @@ opt/app/resources/views/list/piggy-bank-events.twig opt/app/resources/views/list/piggy-banks.twig opt/app/resources/views/new-user/index.twig opt/app/resources/views/partials/boxes.twig +opt/app/resources/views/partials/breadcrumbs.twig opt/app/resources/views/partials/control-bar.twig opt/app/resources/views/partials/empty.twig opt/app/resources/views/partials/favicons.twig @@ -1297,10 +1328,11 @@ opt/app/resources/views/tags/edit.twig opt/app/resources/views/tags/index.twig opt/app/resources/views/tags/show.twig opt/app/resources/views/test/test.twig +opt/app/resources/views/transactions/bulk/edit.twig opt/app/resources/views/transactions/convert.twig opt/app/resources/views/transactions/index.twig opt/app/resources/views/transactions/links/delete.twig -opt/app/resources/views/transactions/mass-delete.twig +opt/app/resources/views/transactions/mass/delete.twig opt/app/resources/views/transactions/mass/edit.twig opt/app/resources/views/transactions/show.twig opt/app/resources/views/transactions/single/create.twig @@ -2280,10 +2312,8 @@ opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/boots opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/none-stubs/app.js opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/react-stubs/Example.js opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/react-stubs/app.js -opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/react-stubs/webpack.mix.js opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/vue-stubs/ExampleComponent.vue opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/vue-stubs/app.js -opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/Presets/vue-stubs/webpack.mix.js opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/ProviderMakeCommand.php opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/QueuedCommand.php opt/app/vendor/laravel/framework/src/Illuminate/Foundation/Console/RequestMakeCommand.php @@ -2801,6 +2831,7 @@ opt/app/vendor/league/commonmark/src/Block/Element/Heading.php opt/app/vendor/league/commonmark/src/Block/Element/HtmlBlock.php opt/app/vendor/league/commonmark/src/Block/Element/IndentedCode.php opt/app/vendor/league/commonmark/src/Block/Element/InlineContainer.php +opt/app/vendor/league/commonmark/src/Block/Element/InlineContainerInterface.php opt/app/vendor/league/commonmark/src/Block/Element/ListBlock.php opt/app/vendor/league/commonmark/src/Block/Element/ListData.php opt/app/vendor/league/commonmark/src/Block/Element/ListItem.php @@ -2833,7 +2864,6 @@ opt/app/vendor/league/commonmark/src/Context.php opt/app/vendor/league/commonmark/src/ContextInterface.php opt/app/vendor/league/commonmark/src/Converter.php opt/app/vendor/league/commonmark/src/Cursor.php -opt/app/vendor/league/commonmark/src/CursorState.php opt/app/vendor/league/commonmark/src/Delimiter/Delimiter.php opt/app/vendor/league/commonmark/src/Delimiter/DelimiterStack.php opt/app/vendor/league/commonmark/src/DocParser.php @@ -3336,10 +3366,10 @@ opt/app/vendor/pragmarx/google2fa-laravel/src/config/config.php opt/app/vendor/pragmarx/google2fa-laravel/tests/spec/Support/AuthenticatorSpec.php opt/app/vendor/pragmarx/google2fa-laravel/upgrading.md opt/app/vendor/pragmarx/google2fa/LICENSE +opt/app/vendor/pragmarx/google2fa/README.md opt/app/vendor/pragmarx/google2fa/changelog.md opt/app/vendor/pragmarx/google2fa/composer.json opt/app/vendor/pragmarx/google2fa/docs/playground.jpg -opt/app/vendor/pragmarx/google2fa/readme.md opt/app/vendor/pragmarx/google2fa/src/Exceptions/IncompatibleWithGoogleAuthenticatorException.php opt/app/vendor/pragmarx/google2fa/src/Exceptions/InvalidCharactersException.php opt/app/vendor/pragmarx/google2fa/src/Exceptions/SecretKeyTooShortException.php @@ -3348,6 +3378,7 @@ opt/app/vendor/pragmarx/google2fa/src/Support/Base32.php opt/app/vendor/pragmarx/google2fa/src/Support/Constants.php opt/app/vendor/pragmarx/google2fa/src/Support/QRCode.php opt/app/vendor/pragmarx/google2fa/src/Support/Url.php +opt/app/vendor/pragmarx/google2fa/tests/Constants.php opt/app/vendor/pragmarx/google2fa/tests/Google2FATest.php opt/app/vendor/pragmarx/google2fa/tests/bootstrap.php opt/app/vendor/pragmarx/google2fa/upgrading.md @@ -4049,6 +4080,8 @@ opt/app/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_7 opt/app/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_8.txt opt/app/vendor/symfony/console/Tests/Fixtures/Style/SymfonyStyle/output/output_9.txt opt/app/vendor/symfony/console/Tests/Fixtures/TestCommand.php +opt/app/vendor/symfony/console/Tests/Fixtures/TestTiti.php +opt/app/vendor/symfony/console/Tests/Fixtures/TestToto.php opt/app/vendor/symfony/console/Tests/Fixtures/application_1.json opt/app/vendor/symfony/console/Tests/Fixtures/application_1.md opt/app/vendor/symfony/console/Tests/Fixtures/application_1.txt @@ -4335,6 +4368,7 @@ opt/app/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php opt/app/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php opt/app/vendor/symfony/debug/Tests/HeaderMock.php opt/app/vendor/symfony/debug/Tests/MockExceptionHandler.php +opt/app/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt opt/app/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt opt/app/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt opt/app/vendor/symfony/debug/composer.json @@ -4751,6 +4785,7 @@ opt/app/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php +opt/app/vendor/symfony/http-kernel/Tests/EventListener/SaveSessionListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php opt/app/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php @@ -6161,7 +6196,6 @@ opt/app/vendor/watson/validating/src/ValidatingModel.php opt/app/vendor/watson/validating/src/ValidatingObserver.php opt/app/vendor/watson/validating/src/ValidatingTrait.php opt/app/vendor/watson/validating/src/ValidationException.php -opt/app/webpack.mix.js proc/cpuinfo sandstorm-http-bridge sandstorm-http-bridge-config diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp index fd65c7f0cd..2def36f84d 100644 --- a/.sandstorm/sandstorm-pkgdef.capnp +++ b/.sandstorm/sandstorm-pkgdef.capnp @@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = ( manifest = ( appTitle = (defaultText = "Firefly III"), - appVersion = 6, - appMarketingVersion = (defaultText = "4.6.12"), + appVersion = 7, + appMarketingVersion = (defaultText = "4.6.13"), actions = [ # Define your "new document" handlers here. diff --git a/CHANGELOG.md b/CHANGELOG.md index 46aee1a99b..8be3f71abc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,28 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [4.6.13] - 2018-01-06 +### Added +- [Issue 1074](https://github.com/firefly-iii/firefly-iii/issues/1074), suggested by [MacPaille](https://github.com/MacPaille) +- [Issue 1077](https://github.com/firefly-iii/firefly-iii/issues/1077), suggested by [wtercato](https://github.com/wtercato) +- Bulk edit of transactions thanks to [vicmosin](https://github.com/vicmosin) ([issue 1078](https://github.com/firefly-iii/firefly-iii/issues/1078)) +- Support for Turkish. +- [Issue 1090](https://github.com/firefly-iii/firefly-iii/issues/1090), suggested by [Findus23](https://github.com/Findus23) +- [Issue 1097](https://github.com/firefly-iii/firefly-iii/issues/1097), suggested by [kelvinhammond](https://github.com/kelvinhammond) +- [Issue 1093](https://github.com/firefly-iii/firefly-iii/issues/1093), suggested by [jinformatique](https://github.com/jinformatique) +- [Issue 1098](https://github.com/firefly-iii/firefly-iii/issues/1098), suggested by [Nik-vr](https://github.com/Nik-vr) + +### Fixed +- [Issue 972](https://github.com/firefly-iii/firefly-iii/issues/972), reported by [pjotrvdh](https://github.com/pjotrvdh) +- [Issue 1079](https://github.com/firefly-iii/firefly-iii/issues/1079), reported by [gavu](https://github.com/gavu) +- [Issue 1080](https://github.com/firefly-iii/firefly-iii/issues/1080), reported by [zjean](https://github.com/zjean) +- [Issue 1083](https://github.com/firefly-iii/firefly-iii/issues/1083), reported by [skuzzle](https://github.com/skuzzle) +- [Issue 1085](https://github.com/firefly-iii/firefly-iii/issues/1085), reported by [nicoschreiner](https://github.com/nicoschreiner) +- [Issue 1087](https://github.com/firefly-iii/firefly-iii/issues/1087), reported by [4oo4](https://github.com/4oo4) +- [Issue 1089](https://github.com/firefly-iii/firefly-iii/issues/1089), reported by [robin5210](https://github.com/robin5210) +- [Issue 1092](https://github.com/firefly-iii/firefly-iii/issues/1092), reported by [kelvinhammond](https://github.com/kelvinhammond) +- [Issue 1096](https://github.com/firefly-iii/firefly-iii/issues/1096), reported by [wtercato](https://github.com/wtercato) + ## [4.6.12] - 2017-12-31 ### Added - Support for Indonesian. @@ -16,7 +38,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 1047](https://github.com/firefly-iii/firefly-iii/issues/1047), as reported by [pkoziol](https://github.com/pkoziol) - [Issue 1048](https://github.com/firefly-iii/firefly-iii/issues/1048), as reported by [webence](https://github.com/webence) - [Issue 1049](https://github.com/firefly-iii/firefly-iii/issues/1049), as reported by [nicoschreiner](https://github.com/nicoschreiner) -- [Issue 1015](https://github.com/firefly-iii/firefly-iii/issues/1015), as reporterd by a user on Tweakers.net +- [Issue 1015](https://github.com/firefly-iii/firefly-iii/issues/1015), as reported by a user on Tweakers.net - [Issue 1056](https://github.com/firefly-iii/firefly-iii/issues/1056), as reported by [repercussion](https://github.com/repercussion) - [Issue 1061](https://github.com/firefly-iii/firefly-iii/issues/1061), as reported by [Meizikyn](https://github.com/Meizikyn) - [Issue 1045](https://github.com/firefly-iii/firefly-iii/issues/1045), as reported by [gavu](https://github.com/gavu) @@ -53,7 +75,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - Reconciliation of accounts ([issue 736](https://github.com/firefly-iii/firefly-iii/issues/736)), as requested by [kristophr](https://github.com/kristophr) and several others ### Changed -- Extended currency list, as suggested by @emuhendis in [issue 994](https://github.com/firefly-iii/firefly-iii/issues/994) +- Extended currency list, as suggested by [emuhendis](https://github.com/emuhendis) in [issue 994](https://github.com/firefly-iii/firefly-iii/issues/994) - [Issue 996](https://github.com/firefly-iii/firefly-iii/issues/996) as suggested by [dp87](https://github.com/dp87) ### Removed @@ -78,7 +100,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). - [Issue 1025](https://github.com/firefly-iii/firefly-iii/issues/1025), reported by [gavu](https://github.com/gavu) -## [4.6.10] - 2017-11-xx +## [4.6.10] - 2017-11-03 ### Added - Greatly expanded Docker support thanks to [alazare619](https://github.com/alazare619) - [Issue 967](https://github.com/firefly-iii/firefly-iii/issues/967), thanks to [Aquariu](https://github.com/Aquariu) @@ -353,8 +375,8 @@ This will be the last release to support PHP 7.0. - Can now make rules for attachments, see [issue 608](https://github.com/firefly-iii/firefly-iii/issues/608), as suggested by [dzaikos](https://github.com/dzaikos). ### Fixed -- Fixed [issue 629](https://github.com/firefly-iii/firefly-iii/issues/629), reported by @forcaeluz -- Fixed [issue 630](https://github.com/firefly-iii/firefly-iii/issues/630), reported by @welbert +- Fixed [issue 629](https://github.com/firefly-iii/firefly-iii/issues/629), reported by [forcaeluz](https://github.com/forcaeluz) +- Fixed [issue 630](https://github.com/firefly-iii/firefly-iii/issues/630), reported by [welbert](https://github.com/welbert) - And more various bug fixes. ## [4.3.8] - 2017-04-08 diff --git a/README.md b/README.md index f6e51b4e73..54a593d0f0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,10 @@ Register for a free Heroku account and instantly run Firefly III on your very ow You can find Firefly III in [the Sandstorm.io marketplace](https://apps.sandstorm.io/app/uws252ya9mep4t77tevn85333xzsgrpgth8q4y1rhknn1hammw70). You can run it on your own installation or on Oasis. +### Other options + +Firefly III is also available as a package on [https://softaculous.com/](Softaculous) and [AMPPS](https://www.ampps.com/). + ## More about Firefly III Personal financial management is pretty difficult, and everybody has their own approach to it. diff --git a/app/Console/Commands/UpgradeDatabase.php b/app/Console/Commands/UpgradeDatabase.php index 3e29848440..ee66cebb58 100644 --- a/app/Console/Commands/UpgradeDatabase.php +++ b/app/Console/Commands/UpgradeDatabase.php @@ -146,6 +146,7 @@ class UpgradeDatabase extends Command // both 0? set to default currency: if (0 === $accountCurrency && 0 === $obCurrency) { + AccountMeta::where('account_id', $account->id)->where('name', 'currency_id')->forceDelete(); AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]); $this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode)); @@ -218,7 +219,7 @@ class UpgradeDatabase extends Command } // when mismatch in transaction: - if ($transaction->transaction_currency_id !== $currency->id) { + if (!(intval($transaction->transaction_currency_id) === intval($currency->id))) { $transaction->foreign_currency_id = $transaction->transaction_currency_id; $transaction->foreign_amount = $transaction->amount; $transaction->transaction_currency_id = $currency->id; @@ -401,24 +402,26 @@ class UpgradeDatabase extends Command // has no currency ID? Must have, so fill in using account preference: if (null === $transaction->transaction_currency_id) { - $transaction->transaction_currency_id = $currency->id; + $transaction->transaction_currency_id = intval($currency->id); Log::debug(sprintf('Transaction #%d has no currency setting, now set to %s', $transaction->id, $currency->code)); $transaction->save(); } // does not match the source account (see above)? Can be fixed // when mismatch in transaction and NO foreign amount is set: - if ($transaction->transaction_currency_id !== $currency->id && null === $transaction->foreign_amount) { + if (!(intval($transaction->transaction_currency_id) === intval($currency->id)) && null === $transaction->foreign_amount) { Log::debug( sprintf( - 'Transaction #%d has a currency setting (#%d) that should be #%d. Amount remains %s, currency is changed.', + 'Transaction #%d has a currency setting (#%d) (%s) that should be #%d (%s). Amount remains %s, currency is changed.', $transaction->id, $transaction->transaction_currency_id, + $this->var_dump_ret(intval($transaction->transaction_currency_id)), $currency->id, + $this->var_dump_ret(intval($currency->id)), $transaction->amount ) ); - $transaction->transaction_currency_id = $currency->id; + $transaction->transaction_currency_id = intval($currency->id); $transaction->save(); } @@ -436,7 +439,7 @@ class UpgradeDatabase extends Command } // if the destination account currency is the same, both foreign_amount and foreign_currency_id must be NULL for both transactions: - if ($opposingCurrency->id === $currency->id) { + if (intval($opposingCurrency->id) === intval($currency->id)) { // update both transactions to match: $transaction->foreign_amount = null; $transaction->foreign_currency_id = null; @@ -450,7 +453,7 @@ class UpgradeDatabase extends Command return; } // if destination account currency is different, both transactions must have this currency as foreign currency id. - if ($opposingCurrency->id !== $currency->id) { + if (!(intval($opposingCurrency->id) === intval($currency->id))) { $transaction->foreign_currency_id = $opposingCurrency->id; $opposing->foreign_currency_id = $opposingCurrency->id; $transaction->save(); @@ -500,4 +503,20 @@ class UpgradeDatabase extends Command return; } + + /** + * @param null $mixed + * + * @return string + */ + private function var_dump_ret($mixed = null): string + { + ob_start(); + var_dump($mixed); + $content = ob_get_contents(); + ob_end_clean(); + + return trim($content); + } + } diff --git a/app/Helpers/Collector/JournalCollector.php b/app/Helpers/Collector/JournalCollector.php index 76b149f5d7..7c67975c24 100644 --- a/app/Helpers/Collector/JournalCollector.php +++ b/app/Helpers/Collector/JournalCollector.php @@ -773,7 +773,8 @@ class JournalCollector implements JournalCollectorInterface $this->query->leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id'); $this->query->leftJoin('categories as transaction_categories', 'transaction_categories.id', '=', 'category_transaction.category_id'); - + $this->query->whereNull('transaction_journal_categories.deleted_at'); + $this->query->whereNull('transaction_categories.deleted_at'); $this->fields[] = 'category_transaction_journal.category_id as transaction_journal_category_id'; $this->fields[] = 'transaction_journal_categories.encrypted as transaction_journal_category_encrypted'; $this->fields[] = 'transaction_journal_categories.name as transaction_journal_category_name'; diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 421425a835..8005640860 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -29,6 +29,7 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; +use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -156,14 +157,14 @@ class AccountController extends Controller * @throws FireflyException * @throws FireflyException */ - public function edit(Request $request, Account $account) + public function edit(Request $request, Account $account, AccountRepositoryInterface $repository) { - /** @var CurrencyRepositoryInterface $repository */ - $repository = app(CurrencyRepositoryInterface::class); + /** @var CurrencyRepositoryInterface $currencyRepos */ + $currencyRepos = app(CurrencyRepositoryInterface::class); $what = config('firefly.shortNamesByFullName')[$account->accountType->type]; $subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]); $subTitleIcon = config('firefly.subIconsByIdentifier.' . $what); - $allCurrencies = $repository->get(); + $allCurrencies = $currencyRepos->get(); $currencySelectList = ExpandedForm::makeSelectList($allCurrencies); $roles = []; foreach (config('firefly.accountRoles') as $role) { @@ -183,7 +184,7 @@ class AccountController extends Controller $openingBalanceAmount = '0' === $account->getOpeningBalanceAmount() ? '' : $openingBalanceAmount; $openingBalanceDate = $account->getOpeningBalanceDate(); $openingBalanceDate = 1900 === $openingBalanceDate->year ? null : $openingBalanceDate->format('Y-m-d'); - $currency = $repository->find(intval($account->getMeta('currency_id'))); + $currency = $currencyRepos->find(intval($account->getMeta('currency_id'))); $preFilled = [ 'accountNumber' => $account->getMeta('accountNumber'), @@ -195,7 +196,15 @@ class AccountController extends Controller 'openingBalance' => $openingBalanceAmount, 'virtualBalance' => $account->virtual_balance, 'currency_id' => $currency->id, + 'notes' => '', ]; + /** @var Note $note */ + $note = $repository->getNote($account); + if (null !== $note) { + $preFilled['notes'] = $note->text; + } + + $request->session()->flash('preFilled', $preFilled); return view( diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index bda724008f..89bbf55b54 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -22,8 +22,13 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; +use FireflyConfig; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\Password; /** * Class ForgotPasswordController @@ -51,4 +56,57 @@ class ForgotPasswordController extends Controller parent::__construct(); $this->middleware('guest'); } + + /** + * Send a reset link to the given user. + * + * @param \Illuminate\Http\Request $request + * + * @param UserRepositoryInterface $repository + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + */ + public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository) + { + $this->validateEmail($request); + + // verify if the user is not a demo user. If so, we give him back an error. + $user = User::where('email', $request->get('email'))->first(); + + if (!is_null($user) && $repository->hasRole($user, 'demo')) { + return back()->withErrors(['email' => trans('firefly.cannot_reset_demo_user')]); + } + + // We will send the password reset link to this user. Once we have attempted + // to send the link, we will examine the response then see the message we + // need to show to the user. Finally, we'll send out a proper response. + $response = $this->broker()->sendResetLink( + $request->only('email') + ); + + if ($response == Password::RESET_LINK_SENT) { + return back()->with('status', trans($response)); + } + + return back()->withErrors(['email' => trans($response)]); // @codeCoverageIgnore + } + + /** + * @codeCoverageIgnore + * Display the form to request a password reset link. + * + * @return \Illuminate\Http\Response + */ + public function showLinkRequestForm() + { + // is allowed to? + $singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; + $userCount = User::count(); + $allowRegistration = true; + if (true === $singleUserMode && $userCount > 0) { + $allowRegistration = false; + } + + return view('auth.passwords.email')->with(compact('allowRegistration')); + } } diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index d07102819d..1231fc749d 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -22,8 +22,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; +use FireflyConfig; use FireflyIII\Http\Controllers\Controller; +use FireflyIII\User; use Illuminate\Foundation\Auth\ResetsPasswords; +use Illuminate\Http\Request; /** * @codeCoverageIgnore @@ -52,4 +55,28 @@ class ResetPasswordController extends Controller parent::__construct(); $this->middleware('guest'); } + + /** + * Display the password reset view for the given token. + * + * If no token is present, display the link request form. + * + * @param Request $request + * @param string|null $token + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function showResetForm(Request $request, $token = null) + { + // is allowed to? + $singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; + $userCount = User::count(); + $allowRegistration = true; + if (true === $singleUserMode && $userCount > 0) { + $allowRegistration = false; + } + return view('auth.passwords.reset')->with( + ['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration] + ); + } } diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php new file mode 100644 index 0000000000..a412ebd2f3 --- /dev/null +++ b/app/Http/Controllers/DebugController.php @@ -0,0 +1,159 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers; + +use Carbon\Carbon; +use DB; +use Illuminate\Http\Request; +use Log; +use Monolog\Handler\RotatingFileHandler; + +/** + * Class DebugController + */ +class DebugController extends Controller +{ + + /** + * @param Request $request + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + */ + public function index(Request $request) + { + $search = ['~', '#']; + $replace = ['\~', '# ']; + + $phpVersion = str_replace($search, $replace, PHP_VERSION); + $phpOs = str_replace($search, $replace, php_uname()); + $interface = PHP_SAPI; + $now = Carbon::create()->format('Y-m-d H:i:s e'); + $extensions = join(', ', get_loaded_extensions()); + $drivers = join(', ', DB::availableDrivers()); + $currentDriver = DB::getDriverName(); + $userAgent = $request->header('user-agent'); + $isSandstorm = var_export(env('IS_SANDSTORM', 'unknown'), true); + $isDocker = var_export(env('IS_DOCKER', 'unknown'), true); + $trustedProxies = env('TRUSTED_PROXIES', '(none)'); + $displayErrors = ini_get('display_errors'); + $errorReporting = $this->errorReporting(intval(ini_get('error_reporting'))); + $appEnv = env('APP_ENV', ''); + $appDebug = var_export(env('APP_DEBUG', false), true); + $appLog = env('APP_LOG', ''); + $appLogLevel = env('APP_LOG_LEVEL', ''); + $packages = $this->collectPackages(); + $cacheDriver = env('CACHE_DRIVER', 'unknown'); + + + // get latest log file: + $logger = Log::getMonolog(); + $handlers = $logger->getHandlers(); + $logContent = ''; + foreach ($handlers as $handler) { + if ($handler instanceof RotatingFileHandler) { + $logFile = $handler->getUrl(); + if (null !== $logFile) { + $logContent = file_get_contents($logFile); + } + } + } + // last few lines + $logContent = 'Truncated from this point <----|' . substr($logContent, -4096); + + return view( + 'debug', + compact( + 'phpVersion', + 'extensions', + 'carbon', + 'appEnv', + 'appDebug', + 'appLog', + 'appLogLevel', + 'now', + 'packages', + 'drivers', + 'currentDriver', + 'userAgent', + 'displayErrors', + 'errorReporting', + 'phpOs', + 'interface', + 'logContent', + 'cacheDriver', + 'isDocker', + 'isSandstorm', + 'trustedProxies' + ) + ); + } + + /** + * Some common combinations. + * + * @param int $value + * + * @return string + */ + protected function errorReporting(int $value): string + { + $array = [ + -1 => 'ALL errors', + E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED => 'E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED', + E_ALL => 'E_ALL', + E_ALL & ~E_DEPRECATED & ~E_STRICT => 'E_ALL & ~E_DEPRECATED & ~E_STRICT', + E_ALL & ~E_NOTICE => 'E_ALL & ~E_NOTICE', + E_ALL & ~E_NOTICE & ~E_STRICT => 'E_ALL & ~E_NOTICE & ~E_STRICT', + E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR => 'E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR', + ]; + if (isset($array[$value])) { + return $array[$value]; + } + + return strval($value); // @codeCoverageIgnore + } + + /** + * @return array + */ + private function collectPackages(): array + { + $packages = []; + $file = realpath(__DIR__ . '/../../../vendor/composer/installed.json'); + if (!($file === false) && file_exists($file)) { + // file exists! + $content = file_get_contents($file); + $json = json_decode($content, true); + foreach ($json as $package) { + $packages[] + = [ + 'name' => $package['name'], + 'version' => $package['version'], + ]; + } + } + + return $packages; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 32c2c63a24..8ca66dbc80 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -24,7 +24,6 @@ namespace FireflyIII\Http\Controllers; use Artisan; use Carbon\Carbon; -use DB; use Exception; use FireflyIII\Events\RequestedVersionCheckStatus; use FireflyIII\Exceptions\FireflyException; @@ -38,7 +37,6 @@ use Illuminate\Http\Request; use Illuminate\Routing\Route; use Illuminate\Support\Collection; use Log; -use Monolog\Handler\RotatingFileHandler; use Preferences; use Response; use Route as RouteFacade; @@ -98,59 +96,6 @@ class HomeController extends Controller return Response::json(['ok' => 'ok']); } - /** - * @param Request $request - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View - */ - public function displayDebug(Request $request) - { - $phpVersion = str_replace('~', '\~', PHP_VERSION); - $phpOs = php_uname(); - $interface = PHP_SAPI; - $now = Carbon::create()->format('Y-m-d H:i:s e'); - $extensions = join(', ', get_loaded_extensions()); - $drivers = join(', ', DB::availableDrivers()); - $currentDriver = DB::getDriverName(); - $userAgent = $request->header('user-agent'); - $isSandstorm = var_export(env('IS_SANDSTORM', 'unknown'), true); - $isDocker = var_export(env('IS_DOCKER', 'unknown'), true); - $trustedProxies = env('TRUSTED_PROXIES', '(none)'); - - // get latest log file: - $logger = Log::getMonolog(); - $handlers = $logger->getHandlers(); - $logContent = ''; - foreach ($handlers as $handler) { - if ($handler instanceof RotatingFileHandler) { - $logFile = $handler->getUrl(); - if (null !== $logFile) { - $logContent = file_get_contents($logFile); - } - } - } - // last few lines - $logContent = 'Truncated from this point <----|' . substr($logContent, -4096); - - return view( - 'debug', - compact( - 'phpVersion', - 'extensions', - 'carbon', - 'now', - 'drivers', - 'currentDriver', - 'userAgent', - 'phpOs', - 'interface', - 'logContent', - 'isDocker', - 'isSandstorm', - 'trustedProxies' - ) - ); - } /** * @throws FireflyException diff --git a/app/Http/Controllers/Import/ConfigurationController.php b/app/Http/Controllers/Import/ConfigurationController.php index 08798efaad..a86bd382bf 100644 --- a/app/Http/Controllers/Import/ConfigurationController.php +++ b/app/Http/Controllers/Import/ConfigurationController.php @@ -78,7 +78,9 @@ class ConfigurationController extends Controller return redirect(route('import.status', [$job->key])); } + $this->repository->updateStatus($job, 'configuring'); + $view = $configurator->getNextView(); $data = $configurator->getNextData(); $subTitle = trans('firefly.import_config_bread_crumb'); @@ -135,6 +137,7 @@ class ConfigurationController extends Controller if (null === $className || !class_exists($className)) { throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".', $type)); // @codeCoverageIgnore } + Log::debug(sprintf('Going to create class "%s"', $className)); /** @var ConfiguratorInterface $configurator */ $configurator = app($className); $configurator->setJob($job); diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php new file mode 100644 index 0000000000..2dfecca07b --- /dev/null +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -0,0 +1,178 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Transaction; + + +use ExpandedForm; +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Http\Requests\BulkEditJournalRequest; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; +use Log; +use Preferences; +use Session; +use View; + +/** + * Class BulkController + */ +class BulkController extends Controller +{ + + + /** + * + */ + public function __construct() + { + parent::__construct(); + + $this->middleware( + function ($request, $next) { + app('view')->share('title', trans('firefly.transactions')); + app('view')->share('mainTitleIcon', 'fa-repeat'); + + return $next($request); + } + ); + } + + /** + * @param Collection $journals + * + * @return View + */ + public function edit(Request $request, Collection $journals) + { + + $subTitle = trans('firefly.mass_bulk_journals'); + + // skip transactions that have multiple destinations, multiple sources or are an opening balance. + $filtered = new Collection; + $messages = []; + /** @var TransactionJournal $journal */ + foreach ($journals as $journal) { + $sources = $journal->sourceAccountList(); + $destinations = $journal->destinationAccountList(); + if ($sources->count() > 1) { + $messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]); + continue; + } + + if ($destinations->count() > 1) { + $messages[] = trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]); + continue; + } + if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) { + $messages[] = trans('firefly.cannot_edit_opening_balance'); + continue; + } + + // cannot edit reconciled transactions / journals: + if ($journal->transactions->first()->reconciled) { + $messages[] = trans('firefly.cannot_edit_reconciled', ['description' => $journal->description, 'id' => $journal->id]); + continue; + } + + $filtered->push($journal); + } + + if (count($messages) > 0) { + $request->session()->flash('info', $messages); + } + + // put previous url in session + $this->rememberPreviousUri('transactions.bulk-edit.uri'); + + // get list of budgets: + /** @var BudgetRepositoryInterface $repository */ + $repository = app(BudgetRepositoryInterface::class); + $budgetList = ExpandedForm::makeSelectListWithEmpty($repository->getActiveBudgets()); + // collect some useful meta data for the mass edit: + $filtered->each( + function (TransactionJournal $journal) { + $journal->transaction_count = $journal->transactions()->count(); + } + ); + + if (0 === $filtered->count()) { + $request->session()->flash('error', trans('firefly.no_edit_multiple_left')); + } + + $journals = $filtered; + + return view('transactions.bulk.edit', compact('journals', 'subTitle', 'budgetList')); + } + + + /** + * @param BulkEditJournalRequest $request + * @param JournalRepositoryInterface $repository + * + * @return mixed + */ + public function update(BulkEditJournalRequest $request, JournalRepositoryInterface $repository) + { + $journalIds = $request->get('journals'); + $ignoreCategory = intval($request->get('ignore_category')) === 1; + $ignoreBudget = intval($request->get('ignore_budget')) === 1; + $ignoreTags = intval($request->get('ignore_tags')) === 1; + $count = 0; + if (is_array($journalIds)) { + foreach ($journalIds as $journalId) { + $journal = $repository->find(intval($journalId)); + if (!is_null($journal)) { + $count++; + Log::debug(sprintf('Found journal #%d', $journal->id)); + // update category if not told to ignore + if ($ignoreCategory === false) { + Log::debug(sprintf('Set category to %s', $request->string('category'))); + $repository->updateCategory($journal, $request->string('category')); + } + // update budget if not told to ignore (and is withdrawal) + if ($ignoreBudget === false) { + Log::debug(sprintf('Set budget to %d', $request->integer('budget_id'))); + $repository->updateBudget($journal, $request->integer('budget_id')); + } + if ($ignoreTags === false) { + Log::debug(sprintf('Set tags to %s', $request->string('budget_id'))); + $repository->updateTags($journal, explode(',', $request->string('tags'))); + } + // update tags if not told to ignore (and is withdrawal) + } + } + } + + Preferences::mark(); + $request->session()->flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count])); + + // redirect to previous URL: + return redirect($this->getPreviousUri('transactions.bulk-edit.uri')); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index 2bb0a44d27..cbae31b26c 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\MassDeleteJournalRequest; use FireflyIII\Http\Requests\MassEditJournalRequest; +use FireflyIII\Http\Requests\MassEditBulkJournalRequest; use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; @@ -71,7 +72,7 @@ class MassController extends Controller // put previous url in session $this->rememberPreviousUri('transactions.mass-delete.uri'); - return view('transactions.mass-delete', compact('journals', 'subTitle')); + return view('transactions.mass.delete', compact('journals', 'subTitle')); } /** @@ -131,7 +132,7 @@ class MassController extends Controller // skip transactions that have multiple destinations, multiple sources or are an opening balance. $filtered = new Collection; $messages = []; - // @var TransactionJournal + /** @var TransactionJournal $journal */ foreach ($journals as $journal) { $sources = $journal->sourceAccountList(); $destinations = $journal->destinationAccountList(); @@ -213,7 +214,7 @@ class MassController extends Controller if (is_array($journalIds)) { foreach ($journalIds as $journalId) { $journal = $repository->find(intval($journalId)); - if ($journal) { + if (!is_null($journal)) { // get optional fields: $what = strtolower($journal->transactionTypeStr()); $sourceAccountId = $request->get('source_account_id')[$journal->id] ?? 0; @@ -264,4 +265,5 @@ class MassController extends Controller // redirect to previous URL: return redirect($this->getPreviousUri('transactions.mass-edit.uri')); } + } diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index 9b640d7b08..efb721d45a 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -57,6 +57,7 @@ class AccountFormRequest extends Request 'openingBalanceDate' => $this->date('openingBalanceDate'), 'ccType' => $this->string('ccType'), 'ccMonthlyPaymentDate' => $this->string('ccMonthlyPaymentDate'), + 'notes' => $this->string('notes'), ]; } diff --git a/app/Http/Requests/BulkEditJournalRequest.php b/app/Http/Requests/BulkEditJournalRequest.php new file mode 100644 index 0000000000..4aefd85029 --- /dev/null +++ b/app/Http/Requests/BulkEditJournalRequest.php @@ -0,0 +1,50 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Http\Requests; + +/** + * Class MassEditBulkJournalRequest. + */ +class BulkEditJournalRequest extends Request +{ + /** + * @return bool + */ + public function authorize() + { + // Only allow logged in users + return auth()->check(); + } + + /** + * @return array + */ + public function rules() + { + + // fixed + return [ + 'journals.*' => 'required|belongsToUser:transaction_journals,id', + ]; + } +} diff --git a/app/Http/Requests/JournalFormRequest.php b/app/Http/Requests/JournalFormRequest.php index 10396f5e50..f23dcdd650 100644 --- a/app/Http/Requests/JournalFormRequest.php +++ b/app/Http/Requests/JournalFormRequest.php @@ -91,33 +91,33 @@ class JournalFormRequest extends Request { $what = $this->get('what'); $rules = [ - 'what' => 'required|in:withdrawal,deposit,transfer', - 'date' => 'required|date', - + 'what' => 'required|in:withdrawal,deposit,transfer', + 'date' => 'required|date', + 'amount_currency_id_amount' => 'exists:transaction_currencies,id|required', // then, custom fields: - 'interest_date' => 'date|nullable', - 'book_date' => 'date|nullable', - 'process_date' => 'date|nullable', - 'due_date' => 'date|nullable', - 'payment_date' => 'date|nullable', - 'invoice_date' => 'date|nullable', - 'internal_reference' => 'min:1,max:255|nullable', - 'notes' => 'min:1,max:50000|nullable', + 'interest_date' => 'date|nullable', + 'book_date' => 'date|nullable', + 'process_date' => 'date|nullable', + 'due_date' => 'date|nullable', + 'payment_date' => 'date|nullable', + 'invoice_date' => 'date|nullable', + 'internal_reference' => 'min:1,max:255|nullable', + 'notes' => 'min:1,max:50000|nullable', // and then transaction rules: - 'description' => 'required|between:1,255', - 'amount' => 'numeric|required|more:0', - 'budget_id' => 'mustExist:budgets,id|belongsToUser:budgets,id|nullable', - 'category' => 'between:1,255|nullable', - 'source_account_id' => 'numeric|belongsToUser:accounts,id|nullable', - 'source_account_name' => 'between:1,255|nullable', - 'destination_account_id' => 'numeric|belongsToUser:accounts,id|nullable', - 'destination_account_name' => 'between:1,255|nullable', - 'piggy_bank_id' => 'between:1,255|nullable', + 'description' => 'required|between:1,255', + 'amount' => 'numeric|required|more:0', + 'budget_id' => 'mustExist:budgets,id|belongsToUser:budgets,id|nullable', + 'category' => 'between:1,255|nullable', + 'source_account_id' => 'numeric|belongsToUser:accounts,id|nullable', + 'source_account_name' => 'between:1,255|nullable', + 'destination_account_id' => 'numeric|belongsToUser:accounts,id|nullable', + 'destination_account_name' => 'between:1,255|nullable', + 'piggy_bank_id' => 'between:1,255|nullable', // foreign currency amounts - 'native_amount' => 'numeric|more:0|nullable', - 'source_amount' => 'numeric|more:0|nullable', - 'destination_amount' => 'numeric|more:0|nullable', + 'native_amount' => 'numeric|more:0|nullable', + 'source_amount' => 'numeric|more:0|nullable', + 'destination_amount' => 'numeric|more:0|nullable', ]; // some rules get an upgrade depending on the type of data: diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index 92916f77f4..dca2d3f774 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -143,7 +143,7 @@ class Request extends FormRequest * * @return int */ - protected function integer(string $field): int + public function integer(string $field): int { return intval($this->get($field)); } diff --git a/app/Import/Configuration/FileConfigurator.php b/app/Import/Configuration/FileConfigurator.php index 8e120c4208..940842abdf 100644 --- a/app/Import/Configuration/FileConfigurator.php +++ b/app/Import/Configuration/FileConfigurator.php @@ -24,11 +24,12 @@ namespace FireflyIII\Import\Configuration; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use FireflyIII\Support\Import\Configuration\File\Initial; use FireflyIII\Support\Import\Configuration\File\Map; use FireflyIII\Support\Import\Configuration\File\Roles; -use FireflyIII\Support\Import\Configuration\File\Upload; +use FireflyIII\Support\Import\Configuration\File\UploadConfig; use Log; /** @@ -36,17 +37,41 @@ use Log; */ class FileConfigurator implements ConfiguratorInterface { + /** @var array */ + private $defaultConfig + = [ + 'stage' => 'initial', + 'has-headers' => false, // assume + 'date-format' => 'Ymd', // assume + 'delimiter' => ',', // assume + 'import-account' => 0, // none, + 'specifics' => [], // none + 'column-count' => 0, // unknown + 'column-roles' => [], // unknown + 'column-do-mapping' => [], // not yet set which columns must be mapped + 'column-mapping-config' => [], // no mapping made yet. + 'file-type' => 'csv', // assume + 'has-config-file' => true, + 'apply-rules' => true, + 'match-bills' => false, + 'auto-start' => false, + ]; /** @var ImportJob */ private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; + + // give job default config: /** @var string */ private $warning = ''; /** - * ConfiguratorInterface constructor. + * FileConfigurator constructor. */ public function __construct() { + Log::debug('Created FileConfigurator'); } /** @@ -60,10 +85,13 @@ class FileConfigurator implements ConfiguratorInterface */ public function configureJob(array $data): bool { + if (is_null($this->job)) { + throw new FireflyException('Cannot call configureJob() without a job.'); + } $class = $this->getConfigurationClass(); $job = $this->job; /** @var ConfigurationInterface $object */ - $object = new $class($this->job); + $object = app($class); $object->setJob($job); $result = $object->storeConfiguration($data); $this->warning = $object->getWarningMessage(); @@ -80,6 +108,10 @@ class FileConfigurator implements ConfiguratorInterface */ public function getNextData(): array { + if (is_null($this->job)) { + throw new FireflyException('Cannot call getNextData() without a job.'); + } + $class = $this->getConfigurationClass(); $job = $this->job; /** @var ConfigurationInterface $object */ @@ -96,52 +128,56 @@ class FileConfigurator implements ConfiguratorInterface */ public function getNextView(): string { - if (!$this->job->configuration['has-file-upload']) { - return 'import.file.upload'; + if (is_null($this->job)) { + throw new FireflyException('Cannot call getNextView() without a job.'); } - if (!$this->job->configuration['initial-config-complete']) { - return 'import.file.initial'; + $config = $this->getConfig(); + $stage = $config['stage'] ?? 'initial'; + switch ($stage) { + case 'initial': // has nothing, no file upload or anything. + return 'import.file.initial'; + case 'upload-config': // has file, needs file config. + return 'import.file.upload-config'; + case 'roles': // has configured file, needs roles. + return 'import.file.roles'; + case 'map': // has roles, needs mapping. + return 'import.file.map'; } - if (!$this->job->configuration['column-roles-complete']) { - return 'import.file.roles'; - } - if (!$this->job->configuration['column-mapping-complete']) { - return 'import.file.map'; - } - - throw new FireflyException('No view for state'); + throw new FireflyException(sprintf('No view for stage "%s"', $stage)); } /** * Return possible warning to user. * * @return string + * @throws FireflyException */ public function getWarningMessage(): string { + if (is_null($this->job)) { + throw new FireflyException('Cannot call getWarningMessage() without a job.'); + } + return $this->warning; } /** * @return bool + * @throws FireflyException */ public function isJobConfigured(): bool { - $config = $this->job->configuration; - $config['has-file-upload'] = $config['has-file-upload'] ?? false; - $config['initial-config-complete'] = $config['initial-config-complete'] ?? false; - $config['column-roles-complete'] = $config['column-roles-complete'] ?? false; - $config['column-mapping-complete'] = $config['column-mapping-complete'] ?? false; - $this->job->configuration = $config; - $this->job->save(); + if (is_null($this->job)) { + throw new FireflyException('Cannot call isJobConfigured() without a job.'); + } + $config = $this->getConfig(); + $stage = $config['stage'] ?? 'initial'; + if ($stage === 'ready') { + Log::debug('isJobConfigured returns true'); - if ($config['initial-config-complete'] - && $config['column-roles-complete'] - && $config['column-mapping-complete'] - && $config['has-file-upload'] - ) { return true; } + Log::debug('isJobConfigured returns false'); return false; } @@ -151,12 +187,24 @@ class FileConfigurator implements ConfiguratorInterface */ public function setJob(ImportJob $job) { - $this->job = $job; - if (null === $this->job->configuration || 0 === count($this->job->configuration)) { - Log::debug(sprintf('Gave import job %s initial configuration.', $this->job->key)); - $this->job->configuration = config('csv.default_config'); - $this->job->save(); - } + Log::debug(sprintf('FileConfigurator::setJob(#%d: %s)', $job->id, $job->key)); + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); + + $config = $this->getConfig(); + $newConfig = array_merge($this->defaultConfig, $config); + $this->repository->setConfiguration($job, $newConfig); + } + + /** + * Short hand method. + * + * @return array + */ + private function getConfig(): array + { + return $this->repository->getConfiguration($this->job); } /** @@ -166,18 +214,22 @@ class FileConfigurator implements ConfiguratorInterface */ private function getConfigurationClass(): string { - $class = false; - switch (true) { - case !$this->job->configuration['has-file-upload']: - $class = Upload::class; - break; - case !$this->job->configuration['initial-config-complete']: + $config = $this->getConfig(); + $stage = $config['stage'] ?? 'initial'; + $class = false; + Log::debug(sprintf('Now in getConfigurationClass() for stage "%s"', $stage)); + + switch ($stage) { + case 'initial': // has nothing, no file upload or anything. $class = Initial::class; break; - case !$this->job->configuration['column-roles-complete']: + case 'upload-config': // has file, needs file config. + $class = UploadConfig::class; + break; + case 'roles': // has configured file, needs roles. $class = Roles::class; break; - case !$this->job->configuration['column-mapping-complete']: + case 'map': // has roles, needs mapping. $class = Map::class; break; default: @@ -185,11 +237,12 @@ class FileConfigurator implements ConfiguratorInterface } if (false === $class || 0 === strlen($class)) { - throw new FireflyException('Cannot handle current job state in getConfigurationClass().'); + throw new FireflyException(sprintf('Cannot handle job stage "%s" in getConfigurationClass().', $stage)); } if (!class_exists($class)) { - throw new FireflyException(sprintf('Class %s does not exist in getConfigurationClass().', $class)); + throw new FireflyException(sprintf('Class %s does not exist in getConfigurationClass().', $class)); // @codeCoverageIgnore } + Log::debug(sprintf('Configuration class is "%s"', $class)); return $class; } diff --git a/app/Import/Configuration/SpectreConfigurator.php b/app/Import/Configuration/SpectreConfigurator.php index 125d7e2bd5..126e964601 100644 --- a/app/Import/Configuration/SpectreConfigurator.php +++ b/app/Import/Configuration/SpectreConfigurator.php @@ -22,7 +22,10 @@ declare(strict_types=1); namespace FireflyIII\Import\Configuration; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; +use FireflyIII\Support\Import\Configuration\Spectre\HaveAccounts; +use Log; /** * Class SpectreConfigurator. @@ -51,7 +54,29 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function configureJob(array $data): bool { - die('cannot store config'); + $config = $this->job->configuration; + $stage = $config['stage']; + $status = $this->job->status; + Log::debug(sprintf('in getNextData(), for stage "%s".', $stage)); + switch ($stage) { + case 'have-accounts': + /** @var HaveAccounts $class */ + $class = app(HaveAccounts::class); + $class->setJob($this->job); + $class->storeConfiguration($data); + + // update job for next step and set to "configured". + $config = $this->job->configuration; + $config['stage'] = 'have-account-mapping'; + $this->job->configuration = $config; + $this->job->status = 'configured'; + $this->job->save(); + return true; + break; + default: + throw new FireflyException(sprintf('Cannot store configuration when job is in state "%s"', $stage)); + break; + } } /** @@ -61,11 +86,34 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function getNextData(): array { - // update config to tell Firefly we've redirected the user. - $config = $this->job->configuration; - $config['is-redirected'] = true; + $config = $this->job->configuration; + $stage = $config['stage']; + $status = $this->job->status; + Log::debug(sprintf('in getNextData(), for stage "%s".', $stage)); + switch ($stage) { + case 'has-token': + // simply redirect to Spectre. + $config['is-redirected'] = true; + $config['stage'] = 'user-logged-in'; + $status = 'configured'; + break; + case 'have-accounts': + // use special class: + /** @var HaveAccounts $class */ + $class = app(HaveAccounts::class); + $class->setJob($this->job); + $data = $class->getData(); + + return $data; + default: + return []; + break; + + } + + // update config and status: $this->job->configuration = $config; - $this->job->status = 'configured'; + $this->job->status = $status; $this->job->save(); return $this->job->configuration; @@ -76,7 +124,22 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function getNextView(): string { - return 'import.spectre.redirect'; + $config = $this->job->configuration; + $stage = $config['stage']; + Log::debug(sprintf('in getNextView(), for stage "%s".', $stage)); + switch ($stage) { + case 'has-token': + // redirect to Spectre. + return 'import.spectre.redirect'; + break; + case 'have-accounts': + return 'import.spectre.accounts'; + break; + default: + return ''; + break; + + } } /** @@ -94,13 +157,20 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function isJobConfigured(): bool { - // job is configured (and can start) when token is empty: $config = $this->job->configuration; - if ($config['has-token'] === false) { - return true; - } + $stage = $config['stage']; + Log::debug(sprintf('in isJobConfigured(), for stage "%s".', $stage)); + switch ($stage) { + case 'has-token': + case 'have-accounts': + Log::debug('isJobConfigured returns false'); - return false; + return false; + default: + Log::debug('isJobConfigured returns true'); + + return true; + } } /** @@ -108,18 +178,27 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function setJob(ImportJob $job) { - $defaultConfig = [ - 'has-token' => false, - 'token' => '', - 'token-expires' => 0, - 'token-url' => '', - 'is-redirected' => false, - + $defaultConfig = [ + 'has-token' => false, + 'token' => '', + 'token-expires' => 0, + 'token-url' => '', + 'is-redirected' => false, + 'customer' => null, + 'login' => null, + 'stage' => 'initial', + 'accounts' => '', + 'accounts-mapped' => '', + 'auto-start' => true, ]; + $extendedStatus = $job->extended_status; + $extendedStatus['steps'] = 100; - $config = $job->configuration; - $finalConfig = array_merge($defaultConfig, $config); - $job->configuration = $finalConfig; + + $config = $job->configuration; + $finalConfig = array_merge($defaultConfig, $config); + $job->configuration = $finalConfig; + $job->extended_status = $extendedStatus; $job->save(); $this->job = $job; } diff --git a/app/Import/Converter/Amount.php b/app/Import/Converter/Amount.php index a72065ea49..802664269a 100644 --- a/app/Import/Converter/Amount.php +++ b/app/Import/Converter/Amount.php @@ -45,8 +45,10 @@ class Amount implements ConverterInterface if (null === $value) { return '0'; } - $value = strval($value); Log::debug(sprintf('Start with amount "%s"', $value)); + $original = $value; + $value = strval($value); + $value = $this->stripAmount($value); $len = strlen($value); $decimalPosition = $len - 3; $altPosition = $len - 2; @@ -81,27 +83,43 @@ class Amount implements ConverterInterface // if decimal is dot, replace all comma's and spaces with nothing. then parse as float (round to 4 pos) if ('.' === $decimal) { $search = [',', ' ']; - $oldValue = $value; $value = str_replace($search, '', $value); - Log::debug(sprintf('Converted amount from "%s" to "%s".', $oldValue, $value)); + Log::debug(sprintf('Converted amount from "%s" to "%s".', $original, $value)); } if (',' === $decimal) { $search = ['.', ' ']; - $oldValue = $value; $value = str_replace($search, '', $value); $value = str_replace(',', '.', $value); - Log::debug(sprintf('Converted amount from "%s" to "%s".', $oldValue, $value)); + Log::debug(sprintf('Converted amount from "%s" to "%s".', $original, $value)); } if (null === $decimal) { // replace all: $search = ['.', ' ', ',']; - $oldValue = $value; $value = str_replace($search, '', $value); - Log::debug(sprintf('No decimal character found. Converted amount from "%s" to "%s".', $oldValue, $value)); + Log::debug(sprintf('No decimal character found. Converted amount from "%s" to "%s".', $original, $value)); } $number = strval(number_format(round(floatval($value), 12), 12, '.', '')); return $number; } + + /** + * @param string $value + * + * @return string + */ + private function stripAmount(string $value): string + { + $str = preg_replace('/[^\-\(\)\.\,0-9 ]/', '', $value); + $len = strlen($str); + if ($str{0} === '(' && $str{$len - 1} === ')') { + $str = '-' . substr($str, 1, ($len - 2)); + } + + Log::debug(sprintf('Stripped "%s" away to "%s"', $value, $str)); + + return $str; + + } } diff --git a/app/Import/FileProcessor/CsvProcessor.php b/app/Import/FileProcessor/CsvProcessor.php index 1ad9d6b973..22327c9445 100644 --- a/app/Import/FileProcessor/CsvProcessor.php +++ b/app/Import/FileProcessor/CsvProcessor.php @@ -26,7 +26,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Import\Object\ImportJournal; use FireflyIII\Import\Specifics\SpecificInterface; use FireflyIII\Models\ImportJob; -use FireflyIII\Models\TransactionJournalMeta; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use Illuminate\Support\Collection; use Iterator; use League\Csv\Reader; @@ -43,6 +43,8 @@ class CsvProcessor implements FileProcessorInterface private $job; /** @var Collection */ private $objects; + /** @var ImportJobRepositoryInterface */ + private $repository; /** @var array */ private $validConverters = []; /** @var array */ @@ -60,9 +62,14 @@ class CsvProcessor implements FileProcessorInterface /** * @return Collection + * @throws FireflyException */ public function getObjects(): Collection { + if (is_null($this->job)) { + throw new FireflyException('Cannot call getObjects() without a job.'); + } + return $this->objects; } @@ -73,9 +80,13 @@ class CsvProcessor implements FileProcessorInterface * * @throws \League\Csv\Exception * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + * @throws FireflyException */ public function run(): bool { + if (is_null($this->job)) { + throw new FireflyException('Cannot call run() without a job.'); + } Log::debug('Now in CsvProcessor run(). Job is now running...'); $entries = new Collection($this->getImportArray()); @@ -86,8 +97,8 @@ class CsvProcessor implements FileProcessorInterface $row = array_values($row); if ($this->rowAlreadyImported($row)) { $message = sprintf('Row #%d has already been imported.', $index); - $this->job->addError($index, $message); - $this->job->addStepsDone(5); // all steps. + $this->repository->addStepsDone($this->job, 5); + $this->addError($index, $message); Log::info($message); return null; @@ -99,23 +110,34 @@ class CsvProcessor implements FileProcessorInterface Log::debug(sprintf('Number of entries left: %d', $notImported->count())); // set (new) number of steps: - $status = $this->job->extended_status; - $status['steps'] = $notImported->count() * 5; - $this->job->extended_status = $status; - $this->job->save(); - Log::debug(sprintf('Number of steps: %d', $notImported->count() * 5)); + $extended = $this->getExtendedStatus(); + $steps = $notImported->count() * 5; + $extended['steps'] = $steps; + $this->setExtendedStatus($extended); + Log::debug(sprintf('Number of steps: %d', $steps)); $notImported->each( function (array $row, int $index) { $journal = $this->importRow($index, $row); $this->objects->push($journal); - $this->job->addStepsDone(1); + $this->repository->addStepsDone($this->job, 1); } ); return true; } + /** + * @codeCoverageIgnore + * Shorthand method + * + * @param array $array + */ + public function setExtendedStatus(array $array) + { + $this->repository->setExtendedStatus($this->job, $array); + } + /** * Set import job for this processor. * @@ -125,11 +147,30 @@ class CsvProcessor implements FileProcessorInterface */ public function setJob(ImportJob $job): FileProcessorInterface { - $this->job = $job; + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); return $this; } + /** + * Shorthand method. + * + * @codeCoverageIgnore + * + * @param int $index + * @param string $message + */ + private function addError(int $index, string $message): void + { + $extended = $this->getExtendedStatus(); + $extended['errors'][$index][] = $message; + $this->setExtendedStatus($extended); + + return; + } + /** * Add meta data to the individual value and verify that it can be handled in a later stage. * @@ -142,7 +183,7 @@ class CsvProcessor implements FileProcessorInterface */ private function annotateValue(int $index, string $value) { - $config = $this->job->configuration; + $config = $this->getConfig(); $role = $config['column-roles'][$index] ?? '_ignore'; $mapped = $config['column-mapping-config'][$index][$value] ?? null; @@ -160,6 +201,29 @@ class CsvProcessor implements FileProcessorInterface return $entry; } + /** + * @codeCoverageIgnore + * Shorthand method. + * + * @return array + */ + private function getConfig(): array + { + return $this->repository->getConfiguration($this->job); + } + + /** + * @codeCoverageIgnore + * Shorthand method. + * + * @return array + */ + private function getExtendedStatus(): array + { + return $this->repository->getExtendedStatus($this->job); + } + + /** * @return Iterator * @@ -169,16 +233,17 @@ class CsvProcessor implements FileProcessorInterface */ private function getImportArray(): Iterator { - $content = $this->job->uploadFileContents(); - $config = $this->job->configuration; - $reader = Reader::createFromString($content); - $delimiter = $config['delimiter']; + $content = $this->repository->uploadFileContents($this->job); + $config = $this->getConfig(); + $reader = Reader::createFromString($content); + $delimiter = $config['delimiter'] ?? ','; + $hasHeaders = isset($config['has-headers']) ? $config['has-headers'] : false; if ('tab' === $delimiter) { - $delimiter = "\t"; + $delimiter = "\t"; // @codeCoverageIgnore } $reader->setDelimiter($delimiter); - if ($config['has-headers']) { - $reader->setHeaderOffset(0); + if ($hasHeaders) { + $reader->setHeaderOffset(0); // @codeCoverageIgnore } $results = $reader->getRecords(); Log::debug('Created a CSV reader.'); @@ -191,6 +256,7 @@ class CsvProcessor implements FileProcessorInterface * * @param int $jsonError * + * @codeCoverageIgnore * @return string */ private function getJsonError(int $jsonError): string @@ -230,7 +296,7 @@ class CsvProcessor implements FileProcessorInterface $jsonError = json_last_error(); if (false === $json) { - throw new FireflyException(sprintf('Error while encoding JSON for CSV row: %s', $this->getJsonError($jsonError))); + throw new FireflyException(sprintf('Error while encoding JSON for CSV row: %s', $this->getJsonError($jsonError))); // @codeCoverageIgnore } $hash = hash('sha256', $json); @@ -251,8 +317,9 @@ class CsvProcessor implements FileProcessorInterface { $row = array_values($row); Log::debug(sprintf('Now at row %d', $index)); - $row = $this->specifics($row); - $hash = $this->getRowHash($row); + $row = $this->specifics($row); + $hash = $this->getRowHash($row); + $config = $this->getConfig(); $journal = new ImportJournal; $journal->setUser($this->job->user); @@ -271,7 +338,8 @@ class CsvProcessor implements FileProcessorInterface } } // set some extra info: - $journal->asset->setDefaultAccountId($this->job->configuration['import-account']); + $importAccount = intval($config['import-account'] ?? 0); + $journal->asset->setDefaultAccountId($importAccount); return $journal; } @@ -288,12 +356,8 @@ class CsvProcessor implements FileProcessorInterface private function rowAlreadyImported(array $array): bool { $hash = $this->getRowHash($array); - $json = json_encode($hash); - $entry = TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') - ->where('data', $json) - ->where('name', 'importHash') - ->first(); - if (null !== $entry) { + $count = $this->repository->countByHash($hash); + if ($count > 0) { return true; } diff --git a/app/Import/Logging/CommandHandler.php b/app/Import/Logging/CommandHandler.php index c35663e53e..eb1d9c1b7a 100644 --- a/app/Import/Logging/CommandHandler.php +++ b/app/Import/Logging/CommandHandler.php @@ -26,6 +26,7 @@ use Illuminate\Console\Command; use Monolog\Handler\AbstractProcessingHandler; /** + * @codeCoverageIgnore * Class CommandHandler. */ class CommandHandler extends AbstractProcessingHandler diff --git a/app/Import/Mapper/AssetAccountIbans.php b/app/Import/Mapper/AssetAccountIbans.php index a782638ca1..cfbdf46437 100644 --- a/app/Import/Mapper/AssetAccountIbans.php +++ b/app/Import/Mapper/AssetAccountIbans.php @@ -44,18 +44,17 @@ class AssetAccountIbans implements MapperInterface /** @var Account $account */ foreach ($set as $account) { - $iban = $account->iban ?? ''; + $iban = $account->iban ?? ''; + $accountId = intval($account->id); if (strlen($iban) > 0) { - $topList[$account->id] = $account->iban . ' (' . $account->name . ')'; + $topList[$accountId] = $account->iban . ' (' . $account->name . ')'; } if (0 === strlen($iban)) { - $list[$account->id] = $account->name; + $list[$accountId] = $account->name; } } - asort($topList); - asort($list); - $list = $topList + $list; + asort($list); $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/AssetAccounts.php b/app/Import/Mapper/AssetAccounts.php index 99b07bd40d..9344cfb522 100644 --- a/app/Import/Mapper/AssetAccounts.php +++ b/app/Import/Mapper/AssetAccounts.php @@ -43,16 +43,15 @@ class AssetAccounts implements MapperInterface /** @var Account $account */ foreach ($set as $account) { - $name = $account->name; - $iban = $account->iban ?? ''; + $accountId = intval($account->id); + $name = $account->name; + $iban = $account->iban ?? ''; if (strlen($iban) > 0) { - $name .= ' (' . $account->iban . ')'; + $name .= ' (' . $iban . ')'; } - $list[$account->id] = $name; + $list[$accountId] = $name; } - asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/Bills.php b/app/Import/Mapper/Bills.php index d15544c414..bea7a2b3ff 100644 --- a/app/Import/Mapper/Bills.php +++ b/app/Import/Mapper/Bills.php @@ -42,10 +42,10 @@ class Bills implements MapperInterface /** @var Bill $bill */ foreach ($result as $bill) { - $list[$bill->id] = $bill->name . ' [' . $bill->match . ']'; + $billId = intval($bill->id); + $list[$billId] = $bill->name . ' [' . $bill->match . ']'; } asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/Budgets.php b/app/Import/Mapper/Budgets.php index f546e68049..119e844be3 100644 --- a/app/Import/Mapper/Budgets.php +++ b/app/Import/Mapper/Budgets.php @@ -37,15 +37,15 @@ class Budgets implements MapperInterface { /** @var BudgetRepositoryInterface $repository */ $repository = app(BudgetRepositoryInterface::class); - $result = $repository->getBudgets(); + $result = $repository->getActiveBudgets(); $list = []; /** @var Budget $budget */ foreach ($result as $budget) { - $list[$budget->id] = $budget->name; + $budgetId = intval($budget->id); + $list[$budgetId] = $budget->name; } asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/Categories.php b/app/Import/Mapper/Categories.php index fae3276f94..21963f8eaf 100644 --- a/app/Import/Mapper/Categories.php +++ b/app/Import/Mapper/Categories.php @@ -42,10 +42,10 @@ class Categories implements MapperInterface /** @var Category $category */ foreach ($result as $category) { - $list[$category->id] = $category->name; + $categoryId = intval($category->id); + $list[$categoryId] = $category->name; } asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/OpposingAccountIbans.php b/app/Import/Mapper/OpposingAccountIbans.php index 4471dcbf22..efddc090b4 100644 --- a/app/Import/Mapper/OpposingAccountIbans.php +++ b/app/Import/Mapper/OpposingAccountIbans.php @@ -50,18 +50,17 @@ class OpposingAccountIbans implements MapperInterface /** @var Account $account */ foreach ($set as $account) { - $iban = $account->iban ?? ''; + $iban = $account->iban ?? ''; + $accountId = intval($account->id); if (strlen($iban) > 0) { - $topList[$account->id] = $account->iban . ' (' . $account->name . ')'; + $topList[$accountId] = $account->iban . ' (' . $account->name . ')'; } if (0 === strlen($iban)) { - $list[$account->id] = $account->name; + $list[$accountId] = $account->name; } } - asort($topList); - asort($list); - $list = $topList + $list; + asort($list); $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/OpposingAccounts.php b/app/Import/Mapper/OpposingAccounts.php index d524530986..e451ace5eb 100644 --- a/app/Import/Mapper/OpposingAccounts.php +++ b/app/Import/Mapper/OpposingAccounts.php @@ -49,16 +49,15 @@ class OpposingAccounts implements MapperInterface /** @var Account $account */ foreach ($set as $account) { - $name = $account->name; - $iban = $account->iban ?? ''; + $accountId = intval($account->id); + $name = $account->name; + $iban = $account->iban ?? ''; if (strlen($iban) > 0) { - $name .= ' (' . $account->iban . ')'; + $name .= ' (' . $iban . ')'; } - $list[$account->id] = $name; + $list[$accountId] = $name; } - asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/Tags.php b/app/Import/Mapper/Tags.php index 1e36239b0e..68536a86b7 100644 --- a/app/Import/Mapper/Tags.php +++ b/app/Import/Mapper/Tags.php @@ -42,10 +42,10 @@ class Tags implements MapperInterface /** @var Tag $tag */ foreach ($result as $tag) { - $list[$tag->id] = $tag->tag; + $tagId = intval($tag->id); + $list[$tagId] = $tag->tag; } asort($list); - $list = [0 => trans('import.map_do_not_map')] + $list; return $list; diff --git a/app/Import/Mapper/TransactionCurrencies.php b/app/Import/Mapper/TransactionCurrencies.php index 4e58b26285..7e81f4a8c8 100644 --- a/app/Import/Mapper/TransactionCurrencies.php +++ b/app/Import/Mapper/TransactionCurrencies.php @@ -22,7 +22,7 @@ declare(strict_types=1); namespace FireflyIII\Import\Mapper; -use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; /** * Class TransactionCurrencies. @@ -34,12 +34,14 @@ class TransactionCurrencies implements MapperInterface */ public function getMap(): array { - $currencies = TransactionCurrency::get(); + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + $currencies = $repository->get(); $list = []; foreach ($currencies as $currency) { - $list[$currency->id] = $currency->name . ' (' . $currency->code . ')'; + $currencyId = intval($currency->id); + $list[$currencyId] = $currency->name . ' (' . $currency->code . ')'; } - asort($list); $list = [0 => trans('import.map_do_not_map')] + $list; diff --git a/app/Import/MapperPreProcess/TagsComma.php b/app/Import/MapperPreProcess/TagsComma.php index d3d2e4165a..43d628c577 100644 --- a/app/Import/MapperPreProcess/TagsComma.php +++ b/app/Import/MapperPreProcess/TagsComma.php @@ -34,6 +34,11 @@ class TagsComma implements PreProcessorInterface */ public function run(string $value): array { - return explode(',', $value); + $set = explode(',', $value); + $set = array_map('trim', $set); + $set = array_filter($set, 'strlen'); + $return = array_values($set); + + return $return; } } diff --git a/app/Import/MapperPreProcess/TagsSpace.php b/app/Import/MapperPreProcess/TagsSpace.php index cd897e7c67..d8967ee9fb 100644 --- a/app/Import/MapperPreProcess/TagsSpace.php +++ b/app/Import/MapperPreProcess/TagsSpace.php @@ -34,6 +34,11 @@ class TagsSpace implements PreProcessorInterface */ public function run(string $value): array { - return explode(' ', $value); + $set = explode(' ', $value); + $set = array_map('trim', $set); + $set = array_filter($set, 'strlen'); + $return = array_values($set); + + return $return; } } diff --git a/app/Import/Object/ImportAccount.php b/app/Import/Object/ImportAccount.php index ba9330e8f3..3d409992ae 100644 --- a/app/Import/Object/ImportAccount.php +++ b/app/Import/Object/ImportAccount.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace FireflyIII\Import\Object; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -74,6 +75,7 @@ class ImportAccount /** * @return Account + * @throws FireflyException */ public function getAccount(): Account { @@ -85,6 +87,7 @@ class ImportAccount } /** + * @codeCoverageIgnore * @return string */ public function getExpectedType(): string @@ -93,6 +96,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param string $expectedType */ public function setExpectedType(string $expectedType) @@ -101,6 +106,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param array $accountIban */ public function setAccountIban(array $accountIban) @@ -109,6 +116,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param array $value */ public function setAccountId(array $value) @@ -117,6 +126,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param array $accountName */ public function setAccountName(array $accountName) @@ -125,6 +136,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param array $accountNumber */ public function setAccountNumber(array $accountNumber) @@ -133,6 +146,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param int $defaultAccountId */ public function setDefaultAccountId(int $defaultAccountId) @@ -141,6 +156,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param int $forbiddenAccountId */ public function setForbiddenAccountId(int $forbiddenAccountId) @@ -149,6 +166,8 @@ class ImportAccount } /** + * @codeCoverageIgnore + * * @param User $user */ public function setUser(User $user) @@ -158,20 +177,21 @@ class ImportAccount } /** - * @return Account + * @return Account|null * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - private function findExistingObject(): Account + private function findExistingObject(): ?Account { Log::debug('In findExistingObject() for Account'); // 0: determin account type: /** @var AccountType $accountType */ - $accountType = AccountType::whereType($this->expectedType)->first(); + $accountType = $this->repository->getAccountType($this->expectedType); // 1: find by ID, iban or name (and type) if (3 === count($this->accountId)) { Log::debug(sprintf('Finding account of type %d and ID %d', $accountType->id, $this->accountId['value'])); /** @var Account $account */ + $account = $this->user->accounts()->where('id', '!=', $this->forbiddenAccountId)->where('account_type_id', $accountType->id)->where( 'id', $this->accountId['value'] @@ -233,13 +253,13 @@ class ImportAccount // 4: do not search by account number. Log::debug('Found NO existing accounts.'); - return new Account; + return null; } /** - * @return Account + * @return Account|null */ - private function findMappedObject(): Account + private function findMappedObject(): ?Account { Log::debug('In findMappedObject() for Account'); $fields = ['accountId', 'accountIban', 'accountNumber', 'accountName']; @@ -248,7 +268,7 @@ class ImportAccount Log::debug(sprintf('Find mapped account based on field "%s" with value', $field), $array); // check if a pre-mapped object exists. $mapped = $this->getMappedObject($array); - if (null !== $mapped->id) { + if (null !== $mapped) { Log::debug(sprintf('Found account #%d!', $mapped->id)); return $mapped; @@ -256,38 +276,38 @@ class ImportAccount } Log::debug('Found no account on mapped data or no map present.'); - return new Account; + return null; } /** * @param array $array * - * @return Account + * @return Account|null */ - private function getMappedObject(array $array): Account + private function getMappedObject(array $array): ?Account { Log::debug('In getMappedObject() for Account'); if (0 === count($array)) { Log::debug('Array is empty, nothing will come of this.'); - return new Account; + return null; } if (array_key_exists('mapped', $array) && null === $array['mapped']) { Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - return new Account; + return null; } Log::debug('Finding a mapped account based on', $array); - $search = intval($array['mapped']); + $search = intval($array['mapped'] ?? 0); $account = $this->repository->find($search); if (null === $account->id) { Log::error(sprintf('There is no account with id #%d. Invalid mapping will be ignored!', $search)); - return new Account; + return null; } // must be of the same type // except when mapped is an asset, then it's fair game. @@ -302,7 +322,7 @@ class ImportAccount ) ); - return new Account; + return null; } Log::debug(sprintf('Found account! #%d ("%s"). Return it', $account->id, $account->name)); @@ -312,19 +332,26 @@ class ImportAccount /** * @return bool + * @throws FireflyException */ private function store(): bool { + if (is_null($this->user)) { + throw new FireflyException('ImportAccount cannot continue without user.'); + } + if ((is_null($this->defaultAccountId) || intval($this->defaultAccountId) === 0) && AccountType::ASSET === $this->expectedType) { + throw new FireflyException('ImportAccount cannot continue without a default account to fall back on.'); + } // 1: find mapped object: $mapped = $this->findMappedObject(); - if (null !== $mapped->id) { + if (null !== $mapped) { $this->account = $mapped; return true; } // 2: find existing by given values: $found = $this->findExistingObject(); - if (null !== $found->id) { + if (null !== $found) { $this->account = $found; return true; @@ -335,7 +362,7 @@ class ImportAccount $oldExpectedType = $this->expectedType; $this->expectedType = AccountType::ASSET; $found = $this->findExistingObject(); - if (null !== $found->id) { + if (null !== $found) { Log::debug('Found asset account!'); $this->account = $found; diff --git a/app/Import/Object/ImportJournal.php b/app/Import/Object/ImportJournal.php index a903ffe7e1..1b3ac44a42 100644 --- a/app/Import/Object/ImportJournal.php +++ b/app/Import/Object/ImportJournal.php @@ -302,6 +302,10 @@ class ImportJournal if (0 === count($info)) { throw new FireflyException('No amount information for this row.'); } + $class = $info['class'] ?? ''; + if (strlen($class) === 0) { + throw new FireflyException('No amount information (conversion class) for this row.'); + } Log::debug(sprintf('Converter class is %s', $info['class'])); /** @var ConverterInterface $amountConverter */ diff --git a/app/Import/Routine/SpectreRoutine.php b/app/Import/Routine/SpectreRoutine.php index fbd12ae9c7..993983e062 100644 --- a/app/Import/Routine/SpectreRoutine.php +++ b/app/Import/Routine/SpectreRoutine.php @@ -24,9 +24,18 @@ namespace FireflyIII\Import\Routine; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\Services\Spectre\Exception\DuplicatedCustomerException; +use FireflyIII\Services\Spectre\Exception\SpectreException; +use FireflyIII\Services\Spectre\Object\Account; use FireflyIII\Services\Spectre\Object\Customer; +use FireflyIII\Services\Spectre\Object\Login; use FireflyIII\Services\Spectre\Object\Token; use FireflyIII\Services\Spectre\Request\CreateTokenRequest; +use FireflyIII\Services\Spectre\Request\ListAccountsRequest; +use FireflyIII\Services\Spectre\Request\ListCustomersRequest; +use FireflyIII\Services\Spectre\Request\ListLoginsRequest; +use FireflyIII\Services\Spectre\Request\ListTransactionsRequest; use FireflyIII\Services\Spectre\Request\NewCustomerRequest; use Illuminate\Support\Collection; use Log; @@ -46,6 +55,9 @@ class SpectreRoutine implements RoutineInterface /** @var ImportJob */ private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; + /** * ImportRoutine constructor. */ @@ -80,57 +92,61 @@ class SpectreRoutine implements RoutineInterface } /** + * A Spectre job that ends up here is either "configured" or "running", and will be set to "running" + * when it is "configured". + * + * Job has several stages, stored in extended status key 'stage' + * + * initial: just begun, nothing happened. action: get a customer and a token. Next status: has-token + * has-token: redirect user to sandstorm, make user login. set job to: user-logged-in + * user-logged-in: customer has an attempt. action: analyse/get attempt and go for next status. + * if attempt failed: job status is error, save a warning somewhere? + * if success, try to get accounts. Save in config key 'accounts'. set status: have-accounts and "configuring" + * + * have-accounts: make user link accounts and select accounts to import from. + * + * If job is "configuring" and stage "have-accounts" then present the accounts and make user link them to + * own asset accounts. Store this mapping, set config to "have-account-mapping" and job status configured". + * + * have-account-mapping: start downloading transactions? + * * * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ public function run(): bool { - if ('configured' !== $this->job->status) { - Log::error(sprintf('Job %s is in state "%s" so it cannot be started.', $this->job->key, $this->job->status)); - - return false; + if ('configured' === $this->job->status) { + $this->repository->updateStatus($this->job, 'running'); } Log::info(sprintf('Start with import job %s using Spectre.', $this->job->key)); set_time_limit(0); // check if job has token first! - $config = $this->job->configuration; - $hasToken = $config['has-token'] ?? false; - if ($hasToken === false) { - Log::debug('Job has no token'); - // create customer if user does not have one: - $customer = $this->getCustomer(); - Log::debug(sprintf('Customer ID is %s', $customer->getId())); - // use customer to request a token: - $uri = route('import.status', [$this->job->key]); - $token = $this->getToken($customer, $uri); - Log::debug(sprintf('Token is %s', $token->getToken())); + $config = $this->job->configuration; + $stage = $config['stage']; - // update job, give it the token: - $config = $this->job->configuration; - $config['has-token'] = true; - $config['token'] = $token->getToken(); - $config['token-expires'] = $token->getExpiresAt()->format('U'); - $config['token-url'] = $token->getConnectUrl(); - $this->job->configuration = $config; - - Log::debug('Job config is now', $config); - - // update job, set status to "configuring". - $this->job->status = 'configuring'; - $this->job->save(); - Log::debug(sprintf('Job status is now %s', $this->job->status)); - - return true; - } - $isRedirected = $config['is-redirected'] ?? false; - if ($isRedirected === true) { - // assume user has "used" the token. - // ... - // now what? - throw new FireflyException('Application cannot handle this.'); + switch ($stage) { + case 'initial': + // get customer and token: + $this->runStageInitial(); + break; + case 'has-token': + // import routine does nothing at this point: + break; + case 'user-logged-in': + $this->runStageLoggedIn(); + break; + case 'have-account-mapping': + $this->runStageHaveMapping(); + break; + default: + throw new FireflyException(sprintf('Cannot handle stage %s', $stage)); } + var_dump($config); + exit; + throw new FireflyException('Application cannot handle this.'); } @@ -139,18 +155,39 @@ class SpectreRoutine implements RoutineInterface */ public function setJob(ImportJob $job) { - $this->job = $job; + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); } /** * @return Customer * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ protected function createCustomer(): Customer { $newCustomerRequest = new NewCustomerRequest($this->job->user); - $newCustomerRequest->call(); - $customer = $newCustomerRequest->getCustomer(); + $customer = null; + try { + $newCustomerRequest->call(); + $customer = $newCustomerRequest->getCustomer(); + } catch (DuplicatedCustomerException $e) { + // already exists, must fetch customer instead. + Log::warning('Customer exists already for user, fetch it.'); + } + if (is_null($customer)) { + $getCustomerRequest = new ListCustomersRequest($this->job->user); + $getCustomerRequest->call(); + $customers = $getCustomerRequest->getCustomers(); + /** @var Customer $current */ + foreach ($customers as $current) { + if ($current->getIdentifier() === 'default_ff3_customer') { + $customer = $current; + break; + } + } + } Preferences::setForUser($this->job->user, 'spectre_customer', $customer->toArray()); @@ -160,15 +197,26 @@ class SpectreRoutine implements RoutineInterface /** * @return Customer - * @throws \FireflyIII\Exceptions\FireflyException + * @throws FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ protected function getCustomer(): Customer { - $preference = Preferences::getForUser($this->job->user, 'spectre_customer', null); - if (is_null($preference)) { - return $this->createCustomer(); + $config = $this->job->configuration; + if (!is_null($config['customer'])) { + $customer = new Customer($config['customer']); + + return $customer; } - $customer = new Customer($preference->data); + + $customer = $this->createCustomer(); + $config['customer'] = [ + 'id' => $customer->getId(), + 'identifier' => $customer->getIdentifier(), + 'secret' => $customer->getSecret(), + ]; + $this->job->configuration = $config; + $this->job->save(); return $customer; } @@ -179,6 +227,7 @@ class SpectreRoutine implements RoutineInterface * * @return Token * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ protected function getToken(Customer $customer, string $returnUri): Token { @@ -191,4 +240,124 @@ class SpectreRoutine implements RoutineInterface return $request->getToken(); } + + /** + * @throws FireflyException + * @throws SpectreException + */ + protected function runStageInitial(): void + { + Log::debug('In runStageInitial()'); + + // create customer if user does not have one: + $customer = $this->getCustomer(); + Log::debug(sprintf('Customer ID is %s', $customer->getId())); + + // use customer to request a token: + $uri = route('import.status', [$this->job->key]); + $token = $this->getToken($customer, $uri); + Log::debug(sprintf('Token is %s', $token->getToken())); + + // update job, give it the token: + $config = $this->job->configuration; + $config['has-token'] = true; + $config['token'] = $token->getToken(); + $config['token-expires'] = $token->getExpiresAt()->format('U'); + $config['token-url'] = $token->getConnectUrl(); + $config['stage'] = 'has-token'; + $this->job->configuration = $config; + + Log::debug('Job config is now', $config); + + // update job, set status to "configuring". + $this->job->status = 'configuring'; + $this->job->save(); + Log::debug(sprintf('Job status is now %s', $this->job->status)); + } + + /** + * @throws FireflyException + * @throws SpectreException + */ + protected function runStageLoggedIn(): void + { + Log::debug('In runStageLoggedIn'); + // list all logins: + $customer = $this->getCustomer(); + $request = new ListLoginsRequest($this->job->user); + $request->setCustomer($customer); + $request->call(); + $logins = $request->getLogins(); + /** @var Login $final */ + $final = null; + // loop logins, find the latest with no error in it: + $time = 0; + /** @var Login $login */ + foreach ($logins as $login) { + $attempt = $login->getLastAttempt(); + $attemptTime = intval($attempt->getCreatedAt()->format('U')); + if ($attemptTime > $time && is_null($attempt->getFailErrorClass())) { + $time = $attemptTime; + $final = $login; + } + } + if (is_null($final)) { + throw new FireflyException('No valid login attempt found.'); + } + + // list the users accounts using this login. + $accountRequest = new ListAccountsRequest($this->job->user); + $accountRequest->setLogin($login); + $accountRequest->call(); + $accounts = $accountRequest->getAccounts(); + + // store accounts in job: + $all = []; + /** @var Account $account */ + foreach ($accounts as $account) { + $all[] = $account->toArray(); + } + + // update job: + $config = $this->job->configuration; + $config['accounts'] = $all; + $config['login'] = $login->toArray(); + $config['stage'] = 'have-accounts'; + $this->job->configuration = $config; + $this->job->status = 'configuring'; + $this->job->save(); + + return; + } + + /** + * + */ + private function runStageHaveMapping() + { + // for each spectre account id in 'account-mappings'. + // find FF account + // get transactions. + // import?! + $config = $this->job->configuration; + $accounts = $config['accounts'] ?? []; + /** @var array $accountArray */ + foreach ($accounts as $accountArray) { + $account = new Account($accountArray); + $importId = intval($config['accounts-mapped'][$account->getid()] ?? 0); + $doImport = $importId !== 0 ? true : false; + if (!$doImport) { + continue; + } + // import into account + $listTransactionsRequest = new ListTransactionsRequest($this->job->user); + $listTransactionsRequest->setAccount($account); + $listTransactionsRequest->call(); + $transactions = $listTransactionsRequest->getTransactions(); + var_dump($transactions);exit; + + } + var_dump($config); + exit; + } } diff --git a/app/Import/Specifics/SnsDescription.php b/app/Import/Specifics/SnsDescription.php index 3ef766e81a..b79d16b9f5 100644 --- a/app/Import/Specifics/SnsDescription.php +++ b/app/Import/Specifics/SnsDescription.php @@ -50,7 +50,10 @@ class SnsDescription implements SpecificInterface */ public function run(array $row): array { - $row = array_values($row); + $row = array_values($row); + if (!isset($row[17])) { + return $row; + } $row[17] = ltrim($row[17], "'"); $row[17] = rtrim($row[17], "'"); diff --git a/app/Import/Storage/ImportStorage.php b/app/Import/Storage/ImportStorage.php index f548ae0068..a9ff0341d0 100644 --- a/app/Import/Storage/ImportStorage.php +++ b/app/Import/Storage/ImportStorage.php @@ -94,8 +94,8 @@ class ImportStorage $this->defaultCurrencyId = $currency->id; $this->transfers = $this->getTransfers(); $config = $job->configuration; - $this->applyRules = $config['apply_rules'] ?? false; - $this->matchBills = $config['match_bills'] ?? false; + $this->applyRules = $config['apply-rules'] ?? false; + $this->matchBills = $config['match-bills'] ?? false; if (true === $this->applyRules) { Log::debug('applyRules seems to be true, get the rules.'); $this->rules = $this->getRules(); diff --git a/app/Models/Account.php b/app/Models/Account.php index 11a1061320..b04ec43d8e 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -345,6 +345,15 @@ class Account extends Model $this->attributes['iban'] = Crypt::encrypt($value); } + /** + * @codeCoverageIgnore + * Get all of the notes. + */ + public function notes() + { + return $this->morphMany(Note::class, 'noteable'); + } + /** * @codeCoverageIgnore * diff --git a/app/Models/Bill.php b/app/Models/Bill.php index b7dcb125cd..ec09d0fcc7 100644 --- a/app/Models/Bill.php +++ b/app/Models/Bill.php @@ -132,7 +132,7 @@ class Bill extends Model */ public function notes() { - return $this->morphMany('FireflyIII\Models\Note', 'noteable'); + return $this->morphMany(Note::class, 'noteable'); } /** diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php index 57015f946b..7dd51ff571 100644 --- a/app/Models/ImportJob.php +++ b/app/Models/ImportJob.php @@ -161,7 +161,7 @@ class ImportJob extends Model */ public function getExtendedStatusAttribute($value) { - if (0 === strlen($value)) { + if (0 === strlen(strval($value))) { return []; } @@ -209,6 +209,7 @@ class ImportJob extends Model $disk = Storage::disk('upload'); $encryptedContent = $disk->get($fileName); $content = Crypt::decrypt($encryptedContent); + $content = trim($content); Log::debug(sprintf('Content size is %d bytes.', strlen($content))); return $content; diff --git a/app/Models/Note.php b/app/Models/Note.php index df8b0de9de..b9fa882cd5 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -57,8 +57,8 @@ class Note extends Model /** * @codeCoverageIgnore - * Get all of the owning noteable models. Currently piggy bank and - * transaction journal. + * + * Get all of the owning noteable models. */ public function noteable() { diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 3c404fdf88..328cfc21e7 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -29,6 +29,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; use FireflyIII\Models\Category; +use FireflyIII\Models\Note; use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; @@ -86,6 +87,28 @@ class AccountRepository implements AccountRepositoryInterface return true; } + /** + * Return account type by string. + * + * @param string $type + * + * @return AccountType|null + */ + public function getAccountType(string $type): ?AccountType + { + return AccountType::whereType($type)->first(); + } + + /** + * @param Account $account + * + * @return Note|null + */ + public function getNote(Account $account): ?Note + { + return $account->notes()->first(); + } + /** * Returns the date of the very last transaction in this account. * @@ -176,6 +199,11 @@ class AccountRepository implements AccountRepositoryInterface } $this->deleteInitialBalance($newAccount); + // update note: + if (isset($data['notes'])) { + $this->updateNote($newAccount, $data['notes']); + } + return $newAccount; } @@ -199,6 +227,12 @@ class AccountRepository implements AccountRepositoryInterface $this->updateInitialBalance($account, $data); } + // update note: + if (isset($data['notes']) && null !== $data['notes']) { + $this->updateNote($account, strval($data['notes'])); + } + + return $account; } @@ -364,7 +398,7 @@ class AccountRepository implements AccountRepositoryInterface 'user_id' => $this->user->id, 'transaction_type_id' => $transactionType->id, 'transaction_currency_id' => $currencyId, - 'description' => 'Initial balance for "' . $account->name . '"', + 'description' => strval(trans('firefly.initial_balance_description', ['account' => $account->name])), 'completed' => true, 'date' => $data['openingBalanceDate'], ] @@ -507,6 +541,33 @@ class AccountRepository implements AccountRepositoryInterface } } + /** + * @param Account $account + * @param string $note + * + * @return bool + */ + protected function updateNote(Account $account, string $note): bool + { + if (0 === strlen($note)) { + $dbNote = $account->notes()->first(); + if (null !== $dbNote) { + $dbNote->delete(); + } + + return true; + } + $dbNote = $account->notes()->first(); + if (null === $dbNote) { + $dbNote = new Note(); + $dbNote->noteable()->associate($account); + } + $dbNote->text = trim($note); + $dbNote->save(); + + return true; + } + /** * @param Account $account * @param TransactionJournal $journal @@ -518,13 +579,15 @@ class AccountRepository implements AccountRepositoryInterface */ protected function updateOpeningBalanceJournal(Account $account, TransactionJournal $journal, array $data): bool { - $date = $data['openingBalanceDate']; - $amount = strval($data['openingBalance']); - $currencyId = intval($data['currency_id']); + $date = $data['openingBalanceDate']; + $amount = strval($data['openingBalance']); + $negativeAmount = bcmul($amount, '-1'); + $currencyId = intval($data['currency_id']); - Log::debug(sprintf('Submitted amount for opening balance to update is %s', $amount)); + Log::debug(sprintf('Submitted amount for opening balance to update is "%s"', $amount)); if (0 === bccomp($amount, '0')) { + Log::notice(sprintf('Amount "%s" is zero, delete opening balance.', $amount)); $journal->delete(); return true; @@ -534,18 +597,18 @@ class AccountRepository implements AccountRepositoryInterface $journal->date = $date; $journal->transaction_currency_id = $currencyId; $journal->save(); + // update transactions: /** @var Transaction $transaction */ foreach ($journal->transactions()->get() as $transaction) { - if ($account->id === $transaction->account_id) { - Log::debug(sprintf('Will change transaction #%d amount from %s to %s', $transaction->id, $transaction->amount, $amount)); + if (intval($account->id) === intval($transaction->account_id)) { + Log::debug(sprintf('Will (eq) change transaction #%d amount from "%s" to "%s"', $transaction->id, $transaction->amount, $amount)); $transaction->amount = $amount; $transaction->transaction_currency_id = $currencyId; $transaction->save(); } - if ($account->id !== $transaction->account_id) { - $negativeAmount = bcmul($amount, '-1'); - Log::debug(sprintf('Will change transaction #%d amount from %s to %s', $transaction->id, $transaction->amount, $negativeAmount)); + if (!(intval($account->id) === intval($transaction->account_id))) { + Log::debug(sprintf('Will (neq) change transaction #%d amount from "%s" to "%s"', $transaction->id, $transaction->amount, $negativeAmount)); $transaction->amount = $negativeAmount; $transaction->transaction_currency_id = $currencyId; $transaction->save(); diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 985b32104c..eb5e70fe0a 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -24,6 +24,8 @@ namespace FireflyIII\Repositories\Account; use Carbon\Carbon; use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Note; use FireflyIII\Models\TransactionJournal; use FireflyIII\User; use Illuminate\Support\Collection; @@ -83,6 +85,15 @@ interface AccountRepositoryInterface */ public function findByName(string $name, array $types): Account; + /** + * Return account type by string. + * + * @param string $type + * + * @return AccountType|null + */ + public function getAccountType(string $type): ?AccountType; + /** * @param array $accountIds * @@ -109,6 +120,13 @@ interface AccountRepositoryInterface */ public function getCashAccount(): Account; + /** + * @param Account $account + * + * @return Note|null + */ + public function getNote(Account $account): ?Note; + /** * Find or create the opposing reconciliation account. * diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index 8925dbaaf3..7300ee4bc2 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -25,6 +25,7 @@ namespace FireflyIII\Repositories\ImportJob; use Crypt; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; +use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Str; @@ -41,6 +42,37 @@ class ImportJobRepository implements ImportJobRepositoryInterface /** @var User */ private $user; + /** + * @param ImportJob $job + * @param int $steps + * + * @return ImportJob + */ + public function addStepsDone(ImportJob $job, int $steps = 1): ImportJob + { + $job->addStepsDone($steps); + + return $job; + } + + /** + * Return number of imported rows with this hash value. + * + * @param string $hash + * + * @return int + */ + public function countByHash(string $hash): int + { + $json = json_encode($hash); + $count = TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->where('data', $json) + ->where('name', 'importHash') + ->count(); + + return intval($count); + } + /** * @param string $type * @@ -62,7 +94,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface $importJob->file_type = $type; $importJob->key = Str::random(12); $importJob->status = 'new'; - $importJob->configuration = config(sprintf('import.default_config.%s', $type)) ?? []; + $importJob->configuration = []; $importJob->extended_status = [ 'steps' => 0, 'done' => 0, @@ -86,6 +118,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface */ public function findByKey(string $key): ImportJob { + /** @var ImportJob $result */ $result = $this->user->importJobs()->where('key', $key)->first(['import_jobs.*']); if (null === $result) { return new ImportJob; @@ -94,6 +127,40 @@ class ImportJobRepository implements ImportJobRepositoryInterface return $result; } + /** + * Return configuration of job. + * + * @param ImportJob $job + * + * @return array + */ + public function getConfiguration(ImportJob $job): array + { + $config = $job->configuration; + if (is_array($config)) { + return $config; + } + + return []; + } + + /** + * Return extended status of job. + * + * @param ImportJob $job + * + * @return array + */ + public function getExtendedStatus(ImportJob $job): array + { + $status = $job->extended_status; + if (is_array($status)) { + return $status; + } + + return []; + } + /** * @param ImportJob $job * @param UploadedFile $file @@ -186,6 +253,30 @@ class ImportJobRepository implements ImportJobRepositoryInterface return $job; } + /** + * @param ImportJob $job + * @param array $array + * + * @return ImportJob + */ + public function setExtendedStatus(ImportJob $job, array $array): ImportJob + { + // remove 'errors' because it gets larger and larger and larger... + $display = $array; + unset($display['errors']); + Log::debug(sprintf('Incoming extended status for job "%s" is (except errors): ', $job->key), $display); + $currentStatus = $job->extended_status; + $newStatus = array_merge($currentStatus, $array); + $job->extended_status = $newStatus; + $job->save(); + + // remove 'errors' because it gets larger and larger and larger... + unset($newStatus['errors']); + Log::debug(sprintf('Set extended status of job "%s" to (except errors): ', $job->key), $newStatus); + + return $job; + } + /** * @param User $user */ @@ -207,4 +298,17 @@ class ImportJobRepository implements ImportJobRepositoryInterface return $job; } + + /** + * Return import file content. + * + * @param ImportJob $job + * + * @return string + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + */ + public function uploadFileContents(ImportJob $job): string + { + return $job->uploadFileContents(); + } } diff --git a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php index 6138806ffa..658befe70a 100644 --- a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php +++ b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php @@ -31,6 +31,23 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; */ interface ImportJobRepositoryInterface { + /** + * @param ImportJob $job + * @param int $steps + * + * @return ImportJob + */ + public function addStepsDone(ImportJob $job, int $steps = 1): ImportJob; + + /** + * Return number of imported rows with this hash value. + * + * @param string $hash + * + * @return int + */ + public function countByHash(string $hash): int; + /** * @param string $type * @@ -45,6 +62,24 @@ interface ImportJobRepositoryInterface */ public function findByKey(string $key): ImportJob; + /** + * Return configuration of job. + * + * @param ImportJob $job + * + * @return array + */ + public function getConfiguration(ImportJob $job): array; + + /** + * Return extended status of job. + * + * @param ImportJob $job + * + * @return array + */ + public function getExtendedStatus(ImportJob $job): array; + /** * @param ImportJob $job * @param UploadedFile $file @@ -69,6 +104,14 @@ interface ImportJobRepositoryInterface */ public function setConfiguration(ImportJob $job, array $configuration): ImportJob; + /** + * @param ImportJob $job + * @param array $array + * + * @return void + */ + public function setExtendedStatus(ImportJob $job, array $array): ImportJob; + /** * @param User $user */ @@ -81,4 +124,13 @@ interface ImportJobRepositoryInterface * @return ImportJob */ public function updateStatus(ImportJob $job, string $status): ImportJob; + + /** + * Return import file content. + * + * @param ImportJob $job + * + * @return string + */ + public function uploadFileContents(ImportJob $job): string; } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index c71afd2e20..7bf6bb78cd 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -22,12 +22,15 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; +use DB; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Note; +use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; @@ -432,6 +435,43 @@ class JournalRepository implements JournalRepositoryInterface return $journal; } + /** + * @param TransactionJournal $journal + * @param int $budgetId + * + * @return TransactionJournal + */ + public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal + { + if ($budgetId === 0) { + $journal->budgets()->detach(); + $journal->save(); + + return $journal; + } + $this->storeBudgetWithJournal($journal, $budgetId); + + return $journal; + } + + /** + * @param TransactionJournal $journal + * @param string $category + * + * @return TransactionJournal + */ + public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal + { + Log::debug(sprintf('In updateCategory("%s")', $category)); + $journal->categories()->detach(); + if (strlen($category) === 0) { + return $journal; + } + $this->storeCategoryWithJournal($journal, $category); + + return $journal; + } + /** * Same as above but for transaction journal with multiple transactions. * @@ -492,4 +532,48 @@ class JournalRepository implements JournalRepositoryInterface return $journal; } + + /** + * Update tags. + * + * @param TransactionJournal $journal + * @param array $array + * + * @return bool + */ + public function updateTags(TransactionJournal $journal, array $array): bool + { + // create tag repository + /** @var TagRepositoryInterface $tagRepository */ + $tagRepository = app(TagRepositoryInterface::class); + + // find or create all tags: + $tags = []; + $ids = []; + foreach ($array as $name) { + if (strlen(trim($name)) > 0) { + $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); + $tags[] = $tag; + $ids[] = $tag->id; + } + } + + // delete all tags connected to journal not in this array: + if (count($ids) > 0) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); + } + // if count is zero, delete them all: + if (0 === count($ids)) { + DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); + } + + // connect each tag to journal (if not yet connected): + /** @var Tag $tag */ + foreach ($tags as $tag) { + Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); + $tagRepository->connect($journal, $tag); + } + + return true; + } } diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 782b38cca3..5a99125173 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -160,6 +160,22 @@ interface JournalRepositoryInterface */ public function update(TransactionJournal $journal, array $data): TransactionJournal; + /** + * @param TransactionJournal $journal + * @param int $budgetId + * + * @return TransactionJournal + */ + public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal; + + /** + * @param TransactionJournal $journal + * @param string $category + * + * @return TransactionJournal + */ + public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal; + /** * @param TransactionJournal $journal * @param array $data @@ -167,4 +183,12 @@ interface JournalRepositoryInterface * @return TransactionJournal */ public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal; + + /** + * @param TransactionJournal $journal + * @param array $tags + * + * @return bool + */ + public function updateTags(TransactionJournal $journal, array $tags): bool; } diff --git a/app/Repositories/Journal/SupportJournalsTrait.php b/app/Repositories/Journal/SupportJournalsTrait.php index 6584e18a80..5815cc8a4f 100644 --- a/app/Repositories/Journal/SupportJournalsTrait.php +++ b/app/Repositories/Journal/SupportJournalsTrait.php @@ -100,6 +100,7 @@ trait SupportJournalsTrait $budget = Budget::find($budgetId); $journal->budgets()->save($budget); } + $journal->touch(); } /** @@ -112,6 +113,7 @@ trait SupportJournalsTrait $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); $journal->categories()->save($category); } + $journal->touch(); } /** @@ -247,6 +249,10 @@ trait SupportJournalsTrait case TransactionType::WITHDRAWAL: // continue: $nativeCurrencyId = intval($accounts[$check]->getMeta('currency_id')); + if ($nativeCurrencyId === 0) { + // fall back to given ID (not everybody upgrades nicely). + $nativeCurrencyId = $submittedCurrencyId; + } // does not match? Then user has submitted amount in a foreign currency: if ($nativeCurrencyId !== $submittedCurrencyId) { diff --git a/app/Repositories/Journal/UpdateJournalsTrait.php b/app/Repositories/Journal/UpdateJournalsTrait.php index e56b62d73a..eb16eaeda3 100644 --- a/app/Repositories/Journal/UpdateJournalsTrait.php +++ b/app/Repositories/Journal/UpdateJournalsTrait.php @@ -37,6 +37,7 @@ use Log; */ trait UpdateJournalsTrait { + /** * When the user edits a split journal, each line is missing crucial data:. * @@ -121,47 +122,5 @@ trait UpdateJournalsTrait $transaction->save(); } - /** - * Update tags. - * - * @param TransactionJournal $journal - * @param array $array - * - * @return bool - */ - protected function updateTags(TransactionJournal $journal, array $array): bool - { - // create tag repository - /** @var TagRepositoryInterface $tagRepository */ - $tagRepository = app(TagRepositoryInterface::class); - // find or create all tags: - $tags = []; - $ids = []; - foreach ($array as $name) { - if (strlen(trim($name)) > 0) { - $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); - $tags[] = $tag; - $ids[] = $tag->id; - } - } - - // delete all tags connected to journal not in this array: - if (count($ids) > 0) { - DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete(); - } - // if count is zero, delete them all: - if (0 === count($ids)) { - DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete(); - } - - // connect each tag to journal (if not yet connected): - /** @var Tag $tag */ - foreach ($tags as $tag) { - Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); - $tagRepository->connect($journal, $tag); - } - - return true; - } } diff --git a/app/Services/Github/Request/UpdateRequest.php b/app/Services/Github/Request/UpdateRequest.php index 5182b75d10..a0f6a58de7 100644 --- a/app/Services/Github/Request/UpdateRequest.php +++ b/app/Services/Github/Request/UpdateRequest.php @@ -32,7 +32,7 @@ use SimpleXMLElement; /** * Class UpdateRequest */ -class UpdateRequest implements GitHubRequest +class UpdateRequest implements GithubRequest { /** @var array */ private $releases = []; diff --git a/app/Services/Spectre/Exception/DuplicatedCustomerException.php b/app/Services/Spectre/Exception/DuplicatedCustomerException.php new file mode 100644 index 0000000000..a9a3a42996 --- /dev/null +++ b/app/Services/Spectre/Exception/DuplicatedCustomerException.php @@ -0,0 +1,32 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Exception; + +/** + * Class DuplicatedCustomerException + */ +class DuplicatedCustomerException extends SpectreException +{ + +} \ No newline at end of file diff --git a/app/Services/Spectre/Exception/SpectreException.php b/app/Services/Spectre/Exception/SpectreException.php new file mode 100644 index 0000000000..78200f7f08 --- /dev/null +++ b/app/Services/Spectre/Exception/SpectreException.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Exception; + +use Exception; + +/** + * Class SpectreException + */ +class SpectreException extends Exception +{ + +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Account.php b/app/Services/Spectre/Object/Account.php new file mode 100644 index 0000000000..92f01ed6c3 --- /dev/null +++ b/app/Services/Spectre/Object/Account.php @@ -0,0 +1,101 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Object; + +use Carbon\Carbon; + +/** + * Class Account + */ +class Account extends SpectreObject +{ + /** @var float */ + private $balance; + /** @var Carbon */ + private $createdAt; + /** @var string */ + private $currencyCode; + /** @var array */ + private $extra = []; + /** @var int */ + private $id; + /** @var int */ + private $loginId; + /** @var string */ + private $name; + /** @var string */ + private $nature; + /** @var Carbon */ + private $updatedAt; + + /** + * Account constructor. + * + * @param array $data + */ + public function __construct(array $data) + { + $this->id = $data['id']; + $this->loginId = $data['login_id']; + $this->currencyCode = $data['currency_code']; + $this->balance = $data['balance']; + $this->name = $data['name']; + $this->nature = $data['nature']; + $this->createdAt = new Carbon($data['created_at']); + $this->updatedAt = new Carbon($data['updated_at']); + + foreach ($data['extra'] as $key => $value) { + $this->extra[$key] = $value; + } + } + + /** + * @return int + */ + public function getId(): int + { + return $this->id; + } + + /** + * @return array + */ + public function toArray(): array + { + $array = [ + 'balance' => $this->balance, + 'created_at' => $this->createdAt->toIso8601String(), + 'currency_code' => $this->currencyCode, + 'extra' => $this->extra, + 'id' => $this->id, + 'login_id' => $this->loginId, + 'name' => $this->name, + 'nature' => $this->nature, + 'updated_at' => $this->updatedAt->toIso8601String(), + ]; + + return $array; + } + +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Attempt.php b/app/Services/Spectre/Object/Attempt.php new file mode 100644 index 0000000000..c6151be494 --- /dev/null +++ b/app/Services/Spectre/Object/Attempt.php @@ -0,0 +1,208 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Object; + +use Carbon\Carbon; + +/** + * Class Attempt + */ +class Attempt extends SpectreObject +{ + /** @var string */ + private $apiMode; + /** @var int */ + private $apiVersion; + /** @var bool */ + private $automaticFetch; + /** @var bool */ + private $categorize; + /** @var Carbon */ + private $consentGivenAt; + /** @var array */ + private $consentTypes = []; + /** @var Carbon */ + private $createdAt; + /** @var array */ + private $customFields = []; + /** @var bool */ + private $dailyRefresh; + /** @var string */ + private $deviceType; + /** @var array */ + private $excludeAccounts = []; + /** @var Carbon */ + private $failAt; + /** @var string */ + private $failErrorClass; + /** @var string */ + private $failMessage; + /** @var string */ + private $fetchType; + /** @var bool */ + private $finished; + /** @var bool */ + private $finishedRecent; + /** @var Carbon */ + private $fromDate; + /** @var int */ + private $id; + /** @var bool */ + private $interactive; + /** @var string */ + private $locale; + /** @var bool */ + private $partial; + /** @var string */ + private $remoteIp; + /** @var bool */ + private $showConsentInformation; + /** @var array */ + private $stages = []; + /** @var bool */ + private $storeCredentials; + /** @var Carbon */ + private $successAt; + /** @var Carbon */ + private $toDate; + /** @var Carbon */ + private $updatedAt; + /** @var string */ + private $userAgent; // undocumented + + /** + * Attempt constructor. + * + * @param array $data + */ + public function __construct(array $data) + { + $this->apiMode = $data['api_mode']; + $this->apiVersion = $data['api_version']; + $this->automaticFetch = $data['automatic_fetch']; + $this->categorize = $data['categorize']; + $this->createdAt = new Carbon($data['created_at']); + $this->consentGivenAt = new Carbon($data['consent_given_at']); + $this->consentTypes = $data['consent_types']; + $this->customFields = $data['custom_fields']; + $this->dailyRefresh = $data['daily_refresh']; + $this->deviceType = $data['device_type']; + $this->userAgent = $data['user_agent'] ?? ''; + $this->remoteIp = $data['remote_ip']; + $this->excludeAccounts = $data['exclude_accounts']; + $this->failAt = new Carbon($data['fail_at']); + $this->failErrorClass = $data['fail_error_class']; + $this->failMessage = $data['fail_message']; + $this->fetchType = $data['fetch_type']; + $this->finished = $data['finished']; + $this->finishedRecent = $data['finished_recent']; + $this->fromDate = new Carbon($data['from_date']); + $this->id = $data['id']; + $this->interactive = $data['interactive']; + $this->locale = $data['locale']; + $this->partial = $data['partial']; + $this->showConsentInformation = $data['show_consent_confirmation']; + $this->stages = $data['stages'] ?? []; + $this->storeCredentials = $data['store_credentials']; + $this->successAt = new Carbon($data['success_at']); + $this->toDate = new Carbon($data['to_date']); + $this->updatedAt = new Carbon($data['updated_at']); + + } + + /** + * @return Carbon + */ + public function getCreatedAt(): Carbon + { + return $this->createdAt; + } + + /** + * @return Carbon + */ + public function getFailAt(): Carbon + { + return $this->failAt; + } + + /** + * @return null|string + */ + public function getFailErrorClass(): ?string + { + return $this->failErrorClass; + } + + /** + * @return null|string + */ + public function getFailMessage(): ?string + { + return $this->failMessage; + } + + /** + * @return array + */ + public function toArray(): array + { + $array = [ + 'api_mode' => $this->apiMode, + 'api_version' => $this->apiVersion, + 'automatic_fetch' => $this->automaticFetch, + 'categorize' => $this->categorize, + 'created_at' => $this->createdAt->toIso8601String(), + 'consent_given_at' => $this->consentGivenAt->toIso8601String(), + 'consent_types' => $this->consentTypes, + 'custom_fields' => $this->customFields, + 'daily_refresh' => $this->dailyRefresh, + 'device_type' => $this->deviceType, + 'user_agent' => $this->userAgent, + 'remote_ip' => $this->remoteIp, + 'exclude_accounts' => $this->excludeAccounts, + 'fail_at' => $this->failAt->toIso8601String(), + 'fail_error_class' => $this->failErrorClass, + 'fail_message' => $this->failMessage, + 'fetch_type' => $this->fetchType, + 'finished' => $this->finished, + 'finished_recent' => $this->finishedRecent, + 'from_date' => $this->fromDate->toIso8601String(), + 'id' => $this->id, + 'interactive' => $this->interactive, + 'locale' => $this->locale, + 'partial' => $this->partial, + 'show_consent_confirmation' => $this->showConsentInformation, + 'stages' => $this->stages, + 'store_credentials' => $this->storeCredentials, + 'success_at' => $this->successAt->toIso8601String(), + 'to_date' => $this->toDate->toIso8601String(), + 'updated_at' => $this->updatedAt->toIso8601String(), + ]; + + return $array; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Holder.php b/app/Services/Spectre/Object/Holder.php new file mode 100644 index 0000000000..b6416f925b --- /dev/null +++ b/app/Services/Spectre/Object/Holder.php @@ -0,0 +1,48 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Object; + +/** + * Class Holder + */ +class Holder extends SpectreObject +{ + /** + * Holder constructor. + * + * @param array $data + */ + public function __construct(array $data) + { + + } + + /** + * @return array + */ + public function toArray(): array + { + return []; + } +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Login.php b/app/Services/Spectre/Object/Login.php new file mode 100644 index 0000000000..fb2624c5ad --- /dev/null +++ b/app/Services/Spectre/Object/Login.php @@ -0,0 +1,146 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Object; + +use Carbon\Carbon; + + +/** + * Class Login + */ +class Login extends SpectreObject +{ + /** @var Carbon */ + private $consentGivenAt; + /** @var array */ + private $consentTypes; + /** @var string */ + private $countryCode; + /** @var Carbon */ + private $createdAt; + /** @var int */ + private $customerId; + /** @var bool */ + private $dailyRefresh; + /** @var Holder */ + private $holderInfo; + /** @var int */ + private $id; + /** @var Attempt */ + private $lastAttempt; + /** @var Carbon */ + private $lastSuccessAt; + /** @var Carbon */ + private $nextRefreshPossibleAt; + /** @var string */ + private $providerCode; + /** @var int */ + private $providerId; + /** @var string */ + private $providerName; + /** @var bool */ + private $showConsentConfirmation; + /** @var string */ + private $status; + /** @var bool */ + private $storeCredentials; + /** @var Carbon */ + private $updatedAt; + + /** + * Login constructor. + * + * @param array $data + */ + public function __construct(array $data) + { + $this->consentGivenAt = new Carbon($data['consent_given_at']); + $this->consentTypes = $data['consent_types']; + $this->countryCode = $data['country_code']; + $this->createdAt = new Carbon($data['created_at']); + $this->updatedAt = new Carbon($data['updated_at']); + $this->customerId = $data['customer_id']; + $this->dailyRefresh = $data['daily_refresh']; + $this->holderInfo = new Holder($data['holder_info']); + $this->id = $data['id']; + $this->lastAttempt = new Attempt($data['last_attempt']); + $this->lastSuccessAt = new Carbon($data['last_success_at']); + $this->nextRefreshPossibleAt = new Carbon($data['next_refresh_possible_at']); + $this->providerCode = $data['provider_code']; + $this->providerId = $data['provider_id']; + $this->providerName = $data['provider_name']; + $this->showConsentConfirmation = $data['show_consent_confirmation']; + $this->status = $data['status']; + $this->storeCredentials = $data['store_credentials']; + + } + + /** + * @return int + */ + public function getId(): int + { + return $this->id; + } + + /** + * @return Attempt + */ + public function getLastAttempt(): Attempt + { + return $this->lastAttempt; + } + + /** + * @return array + */ + public function toArray(): array + { + $array = [ + 'consent_given_at' => $this->consentGivenAt->toIso8601String(), + 'consent_types' => $this->consentTypes, + 'country_code' => $this->countryCode, + 'created_at' => $this->createdAt->toIso8601String(), + 'updated_at' => $this->updatedAt->toIso8601String(), + 'customer_id' => $this->customerId, + 'daily_refresh' => $this->dailyRefresh, + 'holder_info' => $this->holderInfo->toArray(), + 'id' => $this->id, + 'last_attempt' => $this->lastAttempt->toArray(), + 'last_success_at' => $this->lastSuccessAt->toIso8601String(), + 'next_refresh_possible_at' => $this->nextRefreshPossibleAt, + 'provider_code' => $this->providerCode, + 'provider_id' => $this->providerId, + 'provider_name' => $this->providerName, + 'show_consent_confirmation' => $this->showConsentConfirmation, + 'status' => $this->status, + 'store_credentials' => $this->storeCredentials, + + ]; + + return $array; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Transaction.php b/app/Services/Spectre/Object/Transaction.php new file mode 100644 index 0000000000..23c8633a91 --- /dev/null +++ b/app/Services/Spectre/Object/Transaction.php @@ -0,0 +1,41 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Object; + +/** + * Class Transaction + */ +class Transaction extends SpectreObject +{ + /** + * Transaction constructor. + * + * @param array $data + */ + public function __construct(array $data) { + var_dump($data); + exit; + } + +} \ No newline at end of file diff --git a/app/Services/Spectre/Request/CreateTokenRequest.php b/app/Services/Spectre/Request/CreateTokenRequest.php index adacab4ae8..ff0925779c 100644 --- a/app/Services/Spectre/Request/CreateTokenRequest.php +++ b/app/Services/Spectre/Request/CreateTokenRequest.php @@ -44,6 +44,7 @@ class CreateTokenRequest extends SpectreRequest /** * * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ public function call(): void { diff --git a/app/Services/Spectre/Request/ListAccountsRequest.php b/app/Services/Spectre/Request/ListAccountsRequest.php new file mode 100644 index 0000000000..2912137d62 --- /dev/null +++ b/app/Services/Spectre/Request/ListAccountsRequest.php @@ -0,0 +1,93 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Request; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Services\Spectre\Exception\SpectreException; +use FireflyIII\Services\Spectre\Object\Account; +use FireflyIII\Services\Spectre\Object\Login; +use Log; + +/** + * Class ListAccountsRequest + */ +class ListAccountsRequest extends SpectreRequest +{ + /** @var array */ + private $accounts = []; + /** @var Login */ + private $login; + + /** + * @throws SpectreException + * @throws FireflyException + */ + public function call(): void + { + $hasNextPage = true; + $nextId = 0; + while ($hasNextPage) { + Log::debug(sprintf('Now calling ListAccountsRequest for next_id %d', $nextId)); + $parameters = ['from_id' => $nextId, 'login_id' => $this->login->getId()]; + $uri = '/api/v3/accounts?' . http_build_query($parameters); + $response = $this->sendSignedSpectreGet($uri, []); + + // count entries: + Log::debug(sprintf('Found %d entries in data-array', count($response['data']))); + + // extract next ID + $hasNextPage = false; + if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) { + $hasNextPage = true; + $nextId = $response['meta']['next_id']; + Log::debug(sprintf('Next ID is now %d.', $nextId)); + } else { + Log::debug('No next page.'); + } + + // store customers: + foreach ($response['data'] as $accountArray) { + $this->accounts[] = new Account($accountArray); + } + } + } + + /** + * @return array + */ + public function getAccounts(): array + { + return $this->accounts; + } + + /** + * @param Login $login + */ + public function setLogin(Login $login): void + { + $this->login = $login; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Request/ListCustomersRequest.php b/app/Services/Spectre/Request/ListCustomersRequest.php new file mode 100644 index 0000000000..7395c5a37a --- /dev/null +++ b/app/Services/Spectre/Request/ListCustomersRequest.php @@ -0,0 +1,82 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Request; + +use FireflyIII\Services\Spectre\Object\Customer; +use Log; + + +/** + * Class ListCustomersRequest + */ +class ListCustomersRequest extends SpectreRequest +{ + /** @var array */ + private $customers = []; + + /** + * + * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException + */ + public function call(): void + { + $hasNextPage = true; + $nextId = 0; + while ($hasNextPage) { + Log::debug(sprintf('Now calling ListCustomersRequest for next_id %d', $nextId)); + $parameters = ['from_id' => $nextId]; + $uri = '/api/v3/customers/?' . http_build_query($parameters); + $response = $this->sendSignedSpectreGet($uri, []); + + // count entries: + Log::debug(sprintf('Found %d entries in data-array', count($response['data']))); + + // extract next ID + $hasNextPage = false; + if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) { + $hasNextPage = true; + $nextId = $response['meta']['next_id']; + Log::debug(sprintf('Next ID is now %d.', $nextId)); + } else { + Log::debug('No next page.'); + } + + // store customers: + foreach ($response['data'] as $customerArray) { + $this->customers[] = new Customer($customerArray); + } + } + } + + /** + * @return array + */ + public function getCustomers(): array + { + return $this->customers; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Request/ListLoginsRequest.php b/app/Services/Spectre/Request/ListLoginsRequest.php new file mode 100644 index 0000000000..c6444ec514 --- /dev/null +++ b/app/Services/Spectre/Request/ListLoginsRequest.php @@ -0,0 +1,91 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Request; + +use FireflyIII\Services\Spectre\Object\Customer; +use FireflyIII\Services\Spectre\Object\Login; +use Log; +/** + * Class ListLoginsRequest + */ +class ListLoginsRequest extends SpectreRequest +{ + /** @var Customer */ + private $customer; + + /** @var array */ + private $logins = []; + + /** + * @return array + */ + public function getLogins(): array + { + return $this->logins; + } + + /** + * + */ + public function call(): void + { + $hasNextPage = true; + $nextId = 0; + while ($hasNextPage) { + Log::debug(sprintf('Now calling ListLoginsRequest for next_id %d', $nextId)); + $parameters = ['from_id' => $nextId, 'customer_id' => $this->customer->getId()]; + $uri = '/api/v3/logins/?' . http_build_query($parameters); + $response = $this->sendSignedSpectreGet($uri, []); + + // count entries: + Log::debug(sprintf('Found %d entries in data-array', count($response['data']))); + + // extract next ID + $hasNextPage = false; + if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) { + $hasNextPage = true; + $nextId = $response['meta']['next_id']; + Log::debug(sprintf('Next ID is now %d.', $nextId)); + } else { + Log::debug('No next page.'); + } + + // store logins: + /** @var array $loginArray */ + foreach ($response['data'] as $loginArray) { + $this->logins[] = new Login($loginArray); + } + } + } + + /** + * @param Customer $customer + */ + public function setCustomer(Customer $customer): void + { + $this->customer = $customer; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Request/ListTransactionsRequest.php b/app/Services/Spectre/Request/ListTransactionsRequest.php new file mode 100644 index 0000000000..57f45f199a --- /dev/null +++ b/app/Services/Spectre/Request/ListTransactionsRequest.php @@ -0,0 +1,90 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Spectre\Request; + +use FireflyIII\Services\Spectre\Object\Account; +use FireflyIII\Services\Spectre\Object\Transaction; +use Log; +/** + * Class ListTransactionsRequest + */ +class ListTransactionsRequest extends SpectreRequest +{ + /** @var Account */ + private $account; + /** @var array */ + private $transactions = []; + + /** + * + */ + public function call(): void + { + $hasNextPage = true; + $nextId = 0; + while ($hasNextPage) { + Log::debug(sprintf('Now calling ListTransactionsRequest for next_id %d', $nextId)); + $parameters = ['from_id' => $nextId,'account_id' => $this->account->getId()]; + $uri = '/api/v3/transactions?' . http_build_query($parameters); + $response = $this->sendSignedSpectreGet($uri, []); + + // count entries: + Log::debug(sprintf('Found %d entries in data-array', count($response['data']))); + + // extract next ID + $hasNextPage = false; + if (isset($response['meta']['next_id']) && intval($response['meta']['next_id']) > $nextId) { + $hasNextPage = true; + $nextId = $response['meta']['next_id']; + Log::debug(sprintf('Next ID is now %d.', $nextId)); + } else { + Log::debug('No next page.'); + } + + // store customers: + foreach ($response['data'] as $transactionArray) { + $this->transactions[] = new Transaction($transactionArray); + } + } + } + + /** + * @return array + */ + public function getTransactions(): array + { + return $this->transactions; + } + + + /** + * @param Account $account + */ + public function setAccount(Account $account): void + { + $this->account = $account; + } + + +} \ No newline at end of file diff --git a/app/Services/Spectre/Request/NewCustomerRequest.php b/app/Services/Spectre/Request/NewCustomerRequest.php index 0c6960be90..9e8140c20d 100644 --- a/app/Services/Spectre/Request/NewCustomerRequest.php +++ b/app/Services/Spectre/Request/NewCustomerRequest.php @@ -34,6 +34,7 @@ class NewCustomerRequest extends SpectreRequest /** * @throws \FireflyIII\Exceptions\FireflyException + * @throws \FireflyIII\Services\Spectre\Exception\SpectreException */ public function call(): void { diff --git a/app/Services/Spectre/Request/SpectreRequest.php b/app/Services/Spectre/Request/SpectreRequest.php index 8db025b6ba..b7e129ca0f 100644 --- a/app/Services/Spectre/Request/SpectreRequest.php +++ b/app/Services/Spectre/Request/SpectreRequest.php @@ -23,6 +23,8 @@ declare(strict_types=1); namespace FireflyIII\Services\Spectre\Request; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Services\Spectre\Exception\DuplicatedCustomerException; +use FireflyIII\Services\Spectre\Exception\SpectreException; use FireflyIII\User; use Log; use Requests; @@ -179,6 +181,7 @@ abstract class SpectreRequest * @return array * * @throws FireflyException + * @throws SpectreException */ protected function sendSignedSpectreGet(string $uri, array $data): array { @@ -222,6 +225,7 @@ abstract class SpectreRequest * @return array * * @throws FireflyException + * @throws SpectreException */ protected function sendSignedSpectrePost(string $uri, array $data): array { @@ -255,15 +259,21 @@ abstract class SpectreRequest * @param Requests_Response $response * * @throws FireflyException + * @throws SpectreException */ private function detectError(Requests_Response $response): void { $body = $response->body; $array = json_decode($body, true); if (isset($array['error_class'])) { - $message = $array['error_message'] ?? '(no message)'; + $message = $array['error_message'] ?? '(no message)'; + $errorClass = $array['error_class']; + $class = sprintf('\\FireflyIII\\Services\\Spectre\Exception\\%sException', $errorClass); + if (class_exists($class)) { + throw new $class($message); + } - throw new FireflyException(sprintf('Error of class %s: %s', $array['error_class'], $message)); + throw new FireflyException(sprintf('Error of class %s: %s', $errorClass, $message)); } $statusCode = intval($response->status_code); diff --git a/app/Support/Import/Configuration/File/Initial.php b/app/Support/Import/Configuration/File/Initial.php index 66baa95f26..c07b56c4a2 100644 --- a/app/Support/Import/Configuration/File/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -22,62 +22,48 @@ declare(strict_types=1); namespace FireflyIII\Support\Import\Configuration\File; -use ExpandedForm; -use FireflyIII\Models\AccountType; use FireflyIII\Models\ImportJob; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use Log; /** - * Class CsvInitial. + * Class Initial. */ class Initial implements ConfigurationInterface { - /** - * @var ImportJob - */ + /** @var ImportJob */ private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; + + /** @var string */ + private $warning = ''; + + public function __construct() + { + Log::debug('Constructed Initial.'); + } + /** + * Get the data necessary to show the configuration screen. + * * @return array */ public function getData(): array { - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = app(AccountRepositoryInterface::class); - $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); - $delimiters = [ - ',' => trans('form.csv_comma'), - ';' => trans('form.csv_semicolon'), - 'tab' => trans('form.csv_tab'), - ]; + $importFileTypes = []; + $defaultImportType = config('import.options.file.default_import_format'); - // update job with default date format: - $config = $this->job->configuration; - if (!isset($config['date-format'])) { - $config['date-format'] = 'Ymd'; - $this->job->configuration = $config; - $this->job->save(); - } - $specifics = []; - - // collect specifics. - foreach (config('csv.import_specifics') as $name => $className) { - $specifics[$name] = [ - 'name' => $className::getName(), - 'description' => $className::getDescription(), - ]; + foreach (config('import.options.file.import_formats') as $type) { + $importFileTypes[$type] = trans('import.import_file_type_' . $type); } - $data = [ - 'accounts' => ExpandedForm::makeSelectList($accounts), - 'specifix' => [], - 'delimiters' => $delimiters, - 'specifics' => $specifics, + return [ + 'default_type' => $defaultImportType, + 'file_types' => $importFileTypes, ]; - - return $data; } /** @@ -87,7 +73,7 @@ class Initial implements ConfigurationInterface */ public function getWarningMessage(): string { - return ''; + return $this->warning; } /** @@ -97,7 +83,9 @@ class Initial implements ConfigurationInterface */ public function setJob(ImportJob $job): ConfigurationInterface { - $this->job = $job; + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); return $this; } @@ -111,59 +99,44 @@ class Initial implements ConfigurationInterface */ public function storeConfiguration(array $data): bool { - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $importId = $data['csv_import_account'] ?? 0; - $account = $repository->find(intval($importId)); + Log::debug('Now in storeConfiguration for file Upload.'); + $config = $this->getConfig(); + $type = $data['import_file_type'] ?? 'csv'; // assume it's a CSV file. + $config['file-type'] = in_array($type, config('import.options.file.import_formats')) ? $type : 'csv'; - $hasHeaders = isset($data['has_headers']) && 1 === intval($data['has_headers']) ? true : false; - $config = $this->job->configuration; - $config['initial-config-complete'] = true; - $config['has-headers'] = $hasHeaders; - $config['date-format'] = $data['date_format']; - $config['delimiter'] = $data['csv_delimiter']; - $config['delimiter'] = 'tab' === $config['delimiter'] ? "\t" : $config['delimiter']; - $config['apply_rules'] = isset($data['apply_rules']) && 1 === intval($data['apply_rules']) ? true : false; - $config['match_bills'] = isset($data['match_bills']) && 1 === intval($data['match_bills']) ? true : false; + // update config: + $this->repository->setConfiguration($this->job, $config); - Log::debug('Entered import account.', ['id' => $importId]); + // make repository process file: + $uploaded = $this->repository->processFile($this->job, $data['import_file'] ?? null); + Log::debug(sprintf('Result of upload is %s', var_export($uploaded, true))); - if (null !== $account->id) { - Log::debug('Found account.', ['id' => $account->id, 'name' => $account->name]); - $config['import-account'] = $account->id; + // process config, if present: + if (isset($data['configuration_file'])) { + $this->repository->processConfiguration($this->job, $data['configuration_file']); } - if (null === $account->id) { - Log::error('Could not find anything for csv_import_account.', ['id' => $importId]); + if (false === $uploaded) { + $this->warning = 'No valid upload.'; + + return true; } - $config = $this->storeSpecifics($data, $config); - $this->job->configuration = $config; - $this->job->save(); + // if file was upload safely, assume we can go to the next stage: + $config = $this->getConfig(); + $config['stage'] = 'upload-config'; + $this->repository->setConfiguration($this->job, $config); return true; } /** - * @param array $data - * @param array $config + * Short hand method. * * @return array */ - private function storeSpecifics(array $data, array $config): array + private function getConfig(): array { - // loop specifics. - if (isset($data['specifics']) && is_array($data['specifics'])) { - $names = array_keys($data['specifics']); - foreach ($names as $name) { - // verify their content. - $className = sprintf('FireflyIII\Import\Specifics\%s', $name); - if (class_exists($className)) { - $config['specifics'][$name] = 1; - } - } - } - - return $config; + return $this->repository->getConfiguration($this->job); } } diff --git a/app/Support/Import/Configuration/File/Map.php b/app/Support/Import/Configuration/File/Map.php index ec54b7315d..6770d5fa6d 100644 --- a/app/Support/Import/Configuration/File/Map.php +++ b/app/Support/Import/Configuration/File/Map.php @@ -27,6 +27,7 @@ use FireflyIII\Import\Mapper\MapperInterface; use FireflyIII\Import\MapperPreProcess\PreProcessorInterface; use FireflyIII\Import\Specifics\SpecificInterface; use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use League\Csv\Reader; use League\Csv\Statement; @@ -37,12 +38,12 @@ use Log; */ class Map implements ConfigurationInterface { - /** @var array */ - private $configuration = []; /** @var array that holds each column to be mapped by the user */ private $data = []; /** @var ImportJob */ private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; /** @var array */ private $validSpecifics = []; @@ -55,16 +56,16 @@ class Map implements ConfigurationInterface */ public function getData(): array { - $this->configuration = $this->job->configuration; $this->getMappableColumns(); // in order to actually map we also need all possible values from the CSV file. - $content = $this->job->uploadFileContents(); + $config = $this->getConfig(); + $content = $this->repository->uploadFileContents($this->job); $offset = 0; /** @var Reader $reader */ $reader = Reader::createFromString($content); - $reader->setDelimiter($this->configuration['delimiter']); - if ($this->configuration['has-headers']) { + $reader->setDelimiter($config['delimiter']); + if ($config['has-headers']) { $offset = 1; } $stmt = (new Statement)->offset($offset); @@ -106,6 +107,10 @@ class Map implements ConfigurationInterface foreach ($setIndexes as $index) { $this->data[$index]['values'] = array_unique($this->data[$index]['values']); asort($this->data[$index]['values']); + // if the count of this array is zero, there is nothing to map. + if (count($this->data[$index]['values']) === 0) { + unset($this->data[$index]); + } } unset($setIndexes); @@ -136,7 +141,9 @@ class Map implements ConfigurationInterface */ public function setJob(ImportJob $job): ConfigurationInterface { - $this->job = $job; + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); return $this; } @@ -150,7 +157,8 @@ class Map implements ConfigurationInterface */ public function storeConfiguration(array $data): bool { - $config = $this->job->configuration; + $config = $this->getConfig(); + if (isset($data['mapping'])) { foreach ($data['mapping'] as $index => $data) { $config['column-mapping-config'][$index] = []; @@ -164,9 +172,8 @@ class Map implements ConfigurationInterface } // set thing to be completed. - $config['column-mapping-complete'] = true; - $this->job->configuration = $config; - $this->job->save(); + $config['stage'] = 'ready'; + $this->saveConfig($config); return true; } @@ -181,11 +188,21 @@ class Map implements ConfigurationInterface $mapperClass = config('csv.import_roles.' . $column . '.mapper'); $mapperName = sprintf('\\FireflyIII\\Import\Mapper\\%s', $mapperClass); /** @var MapperInterface $mapper */ - $mapper = new $mapperName; + $mapper = app($mapperName); return $mapper; } + /** + * Short hand method. + * + * @return array + */ + private function getConfig(): array + { + return $this->repository->getConfiguration($this->job); + } + /** * @return bool * @@ -193,8 +210,7 @@ class Map implements ConfigurationInterface */ private function getMappableColumns(): bool { - $config = $this->job->configuration; - + $config = $this->getConfig(); /** * @var int * @var bool $mustBeMapped @@ -246,7 +262,9 @@ class Map implements ConfigurationInterface { // run specifics here: // and this is the point where the specifix go to work. - $names = array_keys($this->job->configuration['specifics']); + $config = $this->getConfig(); + $specifics = $config['specifics'] ?? []; + $names = array_keys($specifics); foreach ($names as $name) { if (!in_array($name, $this->validSpecifics)) { throw new FireflyException(sprintf('"%s" is not a valid class name', $name)); @@ -262,6 +280,14 @@ class Map implements ConfigurationInterface return $row; } + /** + * @param array $array + */ + private function saveConfig(array $array) + { + $this->repository->setConfiguration($this->job, $array); + } + /** * @param string $column * @param bool $mustBeMapped diff --git a/app/Support/Import/Configuration/File/Roles.php b/app/Support/Import/Configuration/File/Roles.php index 7ae7495582..884e6bcdbd 100644 --- a/app/Support/Import/Configuration/File/Roles.php +++ b/app/Support/Import/Configuration/File/Roles.php @@ -24,6 +24,7 @@ namespace FireflyIII\Support\Import\Configuration\File; use FireflyIII\Import\Specifics\SpecificInterface; use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; use League\Csv\Reader; use League\Csv\Statement; @@ -40,7 +41,8 @@ class Roles implements ConfigurationInterface private $data = []; /** @var ImportJob */ private $job; - + /** @var ImportJobRepositoryInterface */ + private $repository; /** @var string */ private $warning = ''; @@ -54,8 +56,8 @@ class Roles implements ConfigurationInterface */ public function getData(): array { - $config = $this->job->configuration; - $content = $this->job->uploadFileContents(); + $content = $this->repository->uploadFileContents($this->job); + $config = $this->getConfig(); $headers = []; $offset = 0; // create CSV reader. @@ -112,7 +114,9 @@ class Roles implements ConfigurationInterface */ public function setJob(ImportJob $job): ConfigurationInterface { - $this->job = $job; + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->repository->setUser($job->user); return $this; } @@ -127,26 +131,40 @@ class Roles implements ConfigurationInterface public function storeConfiguration(array $data): bool { Log::debug('Now in storeConfiguration of Roles.'); - $config = $this->job->configuration; + $config = $this->getConfig(); $count = $config['column-count']; for ($i = 0; $i < $count; ++$i) { $role = $data['role'][$i] ?? '_ignore'; $mapping = isset($data['map'][$i]) && $data['map'][$i] === '1' ? true : false; $config['column-roles'][$i] = $role; $config['column-do-mapping'][$i] = $mapping; - Log::debug(sprintf('Column %d has been given role %s', $i, $role)); + Log::debug(sprintf('Column %d has been given role %s (mapping: %s)', $i, $role, var_export($mapping, true))); } - $this->job->configuration = $config; - $this->job->save(); - + $this->saveConfig($config); $this->ignoreUnmappableColumns(); $this->setRolesComplete(); + + $config = $this->getConfig(); + $config['stage'] = 'map'; + $this->saveConfig($config); + $this->isMappingNecessary(); + return true; } + /** + * Short hand method. + * + * @return array + */ + private function getConfig(): array + { + return $this->repository->getConfiguration($this->job); + } + /** * @return array */ @@ -165,11 +183,12 @@ class Roles implements ConfigurationInterface */ private function ignoreUnmappableColumns(): bool { - $config = $this->job->configuration; + $config = $this->getConfig(); $count = $config['column-count']; for ($i = 0; $i < $count; ++$i) { $role = $config['column-roles'][$i] ?? '_ignore'; $mapping = $config['column-do-mapping'][$i] ?? false; + Log::debug(sprintf('Role for column %d is %s, and mapping is %s', $i, $role, var_export($mapping, true))); if ('_ignore' === $role && true === $mapping) { $mapping = false; @@ -177,9 +196,7 @@ class Roles implements ConfigurationInterface } $config['column-do-mapping'][$i] = $mapping; } - - $this->job->configuration = $config; - $this->job->save(); + $this->saveConfig($config); return true; } @@ -189,7 +206,7 @@ class Roles implements ConfigurationInterface */ private function isMappingNecessary() { - $config = $this->job->configuration; + $config = $this->getConfig(); $count = $config['column-count']; $toBeMapped = 0; for ($i = 0; $i < $count; ++$i) { @@ -200,12 +217,11 @@ class Roles implements ConfigurationInterface } Log::debug(sprintf('Found %d columns that need mapping.', $toBeMapped)); if (0 === $toBeMapped) { - // skip setting of map, because none need to be mapped: - $config['column-mapping-complete'] = true; - $this->job->configuration = $config; - $this->job->save(); + $config['stage'] = 'ready'; } + $this->saveConfig($config); + return true; } @@ -248,7 +264,9 @@ class Roles implements ConfigurationInterface */ private function processSpecifics(array $row): array { - $names = array_keys($this->job->configuration['specifics'] ?? []); + $config = $this->getConfig(); + $specifics = $config['specifics'] ?? []; + $names = array_keys($specifics); foreach ($names as $name) { /** @var SpecificInterface $specific */ $specific = app('FireflyIII\Import\Specifics\\' . $name); @@ -258,12 +276,20 @@ class Roles implements ConfigurationInterface return $row; } + /** + * @param array $array + */ + private function saveConfig(array $array) + { + $this->repository->setConfiguration($this->job, $array); + } + /** * @return bool */ private function setRolesComplete(): bool { - $config = $this->job->configuration; + $config = $this->getConfig(); $count = $config['column-count']; $assigned = 0; $hasAmount = false; @@ -278,13 +304,12 @@ class Roles implements ConfigurationInterface } if ($assigned > 0 && $hasAmount) { $config['column-roles-complete'] = true; - $this->job->configuration = $config; - $this->job->save(); - $this->warning = ''; + $this->warning = ''; } if (0 === $assigned || !$hasAmount) { $this->warning = strval(trans('import.roles_warning')); } + $this->saveConfig($config); return true; } @@ -294,11 +319,10 @@ class Roles implements ConfigurationInterface */ private function updateColumCount(): bool { - $config = $this->job->configuration; - $count = $this->data['total']; - $config['column-count'] = $count; - $this->job->configuration = $config; - $this->job->save(); + $config = $this->getConfig(); + $count = $this->data['total']; + $config['column-count'] = $count; + $this->saveConfig($config); return true; } diff --git a/app/Support/Import/Configuration/File/Upload.php b/app/Support/Import/Configuration/File/Upload.php deleted file mode 100644 index 8b6943489d..0000000000 --- a/app/Support/Import/Configuration/File/Upload.php +++ /dev/null @@ -1,116 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Support\Import\Configuration\File; - -use FireflyIII\Models\ImportJob; -use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; -use FireflyIII\Support\Import\Configuration\ConfigurationInterface; -use Log; - -/** - * Class Upload. - */ -class Upload implements ConfigurationInterface -{ - /** @var ImportJob */ - private $job; - - /** @var string */ - private $warning = ''; - - /** - * Get the data necessary to show the configuration screen. - * - * @return array - */ - public function getData(): array - { - $importFileTypes = []; - $defaultImportType = config('import.options.file.default_import_format'); - - foreach (config('import.options.file.import_formats') as $type) { - $importFileTypes[$type] = trans('import.import_file_type_' . $type); - } - - return [ - 'default_type' => $defaultImportType, - 'file_types' => $importFileTypes, - ]; - } - - /** - * Return possible warning to user. - * - * @return string - */ - public function getWarningMessage(): string - { - return $this->warning; - } - - /** - * @param ImportJob $job - * - * @return ConfigurationInterface - */ - public function setJob(ImportJob $job): ConfigurationInterface - { - $this->job = $job; - - return $this; - } - - /** - * Store the result. - * - * @param array $data - * - * @return bool - */ - public function storeConfiguration(array $data): bool - { - Log::debug('Now in storeConfiguration for file Upload.'); - /** @var ImportJobRepositoryInterface $repository */ - $repository = app(ImportJobRepositoryInterface::class); - $type = $data['import_file_type'] ?? 'unknown'; - $config = $this->job->configuration; - $config['file-type'] = in_array($type, config('import.options.file.import_formats')) ? $type : 'unknown'; - $repository->setConfiguration($this->job, $config); - $uploaded = $repository->processFile($this->job, $data['import_file'] ?? null); - $this->job->save(); - Log::debug(sprintf('Result of upload is %s', var_export($uploaded, true))); - // process config, if present: - if (isset($data['configuration_file'])) { - $repository->processConfiguration($this->job, $data['configuration_file']); - } - $config = $this->job->configuration; - $config['has-file-upload'] = $uploaded; - $repository->setConfiguration($this->job, $config); - - if (false === $uploaded) { - $this->warning = 'No valid upload.'; - } - - return true; - } -} diff --git a/app/Support/Import/Configuration/File/UploadConfig.php b/app/Support/Import/Configuration/File/UploadConfig.php new file mode 100644 index 0000000000..5eeda520d8 --- /dev/null +++ b/app/Support/Import/Configuration/File/UploadConfig.php @@ -0,0 +1,191 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Support\Import\Configuration\File; + +use FireflyIII\Models\AccountType; +use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\Support\Import\Configuration\ConfigurationInterface; +use Log; + +/** + * Class UploadConfig. + */ +class UploadConfig implements ConfigurationInterface +{ + /** @var AccountRepositoryInterface */ + private $accountRepository; + /** + * @var ImportJob + */ + private $job; + /** @var ImportJobRepositoryInterface */ + private $repository; + + /** + * @return array + */ + public function getData(): array + { + $accounts = $this->accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $delimiters = [ + ',' => trans('form.csv_comma'), + ';' => trans('form.csv_semicolon'), + 'tab' => trans('form.csv_tab'), + ]; + $config = $this->getConfig(); + $config['date-format'] = $config['date-format'] ?? 'Ymd'; + $specifics = []; + $this->saveConfig($config); + + // collect specifics. + foreach (config('csv.import_specifics') as $name => $className) { + $specifics[$name] = [ + 'name' => $className::getName(), + 'description' => $className::getDescription(), + ]; + } + + $data = [ + 'accounts' => app('expandedform')->makeSelectList($accounts), + 'specifix' => [], + 'delimiters' => $delimiters, + 'specifics' => $specifics, + ]; + + return $data; + } + + /** + * Return possible warning to user. + * + * @return string + */ + public function getWarningMessage(): string + { + return ''; + } + + /** + * @param ImportJob $job + * + * @return ConfigurationInterface + */ + public function setJob(ImportJob $job): ConfigurationInterface + { + $this->job = $job; + $this->repository = app(ImportJobRepositoryInterface::class); + $this->accountRepository = app(AccountRepositoryInterface::class); + $this->repository->setUser($job->user); + $this->accountRepository->setUser($job->user); + + return $this; + } + + /** + * Store the result. + * + * @param array $data + * + * @return bool + */ + public function storeConfiguration(array $data): bool + { + Log::debug('Now in Initial::storeConfiguration()'); + $config = $this->getConfig(); + $importId = intval($data['csv_import_account'] ?? 0); + $account = $this->accountRepository->find($importId); + $delimiter = strval($data['csv_delimiter']); + + // set "headers": + $config['has-headers'] = intval($data['has_headers'] ?? 0) === 1; + $config['date-format'] = strval($data['date_format']); + $config['delimiter'] = 'tab' === $delimiter ? "\t" : $config['delimiter']; + $config['apply-rules'] = intval($data['apply_rules'] ?? 0) === 1; + $config['match-bills'] = intval($data['match_bills'] ?? 0) === 1; + + Log::debug('Entered import account.', ['id' => $importId]); + + + if (null !== $account->id) { + Log::debug('Found account.', ['id' => $account->id, 'name' => $account->name]); + $config['import-account'] = $account->id; + } + + if (null === $account->id) { + Log::error('Could not find anything for csv_import_account.', ['id' => $importId]); + } + + $config = $this->storeSpecifics($data, $config); + Log::debug('Final config is ', $config); + + // onto the next stage! + + $config['stage'] = 'roles'; + $this->saveConfig($config); + + return true; + } + + /** + * Short hand method. + * + * @return array + */ + private function getConfig(): array + { + return $this->repository->getConfiguration($this->job); + } + + /** + * @param array $array + */ + private function saveConfig(array $array) + { + $this->repository->setConfiguration($this->job, $array); + } + + /** + * @param array $data + * @param array $config + * + * @return array + */ + private function storeSpecifics(array $data, array $config): array + { + // loop specifics. + if (isset($data['specifics']) && is_array($data['specifics'])) { + $names = array_keys($data['specifics']); + foreach ($names as $name) { + // verify their content. + $className = sprintf('FireflyIII\Import\Specifics\%s', $name); + if (class_exists($className)) { + $config['specifics'][$name] = 1; + } + } + } + + return $config; + } +} diff --git a/app/Support/Import/Configuration/Spectre/HaveAccounts.php b/app/Support/Import/Configuration/Spectre/HaveAccounts.php new file mode 100644 index 0000000000..796d05afd9 --- /dev/null +++ b/app/Support/Import/Configuration/Spectre/HaveAccounts.php @@ -0,0 +1,157 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Import\Configuration\Spectre; + + +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\ImportJob; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\Import\Configuration\ConfigurationInterface; +use Illuminate\Support\Collection; + +/** + * Class HaveAccounts + */ +class HaveAccounts implements ConfigurationInterface +{ + /** @var ImportJob */ + private $job; + + /** + * Get the data necessary to show the configuration screen. + * + * @return array + */ + public function getData(): array + { + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + /** @var CurrencyRepositoryInterface $currencyRepository */ + $currencyRepository = app(CurrencyRepositoryInterface::class); + $data = []; + $config = $this->job->configuration; + $collection = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $defaultCurrency = app('amount')->getDefaultCurrency(); + $dbAccounts = []; + /** @var Account $dbAccount */ + foreach ($collection as $dbAccount) { + $id = $dbAccount->id; + $currencyId = intval($dbAccount->getMeta('currency_id')); + $currency = $currencyRepository->find($currencyId); + $dbAccounts[$id] = [ + 'account' => $dbAccount, + 'currency' => is_null($currency->id) ? $defaultCurrency : $currency, + ]; + } + + // loop Spectre accounts: + /** + * @var int $index + * @var array $spectreAccount + */ + foreach ($config['accounts'] as $index => $spectreAccount) { + // find accounts with currency code + $code = $spectreAccount['currency_code']; + $selection = $this->filterAccounts($dbAccounts, $code); + $config['accounts'][$index]['options'] = app('expandedform')->makeSelectList($selection); + } + + + $data = [ + 'config' => $config, + ]; + + + return $data; + } + + /** + * Return possible warning to user. + * + * @return string + */ + public function getWarningMessage(): string + { + return ''; + } + + /** + * @param ImportJob $job + * + * @return ConfigurationInterface + */ + public function setJob(ImportJob $job) + { + $this->job = $job; + + return $this; + } + + /** + * Store the result. + * + * @param array $data + * + * @return bool + */ + public function storeConfiguration(array $data): bool + { + $accounts = $data['spectre_account_id'] ?? []; + $mapping = []; + foreach ($accounts as $spectreId) { + $spectreId = intval($spectreId); + $doImport = intval($data['do_import'][$spectreId] ?? 0) === 1; + $account = intval($data['import'][$spectreId] ?? 0); + if ($doImport) { + $mapping[$spectreId] = $account; + } + } + $config = $this->job->configuration; + $config['accounts-mapped'] = $mapping; + $this->job->configuration = $config; + $this->job->save(); + + return true; + } + + /** + * @param array $dbAccounts + * @param string $code + * + * @return Collection + */ + private function filterAccounts(array $dbAccounts, string $code): Collection + { + $collection = new Collection; + foreach ($dbAccounts as $accountId => $data) { + if ($data['currency']->code === $code) { + $collection->push($data['account']); + } + } + + return $collection; + } +} \ No newline at end of file diff --git a/app/Support/SingleCacheProperties.php b/app/Support/SingleCacheProperties.php index a6be94f57c..17bddc463f 100644 --- a/app/Support/SingleCacheProperties.php +++ b/app/Support/SingleCacheProperties.php @@ -38,6 +38,7 @@ class SingleCacheProperties extends CacheProperties $this->properties = new Collection; if (auth()->check()) { $this->addProperty(auth()->user()->id); + $this->addProperty(app('preferences')->lastActivity()); } } } diff --git a/app/Support/Steam.php b/app/Support/Steam.php index b971028029..989801716a 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -72,6 +72,7 @@ class Steam ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) ->where('transactions.foreign_currency_id', $currencyId) + ->where('transactions.transaction_currency_id', '!=', $currencyId) ->sum('transactions.foreign_amount') ); $balance = bcadd($nativeBalance, $foreignBalance); @@ -114,6 +115,7 @@ class Steam ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) ->where('transactions.foreign_currency_id', $currencyId) + ->where('transactions.transaction_currency_id', '!=', $currencyId) ->sum('transactions.foreign_amount') ); $balance = bcadd($nativeBalance, $foreignBalance); diff --git a/composer.json b/composer.json index a82586a995..a047ab4618 100644 --- a/composer.json +++ b/composer.json @@ -99,7 +99,7 @@ }, "scripts": { "pre-install-cmd": [ - "if [ -z ${DYNO+x} ]; then echo Not in Heroku environment.; else php -r \"file_exists('.env') || copy('.env.heroku', '.env');\"; fi" + "@php -r \"if (!(getenv('DYNO'))===false){file_exists('.env') || copy('.env.heroku', '.env');}\"" ], "post-root-package-install": [ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" diff --git a/composer.lock b/composer.lock index 88046c0b2d..f81c640d57 100644 --- a/composer.lock +++ b/composer.lock @@ -947,34 +947,34 @@ }, { "name": "league/commonmark", - "version": "0.16.0", + "version": "0.17.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "c0e41be0f80c51ad3170c9c713f74a0b8dec59ce" + "reference": "3b4c2224524776a584de663c7a04bc8eb2e1544d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c0e41be0f80c51ad3170c9c713f74a0b8dec59ce", - "reference": "c0e41be0f80c51ad3170c9c713f74a0b8dec59ce", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/3b4c2224524776a584de663c7a04bc8eb2e1544d", + "reference": "3b4c2224524776a584de663c7a04bc8eb2e1544d", "shasum": "" }, "require": { "ext-mbstring": "*", - "php": ">=5.4.8" + "php": ">=5.6.5" }, "replace": { "colinodell/commonmark-php": "*" }, "require-dev": { "cebe/markdown": "~1.0", + "commonmark/commonmark.js": "0.28", "erusev/parsedown": "~1.0", - "jgm/commonmark": "0.28", "michelf/php-markdown": "~1.4", "mikehaertl/php-shellcommand": "~1.2.0", - "phpunit/phpunit": "^4.8.35|~5.7", + "phpunit/phpunit": "~5.7|~6.5", "scrutinizer/ocular": "~1.1", - "symfony/finder": "~2.3|~3.0" + "symfony/finder": "~3.0|~4.0" }, "suggest": { "league/commonmark-extras": "Library of useful extensions including smart punctuation" @@ -985,7 +985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.17-dev" + "dev-master": "0.18-dev" } }, "autoload": { @@ -1012,7 +1012,7 @@ "markdown", "parser" ], - "time": "2017-10-31T00:49:55+00:00" + "time": "2017-12-30T22:08:48+00:00" }, { "name": "league/csv", @@ -1448,16 +1448,16 @@ }, { "name": "pragmarx/google2fa", - "version": "v2.0.6", + "version": "v2.0.7", "source": { "type": "git", "url": "https://github.com/antonioribeiro/google2fa.git", - "reference": "bc2d654305e4d09254125f8cd390a7fbc4742d46" + "reference": "5a818bda62fab0c0a79060b06d50d50b5525d631" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/bc2d654305e4d09254125f8cd390a7fbc4742d46", - "reference": "bc2d654305e4d09254125f8cd390a7fbc4742d46", + "url": "https://api.github.com/repos/antonioribeiro/google2fa/zipball/5a818bda62fab0c0a79060b06d50d50b5525d631", + "reference": "5a818bda62fab0c0a79060b06d50d50b5525d631", "shasum": "" }, "require": { @@ -1468,8 +1468,7 @@ }, "require-dev": { "bacon/bacon-qr-code": "~1.0", - "phpspec/phpspec": "~2.1", - "phpunit/phpunit": "~4" + "phpunit/phpunit": "~4|~5|~6" }, "suggest": { "bacon/bacon-qr-code": "Required to generate inline QR Codes." @@ -1483,7 +1482,8 @@ }, "autoload": { "psr-4": { - "PragmaRX\\Google2FA\\": "src/" + "PragmaRX\\Google2FA\\": "src/", + "PragmaRX\\Google2FA\\Tests\\": "tests/" } }, "notification-url": "https://packagist.org/downloads/", @@ -1505,7 +1505,7 @@ "google2fa", "laravel" ], - "time": "2017-09-12T06:55:05+00:00" + "time": "2018-01-06T16:21:07+00:00" }, { "name": "pragmarx/google2fa-laravel", @@ -1974,16 +1974,16 @@ }, { "name": "symfony/console", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "9f21adfb92a9315b73ae2ed43138988ee4913d4e" + "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/9f21adfb92a9315b73ae2ed43138988ee4913d4e", - "reference": "9f21adfb92a9315b73ae2ed43138988ee4913d4e", + "url": "https://api.github.com/repos/symfony/console/zipball/8394c8ef121949e8f858f13bc1e34f05169e4e7d", + "reference": "8394c8ef121949e8f858f13bc1e34f05169e4e7d", "shasum": "" }, "require": { @@ -2039,20 +2039,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:40:10+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/css-selector", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "eac760b414cf1f64362c3dd047b989e4db121332" + "reference": "e66394bc7610e69279bfdb3ab11b4fe65403f556" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/eac760b414cf1f64362c3dd047b989e4db121332", - "reference": "eac760b414cf1f64362c3dd047b989e4db121332", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/e66394bc7610e69279bfdb3ab11b4fe65403f556", + "reference": "e66394bc7610e69279bfdb3ab11b4fe65403f556", "shasum": "" }, "require": { @@ -2092,20 +2092,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:40:10+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/debug", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "543deab3ffff94402440b326fc94153bae2dfa7a" + "reference": "603b95dda8b00020e4e6e60dc906e7b715b1c245" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/543deab3ffff94402440b326fc94153bae2dfa7a", - "reference": "543deab3ffff94402440b326fc94153bae2dfa7a", + "url": "https://api.github.com/repos/symfony/debug/zipball/603b95dda8b00020e4e6e60dc906e7b715b1c245", + "reference": "603b95dda8b00020e4e6e60dc906e7b715b1c245", "shasum": "" }, "require": { @@ -2148,20 +2148,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2017-12-12T08:27:14+00:00" + "time": "2018-01-03T17:14:19+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "d4face19ed8002eec8280bc1c5ec18130472bf43" + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d4face19ed8002eec8280bc1c5ec18130472bf43", - "reference": "d4face19ed8002eec8280bc1c5ec18130472bf43", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74d33aac36208c4d6757807d9f598f0133a3a4eb", + "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb", "shasum": "" }, "require": { @@ -2211,20 +2211,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:48:22+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/finder", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "dac8d7db537bac7ad8143eb11360a8c2231f251a" + "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/dac8d7db537bac7ad8143eb11360a8c2231f251a", - "reference": "dac8d7db537bac7ad8143eb11360a8c2231f251a", + "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f", + "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f", "shasum": "" }, "require": { @@ -2260,20 +2260,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2017-11-05T16:10:10+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "59bf131b5460227a2f583a7dbe6b179f98f9e0a5" + "reference": "4a213be1cc8598089b8c7451529a2927b49b5d26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/59bf131b5460227a2f583a7dbe6b179f98f9e0a5", - "reference": "59bf131b5460227a2f583a7dbe6b179f98f9e0a5", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/4a213be1cc8598089b8c7451529a2927b49b5d26", + "reference": "4a213be1cc8598089b8c7451529a2927b49b5d26", "shasum": "" }, "require": { @@ -2314,20 +2314,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:40:10+00:00" + "time": "2018-01-03T17:14:19+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "48325096bbda77b983e642d21a4dd9bdde3ab73e" + "reference": "1c2a82d6a8ec9b354fe4ef48ad1ad3f1a4f7db0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/48325096bbda77b983e642d21a4dd9bdde3ab73e", - "reference": "48325096bbda77b983e642d21a4dd9bdde3ab73e", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/1c2a82d6a8ec9b354fe4ef48ad1ad3f1a4f7db0e", + "reference": "1c2a82d6a8ec9b354fe4ef48ad1ad3f1a4f7db0e", "shasum": "" }, "require": { @@ -2402,7 +2402,7 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2017-12-15T02:05:18+00:00" + "time": "2018-01-05T08:33:00+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2632,16 +2632,16 @@ }, { "name": "symfony/process", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "bb3ef65d493a6d57297cad6c560ee04e2a8f5098" + "reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/bb3ef65d493a6d57297cad6c560ee04e2a8f5098", - "reference": "bb3ef65d493a6d57297cad6c560ee04e2a8f5098", + "url": "https://api.github.com/repos/symfony/process/zipball/ff69f110c6b33fd33cd2089ba97d6112f44ef0ba", + "reference": "ff69f110c6b33fd33cd2089ba97d6112f44ef0ba", "shasum": "" }, "require": { @@ -2677,20 +2677,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:40:10+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/routing", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "5f248dfac5e4660c74982eb3dadc71cf58595570" + "reference": "e2b6d6fe7b090c7af720b75c7722c6dfa7a52658" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/5f248dfac5e4660c74982eb3dadc71cf58595570", - "reference": "5f248dfac5e4660c74982eb3dadc71cf58595570", + "url": "https://api.github.com/repos/symfony/routing/zipball/e2b6d6fe7b090c7af720b75c7722c6dfa7a52658", + "reference": "e2b6d6fe7b090c7af720b75c7722c6dfa7a52658", "shasum": "" }, "require": { @@ -2755,20 +2755,20 @@ "uri", "url" ], - "time": "2017-12-14T22:37:31+00:00" + "time": "2018-01-04T15:09:34+00:00" }, { "name": "symfony/translation", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6" + "reference": "17b5962d252b2d6d1d37a2485ebb7ddc5b2bef0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/4c5d5582baf2829751a5207659329c1f52eedeb6", - "reference": "4c5d5582baf2829751a5207659329c1f52eedeb6", + "url": "https://api.github.com/repos/symfony/translation/zipball/17b5962d252b2d6d1d37a2485ebb7ddc5b2bef0a", + "reference": "17b5962d252b2d6d1d37a2485ebb7ddc5b2bef0a", "shasum": "" }, "require": { @@ -2823,20 +2823,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2017-12-12T08:27:14+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "757074cf71b952ce9e75b557538948811c2bf006" + "reference": "545be7e78ccbec43e599f10ff7500d0b09eda9d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/757074cf71b952ce9e75b557538948811c2bf006", - "reference": "757074cf71b952ce9e75b557538948811c2bf006", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/545be7e78ccbec43e599f10ff7500d0b09eda9d0", + "reference": "545be7e78ccbec43e599f10ff7500d0b09eda9d0", "shasum": "" }, "require": { @@ -2892,7 +2892,7 @@ "debug", "dump" ], - "time": "2017-12-11T22:06:16+00:00" + "time": "2018-01-03T17:14:19+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -4598,16 +4598,16 @@ }, { "name": "phpunit/phpunit-mock-objects", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933" + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", - "reference": "283b9f4f670e3a6fd6c4ff95c51a952eb5c75933", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/33fd41a76e746b8fa96d00b49a23dadfa8334cdf", + "reference": "33fd41a76e746b8fa96d00b49a23dadfa8334cdf", "shasum": "" }, "require": { @@ -4653,7 +4653,7 @@ "mock", "xunit" ], - "time": "2017-12-10T08:01:53+00:00" + "time": "2018-01-06T05:45:45+00:00" }, { "name": "psr/http-message", @@ -5266,16 +5266,16 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.2", + "version": "v3.4.3", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", - "reference": "e8d36a7b5568d232f5c3f8ef92665836b9f1e038" + "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/class-loader/zipball/e8d36a7b5568d232f5c3f8ef92665836b9f1e038", - "reference": "e8d36a7b5568d232f5c3f8ef92665836b9f1e038", + "url": "https://api.github.com/repos/symfony/class-loader/zipball/e63c12699822bb3b667e7216ba07fbcc3a3e203e", + "reference": "e63c12699822bb3b667e7216ba07fbcc3a3e203e", "shasum": "" }, "require": { @@ -5318,20 +5318,20 @@ ], "description": "Symfony ClassLoader Component", "homepage": "https://symfony.com", - "time": "2017-11-05T16:10:10+00:00" + "time": "2018-01-03T07:37:34+00:00" }, { "name": "symfony/config", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "0356e6d5298e9e72212c0bad65c2f1b49e42d622" + "reference": "0e86d267db0851cf55f339c97df00d693fe8592f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/0356e6d5298e9e72212c0bad65c2f1b49e42d622", - "reference": "0356e6d5298e9e72212c0bad65c2f1b49e42d622", + "url": "https://api.github.com/repos/symfony/config/zipball/0e86d267db0851cf55f339c97df00d693fe8592f", + "reference": "0e86d267db0851cf55f339c97df00d693fe8592f", "shasum": "" }, "require": { @@ -5378,20 +5378,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:48:22+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/filesystem", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "8c2868641d0c4885eee9c12a89c2b695eb1985cd" + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/8c2868641d0c4885eee9c12a89c2b695eb1985cd", - "reference": "8c2868641d0c4885eee9c12a89c2b695eb1985cd", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/760e47a4ee64b4c48f4b30017011e09d4c0f05ed", + "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed", "shasum": "" }, "require": { @@ -5427,20 +5427,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2017-12-14T19:48:22+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03" + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/ac0e49150555c703fef6b696d8eaba1db7a3ca03", - "reference": "ac0e49150555c703fef6b696d8eaba1db7a3ca03", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d52321f0e2b596bd03b5d1dd6eebe71caa925704", + "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704", "shasum": "" }, "require": { @@ -5476,20 +5476,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2017-11-09T12:45:29+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "symfony/yaml", - "version": "v4.0.2", + "version": "v4.0.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "a5ee52d155f06ad23b19eb63c31228ff56ad1116" + "reference": "b84f646b9490d2101e2c25ddeec77ceefbda2eee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/a5ee52d155f06ad23b19eb63c31228ff56ad1116", - "reference": "a5ee52d155f06ad23b19eb63c31228ff56ad1116", + "url": "https://api.github.com/repos/symfony/yaml/zipball/b84f646b9490d2101e2c25ddeec77ceefbda2eee", + "reference": "b84f646b9490d2101e2c25ddeec77ceefbda2eee", "shasum": "" }, "require": { @@ -5534,7 +5534,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2017-12-12T08:41:51+00:00" + "time": "2018-01-03T07:38:00+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/breadcrumbs.php b/config/breadcrumbs.php index 764f93c676..dcfbba2987 100644 --- a/config/breadcrumbs.php +++ b/config/breadcrumbs.php @@ -18,7 +18,7 @@ return [ | */ - 'view' => 'breadcrumbs::bootstrap3', + 'view' => 'partials/breadcrumbs', /* |-------------------------------------------------------------------------- diff --git a/config/csv.php b/config/csv.php index adf39792c3..ed530932c7 100644 --- a/config/csv.php +++ b/config/csv.php @@ -320,18 +320,4 @@ return [ // number of example rows: 'example_rows' => 5, - 'default_config' => [ - 'initial-config-complete' => false, - 'has-headers' => false, // assume - 'date-format' => 'Ymd', // assume - 'delimiter' => ',', // assume - 'import-account' => 0, // none, - 'specifics' => [], // none - 'column-count' => 0, // unknown - 'column-roles' => [], // unknown - 'column-do-mapping' => [], // not yet set which columns must be mapped - 'column-roles-complete' => false, // not yet configured roles for columns - 'column-mapping-config' => [], // no mapping made yet. - 'column-mapping-complete' => false, // so mapping is not complete. - ], ]; diff --git a/config/firefly.php b/config/firefly.php index ba2d8eae30..29e9979ccf 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -33,7 +33,7 @@ return [ 'is_demo_site' => false, ], 'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true), - 'version' => '4.6.12', + 'version' => '4.6.13', 'maxUploadSize' => 15242880, 'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf', 'text/plain'], 'list_length' => 10, @@ -119,6 +119,7 @@ return [ 'id_ID' => ['name_locale' => 'Bahasa Indonesia', 'name_english' => 'Indonesian'], 'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch'], 'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish '], + 'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'], // incomplete languages: //'pt_BR' => ['name_locale' => 'Português do Brasil', 'name_english' => 'Portuguese (Brazil)'], @@ -126,7 +127,7 @@ return [ //'es_ES' => ['name_locale' => 'Spanish', 'name_english' => 'Spanish'], //'ru_RU' => ['name_locale' => 'Русский', 'name_english' => 'Russian'], //'sl_SI' => ['name_locale' => 'Slovenščina', 'name_english' => 'Slovenian'], - //'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'], + // ], 'transactionTypesByWhat' => [ 'expenses' => ['Withdrawal'], diff --git a/index.php b/index.php new file mode 100644 index 0000000000..811130c7c4 --- /dev/null +++ b/index.php @@ -0,0 +1,54 @@ +. + */ + +declare(strict_types=1); + +echo ' + + + + + + Firefly III + + + +

+ Danger! This directory should not be open to the public! +

+

+ /public/ should be the document root of your web server. +

+

+ Leaving your web server configured like this is a huge security risk. +

+

+Please read more on the Github help pages. +

+ + +'; \ No newline at end of file diff --git a/public/js/ff/charts.defaults.js b/public/js/ff/charts.defaults.js index e2764d5567..3070d20e5c 100644 --- a/public/js/ff/charts.defaults.js +++ b/public/js/ff/charts.defaults.js @@ -31,6 +31,7 @@ */ function formatLabel(str, maxwidth) { var sections = []; + str = String(str); var words = str.split(" "); var temp = ""; diff --git a/public/js/ff/import/status.js b/public/js/ff/import/status.js index c05560cafd..fc65d88ace 100644 --- a/public/js/ff/import/status.js +++ b/public/js/ff/import/status.js @@ -174,14 +174,20 @@ function jobIsStalled(data) { /** * This function tells Firefly start the job. It will also initialize a re-check in 500ms time. + * Only when job is in "configured" state. */ function startJob() { - // disable the button, add loading thing. - $('.start-job').prop('disabled', true).text('...'); - $.post(jobStartUri, {_token: token}).fail(reportOnSubmitError); + if (job.status === "configured") { + console.log("Job auto started!"); + // disable the button, add loading thing. + $('.start-job').prop('disabled', true).text('...'); + $.post(jobStartUri, {_token: token}).fail(reportOnSubmitError); - // check status, every 500 ms. - timeOutId = setTimeout(checkJobStatus, startInterval); + // check status, every 500 ms. + timeOutId = setTimeout(checkJobStatus, startInterval); + return; + } + console.log("Job not auto started because state is " + job.status); } /** diff --git a/public/js/ff/reports/default/month.js b/public/js/ff/reports/default/month.js index 9f8e67d060..df694d6a1f 100644 --- a/public/js/ff/reports/default/month.js +++ b/public/js/ff/reports/default/month.js @@ -22,17 +22,10 @@ $(function () { "use strict"; - drawChart(); + lineChart(accountChartUri, 'account-balances-chart'); loadAjaxPartial('categoryReport', categoryReportUri); loadAjaxPartial('budgetReport', budgetReportUri); loadAjaxPartial('balanceReport', balanceReportUri); }); -function drawChart() { - "use strict"; - - // month view: - // draw account chart - lineChart(accountChartUri, 'account-balances-chart'); -} \ No newline at end of file diff --git a/public/js/ff/reports/default/multi-year.js b/public/js/ff/reports/default/multi-year.js index 30ae613b0b..f2a56fd888 100644 --- a/public/js/ff/reports/default/multi-year.js +++ b/public/js/ff/reports/default/multi-year.js @@ -22,18 +22,12 @@ $(function () { "use strict"; - drawChart(); + lineChart(netWorthUri, 'net-worth'); + columnChart(opChartUri, 'income-expenses-chart'); + columnChart(sumChartUri, 'income-expenses-sum-chart'); loadAjaxPartial('budgetPeriodReport', budgetPeriodReportUri); loadAjaxPartial('categoryExpense', categoryExpenseUri); loadAjaxPartial('categoryIncome', categoryIncomeUri); }); -function drawChart() { - "use strict"; - - // income and expense over multi year: - lineChart(netWorthUri, 'net-worth'); - columnChart(opChartUri, 'income-expenses-chart'); - columnChart(sumChartUri, 'income-expenses-sum-chart'); -} diff --git a/public/js/ff/reports/default/year.js b/public/js/ff/reports/default/year.js index 621ee4a0fe..79887f7397 100644 --- a/public/js/ff/reports/default/year.js +++ b/public/js/ff/reports/default/year.js @@ -22,19 +22,12 @@ $(function () { "use strict"; - drawChart(); + lineChart(netWorthUri, 'net-worth'); + columnChart(opChartUri, 'income-expenses-chart'); + columnChart(sumChartUri, 'income-expenses-sum-chart'); loadAjaxPartial('budgetPeriodReport', budgetPeriodReportUri); loadAjaxPartial('categoryExpense', categoryExpenseUri); loadAjaxPartial('categoryIncome', categoryIncomeUri); }); -function drawChart() { - "use strict"; - - lineChart(netWorthUri, 'net-worth'); - columnChart(opChartUri, 'income-expenses-chart'); - columnChart(sumChartUri, 'income-expenses-sum-chart'); - - -} diff --git a/public/js/ff/transactions/list.js b/public/js/ff/transactions/list.js index 70694d0598..fa5fc55946 100644 --- a/public/js/ff/transactions/list.js +++ b/public/js/ff/transactions/list.js @@ -18,7 +18,7 @@ * along with Firefly III. If not, see . */ -/** global: edit_selected_txt, delete_selected_txt, token */ +/** global: edit_selected_txt, edit_bulk_selected_txt, delete_selected_txt, token */ /** * @@ -43,43 +43,14 @@ $(document).ready(function () { countChecked(); }); - // click the edit button: + // click the mass edit button: $('.mass_edit').click(goToMassEdit); + // click the bulk edit button: + $('.bulk_edit').click(goToBulkEdit); // click the delete button: $('.mass_delete').click(goToMassDelete); - // click reconcile button - // $('.mass_reconcile').click(goToReconcile); }); -/** - * - * @returns {boolean} - */ -function goToReconcile() { - - var checked = $('.select_all_single:checked'); - var ids = []; - $.each(checked, function (i, v) { - ids.push(parseInt($(v).data('transaction'))); - }); - - // go to specially crafted URL: - var bases = document.getElementsByTagName('base'); - var baseHref = null; - - if (bases.length > 0) { - baseHref = bases[0].href; - } - - $.post(baseHref + 'transactions/reconcile', {transactions: ids, _token: token}).done(function () { - window.location.reload(true); - }).fail(function () { - alert('Could not reconcile transactions: please check the logs and try again later.'); - }); - - return false; -} - /** * * @returns {boolean} @@ -100,6 +71,26 @@ function goToMassEdit() { return false; } +/** + * + * @returns {boolean} + */ +function goToBulkEdit() { + "use strict"; + var checkedArray = getCheckboxes(); + + // go to specially crafted URL: + var bases = document.getElementsByTagName('base'); + var baseHref = null; + + if (bases.length > 0) { + baseHref = bases[0].href; + } + + window.location.href = baseHref + '/transactions/bulk/edit/' + checkedArray; + return false; +} + /** * * @returns {boolean} @@ -144,6 +135,7 @@ function countChecked() { var checked = $('.select_all_single:checked').length; if (checked > 0) { $('.mass_edit span').text(edit_selected_txt + ' (' + checked + ')'); + $('.bulk_edit span').text(edit_bulk_selected_txt + ' (' + checked + ')'); $('.mass_delete span').text(delete_selected_txt + ' (' + checked + ')'); // get amount for the transactions: diff --git a/public/js/ff/transactions/mass/edit-bulk.js b/public/js/ff/transactions/mass/edit-bulk.js new file mode 100644 index 0000000000..0aa1f01a3c --- /dev/null +++ b/public/js/ff/transactions/mass/edit-bulk.js @@ -0,0 +1,43 @@ +/* + * edit.js + * Copyright (c) 2017 thegrumpydictator@gmail.com + * + * This file is part of Firefly III. + * + * Firefly III is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Firefly III is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Firefly III. If not, see . + */ + +/** global: what */ + +$(document).ready(function () { + "use strict"; + + $.getJSON('json/categories').done(function (data) { + $('input[name="category"]').typeahead({source: data}); + }); + + $.getJSON('json/tags').done(function (data) { + var opt = { + typeahead: { + source: data, + afterSelect: function () { + this.$element.val(""); + } + } + }; + $('input[name="tags"]').tagsinput( + opt + ); + }); +}); \ No newline at end of file diff --git a/public/js/lib/Chart.bundle.min.js b/public/js/lib/Chart.bundle.min.js index efb0b2a97c..f832ef4e87 100644 --- a/public/js/lib/Chart.bundle.min.js +++ b/public/js/lib/Chart.bundle.min.js @@ -1,10 +1,10 @@ /*! * Chart.js * http://chartjs.org/ - * Version: 2.7.0 + * Version: 2.7.1 * * Copyright 2017 Nick Downie * Released under the MIT license * https://github.com/chartjs/Chart.js/blob/master/LICENSE.md */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Chart=t()}}(function(){return function t(e,n,i){function a(o,s){if(!n[o]){if(!e[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var d=n[o]={exports:{}};e[o][0].call(d.exports,function(t){var n=e[o][1][t];return a(n||t)},d,d.exports,t,e,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;on?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o==-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],"[object Array]"===(e={}.toString.call(t))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+-.4986*o,n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function x(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function _(t){return p(y(t))}function k(t){var e,n,i,a=t[0],r=t[1];return i=t[2]/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=r<=1?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a0)for(n=0;n=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function N(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(Ne[t]=a),e&&(Ne[e[0]]=function(){return Y(a.apply(this,arguments),e[1],e[2])}),n&&(Ne[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function z(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,n,i=t.match(Le);for(e=0,n=i.length;e=0&&We.test(t);)t=t.replace(We,function(t){return e.longDateFormat(t)||t}),We.lastIndex=0,n-=1;return t}function E(t,e,n){nn[t]=D(e)?e:function(t,i){return t&&n?n:e}}function j(t,e){return d(nn,t)?nn[t](e._strict,e._locale):new RegExp(U(t))}function U(t){return q(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function q(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function G(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),s(e)&&(i=function(t,n){n[e]=_(t)}),n=0;n=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function at(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function rt(t,e,n){var i=7+e-n;return-((7+at(t,0,i).getUTCDay()-e)%7)+i-1}function ot(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+rt(t,i,a);return s<=0?o=et(r=t-1)+s:s>et(t)?(r=t+1,o=s-et(t)):(r=t,o=s),{year:r,dayOfYear:o}}function st(t,e,n){var i,a,r=rt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+lt(a=t.year()-1,e,n):o>lt(t.year(),e,n)?(i=o-lt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function lt(t,e,n){var i=rt(t,e,n),a=rt(t+1,e,n);return(et(t)-i+a)/7}function ut(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function dt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function ct(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:null:-1!==(a=gn.call(this._minWeekdaysParse,o))?a:-1!==(a=gn.call(this._weekdaysParse,o))?a:-1!==(a=gn.call(this._shortWeekdaysParse,o))?a:null}function ht(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=h([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=q(s[e]),l[e]=q(l[e]),u[e]=q(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ft(){return this.hours()%12||12}function gt(t,e){N(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function mt(t,e){return e._meridiemParse}function pt(t){return t?t.toLowerCase().replace("_","-"):t}function vt(t){for(var e,n,i,a,r=0;r0;){if(i=yt(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&k(a,n,!0)>=e-1)break;e--}r++}return null}function yt(n){var i=null;if(!On[n]&&void 0!==e&&e&&e.exports)try{i=Pn._abbr,t("./locale/"+n),bt(i)}catch(t){}return On[n]}function bt(t,e){var n;return t&&(n=o(e)?_t(t):xt(t,e))&&(Pn=n),Pn._abbr}function xt(t,e){if(null!==e){var n=An;if(e.abbr=t,null!=On[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=On[t]._config;else if(null!=e.parentLocale){if(null==On[e.parentLocale])return Fn[e.parentLocale]||(Fn[e.parentLocale]=[]),Fn[e.parentLocale].push({name:t,config:e}),null;n=On[e.parentLocale]._config}return On[t]=new P(C(n,e)),Fn[t]&&Fn[t].forEach(function(t){xt(t.name,t.config)}),bt(t),On[t]}return delete On[t],null}function _t(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return Pn;if(!i(t)){if(e=yt(t))return e;t=[t]}return vt(t)}function kt(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[on]<0||n[on]>11?on:n[sn]<1||n[sn]>J(n[rn],n[on])?sn:n[ln]<0||n[ln]>24||24===n[ln]&&(0!==n[un]||0!==n[dn]||0!==n[cn])?ln:n[un]<0||n[un]>59?un:n[dn]<0||n[dn]>59?dn:n[cn]<0||n[cn]>999?cn:-1,g(t)._overflowDayOfYear&&(esn)&&(e=sn),g(t)._overflowWeeks&&-1===e&&(e=hn),g(t)._overflowWeekday&&-1===e&&(e=fn),g(t).overflow=e),t}function wt(t){var e,n,i,a,r,o,s=t._i,l=Rn.exec(s)||Ln.exec(s);if(l){for(g(t).iso=!0,e=0,n=Yn.length;e10?"YYYY ":"YY "),r="HH:mm"+(n[4]?":ss":""),n[1]){var d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][new Date(n[2]).getDay()];if(n[1].substr(0,3)!==d)return g(t).weekdayMismatch=!0,void(t._isValid=!1)}switch(n[5].length){case 2:s=0===l?" +0000":((l="YXWVUTSRQPONZABCDEFGHIKLM".indexOf(n[5][1].toUpperCase())-12)<0?" -":" +")+(""+l).replace(/^-?/,"0").match(/..$/)[0]+"00";break;case 4:s=u[n[5]];break;default:s=u[" GMT"]}n[5]=s,t._i=n.splice(1).join(""),o=" ZZ",t._f=i+a+r+o,It(t),g(t).rfc2822=!0}else t._isValid=!1}function St(t){var e=zn.exec(t._i);null===e?(wt(t),!1===t._isValid&&(delete t._isValid,Mt(t),!1===t._isValid&&(delete t._isValid,n.createFromInputFallback(t)))):t._d=new Date(+e[1])}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(t){var e=new Date(n.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Pt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[sn]&&null==t._a[on]&&Tt(t),null!=t._dayOfYear&&(a=Dt(t._a[rn],i[rn]),(t._dayOfYear>et(a)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=at(a,0,t._dayOfYear),t._a[on]=n.getUTCMonth(),t._a[sn]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;e<7;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[ln]&&0===t._a[un]&&0===t._a[dn]&&0===t._a[cn]&&(t._nextDay=!0,t._a[ln]=0),t._d=(t._useUTC?at:it).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[ln]=24)}}function Tt(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=Dt(e.GG,t._a[rn],st(Nt(),1,4).year),i=Dt(e.W,1),((a=Dt(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=st(Nt(),r,o);n=Dt(e.gg,t._a[rn],u.year),i=Dt(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>lt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=ot(n,i,a,r,o),t._a[rn]=s.year,t._dayOfYear=s.dayOfYear)}function It(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,a,r,o,s=""+t._i,l=s.length,u=0;for(a=H(t._f,t._locale).match(Le)||[],e=0;e0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),u+=i.length),Ne[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),X(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[ln]<=12&&!0===g(t).bigHour&&t._a[ln]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[ln]=At(t._locale,t._a[ln],t._meridiem),Pt(t),kt(t)}else Mt(t);else wt(t)}function At(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}function Ot(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;ar&&(e=r),oe.call(this,t,e,n,i,a))}function oe(t,e,n,i,a){var r=ot(t,e,n,i,a),o=at(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function se(t){return t}function le(t,e,n,i){var a=_t(),r=h().set(i,e);return a[n](r,t)}function ue(t,e,n){if(s(t)&&(e=t,t=void 0),t=t||"",null!=e)return le(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=le(t,i,n,"month");return a}function de(t,e,n,i){"boolean"==typeof t?(s(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,s(e)&&(n=e,e=void 0),e=e||"");var a=_t(),r=t?a._week.dow:0;if(null!=n)return le(e,(n+r)%7,i,"day");var o,l=[];for(o=0;o<7;o++)l[o]=le(e,(o+r)%7,i,"day");return l}function ce(t,e,n,i){var a=Xt(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function he(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function ge(t){return 146097*t/4800}function me(t){return function(){return this.as(t)}}function pe(t){return function(){return this.isValid()?this._data[t]:NaN}}function ve(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ye(t,e,n){var i=Xt(t).abs(),a=bi(i.as("s")),r=bi(i.as("m")),o=bi(i.as("h")),s=bi(i.as("d")),l=bi(i.as("M")),u=bi(i.as("y")),d=a<=xi.ss&&["s",a]||a0,d[4]=n,ve.apply(null,d)}function be(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n,i=_i(this._milliseconds)/1e3,a=_i(this._days),r=_i(this._months);e=x((t=x(i/60))/60),i%=60,t%=60;var o=n=x(r/12),s=r%=12,l=a,u=e,d=t,c=i,h=this.asSeconds();return h?(h<0?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(u||d||c?"T":"")+(u?u+"H":"")+(d?d+"M":"")+(c?c+"S":""):"P0D"}var xe,_e,ke=_e=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i68?1900:2e3)};var xn=R("FullYear",!0);N("w",["ww",2],"wo","week"),N("W",["WW",2],"Wo","isoWeek"),T("week","w"),T("isoWeek","W"),O("week",5),O("isoWeek",5),E("w",je),E("ww",je,Be),E("W",je),E("WW",je,Be),Z(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=_(t)});var _n={dow:0,doy:6};N("d",0,"do","day"),N("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),N("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),N("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),N("e",0,0,"weekday"),N("E",0,0,"isoWeekday"),T("day","d"),T("weekday","e"),T("isoWeekday","E"),O("day",11),O("weekday",11),O("isoWeekday",11),E("d",je),E("e",je),E("E",je),E("dd",function(t,e){return e.weekdaysMinRegex(t)}),E("ddd",function(t,e){return e.weekdaysShortRegex(t)}),E("dddd",function(t,e){return e.weekdaysRegex(t)}),Z(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),Z(["d","e","E"],function(t,e,n,i){e[i]=_(t)});var kn="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),wn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Mn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Sn=en,Dn=en,Cn=en;N("H",["HH",2],0,"hour"),N("h",["hh",2],0,ft),N("k",["kk",2],0,function(){return this.hours()||24}),N("hmm",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)}),N("hmmss",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)+Y(this.seconds(),2)}),N("Hmm",0,0,function(){return""+this.hours()+Y(this.minutes(),2)}),N("Hmmss",0,0,function(){return""+this.hours()+Y(this.minutes(),2)+Y(this.seconds(),2)}),gt("a",!0),gt("A",!1),T("hour","h"),O("hour",13),E("a",mt),E("A",mt),E("H",je),E("h",je),E("k",je),E("HH",je,Be),E("hh",je,Be),E("kk",je,Be),E("hmm",Ue),E("hmmss",qe),E("Hmm",Ue),E("Hmmss",qe),G(["H","HH"],ln),G(["k","kk"],function(t,e,n){var i=_(t);e[ln]=24===i?0:i}),G(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),G(["h","hh"],function(t,e,n){e[ln]=_(t),g(n).bigHour=!0}),G("hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i)),g(n).bigHour=!0}),G("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a)),g(n).bigHour=!0}),G("Hmm",function(t,e,n){var i=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i))}),G("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[ln]=_(t.substr(0,i)),e[un]=_(t.substr(i,2)),e[dn]=_(t.substr(a))});var Pn,Tn=/[ap]\.?m?\.?/i,In=R("Hours",!0),An={calendar:Te,longDateFormat:Ie,invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:Ae,relativeTime:Oe,months:pn,monthsShort:vn,week:_n,weekdays:kn,weekdaysMin:Mn,weekdaysShort:wn,meridiemParse:Tn},On={},Fn={},Rn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Ln=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Wn=/Z|[+-]\d\d(?::?\d\d)?/,Yn=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Nn=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],zn=/^\/?Date\((\-?\d+)/i,Bn=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var Vn=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?tthis?this:t:p()}),En=["year","quarter","month","week","day","hour","minute","second","millisecond"];jt("Z",":"),jt("ZZ",""),E("Z",$e),E("ZZ",$e),G(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ut($e,t)});var jn=/([\+\-]|\d\d)/gi;n.updateOffset=function(){};var Un=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,qn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Xt.fn=Vt.prototype,Xt.invalid=function(){return Xt(NaN)};var Gn=$t(1,"add"),Zn=$t(-1,"subtract");n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xn=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});N(0,["gg",2],0,function(){return this.weekYear()%100}),N(0,["GG",2],0,function(){return this.isoWeekYear()%100}),ae("gggg","weekYear"),ae("ggggg","weekYear"),ae("GGGG","isoWeekYear"),ae("GGGGG","isoWeekYear"),T("weekYear","gg"),T("isoWeekYear","GG"),O("weekYear",1),O("isoWeekYear",1),E("G",Ke),E("g",Ke),E("GG",je,Be),E("gg",je,Be),E("GGGG",Ze,He),E("gggg",Ze,He),E("GGGGG",Xe,Ee),E("ggggg",Xe,Ee),Z(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=_(t)}),Z(["gg","GG"],function(t,e,i,a){e[a]=n.parseTwoDigitYear(t)}),N("Q",0,"Qo","quarter"),T("quarter","Q"),O("quarter",7),E("Q",ze),G("Q",function(t,e){e[on]=3*(_(t)-1)}),N("D",["DD",2],"Do","date"),T("date","D"),O("date",9),E("D",je),E("DD",je,Be),E("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),G(["D","DD"],sn),G("Do",function(t,e){e[sn]=_(t.match(je)[0],10)});var Jn=R("Date",!0);N("DDD",["DDDD",3],"DDDo","dayOfYear"),T("dayOfYear","DDD"),O("dayOfYear",4),E("DDD",Ge),E("DDDD",Ve),G(["DDD","DDDD"],function(t,e,n){n._dayOfYear=_(t)}),N("m",["mm",2],0,"minute"),T("minute","m"),O("minute",14),E("m",je),E("mm",je,Be),G(["m","mm"],un);var Kn=R("Minutes",!1);N("s",["ss",2],0,"second"),T("second","s"),O("second",15),E("s",je),E("ss",je,Be),G(["s","ss"],dn);var Qn=R("Seconds",!1);N("S",0,0,function(){return~~(this.millisecond()/100)}),N(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),N(0,["SSS",3],0,"millisecond"),N(0,["SSSS",4],0,function(){return 10*this.millisecond()}),N(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),N(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),N(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),N(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),N(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),T("millisecond","ms"),O("millisecond",16),E("S",Ge,ze),E("SS",Ge,Be),E("SSS",Ge,Ve);var $n;for($n="SSSS";$n.length<=9;$n+="S")E($n,Je);for($n="S";$n.length<=9;$n+="S")G($n,function(t,e){e[cn]=_(1e3*("0."+t))});var ti=R("Milliseconds",!1);N("z",0,0,"zoneAbbr"),N("zz",0,0,"zoneName");var ei=y.prototype;ei.add=Gn,ei.calendar=function(t,e){var i=t||Nt(),a=qt(i,this).startOf("day"),r=n.calendarFormat(this,a)||"sameElse",o=e&&(D(e[r])?e[r].call(this,i):e[r]);return this.format(o||this.localeData().calendar(r,this,Nt(i)))},ei.clone=function(){return new y(this)},ei.diff=function(t,e,n){var i,a,r,o;return this.isValid()&&(i=qt(t,this)).isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),"year"===(e=I(e))||"month"===e||"quarter"===e?(o=ee(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:x(o)):NaN},ei.endOf=function(t){return void 0===(t=I(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},ei.format=function(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=V(this,t);return this.localeData().postformat(e)},ei.from=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.fromNow=function(t){return this.from(Nt(),t)},ei.to=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},ei.toNow=function(t){return this.to(Nt(),t)},ei.get=function(t){return t=I(t),D(this[t])?this[t]():this},ei.invalidAt=function(){return g(this).overflow},ei.isAfter=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=I(o(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()9999?V(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():V(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},ei.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},ei.toJSON=function(){return this.isValid()?this.toISOString():null},ei.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},ei.unix=function(){return Math.floor(this.valueOf()/1e3)},ei.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},ei.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},ei.year=xn,ei.isLeapYear=function(){return nt(this.year())},ei.weekYear=function(t){return re.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},ei.isoWeekYear=function(t){return re.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},ei.quarter=ei.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},ei.month=$,ei.daysInMonth=function(){return J(this.year(),this.month())},ei.week=ei.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},ei.isoWeek=ei.isoWeeks=function(t){var e=st(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},ei.weeksInYear=function(){var t=this.localeData()._week;return lt(this.year(),t.dow,t.doy)},ei.isoWeeksInYear=function(){return lt(this.year(),1,4)},ei.date=Jn,ei.day=ei.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ut(t,this.localeData()),this.add(t-e,"d")):e},ei.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},ei.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=dt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},ei.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},ei.hour=ei.hours=In,ei.minute=ei.minutes=Kn,ei.second=ei.seconds=Qn,ei.millisecond=ei.milliseconds=ti,ei.utcOffset=function(t,e,i){var a,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ut($e,t)))return this}else Math.abs(t)<16&&!i&&(t*=60);return!this._isUTC&&e&&(a=Gt(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),r!==t&&(!e||this._changeInProgress?te(this,Xt(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},ei.utc=function(t){return this.utcOffset(0,t)},ei.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Gt(this),"m")),this},ei.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ut(Qe,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},ei.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Nt(t).utcOffset():0,(this.utcOffset()-t)%60==0)},ei.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},ei.isLocal=function(){return!!this.isValid()&&!this._isUTC},ei.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},ei.isUtc=Zt,ei.isUTC=Zt,ei.zoneAbbr=function(){return this._isUTC?"UTC":""},ei.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},ei.dates=M("dates accessor is deprecated. Use date instead.",Jn),ei.months=M("months accessor is deprecated. Use month instead",$),ei.years=M("years accessor is deprecated. Use year instead",xn),ei.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),ei.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Lt(t))._a){var e=t._isUTC?h(t._a):Nt(t._a);this._isDSTShifted=this.isValid()&&k(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var ni=P.prototype;ni.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return D(i)?i.call(e,n):i},ni.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},ni.invalidDate=function(){return this._invalidDate},ni.ordinal=function(t){return this._ordinal.replace("%d",t)},ni.preparse=se,ni.postformat=se,ni.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return D(a)?a(t,e,n,i):a.replace(/%d/i,t)},ni.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return D(n)?n(e):n.replace(/%s/i,e)},ni.set=function(t){var e,n;for(n in t)D(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},ni.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||mn).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},ni.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[mn.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},ni.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return K.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=h([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},ni.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=bn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},ni.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=yn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},ni.week=function(t){return st(t,this._week.dow,this._week.doy).week},ni.firstDayOfYear=function(){return this._week.doy},ni.firstDayOfWeek=function(){return this._week.dow},ni.weekdays=function(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone},ni.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},ni.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},ni.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return ct.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},ni.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=Sn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},ni.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=Dn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},ni.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Cn),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},ni.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},ni.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},bt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",bt),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",_t);var ii=Math.abs,ai=me("ms"),ri=me("s"),oi=me("m"),si=me("h"),li=me("d"),ui=me("w"),di=me("M"),ci=me("y"),hi=pe("milliseconds"),fi=pe("seconds"),gi=pe("minutes"),mi=pe("hours"),pi=pe("days"),vi=pe("months"),yi=pe("years"),bi=Math.round,xi={ss:44,s:45,m:45,h:22,d:26,M:11},_i=Math.abs,ki=Vt.prototype;return ki.isValid=function(){return this._isValid},ki.abs=function(){var t=this._data;return this._milliseconds=ii(this._milliseconds),this._days=ii(this._days),this._months=ii(this._months),t.milliseconds=ii(t.milliseconds),t.seconds=ii(t.seconds),t.minutes=ii(t.minutes),t.hours=ii(t.hours),t.months=ii(t.months),t.years=ii(t.years),this},ki.add=function(t,e){return ce(this,t,e,1)},ki.subtract=function(t,e){return ce(this,t,e,-1)},ki.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=I(t))||"year"===t)return e=this._days+i/864e5,n=this._months+fe(e),"month"===t?n:n/12;switch(e=this._days+Math.round(ge(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},ki.asMilliseconds=ai,ki.asSeconds=ri,ki.asMinutes=oi,ki.asHours=si,ki.asDays=li,ki.asWeeks=ui,ki.asMonths=di,ki.asYears=ci,ki.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN},ki._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*he(ge(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=x(r/1e3),l.seconds=t%60,e=x(t/60),l.minutes=e%60,n=x(e/60),l.hours=n%24,o+=x(n/24),a=x(fe(o)),s+=a,o-=he(ge(a)),i=x(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},ki.get=function(t){return t=I(t),this.isValid()?this[t+"s"]():NaN},ki.milliseconds=hi,ki.seconds=fi,ki.minutes=gi,ki.hours=mi,ki.days=pi,ki.weeks=function(){return x(this.days()/7)},ki.months=vi,ki.years=yi,ki.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=ye(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},ki.toISOString=be,ki.toString=be,ki.toJSON=be,ki.locale=ne,ki.localeData=ie,ki.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",be),ki.lang=Xn,N("X",0,0,"unix"),N("x",0,0,"valueOf"),E("x",Ke),E("X",tn),G("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),G("x",function(t,e,n){n._d=new Date(_(t))}),n.version="2.18.1",function(t){xe=t}(Nt),n.fn=ei,n.min=function(){return zt("isBefore",[].slice.call(arguments,0))},n.max=function(){return zt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(t){return Nt(1e3*t)},n.months=function(t,e){return ue(t,e,"months")},n.isDate=l,n.locale=bt,n.invalid=p,n.duration=Xt,n.isMoment=b,n.weekdays=function(t,e,n){return de(t,e,n,"weekdays")},n.parseZone=function(){return Nt.apply(null,arguments).parseZone()},n.localeData=_t,n.isDuration=Ht,n.monthsShort=function(t,e){return ue(t,e,"monthsShort")},n.weekdaysMin=function(t,e,n){return de(t,e,n,"weekdaysMin")},n.defineLocale=xt,n.updateLocale=function(t,e){if(null!=e){var n,i=An;null!=On[t]&&(i=On[t]._config),(n=new P(e=C(i,e))).parentLocale=On[t],On[t]=n,bt(t)}else null!=On[t]&&(null!=On[t].parentLocale?On[t]=On[t].parentLocale:null!=On[t]&&delete On[t]);return On[t]},n.locales=function(){return Pe(On)},n.weekdaysShort=function(t,e,n){return de(t,e,n,"weekdaysShort")},n.normalizeUnits=I,n.relativeTimeRounding=function(t){return void 0===t?bi:"function"==typeof t&&(bi=t,!0)},n.relativeTimeThreshold=function(t,e){return void 0!==xi[t]&&(void 0===e?xi[t]:(xi[t]=e,"s"===t&&(xi.ss=e-1),!0))},n.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=ei,n})},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index=0&&a>0)&&(p+=a));return r=c.getPixelForValue(p),o=c.getPixelForValue(p+f),s=(o-r)/2,{size:s,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i,a,o,s,l,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],m=f.length,p=n.start,v=n.end;return 1===m?(i=g>p?g-p:v-g,a=g0&&(i=(g-f[e-1])/2,e===m-1&&(a=i)),e');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=h/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),m=n&&l.animateScale?0:i.innerRadius,p=n&&l.animateScale?0:i.outerRadius,v=r.valueAtIndexOrDefault;r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,e,a.data.labels[e])}});var y=t._model;this.removeHoverStyle(t),n&&l.animateRotate||(y.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,c=d.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,o=i.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:r.valueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),n.dataset.pivot(),r.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,o=this.chart.options.elements.point;a.radius=n.radius?n.radius:r.valueAtIndexOrDefault(e.pointRadius,i,o.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:r.valueAtIndexOrDefault(e.pointBackgroundColor,i,o.backgroundColor),a.borderColor=n.borderColor?n.borderColor:r.valueAtIndexOrDefault(e.pointBorderColor,i,o.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:r.valueAtIndexOrDefault(e.pointBorderWidth,i,o.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(28),o=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function s(t){return"top"===t||"bottom"===t}var l=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var r=this;i=e(i);var s=o.acquireContext(n,i),l=s&&s.canvas,u=l&&l.height,d=l&&l.width;r.id=a.uid(),r.ctx=s,r.canvas=l,r.config=i,r.width=d,r.height=u,r.aspectRatio=u?d/u:null,r.options=i.options,r._bufferedRender=!1,r.chart=r,r.controller=r,t.instances[r.id]=r,Object.defineProperty(r,"data",{get:function(){return r.config.data},set:function(t){r.config.data=t}}),s&&l?(r.initialize(),r.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,o=Math.max(0,Math.floor(a.getMaximumWidth(i))),s=Math.max(0,Math.floor(r?o/r:a.getMaximumHeight(i)));if((e.width!==o||e.height!==s)&&(i.width=e.width=o,i.height=e.height=s,i.style.width=o+"px",i.style.height=s+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:o,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},r=[];n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,o=a.valueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(o);if(l){s(r.position)!==s(n.dposition)&&(r.position=n.dposition);var u=new l({id:r.id,options:r,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r);else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==l.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),l.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==l.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),l.notify(e,"afterScaleUpdate"),l.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==l.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==l.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),l.notify(n,"afterDatasetDraw",[a]))},getElementAtEvent:function(t){return r.modes.single(this,t)},getElementsAtEvent:function(t){return r.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return r.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=r.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return r.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;ti&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n=n[e].length&&n[e].push({}),!n[e][o].type||l.type&&l.type!==n[e][o].type?r.merge(n[e][o],[t.scaleService.getScaleDefaults(s),l]):r.merge(n[e][o],l)}else r._merger(e,n,i,a)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i=0;i--){var a=t[i];if(e(a))return a}},r.inherits=function(t){var e=this,n=t&&t.hasOwnProperty("constructor")?t.constructor:function(){return e.apply(this,arguments)},i=function(){this.constructor=n};return i.prototype=e.prototype,n.prototype=new i,n.extend=r.inherits,t&&r.extend(n.prototype,t),n.__super__=e.prototype,n},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),s=o.length;for(e=0;e0?o[e-1]:null,(a=e0?o[e-1]:null,a=e=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return n=Math.round((n-s.left-u)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-d)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(r.getStyle(e,"padding-left"),10),i=parseInt(r.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,o=r.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},r.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(r.getStyle(e,"padding-top"),10),i=parseInt(r.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,o=r.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=r+"px"}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;ui&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,25:25,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return l(t,e,{intersect:!0})},point:function(t,e){return r(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var r=s(n.axis),l=o(t,a,n.intersect,r);return l.length>1&&l.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),l.slice(0,1)},x:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inXRange(r.x)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inYRange(r.y)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;oh&&lt.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){s.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){s.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},r=i(t._ticks),o=t.options,u=o.ticks,d=o.scaleLabel,c=o.gridLines,h=o.display,f=t.isHorizontal(),g=n(u),m=o.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?m:0,a.height=f?h&&c.drawTicks?m:0:t.maxHeight,d.display&&h){var p=l(d)+s.options.toPadding(d.padding).height;f?a.height+=p:a.width+=p}if(u.display&&h){var v=s.longestText(t.ctx,g.font,r,t.longestTextCache),y=s.numberOfLabelLines(r),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=s.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_)*v+g.size*y+b*(y-1)+b;a.height=Math.min(t.maxHeight,a.height+w+x),t.ctx.font=g.font;var M=e(t.ctx,r[0],g.font),S=e(t.ctx,r[r.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?k*M+3:k*b+3,t.paddingRight="bottom"===o.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else u.mirror?v=0:v+=x+b,a.width=Math.min(t.maxWidth,a.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){s.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(s.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:s.noop,getPixelForValue:s.noop,getValueForPixel:s.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,r=this,o=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=s.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),o&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1||s.isNullOrUndef(i.label))&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var o=e.ctx,u=r.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=s.valueOrDefault(d.fontColor,u.defaultFontColor),y=n(d),b=s.valueOrDefault(c.fontColor,u.defaultFontColor),x=n(c),_=h.drawTicks?h.tickMarkLength:0,k=s.valueOrDefault(f.fontColor,u.defaultFontColor),w=n(f),M=s.options.toPadding(f.padding),S=s.toRadians(e.labelRotation),D=[],C="right"===i.position?e.left:e.right-_,P="right"===i.position?e.left+_:e.right,T="bottom"===i.position?e.top:e.bottom-_,I="bottom"===i.position?e.top+_:e.bottom;if(s.each(p,function(n,r){if(void 0!==n.label){var o,l,c,f,v=n.label;r===e.zeroLineIndex&&i.offset===h.offsetGridLines?(o=h.zeroLineWidth,l=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(o=s.valueAtIndexOrDefault(h.lineWidth,r),l=s.valueAtIndexOrDefault(h.color,r),c=s.valueOrDefault(h.borderDash,u.borderDash),f=s.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var y,b,x,k,w,M,A,O,F,R,L="middle",W="middle",Y=d.padding;if(m){var N=_+Y;"bottom"===i.position?(W=g?"middle":"top",L=g?"right":"center",R=e.top+N):(W=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-N);var z=a(e,r,h.offsetGridLines&&p.length>1);z1);H0)n=t.stepSize;else{var r=i.niceNum(e.max-e.min,!1);n=i.niceNum(r/(t.maxTicks-1),!0)}var o=Math.floor(e.min/n)*n,s=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(o=t.min,s=t.max);var l=(s-o)/n;l=i.almostEquals(l,Math.round(l),n/1e3)?Math.round(l):Math.ceil(l),a.push(void 0!==t.min?t.min:o);for(var u=1;u3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.indexi.height-e.height&&(o="bottom");var s,l,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===o?(s=function(t){return t<=h},l=function(t){return t>h}):(s=function(t){return t<=e.width/2},l=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},s(n.x)?(r="left",u(n.x)&&(r="center",o=c(n.y))):l(n.x)&&(r="right",d(n.x)&&(r="center",o=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:r,yAlign:g.yAlign?g.yAlign:o}}function d(t,e,n){var i=t.x,a=t.y,r=t.caretSize,o=t.caretPadding,s=t.cornerRadius,l=n.xAlign,u=n.yAlign,d=r+o,c=s+o;return"right"===l?i-=e.width:"center"===l&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===l?i+=d:"right"===l&&(i-=d):"left"===l?i-=c:"right"===l&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=s(this._options)},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),r=e.afterTitle.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,o=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};n(r.before,a.beforeLabel.call(i,t,e)),n(r.lines,a.label.call(i,t,e)),n(r.after,a.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),r=e.afterFooter.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=s(c),g=a._active,m=a._data,p={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},y={width:h.width,height:h.height},b={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var x=[],_=[];b=t.Tooltip.positioners[c.position](g,a._eventPosition);var k=[];for(n=0,i=g.length;n0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!r.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;el;)a-=2*Math.PI;for(;a=s&&a<=l,d=o>=n.innerRadius&&o<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,s=a._view,l=a._chart.ctx,u=s.spanGaps,d=a._children.slice(),c=o.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),l.save(),l.lineCap=s.borderCapStyle||c.borderCapStyle,l.setLineDash&&l.setLineDash(s.borderDash||c.borderDash),l.lineDashOffset=s.borderDashOffset||c.borderDashOffset,l.lineJoin=s.borderJoinStyle||c.borderJoinStyle,l.lineWidth=s.borderWidth||c.borderWidth,l.strokeStyle=s.borderColor||o.defaultColor,l.beginPath(),h=-1,t=0;te?1:-1,o=1,s=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,r=1,o=(a=u.base)>i?1:-1,s=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==s?h*r:0),g=n+("right"!==s?-h*r:0),m=i+("top"!==s?h*o:0),p=a+("bottom"!==s?-h*o:0);f!==g&&(i=m,a=p),m!==p&&(e=f,n=g)}l.beginPath(),l.fillStyle=u.backgroundColor,l.strokeStyle=u.borderColor,l.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],y=["bottom","left","top","right"].indexOf(s,0);-1===y&&(y=0);var b=t(0);l.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=t(x),l.lineTo(b[0],b[1]);l.fill(),d&&l.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var r=a(n);return i(n)?t>=r.left&&t<=r.right:e>=r.top&&e<=r.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,i/2),s=Math.min(r,a/2);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+s),t.lineTo(e+i,n+a-s),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+o,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var r,o,s,l,u,d;if("object"!=typeof e||"[object HTMLImageElement]"!==(r=e.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-o/2,a+u/3),t.lineTo(i+o/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var r,o,s;if(i.isArray(t))if(o=t.length,a)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a
';var a=e.childNodes[0],o=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,o.scrollLeft=1e6,o.scrollTop=1e6};var s=function(){e._reset(),t()};return r(a,"scroll",s.bind(a,"expand")),r(o,"scroll",s.bind(o,"shrink")),e}function c(t,e){var n=(t[v]||(t[v]={})).renderProxy=function(t){t.animationName===x&&e()};p.each(_,function(e){r(t,e,n)}),t.classList.add(b)}function h(t){var e=t[v]||{},n=e.renderProxy;n&&(p.each(_,function(e){o(t,e,n)}),delete e.renderProxy),t.classList.remove(b)}function f(t,e,n){var i=t[v]||(t[v]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(s("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[v]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function m(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var p=t(45),v="$chartjs",y="chartjs-",b=y+"render-monitor",x=y+"render-animation",_=["animationstart","webkitAnimationStart"],k={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},w=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";m(this,"@-webkit-keyframes "+x+"{"+t+"}@keyframes "+x+"{"+t+"}."+b+"{-webkit-animation:"+x+" 0.001s;animation:"+x+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[v]){var n=e[v].initial;["height","width"].forEach(function(t){var i=n[t];p.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),p.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[v]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[v]||(n[v]={});r(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(l(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[v]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else g(i)}},p.addEvent=r,p.removeEvent=o},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),r=t(47),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),void 0!==r&&null!==r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return e=i.isHorizontal(),{x:e?r:null,y:e?null:r}}return null}function n(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function o(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function s(t){return t&&!t.skip}function l(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}function u(t,e,n,i,a,r){var o,u,d,c,h,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,u=m+!!r;o');for(var n=0;n'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("");return e.push(""),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});o.configure(e,i,n),o.addBox(e,i),e.legend=i}var o=t.layoutService,s=r.noop;return t.Legend=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,n=t.options,a=n.labels,o=n.display,s=t.ctx,l=i.global,u=r.valueOrDefault,d=u(a.fontSize,l.defaultFontSize),c=u(a.fontStyle,l.defaultFontStyle),h=u(a.fontFamily,l.defaultFontFamily),f=r.fontString(d,c,h),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=o?10:0):(m.width=o?10:0,m.height=t.maxHeight),o)if(s.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+a.padding:0;s.textAlign="left",s.textBaseline="top",r.each(t.legendItems,function(n,i){var r=e(a,d)+d/2+s.measureText(n.text).width;v[v.length-1]+r+a.padding>=t.width&&(y+=d+a.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:r,height:d},v[v.length-1]+=r+a.padding}),m.height+=y}else{var b=a.padding,x=t.columnWidths=[],_=a.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+s.measureText(t.text).width;w+M>m.height&&(_+=k+a.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[n]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,o=i.global,s=o.elements.line,l=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=r.valueOrDefault,f=h(a.fontColor,o.defaultFontColor),g=h(a.fontSize,o.defaultFontSize),m=h(a.fontStyle,o.defaultFontStyle),p=h(a.fontFamily,o.defaultFontFamily),v=r.fontString(g,m,p);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var y=e(a,g),b=t.legendHitBoxes,x=function(t,e,i){if(!(isNaN(y)||y<=0)){c.save(),c.fillStyle=h(i.fillStyle,o.defaultColor),c.lineCap=h(i.lineCap,s.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,s.borderDashOffset),c.lineJoin=h(i.lineJoin,s.borderJoinStyle),c.lineWidth=h(i.lineWidth,s.borderWidth),c.strokeStyle=h(i.strokeStyle,o.defaultColor);var a=0===h(i.lineWidth,s.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,s.borderDash)),n.labels&&n.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=e+u;r.canvas.drawPoint(c,i.pointStyle,l,d,f)}else a||c.strokeRect(t,e,y,g),c.fillRect(t,e,y,g);c.restore()}},_=function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(r+i,o),c.stroke())},k=t.isHorizontal();d=k?{x:t.left+(l-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var w=g+a.padding;r.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,r=y+g/2+i,o=d.x,s=d.y;k?o+r>=l&&(s=d.y+=w,d.line++,o=d.x=t.left+(l-u[d.line])/2):s+w>t.bottom&&(o=d.x=o+t.columnWidths[d.line]+a.padding,s=d.y=t.top+a.padding,d.line++),x(o,s,e),b[n].left=o,b[n].top=s,_(o,s,e,i),k?d.x+=r+a.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(r.mergeIf(e,i.global.legend),a?(o.configure(t,a,e),a.options=e):n(t,e)):a&&(o.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,o=r.noop;return t.Title=a.extend({initialize:function(t){var e=this;r.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=r.valueOrDefault,n=t.options,a=n.display,o=e(n.fontSize,i.global.defaultFontSize),s=t.minSize,l=r.isArray(n.text)?n.text.length:1,u=r.options.toLineHeight(n.lineHeight,o),d=a?l*u+2*n.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),c=n(a.fontStyle,o.defaultFontStyle),h=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,c,h),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,s=a.titleBlock;o?(r.mergeIf(o,i.global.title),s?(n.configure(a,s,o),s.options=o):e(a,o)):s&&(t.layoutService.removeBox(a,s),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e={position:"bottom"},n=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels();t=n||t;var s=o.indexOf(t);e=-1!==s?s:e}if(i.isHorizontal()){var l=i.width/r,u=l*(e-i.minIndex);return a&&(u+=l/2),i.left+Math.round(u)}var d=i.height/r,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",n,e)}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:r.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return o?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,r=i.data.datasets,o=e.isHorizontal();e.min=null,e.max=null;var s=n.stacked;if(void 0===s&&a.each(r,function(e,n){if(!s){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(s=!0)}}),n.stacked||s){var l={};a.each(r,function(r,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&t(s)&&a.each(r.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(l,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),r=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?r:Math.max(e.max,r)})}else a.each(r,function(n,r){var o=i.getDatasetMeta(r);i.isDatasetVisible(r)&&t(o)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:ie.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var r=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*r)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),r=n.end-i;return n.isHorizontal()?(e=n.left+n.width/r*(a-i),Math.round(e)):(e=n.bottom-n.height/r*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=a.generators.linear(r,t);t.handleDirectionalChanges(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,r=e.chart,o=r.data.datasets,s=i.valueOrDefault,l=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(o,function(e,n){if(!u){var i=r.getDatasetMeta(n);r.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(o,function(a,o){var s=r.getDatasetMeta(o),l=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");r.isDatasetVisible(o)&&t(s)&&(void 0===d[l]&&(d[l]=[]),i.each(a.data,function(t,i){var a=d[l],r=+e.getRightValue(t);isNaN(r)||s.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=r)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(o,function(n,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:ie.max&&(e.max=i),0!==i&&(null===e.minNotZero||ia?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){var i,r,l,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;ic.r&&(c.r=p.end,h.r=g),v.startc.b&&(c.b=v.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,r=a.valueOrDefault,o=t.options,s=o.angleLines,l=o.pointLabels;i.lineWidth=s.lineWidth,i.strokeStyle=s.color;var u=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(s.display){var m=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(l.display){var v=t.getPointPosition(g,u+5),y=r(l.fontColor,p.defaultFontColor);i.font=f.font,i.fillStyle=y;var b=t.getIndexAngle(g),x=a.toDegrees(b);i.textAlign=d(x),h(x,t._pointLabelSizes[g],v),c(i,t.pointLabels[g]||"",v,f.size)}}}function g(t,n,i,r){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(n.color,r-1),o.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,r-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=e(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,r=a.valueOrDefault;if(e.display){var o=t.ctx,s=this.getIndexAngle(0),l=r(i.fontSize,p.defaultFontSize),u=r(i.fontStyle,p.defaultFontStyle),d=r(i.fontFamily,p.defaultFontFamily),c=a.fontString(l,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=r(i.fontColor,p.defaultFontColor);if(o.font=c,o.save(),o.translate(t.xCenter,t.yCenter),o.rotate(s),i.showLabelBackdrop){var h=o.measureText(e).width;o.fillStyle=i.backdropColor,o.fillRect(-h/2-i.backdropPaddingX,-u-l/2-i.backdropPaddingY,h+2*i.backdropPaddingX,l+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=d,o.fillText(e,0,-u),o.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",y,v)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},r=[];for(e=0,n=t.length;ee&&s=0&&o<=s;){if(i=o+s>>1,a=t[i-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}function s(t,e,n,i){var a=o(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],s=a.lo?a.hi?a.hi:t[t.length-1]:t[1],l=s[e]-r[e],u=l?(n-r[e])/l:0,d=(s[i]-r[i])*u;return r[i]+d}function l(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?p(t,i):(t instanceof p||(t=p(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(y.isNullOrUndef(t))return null;var n=e.options.time,i=l(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,r,o,s=e-t,l=_[n],u=l.size,d=l.steps;if(!d)return Math.ceil(s/((i||1)*u));for(a=0,r=d.length;a1?e[1]:i,o=e[0],l=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2),a.time.max||(r=e[e.length-1],o=e.length>1?e[e.length-2]:n,u=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2)),{left:l,right:u}}function m(t,e){var n,i,a,r,o=[];for(n=0,i=t.length;n=a&&n<=o&&x.push(n);return i.min=a,i.max=o,i._unit=v,i._majorUnit=y,i._minorFormat=d[v],i._majorFormat=d[y],i._table=r(i._timestamps.data,a,o,s.distribution),i._offsets=g(i._table,x,a,o,s),m(x,y)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,r=i.labels&&t=0&&tn?(e+.05)/(n+.05):(n+.05)/(e+.05)},level:function(t){var e=this.contrast(t);return e>=7.1?"AAA":e>=4.5?"AA":""},dark:function(){var t=this.values.rgb;return(299*t[0]+587*t[1]+114*t[2])/1e3<128},light:function(){return!this.dark()},negate:function(){for(var t=[],e=0;e<3;e++)t[e]=255-this.values.rgb[e];return this.setValues("rgb",t),this},lighten:function(t){var e=this.values.hsl;return e[2]+=e[2]*t,this.setValues("hsl",e),this},darken:function(t){var e=this.values.hsl;return e[2]-=e[2]*t,this.setValues("hsl",e),this},saturate:function(t){var e=this.values.hsl;return e[1]+=e[1]*t,this.setValues("hsl",e),this},desaturate:function(t){var e=this.values.hsl;return e[1]-=e[1]*t,this.setValues("hsl",e),this},whiten:function(t){var e=this.values.hwb;return e[1]+=e[1]*t,this.setValues("hwb",e),this},blacken:function(t){var e=this.values.hwb;return e[2]+=e[2]*t,this.setValues("hwb",e),this},greyscale:function(){var t=this.values.rgb,e=.3*t[0]+.59*t[1]+.11*t[2];return this.setValues("rgb",[e,e,e]),this},clearer:function(t){var e=this.values.alpha;return this.setValues("alpha",e-e*t),this},opaquer:function(t){var e=this.values.alpha;return this.setValues("alpha",e+e*t),this},rotate:function(t){var e=this.values.hsl,n=(e[0]+t)%360;return e[0]=n<0?360+n:n,this.setValues("hsl",e),this},mix:function(t,e){var n=this,i=t,a=void 0===e?.5:e,r=2*a-1,o=n.alpha()-i.alpha(),s=((r*o==-1?r:(r+o)/(1+r*o))+1)/2,l=1-s;return this.rgb(s*n.red()+l*i.red(),s*n.green()+l*i.green(),s*n.blue()+l*i.blue()).alpha(n.alpha()*a+i.alpha()*(1-a))},toJSON:function(){return this.rgb()},clone:function(){var t,e,n=new r,i=this.values,a=n.values;for(var o in i)i.hasOwnProperty(o)&&(t=i[o],"[object Array]"===(e={}.toString.call(t))?a[o]=t.slice(0):"[object Number]"===e?a[o]=t:console.error("unexpected color value:",t));return n}},r.prototype.spaces={rgb:["red","green","blue"],hsl:["hue","saturation","lightness"],hsv:["hue","saturation","value"],hwb:["hue","whiteness","blackness"],cmyk:["cyan","magenta","yellow","black"]},r.prototype.maxes={rgb:[255,255,255],hsl:[360,100,100],hsv:[360,100,100],hwb:[360,100,100],cmyk:[100,100,100,100]},r.prototype.getValues=function(t){for(var e=this.values,n={},i=0;i.04045?Math.pow((e+.055)/1.055,2.4):e/12.92)+.3576*(n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92)+.1805*(i=i>.04045?Math.pow((i+.055)/1.055,2.4):i/12.92)),100*(.2126*e+.7152*n+.0722*i),100*(.0193*e+.1192*n+.9505*i)]}function d(t){var e,n,i,a=u(t),r=a[0],o=a[1],s=a[2];return r/=95.047,o/=100,s/=108.883,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,s=s>.008856?Math.pow(s,1/3):7.787*s+16/116,e=116*o-16,n=500*(r-o),i=200*(o-s),[e,n,i]}function c(t){var e,n,i,a,r,o=t[0]/360,s=t[1]/100,l=t[2]/100;if(0==s)return r=255*l,[r,r,r];e=2*l-(n=l<.5?l*(1+s):l+s-l*s),a=[0,0,0];for(var u=0;u<3;u++)(i=o+1/3*-(u-1))<0&&i++,i>1&&i--,r=6*i<1?e+6*(n-e)*i:2*i<1?n:3*i<2?e+(n-e)*(2/3-i)*6:e,a[u]=255*r;return a}function h(t){var e=t[0]/60,n=t[1]/100,i=t[2]/100,a=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-n),s=255*i*(1-n*r),l=255*i*(1-n*(1-r)),i=255*i;switch(a){case 0:return[i,l,o];case 1:return[s,i,o];case 2:return[o,i,l];case 3:return[o,s,i];case 4:return[l,o,i];case 5:return[i,o,s]}}function f(t){var e,n,i,a,o=t[0]/360,s=t[1]/100,l=t[2]/100,u=s+l;switch(u>1&&(s/=u,l/=u),e=Math.floor(6*o),n=1-l,i=6*o-e,0!=(1&e)&&(i=1-i),a=s+i*(n-s),e){default:case 6:case 0:r=n,g=a,b=s;break;case 1:r=a,g=n,b=s;break;case 2:r=s,g=n,b=a;break;case 3:r=s,g=a,b=n;break;case 4:r=a,g=s,b=n;break;case 5:r=n,g=s,b=a}return[255*r,255*g,255*b]}function m(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100,s=t[3]/100;return e=1-Math.min(1,a*(1-s)+s),n=1-Math.min(1,r*(1-s)+s),i=1-Math.min(1,o*(1-s)+s),[255*e,255*n,255*i]}function p(t){var e,n,i,a=t[0]/100,r=t[1]/100,o=t[2]/100;return e=3.2406*a+-1.5372*r+-.4986*o,n=-.9689*a+1.8758*r+.0415*o,i=.0557*a+-.204*r+1.057*o,e=e>.0031308?1.055*Math.pow(e,1/2.4)-.055:e*=12.92,n=n>.0031308?1.055*Math.pow(n,1/2.4)-.055:n*=12.92,i=i>.0031308?1.055*Math.pow(i,1/2.4)-.055:i*=12.92,e=Math.min(Math.max(0,e),1),n=Math.min(Math.max(0,n),1),i=Math.min(Math.max(0,i),1),[255*e,255*n,255*i]}function v(t){var e,n,i,a=t[0],r=t[1],o=t[2];return a/=95.047,r/=100,o/=108.883,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,r=r>.008856?Math.pow(r,1/3):7.787*r+16/116,o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,e=116*r-16,n=500*(a-r),i=200*(r-o),[e,n,i]}function y(t){var e,n,i,a,r=t[0],o=t[1],s=t[2];return r<=8?a=(n=100*r/903.3)/100*7.787+16/116:(n=100*Math.pow((r+16)/116,3),a=Math.pow(n/100,1/3)),e=e/95.047<=.008856?e=95.047*(o/500+a-16/116)/7.787:95.047*Math.pow(o/500+a,3),i=i/108.883<=.008859?i=108.883*(a-s/200-16/116)/7.787:108.883*Math.pow(a-s/200,3),[e,n,i]}function x(t){var e,n,i,a=t[0],r=t[1],o=t[2];return e=Math.atan2(o,r),(n=360*e/2/Math.PI)<0&&(n+=360),i=Math.sqrt(r*r+o*o),[a,i,n]}function _(t){return p(y(t))}function k(t){var e,n,i,a=t[0],r=t[1];return i=t[2]/360*2*Math.PI,e=r*Math.cos(i),n=r*Math.sin(i),[a,e,n]}function w(t){return M[t]}e.exports={rgb2hsl:i,rgb2hsv:a,rgb2hwb:o,rgb2cmyk:s,rgb2keyword:l,rgb2xyz:u,rgb2lab:d,rgb2lch:function(t){return x(d(t))},hsl2rgb:c,hsl2hsv:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return 0===r?[0,0,0]:(r*=2,a*=r<=1?r:2-r,n=(r+a)/2,e=2*a/(r+a),[i,100*e,100*n])},hsl2hwb:function(t){return o(c(t))},hsl2cmyk:function(t){return s(c(t))},hsl2keyword:function(t){return l(c(t))},hsv2rgb:h,hsv2hsl:function(t){var e,n,i=t[0],a=t[1]/100,r=t[2]/100;return n=(2-a)*r,e=a*r,e/=n<=1?n:2-n,e=e||0,n/=2,[i,100*e,100*n]},hsv2hwb:function(t){return o(h(t))},hsv2cmyk:function(t){return s(h(t))},hsv2keyword:function(t){return l(h(t))},hwb2rgb:f,hwb2hsl:function(t){return i(f(t))},hwb2hsv:function(t){return a(f(t))},hwb2cmyk:function(t){return s(f(t))},hwb2keyword:function(t){return l(f(t))},cmyk2rgb:m,cmyk2hsl:function(t){return i(m(t))},cmyk2hsv:function(t){return a(m(t))},cmyk2hwb:function(t){return o(m(t))},cmyk2keyword:function(t){return l(m(t))},keyword2rgb:w,keyword2hsl:function(t){return i(w(t))},keyword2hsv:function(t){return a(w(t))},keyword2hwb:function(t){return o(w(t))},keyword2cmyk:function(t){return s(w(t))},keyword2lab:function(t){return d(w(t))},keyword2xyz:function(t){return u(w(t))},xyz2rgb:p,xyz2lab:v,xyz2lch:function(t){return x(v(t))},lab2xyz:y,lab2rgb:_,lab2lch:x,lch2lab:k,lch2xyz:function(t){return y(k(t))},lch2rgb:function(t){return _(k(t))}};var M={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},S={};for(var D in M)S[JSON.stringify(M[D])]=D},{}],4:[function(t,e,n){var i=t(3),a=function(){return new u};for(var r in i){a[r+"Raw"]=function(t){return function(e){return"number"==typeof e&&(e=Array.prototype.slice.call(arguments)),i[t](e)}}(r);var o=/(\w+)2(\w+)/.exec(r),s=o[1],l=o[2];(a[s]=a[s]||{})[l]=a[r]=function(t){return function(e){"number"==typeof e&&(e=Array.prototype.slice.call(arguments));var n=i[t](e);if("string"==typeof n||void 0===n)return n;for(var a=0;a0)for(n=0;n=0?n?"+":"":"-")+Math.pow(10,Math.max(0,a)).toString().substr(1)+i}function N(t,e,n,i){var a=i;"string"==typeof i&&(a=function(){return this[i]()}),t&&(Re[t]=a),e&&(Re[e[0]]=function(){return Y(a.apply(this,arguments),e[1],e[2])}),n&&(Re[n]=function(){return this.localeData().ordinal(a.apply(this,arguments),t)})}function z(t){return t.match(/\[[\s\S]/)?t.replace(/^\[|\]$/g,""):t.replace(/\\/g,"")}function B(t){var e,n,i=t.match(Ie);for(e=0,n=i.length;e=0&&Oe.test(t);)t=t.replace(Oe,function(t){return e.longDateFormat(t)||t}),Oe.lastIndex=0,n-=1;return t}function E(t,e,n){Ke[t]=D(e)?e:function(t,i){return t&&n?n:e}}function j(t,e){return d(Ke,t)?Ke[t](e._strict,e._locale):new RegExp(U(t))}function U(t){return q(t.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(t,e,n,i,a){return e||n||i||a}))}function q(t){return t.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function G(t,e){var n,i=e;for("string"==typeof t&&(t=[t]),s(e)&&(i=function(t,n){n[e]=_(t)}),n=0;n=0&&isFinite(s.getFullYear())&&s.setFullYear(t),s}function at(t){var e=new Date(Date.UTC.apply(null,arguments));return t<100&&t>=0&&isFinite(e.getUTCFullYear())&&e.setUTCFullYear(t),e}function rt(t,e,n){var i=7+e-n;return-((7+at(t,0,i).getUTCDay()-e)%7)+i-1}function ot(t,e,n,i,a){var r,o,s=1+7*(e-1)+(7+n-i)%7+rt(t,i,a);return s<=0?o=et(r=t-1)+s:s>et(t)?(r=t+1,o=s-et(t)):(r=t,o=s),{year:r,dayOfYear:o}}function st(t,e,n){var i,a,r=rt(t.year(),e,n),o=Math.floor((t.dayOfYear()-r-1)/7)+1;return o<1?i=o+lt(a=t.year()-1,e,n):o>lt(t.year(),e,n)?(i=o-lt(t.year(),e,n),a=t.year()+1):(a=t.year(),i=o),{week:i,year:a}}function lt(t,e,n){var i=rt(t,e,n),a=rt(t+1,e,n);return(et(t)-i+a)/7}function ut(t,e){return"string"!=typeof t?t:isNaN(t)?"number"==typeof(t=e.weekdaysParse(t))?t:null:parseInt(t,10)}function dt(t,e){return"string"==typeof t?e.weekdaysParse(t)%7||7:isNaN(t)?null:t}function ct(t,e,n){var i,a,r,o=t.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],i=0;i<7;++i)r=h([2e3,1]).day(i),this._minWeekdaysParse[i]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[i]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[i]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===e?-1!==(a=un.call(this._weekdaysParse,o))?a:null:"ddd"===e?-1!==(a=un.call(this._shortWeekdaysParse,o))?a:null:-1!==(a=un.call(this._minWeekdaysParse,o))?a:null:"dddd"===e?-1!==(a=un.call(this._weekdaysParse,o))?a:-1!==(a=un.call(this._shortWeekdaysParse,o))?a:-1!==(a=un.call(this._minWeekdaysParse,o))?a:null:"ddd"===e?-1!==(a=un.call(this._shortWeekdaysParse,o))?a:-1!==(a=un.call(this._weekdaysParse,o))?a:-1!==(a=un.call(this._minWeekdaysParse,o))?a:null:-1!==(a=un.call(this._minWeekdaysParse,o))?a:-1!==(a=un.call(this._weekdaysParse,o))?a:-1!==(a=un.call(this._shortWeekdaysParse,o))?a:null}function ht(){function t(t,e){return e.length-t.length}var e,n,i,a,r,o=[],s=[],l=[],u=[];for(e=0;e<7;e++)n=h([2e3,1]).day(e),i=this.weekdaysMin(n,""),a=this.weekdaysShort(n,""),r=this.weekdays(n,""),o.push(i),s.push(a),l.push(r),u.push(i),u.push(a),u.push(r);for(o.sort(t),s.sort(t),l.sort(t),u.sort(t),e=0;e<7;e++)s[e]=q(s[e]),l[e]=q(l[e]),u[e]=q(u[e]);this._weekdaysRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+o.join("|")+")","i")}function ft(){return this.hours()%12||12}function gt(t,e){N(t,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),e)})}function mt(t,e){return e._meridiemParse}function pt(t){return t?t.toLowerCase().replace("_","-"):t}function vt(t){for(var e,n,i,a,r=0;r0;){if(i=yt(a.slice(0,e).join("-")))return i;if(n&&n.length>=e&&k(a,n,!0)>=e-1)break;e--}r++}return null}function yt(n){var i=null;if(!Sn[n]&&void 0!==e&&e&&e.exports)try{i=kn._abbr,t("./locale/"+n),bt(i)}catch(t){}return Sn[n]}function bt(t,e){var n;return t&&(n=o(e)?_t(t):xt(t,e))&&(kn=n),kn._abbr}function xt(t,e){if(null!==e){var n=Mn;if(e.abbr=t,null!=Sn[t])S("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),n=Sn[t]._config;else if(null!=e.parentLocale){if(null==Sn[e.parentLocale])return Dn[e.parentLocale]||(Dn[e.parentLocale]=[]),Dn[e.parentLocale].push({name:t,config:e}),null;n=Sn[e.parentLocale]._config}return Sn[t]=new P(C(n,e)),Dn[t]&&Dn[t].forEach(function(t){xt(t.name,t.config)}),bt(t),Sn[t]}return delete Sn[t],null}function _t(t){var e;if(t&&t._locale&&t._locale._abbr&&(t=t._locale._abbr),!t)return kn;if(!i(t)){if(e=yt(t))return e;t=[t]}return vt(t)}function kt(t){var e,n=t._a;return n&&-2===g(t).overflow&&(e=n[tn]<0||n[tn]>11?tn:n[en]<1||n[en]>J(n[$e],n[tn])?en:n[nn]<0||n[nn]>24||24===n[nn]&&(0!==n[an]||0!==n[rn]||0!==n[on])?nn:n[an]<0||n[an]>59?an:n[rn]<0||n[rn]>59?rn:n[on]<0||n[on]>999?on:-1,g(t)._overflowDayOfYear&&(e<$e||e>en)&&(e=en),g(t)._overflowWeeks&&-1===e&&(e=sn),g(t)._overflowWeekday&&-1===e&&(e=ln),g(t).overflow=e),t}function wt(t){var e,n,i,a,r,o,s=t._i,l=Cn.exec(s)||Pn.exec(s);if(l){for(g(t).iso=!0,e=0,n=An.length;e10?"YYYY ":"YY "),r="HH:mm"+(n[4]?":ss":""),n[1]){var d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][new Date(n[2]).getDay()];if(n[1].substr(0,3)!==d)return g(t).weekdayMismatch=!0,void(t._isValid=!1)}switch(n[5].length){case 2:s=0===l?" +0000":((l="YXWVUTSRQPONZABCDEFGHIKLM".indexOf(n[5][1].toUpperCase())-12)<0?" -":" +")+(""+l).replace(/^-?/,"0").match(/..$/)[0]+"00";break;case 4:s=u[n[5]];break;default:s=u[" GMT"]}n[5]=s,t._i=n.splice(1).join(""),o=" ZZ",t._f=i+a+r+o,At(t),g(t).rfc2822=!0}else t._isValid=!1}function St(t){var e=On.exec(t._i);null===e?(wt(t),!1===t._isValid&&(delete t._isValid,Mt(t),!1===t._isValid&&(delete t._isValid,n.createFromInputFallback(t)))):t._d=new Date(+e[1])}function Dt(t,e,n){return null!=t?t:null!=e?e:n}function Ct(t){var e=new Date(n.now());return t._useUTC?[e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate()]:[e.getFullYear(),e.getMonth(),e.getDate()]}function Pt(t){var e,n,i,a,r=[];if(!t._d){for(i=Ct(t),t._w&&null==t._a[en]&&null==t._a[tn]&&Tt(t),null!=t._dayOfYear&&(a=Dt(t._a[$e],i[$e]),(t._dayOfYear>et(a)||0===t._dayOfYear)&&(g(t)._overflowDayOfYear=!0),n=at(a,0,t._dayOfYear),t._a[tn]=n.getUTCMonth(),t._a[en]=n.getUTCDate()),e=0;e<3&&null==t._a[e];++e)t._a[e]=r[e]=i[e];for(;e<7;e++)t._a[e]=r[e]=null==t._a[e]?2===e?1:0:t._a[e];24===t._a[nn]&&0===t._a[an]&&0===t._a[rn]&&0===t._a[on]&&(t._nextDay=!0,t._a[nn]=0),t._d=(t._useUTC?at:it).apply(null,r),null!=t._tzm&&t._d.setUTCMinutes(t._d.getUTCMinutes()-t._tzm),t._nextDay&&(t._a[nn]=24)}}function Tt(t){var e,n,i,a,r,o,s,l;if(null!=(e=t._w).GG||null!=e.W||null!=e.E)r=1,o=4,n=Dt(e.GG,t._a[$e],st(Nt(),1,4).year),i=Dt(e.W,1),((a=Dt(e.E,1))<1||a>7)&&(l=!0);else{r=t._locale._week.dow,o=t._locale._week.doy;var u=st(Nt(),r,o);n=Dt(e.gg,t._a[$e],u.year),i=Dt(e.w,u.week),null!=e.d?((a=e.d)<0||a>6)&&(l=!0):null!=e.e?(a=e.e+r,(e.e<0||e.e>6)&&(l=!0)):a=r}i<1||i>lt(n,r,o)?g(t)._overflowWeeks=!0:null!=l?g(t)._overflowWeekday=!0:(s=ot(n,i,a,r,o),t._a[$e]=s.year,t._dayOfYear=s.dayOfYear)}function At(t){if(t._f!==n.ISO_8601)if(t._f!==n.RFC_2822){t._a=[],g(t).empty=!0;var e,i,a,r,o,s=""+t._i,l=s.length,u=0;for(a=H(t._f,t._locale).match(Ie)||[],e=0;e0&&g(t).unusedInput.push(o),s=s.slice(s.indexOf(i)+i.length),u+=i.length),Re[r]?(i?g(t).empty=!1:g(t).unusedTokens.push(r),X(r,i,t)):t._strict&&!i&&g(t).unusedTokens.push(r);g(t).charsLeftOver=l-u,s.length>0&&g(t).unusedInput.push(s),t._a[nn]<=12&&!0===g(t).bigHour&&t._a[nn]>0&&(g(t).bigHour=void 0),g(t).parsedDateParts=t._a.slice(0),g(t).meridiem=t._meridiem,t._a[nn]=It(t._locale,t._a[nn],t._meridiem),Pt(t),kt(t)}else Mt(t);else wt(t)}function It(t,e,n){var i;return null==n?e:null!=t.meridiemHour?t.meridiemHour(e,n):null!=t.isPM?((i=t.isPM(n))&&e<12&&(e+=12),i||12!==e||(e=0),e):e}function Ot(t){var e,n,i,a,r;if(0===t._f.length)return g(t).invalidFormat=!0,void(t._d=new Date(NaN));for(a=0;ar&&(e=r),oe.call(this,t,e,n,i,a))}function oe(t,e,n,i,a){var r=ot(t,e,n,i,a),o=at(r.year,0,r.dayOfYear);return this.year(o.getUTCFullYear()),this.month(o.getUTCMonth()),this.date(o.getUTCDate()),this}function se(t){return t}function le(t,e,n,i){var a=_t(),r=h().set(i,e);return a[n](r,t)}function ue(t,e,n){if(s(t)&&(e=t,t=void 0),t=t||"",null!=e)return le(t,e,n,"month");var i,a=[];for(i=0;i<12;i++)a[i]=le(t,i,n,"month");return a}function de(t,e,n,i){"boolean"==typeof t?(s(e)&&(n=e,e=void 0),e=e||""):(n=e=t,t=!1,s(e)&&(n=e,e=void 0),e=e||"");var a=_t(),r=t?a._week.dow:0;if(null!=n)return le(e,(n+r)%7,i,"day");var o,l=[];for(o=0;o<7;o++)l[o]=le(e,(o+r)%7,i,"day");return l}function ce(t,e,n,i){var a=Xt(e,n);return t._milliseconds+=i*a._milliseconds,t._days+=i*a._days,t._months+=i*a._months,t._bubble()}function he(t){return t<0?Math.floor(t):Math.ceil(t)}function fe(t){return 4800*t/146097}function ge(t){return 146097*t/4800}function me(t){return function(){return this.as(t)}}function pe(t){return function(){return this.isValid()?this._data[t]:NaN}}function ve(t,e,n,i,a){return a.relativeTime(e||1,!!n,t,i)}function ye(t,e,n){var i=Xt(t).abs(),a=hi(i.as("s")),r=hi(i.as("m")),o=hi(i.as("h")),s=hi(i.as("d")),l=hi(i.as("M")),u=hi(i.as("y")),d=a<=fi.ss&&["s",a]||a0,d[4]=n,ve.apply(null,d)}function be(){if(!this.isValid())return this.localeData().invalidDate();var t,e,n,i=gi(this._milliseconds)/1e3,a=gi(this._days),r=gi(this._months);e=x((t=x(i/60))/60),i%=60,t%=60;var o=n=x(r/12),s=r%=12,l=a,u=e,d=t,c=i,h=this.asSeconds();return h?(h<0?"-":"")+"P"+(o?o+"Y":"")+(s?s+"M":"")+(l?l+"D":"")+(u||d||c?"T":"")+(u?u+"H":"")+(d?d+"M":"")+(c?c+"S":""):"P0D"}var xe,_e,ke=_e=Array.prototype.some?Array.prototype.some:function(t){for(var e=Object(this),n=e.length>>>0,i=0;i68?1900:2e3)};var mn=R("FullYear",!0);N("w",["ww",2],"wo","week"),N("W",["WW",2],"Wo","isoWeek"),T("week","w"),T("isoWeek","W"),O("week",5),O("isoWeek",5),E("w",Be),E("ww",Be,We),E("W",Be),E("WW",Be,We),Z(["w","ww","W","WW"],function(t,e,n,i){e[i.substr(0,1)]=_(t)});N("d",0,"do","day"),N("dd",0,0,function(t){return this.localeData().weekdaysMin(this,t)}),N("ddd",0,0,function(t){return this.localeData().weekdaysShort(this,t)}),N("dddd",0,0,function(t){return this.localeData().weekdays(this,t)}),N("e",0,0,"weekday"),N("E",0,0,"isoWeekday"),T("day","d"),T("weekday","e"),T("isoWeekday","E"),O("day",11),O("weekday",11),O("isoWeekday",11),E("d",Be),E("e",Be),E("E",Be),E("dd",function(t,e){return e.weekdaysMinRegex(t)}),E("ddd",function(t,e){return e.weekdaysShortRegex(t)}),E("dddd",function(t,e){return e.weekdaysRegex(t)}),Z(["dd","ddd","dddd"],function(t,e,n,i){var a=n._locale.weekdaysParse(t,i,n._strict);null!=a?e.d=a:g(n).invalidWeekday=t}),Z(["d","e","E"],function(t,e,n,i){e[i]=_(t)});var pn="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),vn="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),yn="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),bn=Je,xn=Je,_n=Je;N("H",["HH",2],0,"hour"),N("h",["hh",2],0,ft),N("k",["kk",2],0,function(){return this.hours()||24}),N("hmm",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)}),N("hmmss",0,0,function(){return""+ft.apply(this)+Y(this.minutes(),2)+Y(this.seconds(),2)}),N("Hmm",0,0,function(){return""+this.hours()+Y(this.minutes(),2)}),N("Hmmss",0,0,function(){return""+this.hours()+Y(this.minutes(),2)+Y(this.seconds(),2)}),gt("a",!0),gt("A",!1),T("hour","h"),O("hour",13),E("a",mt),E("A",mt),E("H",Be),E("h",Be),E("k",Be),E("HH",Be,We),E("hh",Be,We),E("kk",Be,We),E("hmm",Ve),E("hmmss",He),E("Hmm",Ve),E("Hmmss",He),G(["H","HH"],nn),G(["k","kk"],function(t,e,n){var i=_(t);e[nn]=24===i?0:i}),G(["a","A"],function(t,e,n){n._isPm=n._locale.isPM(t),n._meridiem=t}),G(["h","hh"],function(t,e,n){e[nn]=_(t),g(n).bigHour=!0}),G("hmm",function(t,e,n){var i=t.length-2;e[nn]=_(t.substr(0,i)),e[an]=_(t.substr(i)),g(n).bigHour=!0}),G("hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[nn]=_(t.substr(0,i)),e[an]=_(t.substr(i,2)),e[rn]=_(t.substr(a)),g(n).bigHour=!0}),G("Hmm",function(t,e,n){var i=t.length-2;e[nn]=_(t.substr(0,i)),e[an]=_(t.substr(i))}),G("Hmmss",function(t,e,n){var i=t.length-4,a=t.length-2;e[nn]=_(t.substr(0,i)),e[an]=_(t.substr(i,2)),e[rn]=_(t.substr(a))});var kn,wn=R("Hours",!0),Mn={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:cn,monthsShort:hn,week:{dow:0,doy:6},weekdays:pn,weekdaysMin:yn,weekdaysShort:vn,meridiemParse:/[ap]\.?m?\.?/i},Sn={},Dn={},Cn=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Pn=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/,Tn=/Z|[+-]\d\d(?::?\d\d)?/,An=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],In=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],On=/^\/?Date\((\-?\d+)/i,Fn=/^((?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d?\d\s(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(?:\d\d)?\d\d\s)(\d\d:\d\d)(\:\d\d)?(\s(?:UT|GMT|[ECMP][SD]T|[A-IK-Za-ik-z]|[+-]\d{4}))$/;n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(t){t._d=new Date(t._i+(t._useUTC?" UTC":""))}),n.ISO_8601=function(){},n.RFC_2822=function(){};var Rn=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var t=Nt.apply(null,arguments);return this.isValid()&&t.isValid()?tthis?this:t:p()}),Wn=["year","quarter","month","week","day","hour","minute","second","millisecond"];jt("Z",":"),jt("ZZ",""),E("Z",Xe),E("ZZ",Xe),G(["Z","ZZ"],function(t,e,n){n._useUTC=!0,n._tzm=Ut(Xe,t)});var Yn=/([\+\-]|\d\d)/gi;n.updateOffset=function(){};var Nn=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,zn=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Xt.fn=Vt.prototype,Xt.invalid=function(){return Xt(NaN)};var Bn=$t(1,"add"),Vn=$t(-1,"subtract");n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Hn=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(t){return void 0===t?this.localeData():this.locale(t)});N(0,["gg",2],0,function(){return this.weekYear()%100}),N(0,["GG",2],0,function(){return this.isoWeekYear()%100}),ae("gggg","weekYear"),ae("ggggg","weekYear"),ae("GGGG","isoWeekYear"),ae("GGGGG","isoWeekYear"),T("weekYear","gg"),T("isoWeekYear","GG"),O("weekYear",1),O("isoWeekYear",1),E("G",Ge),E("g",Ge),E("GG",Be,We),E("gg",Be,We),E("GGGG",je,Ne),E("gggg",je,Ne),E("GGGGG",Ue,ze),E("ggggg",Ue,ze),Z(["gggg","ggggg","GGGG","GGGGG"],function(t,e,n,i){e[i.substr(0,2)]=_(t)}),Z(["gg","GG"],function(t,e,i,a){e[a]=n.parseTwoDigitYear(t)}),N("Q",0,"Qo","quarter"),T("quarter","Q"),O("quarter",7),E("Q",Le),G("Q",function(t,e){e[tn]=3*(_(t)-1)}),N("D",["DD",2],"Do","date"),T("date","D"),O("date",9),E("D",Be),E("DD",Be,We),E("Do",function(t,e){return t?e._dayOfMonthOrdinalParse||e._ordinalParse:e._dayOfMonthOrdinalParseLenient}),G(["D","DD"],en),G("Do",function(t,e){e[en]=_(t.match(Be)[0],10)});var En=R("Date",!0);N("DDD",["DDDD",3],"DDDo","dayOfYear"),T("dayOfYear","DDD"),O("dayOfYear",4),E("DDD",Ee),E("DDDD",Ye),G(["DDD","DDDD"],function(t,e,n){n._dayOfYear=_(t)}),N("m",["mm",2],0,"minute"),T("minute","m"),O("minute",14),E("m",Be),E("mm",Be,We),G(["m","mm"],an);var jn=R("Minutes",!1);N("s",["ss",2],0,"second"),T("second","s"),O("second",15),E("s",Be),E("ss",Be,We),G(["s","ss"],rn);var Un=R("Seconds",!1);N("S",0,0,function(){return~~(this.millisecond()/100)}),N(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),N(0,["SSS",3],0,"millisecond"),N(0,["SSSS",4],0,function(){return 10*this.millisecond()}),N(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),N(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),N(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),N(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),N(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),T("millisecond","ms"),O("millisecond",16),E("S",Ee,Le),E("SS",Ee,We),E("SSS",Ee,Ye);var qn;for(qn="SSSS";qn.length<=9;qn+="S")E(qn,qe);for(qn="S";qn.length<=9;qn+="S")G(qn,function(t,e){e[on]=_(1e3*("0."+t))});var Gn=R("Milliseconds",!1);N("z",0,0,"zoneAbbr"),N("zz",0,0,"zoneName");var Zn=y.prototype;Zn.add=Bn,Zn.calendar=function(t,e){var i=t||Nt(),a=qt(i,this).startOf("day"),r=n.calendarFormat(this,a)||"sameElse",o=e&&(D(e[r])?e[r].call(this,i):e[r]);return this.format(o||this.localeData().calendar(r,this,Nt(i)))},Zn.clone=function(){return new y(this)},Zn.diff=function(t,e,n){var i,a,r,o;return this.isValid()&&(i=qt(t,this)).isValid()?(a=6e4*(i.utcOffset()-this.utcOffset()),"year"===(e=A(e))||"month"===e||"quarter"===e?(o=ee(this,i),"quarter"===e?o/=3:"year"===e&&(o/=12)):(r=this-i,o="second"===e?r/1e3:"minute"===e?r/6e4:"hour"===e?r/36e5:"day"===e?(r-a)/864e5:"week"===e?(r-a)/6048e5:r),n?o:x(o)):NaN},Zn.endOf=function(t){return void 0===(t=A(t))||"millisecond"===t?this:("date"===t&&(t="day"),this.startOf(t).add(1,"isoWeek"===t?"week":t).subtract(1,"ms"))},Zn.format=function(t){t||(t=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var e=V(this,t);return this.localeData().postformat(e)},Zn.from=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({to:this,from:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Zn.fromNow=function(t){return this.from(Nt(),t)},Zn.to=function(t,e){return this.isValid()&&(b(t)&&t.isValid()||Nt(t).isValid())?Xt({from:this,to:t}).locale(this.locale()).humanize(!e):this.localeData().invalidDate()},Zn.toNow=function(t){return this.to(Nt(),t)},Zn.get=function(t){return t=A(t),D(this[t])?this[t]():this},Zn.invalidAt=function(){return g(this).overflow},Zn.isAfter=function(t,e){var n=b(t)?t:Nt(t);return!(!this.isValid()||!n.isValid())&&("millisecond"===(e=A(o(e)?"millisecond":e))?this.valueOf()>n.valueOf():n.valueOf()9999?V(t,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):D(Date.prototype.toISOString)?this.toDate().toISOString():V(t,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},Zn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var t="moment",e="";this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",e="Z");var n="["+t+'("]',i=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",a=e+'[")]';return this.format(n+i+"-MM-DD[T]HH:mm:ss.SSS"+a)},Zn.toJSON=function(){return this.isValid()?this.toISOString():null},Zn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},Zn.unix=function(){return Math.floor(this.valueOf()/1e3)},Zn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},Zn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},Zn.year=mn,Zn.isLeapYear=function(){return nt(this.year())},Zn.weekYear=function(t){return re.call(this,t,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},Zn.isoWeekYear=function(t){return re.call(this,t,this.isoWeek(),this.isoWeekday(),1,4)},Zn.quarter=Zn.quarters=function(t){return null==t?Math.ceil((this.month()+1)/3):this.month(3*(t-1)+this.month()%3)},Zn.month=$,Zn.daysInMonth=function(){return J(this.year(),this.month())},Zn.week=Zn.weeks=function(t){var e=this.localeData().week(this);return null==t?e:this.add(7*(t-e),"d")},Zn.isoWeek=Zn.isoWeeks=function(t){var e=st(this,1,4).week;return null==t?e:this.add(7*(t-e),"d")},Zn.weeksInYear=function(){var t=this.localeData()._week;return lt(this.year(),t.dow,t.doy)},Zn.isoWeeksInYear=function(){return lt(this.year(),1,4)},Zn.date=En,Zn.day=Zn.days=function(t){if(!this.isValid())return null!=t?this:NaN;var e=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=t?(t=ut(t,this.localeData()),this.add(t-e,"d")):e},Zn.weekday=function(t){if(!this.isValid())return null!=t?this:NaN;var e=(this.day()+7-this.localeData()._week.dow)%7;return null==t?e:this.add(t-e,"d")},Zn.isoWeekday=function(t){if(!this.isValid())return null!=t?this:NaN;if(null!=t){var e=dt(t,this.localeData());return this.day(this.day()%7?e:e-7)}return this.day()||7},Zn.dayOfYear=function(t){var e=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==t?e:this.add(t-e,"d")},Zn.hour=Zn.hours=wn,Zn.minute=Zn.minutes=jn,Zn.second=Zn.seconds=Un,Zn.millisecond=Zn.milliseconds=Gn,Zn.utcOffset=function(t,e,i){var a,r=this._offset||0;if(!this.isValid())return null!=t?this:NaN;if(null!=t){if("string"==typeof t){if(null===(t=Ut(Xe,t)))return this}else Math.abs(t)<16&&!i&&(t*=60);return!this._isUTC&&e&&(a=Gt(this)),this._offset=t,this._isUTC=!0,null!=a&&this.add(a,"m"),r!==t&&(!e||this._changeInProgress?te(this,Xt(t-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Gt(this)},Zn.utc=function(t){return this.utcOffset(0,t)},Zn.local=function(t){return this._isUTC&&(this.utcOffset(0,t),this._isUTC=!1,t&&this.subtract(Gt(this),"m")),this},Zn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var t=Ut(Ze,this._i);null!=t?this.utcOffset(t):this.utcOffset(0,!0)}return this},Zn.hasAlignedHourOffset=function(t){return!!this.isValid()&&(t=t?Nt(t).utcOffset():0,(this.utcOffset()-t)%60==0)},Zn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},Zn.isLocal=function(){return!!this.isValid()&&!this._isUTC},Zn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},Zn.isUtc=Zt,Zn.isUTC=Zt,Zn.zoneAbbr=function(){return this._isUTC?"UTC":""},Zn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},Zn.dates=M("dates accessor is deprecated. Use date instead.",En),Zn.months=M("months accessor is deprecated. Use month instead",$),Zn.years=M("years accessor is deprecated. Use year instead",mn),Zn.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(t,e){return null!=t?("string"!=typeof t&&(t=-t),this.utcOffset(t,e),this):-this.utcOffset()}),Zn.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var t={};if(v(t,this),(t=Lt(t))._a){var e=t._isUTC?h(t._a):Nt(t._a);this._isDSTShifted=this.isValid()&&k(t._a,e.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted});var Xn=P.prototype;Xn.calendar=function(t,e,n){var i=this._calendar[t]||this._calendar.sameElse;return D(i)?i.call(e,n):i},Xn.longDateFormat=function(t){var e=this._longDateFormat[t],n=this._longDateFormat[t.toUpperCase()];return e||!n?e:(this._longDateFormat[t]=n.replace(/MMMM|MM|DD|dddd/g,function(t){return t.slice(1)}),this._longDateFormat[t])},Xn.invalidDate=function(){return this._invalidDate},Xn.ordinal=function(t){return this._ordinal.replace("%d",t)},Xn.preparse=se,Xn.postformat=se,Xn.relativeTime=function(t,e,n,i){var a=this._relativeTime[n];return D(a)?a(t,e,n,i):a.replace(/%d/i,t)},Xn.pastFuture=function(t,e){var n=this._relativeTime[t>0?"future":"past"];return D(n)?n(e):n.replace(/%s/i,e)},Xn.set=function(t){var e,n;for(n in t)D(e=t[n])?this[n]=e:this["_"+n]=e;this._config=t,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},Xn.months=function(t,e){return t?i(this._months)?this._months[t.month()]:this._months[(this._months.isFormat||dn).test(e)?"format":"standalone"][t.month()]:i(this._months)?this._months:this._months.standalone},Xn.monthsShort=function(t,e){return t?i(this._monthsShort)?this._monthsShort[t.month()]:this._monthsShort[dn.test(e)?"format":"standalone"][t.month()]:i(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},Xn.monthsParse=function(t,e,n){var i,a,r;if(this._monthsParseExact)return K.call(this,t,e,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),i=0;i<12;i++){if(a=h([2e3,i]),n&&!this._longMonthsParse[i]&&(this._longMonthsParse[i]=new RegExp("^"+this.months(a,"").replace(".","")+"$","i"),this._shortMonthsParse[i]=new RegExp("^"+this.monthsShort(a,"").replace(".","")+"$","i")),n||this._monthsParse[i]||(r="^"+this.months(a,"")+"|^"+this.monthsShort(a,""),this._monthsParse[i]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===e&&this._longMonthsParse[i].test(t))return i;if(n&&"MMM"===e&&this._shortMonthsParse[i].test(t))return i;if(!n&&this._monthsParse[i].test(t))return i}},Xn.monthsRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsStrictRegex:this._monthsRegex):(d(this,"_monthsRegex")||(this._monthsRegex=gn),this._monthsStrictRegex&&t?this._monthsStrictRegex:this._monthsRegex)},Xn.monthsShortRegex=function(t){return this._monthsParseExact?(d(this,"_monthsRegex")||tt.call(this),t?this._monthsShortStrictRegex:this._monthsShortRegex):(d(this,"_monthsShortRegex")||(this._monthsShortRegex=fn),this._monthsShortStrictRegex&&t?this._monthsShortStrictRegex:this._monthsShortRegex)},Xn.week=function(t){return st(t,this._week.dow,this._week.doy).week},Xn.firstDayOfYear=function(){return this._week.doy},Xn.firstDayOfWeek=function(){return this._week.dow},Xn.weekdays=function(t,e){return t?i(this._weekdays)?this._weekdays[t.day()]:this._weekdays[this._weekdays.isFormat.test(e)?"format":"standalone"][t.day()]:i(this._weekdays)?this._weekdays:this._weekdays.standalone},Xn.weekdaysMin=function(t){return t?this._weekdaysMin[t.day()]:this._weekdaysMin},Xn.weekdaysShort=function(t){return t?this._weekdaysShort[t.day()]:this._weekdaysShort},Xn.weekdaysParse=function(t,e,n){var i,a,r;if(this._weekdaysParseExact)return ct.call(this,t,e,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),i=0;i<7;i++){if(a=h([2e3,1]).day(i),n&&!this._fullWeekdaysParse[i]&&(this._fullWeekdaysParse[i]=new RegExp("^"+this.weekdays(a,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[i]=new RegExp("^"+this.weekdaysShort(a,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[i]=new RegExp("^"+this.weekdaysMin(a,"").replace(".",".?")+"$","i")),this._weekdaysParse[i]||(r="^"+this.weekdays(a,"")+"|^"+this.weekdaysShort(a,"")+"|^"+this.weekdaysMin(a,""),this._weekdaysParse[i]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===e&&this._fullWeekdaysParse[i].test(t))return i;if(n&&"ddd"===e&&this._shortWeekdaysParse[i].test(t))return i;if(n&&"dd"===e&&this._minWeekdaysParse[i].test(t))return i;if(!n&&this._weekdaysParse[i].test(t))return i}},Xn.weekdaysRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysStrictRegex:this._weekdaysRegex):(d(this,"_weekdaysRegex")||(this._weekdaysRegex=bn),this._weekdaysStrictRegex&&t?this._weekdaysStrictRegex:this._weekdaysRegex)},Xn.weekdaysShortRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(d(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=xn),this._weekdaysShortStrictRegex&&t?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},Xn.weekdaysMinRegex=function(t){return this._weekdaysParseExact?(d(this,"_weekdaysRegex")||ht.call(this),t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(d(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=_n),this._weekdaysMinStrictRegex&&t?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},Xn.isPM=function(t){return"p"===(t+"").toLowerCase().charAt(0)},Xn.meridiem=function(t,e,n){return t>11?n?"pm":"PM":n?"am":"AM"},bt("en",{dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(t){var e=t%10;return t+(1===_(t%100/10)?"th":1===e?"st":2===e?"nd":3===e?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",bt),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",_t);var Jn=Math.abs,Kn=me("ms"),Qn=me("s"),$n=me("m"),ti=me("h"),ei=me("d"),ni=me("w"),ii=me("M"),ai=me("y"),ri=pe("milliseconds"),oi=pe("seconds"),si=pe("minutes"),li=pe("hours"),ui=pe("days"),di=pe("months"),ci=pe("years"),hi=Math.round,fi={ss:44,s:45,m:45,h:22,d:26,M:11},gi=Math.abs,mi=Vt.prototype;return mi.isValid=function(){return this._isValid},mi.abs=function(){var t=this._data;return this._milliseconds=Jn(this._milliseconds),this._days=Jn(this._days),this._months=Jn(this._months),t.milliseconds=Jn(t.milliseconds),t.seconds=Jn(t.seconds),t.minutes=Jn(t.minutes),t.hours=Jn(t.hours),t.months=Jn(t.months),t.years=Jn(t.years),this},mi.add=function(t,e){return ce(this,t,e,1)},mi.subtract=function(t,e){return ce(this,t,e,-1)},mi.as=function(t){if(!this.isValid())return NaN;var e,n,i=this._milliseconds;if("month"===(t=A(t))||"year"===t)return e=this._days+i/864e5,n=this._months+fe(e),"month"===t?n:n/12;switch(e=this._days+Math.round(ge(this._months)),t){case"week":return e/7+i/6048e5;case"day":return e+i/864e5;case"hour":return 24*e+i/36e5;case"minute":return 1440*e+i/6e4;case"second":return 86400*e+i/1e3;case"millisecond":return Math.floor(864e5*e)+i;default:throw new Error("Unknown unit "+t)}},mi.asMilliseconds=Kn,mi.asSeconds=Qn,mi.asMinutes=$n,mi.asHours=ti,mi.asDays=ei,mi.asWeeks=ni,mi.asMonths=ii,mi.asYears=ai,mi.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*_(this._months/12):NaN},mi._bubble=function(){var t,e,n,i,a,r=this._milliseconds,o=this._days,s=this._months,l=this._data;return r>=0&&o>=0&&s>=0||r<=0&&o<=0&&s<=0||(r+=864e5*he(ge(s)+o),o=0,s=0),l.milliseconds=r%1e3,t=x(r/1e3),l.seconds=t%60,e=x(t/60),l.minutes=e%60,n=x(e/60),l.hours=n%24,o+=x(n/24),a=x(fe(o)),s+=a,o-=he(ge(a)),i=x(s/12),s%=12,l.days=o,l.months=s,l.years=i,this},mi.get=function(t){return t=A(t),this.isValid()?this[t+"s"]():NaN},mi.milliseconds=ri,mi.seconds=oi,mi.minutes=si,mi.hours=li,mi.days=ui,mi.weeks=function(){return x(this.days()/7)},mi.months=di,mi.years=ci,mi.humanize=function(t){if(!this.isValid())return this.localeData().invalidDate();var e=this.localeData(),n=ye(this,!t,e);return t&&(n=e.pastFuture(+this,n)),e.postformat(n)},mi.toISOString=be,mi.toString=be,mi.toJSON=be,mi.locale=ne,mi.localeData=ie,mi.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",be),mi.lang=Hn,N("X",0,0,"unix"),N("x",0,0,"valueOf"),E("x",Ge),E("X",/[+-]?\d+(\.\d{1,3})?/),G("X",function(t,e,n){n._d=new Date(1e3*parseFloat(t,10))}),G("x",function(t,e,n){n._d=new Date(_(t))}),n.version="2.18.1",function(t){xe=t}(Nt),n.fn=Zn,n.min=function(){return zt("isBefore",[].slice.call(arguments,0))},n.max=function(){return zt("isAfter",[].slice.call(arguments,0))},n.now=function(){return Date.now?Date.now():+new Date},n.utc=h,n.unix=function(t){return Nt(1e3*t)},n.months=function(t,e){return ue(t,e,"months")},n.isDate=l,n.locale=bt,n.invalid=p,n.duration=Xt,n.isMoment=b,n.weekdays=function(t,e,n){return de(t,e,n,"weekdays")},n.parseZone=function(){return Nt.apply(null,arguments).parseZone()},n.localeData=_t,n.isDuration=Ht,n.monthsShort=function(t,e){return ue(t,e,"monthsShort")},n.weekdaysMin=function(t,e,n){return de(t,e,n,"weekdaysMin")},n.defineLocale=xt,n.updateLocale=function(t,e){if(null!=e){var n,i=Mn;null!=Sn[t]&&(i=Sn[t]._config),(n=new P(e=C(i,e))).parentLocale=Sn[t],Sn[t]=n,bt(t)}else null!=Sn[t]&&(null!=Sn[t].parentLocale?Sn[t]=Sn[t].parentLocale:null!=Sn[t]&&delete Sn[t]);return Sn[t]},n.locales=function(){return Pe(Sn)},n.weekdaysShort=function(t,e,n){return de(t,e,n,"weekdaysShort")},n.normalizeUnits=A,n.relativeTimeRounding=function(t){return void 0===t?hi:"function"==typeof t&&(hi=t,!0)},n.relativeTimeThreshold=function(t,e){return void 0!==fi[t]&&(void 0===e?fi[t]:(fi[t]=e,"s"===t&&(fi.ss=e-1),!0))},n.calendarFormat=function(t,e){var n=t.diff(e,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=Zn,n})},{}],7:[function(t,e,n){var i=t(29)();i.helpers=t(45),t(27)(i),i.defaults=t(25),i.Element=t(26),i.elements=t(40),i.Interaction=t(28),i.platform=t(48),t(31)(i),t(22)(i),t(23)(i),t(24)(i),t(30)(i),t(33)(i),t(32)(i),t(35)(i),t(54)(i),t(52)(i),t(53)(i),t(55)(i),t(56)(i),t(57)(i),t(15)(i),t(16)(i),t(17)(i),t(18)(i),t(19)(i),t(20)(i),t(21)(i),t(8)(i),t(9)(i),t(10)(i),t(11)(i),t(12)(i),t(13)(i),t(14)(i);var a=[];a.push(t(49)(i),t(50)(i),t(51)(i)),i.plugins.register(a),i.platform.initialize(),e.exports=i,"undefined"!=typeof window&&(window.Chart=i),i.canvasHelpers=i.helpers.canvas},{10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,19:19,20:20,21:21,22:22,23:23,24:24,25:25,26:26,27:27,28:28,29:29,30:30,31:31,32:32,33:33,35:35,40:40,45:45,48:48,49:49,50:50,51:51,52:52,53:53,54:54,55:55,56:56,57:57,8:8,9:9}],8:[function(t,e,n){"use strict";e.exports=function(t){t.Bar=function(e,n){return n.type="bar",new t(e,n)}}},{}],9:[function(t,e,n){"use strict";e.exports=function(t){t.Bubble=function(e,n){return n.type="bubble",new t(e,n)}}},{}],10:[function(t,e,n){"use strict";e.exports=function(t){t.Doughnut=function(e,n){return n.type="doughnut",new t(e,n)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t){t.Line=function(e,n){return n.type="line",new t(e,n)}}},{}],12:[function(t,e,n){"use strict";e.exports=function(t){t.PolarArea=function(e,n){return n.type="polarArea",new t(e,n)}}},{}],13:[function(t,e,n){"use strict";e.exports=function(t){t.Radar=function(e,n){return n.type="radar",new t(e,n)}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t){t.Scatter=function(e,n){return n.type="scatter",new t(e,n)}}},{}],15:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("bar",{hover:{mode:"label"},scales:{xAxes:[{type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}],yAxes:[{type:"linear"}]}}),i._set("horizontalBar",{hover:{mode:"index",axis:"y"},scales:{xAxes:[{type:"linear",position:"bottom"}],yAxes:[{position:"left",type:"category",categoryPercentage:.8,barPercentage:.9,offset:!0,gridLines:{offsetGridLines:!0}}]},elements:{rectangle:{borderSkipped:"left"}},tooltips:{callbacks:{title:function(t,e){var n="";return t.length>0&&(t[0].yLabel?n=t[0].yLabel:e.labels.length>0&&t[0].index=0&&a>0)&&(p+=a));return r=c.getPixelForValue(p),o=c.getPixelForValue(p+f),s=(o-r)/2,{size:s,base:r,head:o,center:o+s/2}},calculateBarIndexPixels:function(t,e,n){var i,a,o,s,l,u,d=this,c=n.scale.options,h=d.getStackIndex(t),f=n.pixels,g=f[e],m=f.length,p=n.start,v=n.end;return 1===m?(i=g>p?g-p:v-g,a=g0&&(i=(g-f[e-1])/2,e===m-1&&(a=i)),e');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i],l=s&&s.custom||{},u=r.valueAtIndexOrDefault,d=t.options.elements.arc;return{text:n,fillStyle:l.backgroundColor?l.backgroundColor:u(o.backgroundColor,i,d.backgroundColor),strokeStyle:l.borderColor?l.borderColor:u(o.borderColor,i,d.borderColor),lineWidth:l.borderWidth?l.borderWidth:u(o.borderWidth,i,d.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n=Math.PI?-1:g<-Math.PI?1:0))+f,p={x:Math.cos(g),y:Math.sin(g)},v={x:Math.cos(m),y:Math.sin(m)},y=g<=0&&m>=0||g<=2*Math.PI&&2*Math.PI<=m,b=g<=.5*Math.PI&&.5*Math.PI<=m||g<=2.5*Math.PI&&2.5*Math.PI<=m,x=g<=-Math.PI&&-Math.PI<=m||g<=Math.PI&&Math.PI<=m,_=g<=.5*-Math.PI&&.5*-Math.PI<=m||g<=1.5*Math.PI&&1.5*Math.PI<=m,k=h/100,w={x:x?-1:Math.min(p.x*(p.x<0?1:k),v.x*(v.x<0?1:k)),y:_?-1:Math.min(p.y*(p.y<0?1:k),v.y*(v.y<0?1:k))},M={x:y?1:Math.max(p.x*(p.x>0?1:k),v.x*(v.x>0?1:k)),y:b?1:Math.max(p.y*(p.y>0?1:k),v.y*(v.y>0?1:k))},S={width:.5*(M.x-w.x),height:.5*(M.y-w.y)};u=Math.min(s/S.width,l/S.height),d={x:-.5*(M.x+w.x),y:-.5*(M.y+w.y)}}n.borderWidth=e.getMaxBorderWidth(c.data),n.outerRadius=Math.max((u-n.borderWidth)/2,0),n.innerRadius=Math.max(h?n.outerRadius/100*h:0,0),n.radiusLength=(n.outerRadius-n.innerRadius)/n.getVisibleDatasetCount(),n.offsetX=d.x*n.outerRadius,n.offsetY=d.y*n.outerRadius,c.total=e.calculateTotal(),e.outerRadius=n.outerRadius-n.radiusLength*e.getRingIndex(e.index),e.innerRadius=Math.max(e.outerRadius-n.radiusLength,0),r.each(c.data,function(n,i){e.updateElement(n,i,t)})},updateElement:function(t,e,n){var i=this,a=i.chart,o=a.chartArea,s=a.options,l=s.animation,u=(o.left+o.right)/2,d=(o.top+o.bottom)/2,c=s.rotation,h=s.rotation,f=i.getDataset(),g=n&&l.animateRotate?0:t.hidden?0:i.calculateCircumference(f.data[e])*(s.circumference/(2*Math.PI)),m=n&&l.animateScale?0:i.innerRadius,p=n&&l.animateScale?0:i.outerRadius,v=r.valueAtIndexOrDefault;r.extend(t,{_datasetIndex:i.index,_index:e,_model:{x:u+a.offsetX,y:d+a.offsetY,startAngle:c,endAngle:h,circumference:g,outerRadius:p,innerRadius:m,label:v(f.label,e,a.data.labels[e])}});var y=t._model;this.removeHoverStyle(t),n&&l.animateRotate||(y.startAngle=0===e?s.rotation:i.getMeta().data[e-1]._model.endAngle,y.endAngle=y.startAngle+y.circumference),t.pivot()},removeHoverStyle:function(e){t.DatasetController.prototype.removeHoverStyle.call(this,e,this.chart.options.elements.arc)},calculateTotal:function(){var t,e=this.getDataset(),n=this.getMeta(),i=0;return r.each(n.data,function(n,a){t=e.data[a],isNaN(t)||n.hidden||(i+=Math.abs(t))}),i},calculateCircumference:function(t){var e=this.getMeta().total;return e>0&&!isNaN(t)?2*Math.PI*(t/e):0},getMaxBorderWidth:function(t){for(var e,n,i=0,a=this.index,r=t.length,o=0;o(i=e>i?e:i)?n:i;return i}})}},{25:25,40:40,45:45}],18:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("line",{showLines:!0,spanGaps:!1,hover:{mode:"label"},scales:{xAxes:[{type:"category",id:"x-axis-0"}],yAxes:[{type:"linear",id:"y-axis-0"}]}}),e.exports=function(t){function e(t,e){return r.valueOrDefault(t.showLine,e.showLines)}t.controllers.line=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,update:function(t){var n,i,a,o=this,s=o.getMeta(),l=s.dataset,u=s.data||[],d=o.chart.options,c=d.elements.line,h=o.getScaleForId(s.yAxisID),f=o.getDataset(),g=e(f,d);for(g&&(a=l.custom||{},void 0!==f.tension&&void 0===f.lineTension&&(f.lineTension=f.tension),l._scale=h,l._datasetIndex=o.index,l._children=u,l._model={spanGaps:f.spanGaps?f.spanGaps:d.spanGaps,tension:a.tension?a.tension:r.valueOrDefault(f.lineTension,c.tension),backgroundColor:a.backgroundColor?a.backgroundColor:f.backgroundColor||c.backgroundColor,borderWidth:a.borderWidth?a.borderWidth:f.borderWidth||c.borderWidth,borderColor:a.borderColor?a.borderColor:f.borderColor||c.borderColor,borderCapStyle:a.borderCapStyle?a.borderCapStyle:f.borderCapStyle||c.borderCapStyle,borderDash:a.borderDash?a.borderDash:f.borderDash||c.borderDash,borderDashOffset:a.borderDashOffset?a.borderDashOffset:f.borderDashOffset||c.borderDashOffset,borderJoinStyle:a.borderJoinStyle?a.borderJoinStyle:f.borderJoinStyle||c.borderJoinStyle,fill:a.fill?a.fill:void 0!==f.fill?f.fill:c.fill,steppedLine:a.steppedLine?a.steppedLine:r.valueOrDefault(f.steppedLine,c.stepped),cubicInterpolationMode:a.cubicInterpolationMode?a.cubicInterpolationMode:r.valueOrDefault(f.cubicInterpolationMode,c.cubicInterpolationMode)},l.pivot()),n=0,i=u.length;n');var n=t.data,i=n.datasets,a=n.labels;if(i.length)for(var r=0;r'),a[r]&&e.push(a[r]),e.push("");return e.push(""),e.join("")},legend:{labels:{generateLabels:function(t){var e=t.data;return e.labels.length&&e.datasets.length?e.labels.map(function(n,i){var a=t.getDatasetMeta(0),o=e.datasets[0],s=a.data[i].custom||{},l=r.valueAtIndexOrDefault,u=t.options.elements.arc;return{text:n,fillStyle:s.backgroundColor?s.backgroundColor:l(o.backgroundColor,i,u.backgroundColor),strokeStyle:s.borderColor?s.borderColor:l(o.borderColor,i,u.borderColor),lineWidth:s.borderWidth?s.borderWidth:l(o.borderWidth,i,u.borderWidth),hidden:isNaN(o.data[i])||a.data[i].hidden,index:i}}):[]}},onClick:function(t,e){var n,i,a,r=e.index,o=this.chart;for(n=0,i=(o.data.datasets||[]).length;n0&&!isNaN(t)?2*Math.PI/e:0}})}},{25:25,40:40,45:45}],20:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("radar",{scale:{type:"radialLinear"},elements:{line:{tension:0}}}),e.exports=function(t){t.controllers.radar=t.DatasetController.extend({datasetElementType:a.Line,dataElementType:a.Point,linkScales:r.noop,update:function(t){var e=this,n=e.getMeta(),i=n.dataset,a=n.data,o=i.custom||{},s=e.getDataset(),l=e.chart.options.elements.line,u=e.chart.scale;void 0!==s.tension&&void 0===s.lineTension&&(s.lineTension=s.tension),r.extend(n.dataset,{_datasetIndex:e.index,_scale:u,_children:a,_loop:!0,_model:{tension:o.tension?o.tension:r.valueOrDefault(s.lineTension,l.tension),backgroundColor:o.backgroundColor?o.backgroundColor:s.backgroundColor||l.backgroundColor,borderWidth:o.borderWidth?o.borderWidth:s.borderWidth||l.borderWidth,borderColor:o.borderColor?o.borderColor:s.borderColor||l.borderColor,fill:o.fill?o.fill:void 0!==s.fill?s.fill:l.fill,borderCapStyle:o.borderCapStyle?o.borderCapStyle:s.borderCapStyle||l.borderCapStyle,borderDash:o.borderDash?o.borderDash:s.borderDash||l.borderDash,borderDashOffset:o.borderDashOffset?o.borderDashOffset:s.borderDashOffset||l.borderDashOffset,borderJoinStyle:o.borderJoinStyle?o.borderJoinStyle:s.borderJoinStyle||l.borderJoinStyle}}),n.dataset.pivot(),r.each(a,function(n,i){e.updateElement(n,i,t)},e),e.updateBezierControlPoints()},updateElement:function(t,e,n){var i=this,a=t.custom||{},o=i.getDataset(),s=i.chart.scale,l=i.chart.options.elements.point,u=s.getPointPositionForValue(e,o.data[e]);void 0!==o.radius&&void 0===o.pointRadius&&(o.pointRadius=o.radius),void 0!==o.hitRadius&&void 0===o.pointHitRadius&&(o.pointHitRadius=o.hitRadius),r.extend(t,{_datasetIndex:i.index,_index:e,_scale:s,_model:{x:n?s.xCenter:u.x,y:n?s.yCenter:u.y,tension:a.tension?a.tension:r.valueOrDefault(o.lineTension,i.chart.options.elements.line.tension),radius:a.radius?a.radius:r.valueAtIndexOrDefault(o.pointRadius,e,l.radius),backgroundColor:a.backgroundColor?a.backgroundColor:r.valueAtIndexOrDefault(o.pointBackgroundColor,e,l.backgroundColor),borderColor:a.borderColor?a.borderColor:r.valueAtIndexOrDefault(o.pointBorderColor,e,l.borderColor),borderWidth:a.borderWidth?a.borderWidth:r.valueAtIndexOrDefault(o.pointBorderWidth,e,l.borderWidth),pointStyle:a.pointStyle?a.pointStyle:r.valueAtIndexOrDefault(o.pointStyle,e,l.pointStyle),hitRadius:a.hitRadius?a.hitRadius:r.valueAtIndexOrDefault(o.pointHitRadius,e,l.hitRadius)}}),t._model.skip=a.skip?a.skip:isNaN(t._model.x)||isNaN(t._model.y)},updateBezierControlPoints:function(){var t=this.chart.chartArea,e=this.getMeta();r.each(e.data,function(n,i){var a=n._model,o=r.splineCurve(r.previousItem(e.data,i,!0)._model,a,r.nextItem(e.data,i,!0)._model,a.tension);a.controlPointPreviousX=Math.max(Math.min(o.previous.x,t.right),t.left),a.controlPointPreviousY=Math.max(Math.min(o.previous.y,t.bottom),t.top),a.controlPointNextX=Math.max(Math.min(o.next.x,t.right),t.left),a.controlPointNextY=Math.max(Math.min(o.next.y,t.bottom),t.top),n.pivot()})},setHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model;a.radius=n.hoverRadius?n.hoverRadius:r.valueAtIndexOrDefault(e.pointHoverRadius,i,this.chart.options.elements.point.hoverRadius),a.backgroundColor=n.hoverBackgroundColor?n.hoverBackgroundColor:r.valueAtIndexOrDefault(e.pointHoverBackgroundColor,i,r.getHoverColor(a.backgroundColor)),a.borderColor=n.hoverBorderColor?n.hoverBorderColor:r.valueAtIndexOrDefault(e.pointHoverBorderColor,i,r.getHoverColor(a.borderColor)),a.borderWidth=n.hoverBorderWidth?n.hoverBorderWidth:r.valueAtIndexOrDefault(e.pointHoverBorderWidth,i,a.borderWidth)},removeHoverStyle:function(t){var e=this.chart.data.datasets[t._datasetIndex],n=t.custom||{},i=t._index,a=t._model,o=this.chart.options.elements.point;a.radius=n.radius?n.radius:r.valueAtIndexOrDefault(e.pointRadius,i,o.radius),a.backgroundColor=n.backgroundColor?n.backgroundColor:r.valueAtIndexOrDefault(e.pointBackgroundColor,i,o.backgroundColor),a.borderColor=n.borderColor?n.borderColor:r.valueAtIndexOrDefault(e.pointBorderColor,i,o.borderColor),a.borderWidth=n.borderWidth?n.borderWidth:r.valueAtIndexOrDefault(e.pointBorderWidth,i,o.borderWidth)}})}},{25:25,40:40,45:45}],21:[function(t,e,n){"use strict";t(25)._set("scatter",{hover:{mode:"single"},scales:{xAxes:[{id:"x-axis-1",type:"linear",position:"bottom"}],yAxes:[{id:"y-axis-1",type:"linear",position:"left"}]},showLines:!1,tooltips:{callbacks:{title:function(){return""},label:function(t){return"("+t.xLabel+", "+t.yLabel+")"}}}}),e.exports=function(t){t.controllers.scatter=t.controllers.line}},{25:25}],22:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{animation:{duration:1e3,easing:"easeOutQuart",onProgress:r.noop,onComplete:r.noop}}),e.exports=function(t){t.Animation=a.extend({chart:null,currentStep:0,numSteps:60,easing:"",render:null,onAnimationProgress:null,onAnimationComplete:null}),t.animationService={frameDuration:17,animations:[],dropFrames:0,request:null,addAnimation:function(t,e,n,i){var a,r,o=this.animations;for(e.chart=t,i||(t.animating=!0),a=0,r=o.length;a1&&(n=Math.floor(t.dropFrames),t.dropFrames=t.dropFrames%1),t.advance(1+n);var i=Date.now();t.dropFrames+=(i-e)/t.frameDuration,t.animations.length>0&&t.requestAnimationFrame()},advance:function(t){for(var e,n,i=this.animations,a=0;a=e.numSteps?(r.callback(e.onAnimationComplete,[e],n),n.animating=!1,i.splice(a,1)):++a}},Object.defineProperty(t.Animation.prototype,"animationObject",{get:function(){return this}}),Object.defineProperty(t.Animation.prototype,"chartInstance",{get:function(){return this.chart},set:function(t){this.chart=t}})}},{25:25,26:26,45:45}],23:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(28),o=t(48);e.exports=function(t){function e(t){var e=(t=t||{}).data=t.data||{};return e.datasets=e.datasets||[],e.labels=e.labels||[],t.options=a.configMerge(i.global,i[t.type],t.options||{}),t}function n(t){var e=t.options;e.scale?t.scale.options=e.scale:e.scales&&e.scales.xAxes.concat(e.scales.yAxes).forEach(function(e){t.scales[e.id].options=e}),t.tooltip._options=e.tooltips}function s(t){return"top"===t||"bottom"===t}var l=t.plugins;t.types={},t.instances={},t.controllers={},a.extend(t.prototype,{construct:function(n,i){var r=this;i=e(i);var s=o.acquireContext(n,i),l=s&&s.canvas,u=l&&l.height,d=l&&l.width;r.id=a.uid(),r.ctx=s,r.canvas=l,r.config=i,r.width=d,r.height=u,r.aspectRatio=u?d/u:null,r.options=i.options,r._bufferedRender=!1,r.chart=r,r.controller=r,t.instances[r.id]=r,Object.defineProperty(r,"data",{get:function(){return r.config.data},set:function(t){r.config.data=t}}),s&&l?(r.initialize(),r.update()):console.error("Failed to create chart: can't acquire context from the given item")},initialize:function(){var t=this;return l.notify(t,"beforeInit"),a.retinaScale(t,t.options.devicePixelRatio),t.bindEvents(),t.options.responsive&&t.resize(!0),t.ensureScalesHaveIDs(),t.buildScales(),t.initToolTip(),l.notify(t,"afterInit"),t},clear:function(){return a.canvas.clear(this),this},stop:function(){return t.animationService.cancelAnimation(this),this},resize:function(t){var e=this,n=e.options,i=e.canvas,r=n.maintainAspectRatio&&e.aspectRatio||null,o=Math.max(0,Math.floor(a.getMaximumWidth(i))),s=Math.max(0,Math.floor(r?o/r:a.getMaximumHeight(i)));if((e.width!==o||e.height!==s)&&(i.width=e.width=o,i.height=e.height=s,i.style.width=o+"px",i.style.height=s+"px",a.retinaScale(e,n.devicePixelRatio),!t)){var u={width:o,height:s};l.notify(e,"resize",[u]),e.options.onResize&&e.options.onResize(e,u),e.stop(),e.update(e.options.responsiveAnimationDuration)}},ensureScalesHaveIDs:function(){var t=this.options,e=t.scales||{},n=t.scale;a.each(e.xAxes,function(t,e){t.id=t.id||"x-axis-"+e}),a.each(e.yAxes,function(t,e){t.id=t.id||"y-axis-"+e}),n&&(n.id=n.id||"scale")},buildScales:function(){var e=this,n=e.options,i=e.scales={},r=[];n.scales&&(r=r.concat((n.scales.xAxes||[]).map(function(t){return{options:t,dtype:"category",dposition:"bottom"}}),(n.scales.yAxes||[]).map(function(t){return{options:t,dtype:"linear",dposition:"left"}}))),n.scale&&r.push({options:n.scale,dtype:"radialLinear",isDefault:!0,dposition:"chartArea"}),a.each(r,function(n){var r=n.options,o=a.valueOrDefault(r.type,n.dtype),l=t.scaleService.getScaleConstructor(o);if(l){s(r.position)!==s(n.dposition)&&(r.position=n.dposition);var u=new l({id:r.id,options:r,ctx:e.ctx,chart:e});i[u.id]=u,u.mergeTicksOptions(),n.isDefault&&(e.scale=u)}}),t.scaleService.addScalesToLayout(this)},buildOrUpdateControllers:function(){var e=this,n=[],i=[];return a.each(e.data.datasets,function(a,r){var o=e.getDatasetMeta(r),s=a.type||e.config.type;if(o.type&&o.type!==s&&(e.destroyDatasetMeta(r),o=e.getDatasetMeta(r)),o.type=s,n.push(o.type),o.controller)o.controller.updateIndex(r);else{var l=t.controllers[o.type];if(void 0===l)throw new Error('"'+o.type+'" is not a chart type.');o.controller=new l(e,r),i.push(o.controller)}},e),i},resetElements:function(){var t=this;a.each(t.data.datasets,function(e,n){t.getDatasetMeta(n).controller.reset()},t)},reset:function(){this.resetElements(),this.tooltip.initialize()},update:function(t){var e=this;if(t&&"object"==typeof t||(t={duration:t,lazy:arguments[1]}),n(e),!1!==l.notify(e,"beforeUpdate")){e.tooltip._data=e.data;var i=e.buildOrUpdateControllers();a.each(e.data.datasets,function(t,n){e.getDatasetMeta(n).controller.buildOrUpdateElements()},e),e.updateLayout(),a.each(i,function(t){t.reset()}),e.updateDatasets(),e.tooltip.initialize(),e.lastActive=[],l.notify(e,"afterUpdate"),e._bufferedRender?e._bufferedRequest={duration:t.duration,easing:t.easing,lazy:t.lazy}:e.render(t)}},updateLayout:function(){var e=this;!1!==l.notify(e,"beforeLayout")&&(t.layoutService.update(this,this.width,this.height),l.notify(e,"afterScaleUpdate"),l.notify(e,"afterLayout"))},updateDatasets:function(){var t=this;if(!1!==l.notify(t,"beforeDatasetsUpdate")){for(var e=0,n=t.data.datasets.length;e=0;--n)e.isDatasetVisible(n)&&e.drawDataset(n,t);l.notify(e,"afterDatasetsDraw",[t])}},drawDataset:function(t,e){var n=this,i=n.getDatasetMeta(t),a={meta:i,index:t,easingValue:e};!1!==l.notify(n,"beforeDatasetDraw",[a])&&(i.controller.draw(e),l.notify(n,"afterDatasetDraw",[a]))},_drawTooltip:function(t){var e=this,n=e.tooltip,i={tooltip:n,easingValue:t};!1!==l.notify(e,"beforeTooltipDraw",[i])&&(n.draw(),l.notify(e,"afterTooltipDraw",[i]))},getElementAtEvent:function(t){return r.modes.single(this,t)},getElementsAtEvent:function(t){return r.modes.label(this,t,{intersect:!0})},getElementsAtXAxis:function(t){return r.modes["x-axis"](this,t,{intersect:!0})},getElementsAtEventForMode:function(t,e,n){var i=r.modes[e];return"function"==typeof i?i(this,t,n):[]},getDatasetAtEvent:function(t){return r.modes.dataset(this,t,{intersect:!0})},getDatasetMeta:function(t){var e=this,n=e.data.datasets[t];n._meta||(n._meta={});var i=n._meta[e.id];return i||(i=n._meta[e.id]={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null}),i},getVisibleDatasetCount:function(){for(var t=0,e=0,n=this.data.datasets.length;e0||(a.forEach(function(e){delete t[e]}),delete t._chartjs)}}var a=["push","pop","shift","splice","unshift"];t.DatasetController=function(t,e){this.initialize(t,e)},i.extend(t.DatasetController.prototype,{datasetElementType:null,dataElementType:null,initialize:function(t,e){var n=this;n.chart=t,n.index=e,n.linkScales(),n.addElements()},updateIndex:function(t){this.index=t},linkScales:function(){var t=this,e=t.getMeta(),n=t.getDataset();null===e.xAxisID&&(e.xAxisID=n.xAxisID||t.chart.options.scales.xAxes[0].id),null===e.yAxisID&&(e.yAxisID=n.yAxisID||t.chart.options.scales.yAxes[0].id)},getDataset:function(){return this.chart.data.datasets[this.index]},getMeta:function(){return this.chart.getDatasetMeta(this.index)},getScaleForId:function(t){return this.chart.scales[t]},reset:function(){this.update(!0)},destroy:function(){this._data&&n(this._data,this)},createMetaDataset:function(){var t=this,e=t.datasetElementType;return e&&new e({_chart:t.chart,_datasetIndex:t.index})},createMetaData:function(t){var e=this,n=e.dataElementType;return n&&new n({_chart:e.chart,_datasetIndex:e.index,_index:t})},addElements:function(){var t,e,n=this,i=n.getMeta(),a=n.getDataset().data||[],r=i.data;for(t=0,e=a.length;ti&&t.insertElements(i,a-i)},insertElements:function(t,e){for(var n=0;n=n[e].length&&n[e].push({}),!n[e][o].type||l.type&&l.type!==n[e][o].type?r.merge(n[e][o],[t.scaleService.getScaleDefaults(s),l]):r.merge(n[e][o],l)}else r._merger(e,n,i,a)}})},r.where=function(t,e){if(r.isArray(t)&&Array.prototype.filter)return t.filter(e);var n=[];return r.each(t,function(t){e(t)&&n.push(t)}),n},r.findIndex=Array.prototype.findIndex?function(t,e,n){return t.findIndex(e,n)}:function(t,e,n){n=void 0===n?t:n;for(var i=0,a=t.length;i=0;i--){var a=t[i];if(e(a))return a}},r.isNumber=function(t){return!isNaN(parseFloat(t))&&isFinite(t)},r.almostEquals=function(t,e,n){return Math.abs(t-e)t},r.max=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.max(t,e)},Number.NEGATIVE_INFINITY)},r.min=function(t){return t.reduce(function(t,e){return isNaN(e)?t:Math.min(t,e)},Number.POSITIVE_INFINITY)},r.sign=Math.sign?function(t){return Math.sign(t)}:function(t){return 0==(t=+t)||isNaN(t)?t:t>0?1:-1},r.log10=Math.log10?function(t){return Math.log10(t)}:function(t){return Math.log(t)/Math.LN10},r.toRadians=function(t){return t*(Math.PI/180)},r.toDegrees=function(t){return t*(180/Math.PI)},r.getAngleFromPoint=function(t,e){var n=e.x-t.x,i=e.y-t.y,a=Math.sqrt(n*n+i*i),r=Math.atan2(i,n);return r<-.5*Math.PI&&(r+=2*Math.PI),{angle:r,distance:a}},r.distanceBetweenPoints=function(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))},r.aliasPixel=function(t){return t%2==0?0:.5},r.splineCurve=function(t,e,n,i){var a=t.skip?e:t,r=e,o=n.skip?e:n,s=Math.sqrt(Math.pow(r.x-a.x,2)+Math.pow(r.y-a.y,2)),l=Math.sqrt(Math.pow(o.x-r.x,2)+Math.pow(o.y-r.y,2)),u=s/(s+l),d=l/(s+l),c=i*(u=isNaN(u)?0:u),h=i*(d=isNaN(d)?0:d);return{previous:{x:r.x-c*(o.x-a.x),y:r.y-c*(o.y-a.y)},next:{x:r.x+h*(o.x-a.x),y:r.y+h*(o.y-a.y)}}},r.EPSILON=Number.EPSILON||1e-14,r.splineCurveMonotone=function(t){var e,n,i,a,o=(t||[]).map(function(t){return{model:t._model,deltaK:0,mK:0}}),s=o.length;for(e=0;e0?o[e-1]:null,(a=e0?o[e-1]:null,a=e=t.length-1?t[0]:t[e+1]:e>=t.length-1?t[t.length-1]:t[e+1]},r.previousItem=function(t,e,n){return n?e<=0?t[t.length-1]:t[e-1]:e<=0?t[0]:t[e-1]},r.niceNum=function(t,e){var n=Math.floor(r.log10(t)),i=t/Math.pow(10,n);return(e?i<1.5?1:i<3?2:i<7?5:10:i<=1?1:i<=2?2:i<=5?5:10)*Math.pow(10,n)},r.requestAnimFrame="undefined"==typeof window?function(t){t()}:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},r.getRelativePosition=function(t,e){var n,i,a=t.originalEvent||t,o=t.currentTarget||t.srcElement,s=o.getBoundingClientRect(),l=a.touches;l&&l.length>0?(n=l[0].clientX,i=l[0].clientY):(n=a.clientX,i=a.clientY);var u=parseFloat(r.getStyle(o,"padding-left")),d=parseFloat(r.getStyle(o,"padding-top")),c=parseFloat(r.getStyle(o,"padding-right")),h=parseFloat(r.getStyle(o,"padding-bottom")),f=s.right-s.left-u-c,g=s.bottom-s.top-d-h;return n=Math.round((n-s.left-u)/f*o.width/e.currentDevicePixelRatio),i=Math.round((i-s.top-d)/g*o.height/e.currentDevicePixelRatio),{x:n,y:i}},r.getConstraintWidth=function(t){return o(t,"max-width","clientWidth")},r.getConstraintHeight=function(t){return o(t,"max-height","clientHeight")},r.getMaximumWidth=function(t){var e=t.parentNode;if(!e)return t.clientWidth;var n=parseInt(r.getStyle(e,"padding-left"),10),i=parseInt(r.getStyle(e,"padding-right"),10),a=e.clientWidth-n-i,o=r.getConstraintWidth(t);return isNaN(o)?a:Math.min(a,o)},r.getMaximumHeight=function(t){var e=t.parentNode;if(!e)return t.clientHeight;var n=parseInt(r.getStyle(e,"padding-top"),10),i=parseInt(r.getStyle(e,"padding-bottom"),10),a=e.clientHeight-n-i,o=r.getConstraintHeight(t);return isNaN(o)?a:Math.min(a,o)},r.getStyle=function(t,e){return t.currentStyle?t.currentStyle[e]:document.defaultView.getComputedStyle(t,null).getPropertyValue(e)},r.retinaScale=function(t,e){var n=t.currentDevicePixelRatio=e||window.devicePixelRatio||1;if(1!==n){var i=t.canvas,a=t.height,r=t.width;i.height=a*n,i.width=r*n,t.ctx.scale(n,n),i.style.height=a+"px",i.style.width=r+"px"}},r.fontString=function(t,e,n){return e+" "+t+"px "+n},r.longestText=function(t,e,n,i){var a=(i=i||{}).data=i.data||{},o=i.garbageCollect=i.garbageCollect||[];i.font!==e&&(a=i.data={},o=i.garbageCollect=[],i.font=e),t.font=e;var s=0;r.each(n,function(e){void 0!==e&&null!==e&&!0!==r.isArray(e)?s=r.measureText(t,a,o,s,e):r.isArray(e)&&r.each(e,function(e){void 0===e||null===e||r.isArray(e)||(s=r.measureText(t,a,o,s,e))})});var l=o.length/2;if(l>n.length){for(var u=0;ui&&(i=r),i},r.numberOfLabelLines=function(t){var e=1;return r.each(t,function(t){r.isArray(t)&&t.length>e&&(e=t.length)}),e},r.color=i?function(t){return t instanceof CanvasGradient&&(t=a.global.defaultColor),i(t)}:function(t){return console.error("Color.js not found!"),t},r.getHoverColor=function(t){return t instanceof CanvasPattern?t:r.color(t).saturate(.5).darken(.1).rgbString()}}},{2:2,25:25,45:45}],28:[function(t,e,n){"use strict";function i(t,e){return t.native?{x:t.x,y:t.y}:u.getRelativePosition(t,e)}function a(t,e){var n,i,a,r,o;for(i=0,r=t.data.datasets.length;i0&&(u=t.getDatasetMeta(u[0]._datasetIndex).data),u},"x-axis":function(t,e){return l(t,e,{intersect:!1})},point:function(t,e){return r(t,i(e,t))},nearest:function(t,e,n){var a=i(e,t);n.axis=n.axis||"xy";var r=s(n.axis),l=o(t,a,n.intersect,r);return l.length>1&&l.sort(function(t,e){var n=t.getArea()-e.getArea();return 0===n&&(n=t._datasetIndex-e._datasetIndex),n}),l.slice(0,1)},x:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inXRange(r.x)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o},y:function(t,e,n){var r=i(e,t),o=[],s=!1;return a(t,function(t){t.inYRange(r.y)&&o.push(t),t.inRange(r.x,r.y)&&(s=!0)}),n.intersect&&!s&&(o=[]),o}}}},{45:45}],29:[function(t,e,n){"use strict";t(25)._set("global",{responsive:!0,responsiveAnimationDuration:0,maintainAspectRatio:!0,events:["mousemove","mouseout","click","touchstart","touchmove"],hover:{onHover:null,mode:"nearest",intersect:!0,animationDuration:400},onClick:null,defaultColor:"rgba(0,0,0,0.1)",defaultFontColor:"#666",defaultFontFamily:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",defaultFontSize:12,defaultFontStyle:"normal",showLines:!0,elements:{},layout:{padding:{top:0,right:0,bottom:0,left:0}}}),e.exports=function(){var t=function(t,e){return this.construct(t,e),this};return t.Chart=t,t}},{25:25}],30:[function(t,e,n){"use strict";var i=t(45);e.exports=function(t){function e(t,e){return i.where(t,function(t){return t.position===e})}function n(t,e){t.forEach(function(t,e){return t._tmpIndex_=e,t}),t.sort(function(t,n){var i=e?n:t,a=e?t:n;return i.weight===a.weight?i._tmpIndex_-a._tmpIndex_:i.weight-a.weight}),t.forEach(function(t){delete t._tmpIndex_})}t.layoutService={defaults:{},addBox:function(t,e){t.boxes||(t.boxes=[]),e.fullWidth=e.fullWidth||!1,e.position=e.position||"top",e.weight=e.weight||0,t.boxes.push(e)},removeBox:function(t,e){var n=t.boxes?t.boxes.indexOf(e):-1;-1!==n&&t.boxes.splice(n,1)},configure:function(t,e,n){for(var i,a=["fullWidth","position","weight"],r=a.length,o=0;oh&&lt.maxHeight){l--;break}l++,c=u*d}t.labelRotation=l},afterCalculateTickRotation:function(){s.callback(this.options.afterCalculateTickRotation,[this])},beforeFit:function(){s.callback(this.options.beforeFit,[this])},fit:function(){var t=this,a=t.minSize={width:0,height:0},r=i(t._ticks),o=t.options,u=o.ticks,d=o.scaleLabel,c=o.gridLines,h=o.display,f=t.isHorizontal(),g=n(u),m=o.gridLines.tickMarkLength;if(a.width=f?t.isFullWidth()?t.maxWidth-t.margins.left-t.margins.right:t.maxWidth:h&&c.drawTicks?m:0,a.height=f?h&&c.drawTicks?m:0:t.maxHeight,d.display&&h){var p=l(d)+s.options.toPadding(d.padding).height;f?a.height+=p:a.width+=p}if(u.display&&h){var v=s.longestText(t.ctx,g.font,r,t.longestTextCache),y=s.numberOfLabelLines(r),b=.5*g.size,x=t.options.ticks.padding;if(f){t.longestLabelWidth=v;var _=s.toRadians(t.labelRotation),k=Math.cos(_),w=Math.sin(_)*v+g.size*y+b*(y-1)+b;a.height=Math.min(t.maxHeight,a.height+w+x),t.ctx.font=g.font;var M=e(t.ctx,r[0],g.font),S=e(t.ctx,r[r.length-1],g.font);0!==t.labelRotation?(t.paddingLeft="bottom"===o.position?k*M+3:k*b+3,t.paddingRight="bottom"===o.position?k*b+3:k*S+3):(t.paddingLeft=M/2+3,t.paddingRight=S/2+3)}else u.mirror?v=0:v+=x+b,a.width=Math.min(t.maxWidth,a.width+v),t.paddingTop=g.size/2,t.paddingBottom=g.size/2}t.handleMargins(),t.width=a.width,t.height=a.height},handleMargins:function(){var t=this;t.margins&&(t.paddingLeft=Math.max(t.paddingLeft-t.margins.left,0),t.paddingTop=Math.max(t.paddingTop-t.margins.top,0),t.paddingRight=Math.max(t.paddingRight-t.margins.right,0),t.paddingBottom=Math.max(t.paddingBottom-t.margins.bottom,0))},afterFit:function(){s.callback(this.options.afterFit,[this])},isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},isFullWidth:function(){return this.options.fullWidth},getRightValue:function(t){if(s.isNullOrUndef(t))return NaN;if("number"==typeof t&&!isFinite(t))return NaN;if(t)if(this.isHorizontal()){if(void 0!==t.x)return this.getRightValue(t.x)}else if(void 0!==t.y)return this.getRightValue(t.y);return t},getLabelForIndex:s.noop,getPixelForValue:s.noop,getValueForPixel:s.noop,getPixelForTick:function(t){var e=this,n=e.options.offset;if(e.isHorizontal()){var i=(e.width-(e.paddingLeft+e.paddingRight))/Math.max(e._ticks.length-(n?0:1),1),a=i*t+e.paddingLeft;n&&(a+=i/2);var r=e.left+Math.round(a);return r+=e.isFullWidth()?e.margins.left:0}var o=e.height-(e.paddingTop+e.paddingBottom);return e.top+t*(o/(e._ticks.length-1))},getPixelForDecimal:function(t){var e=this;if(e.isHorizontal()){var n=(e.width-(e.paddingLeft+e.paddingRight))*t+e.paddingLeft,i=e.left+Math.round(n);return i+=e.isFullWidth()?e.margins.left:0}return e.top+t*e.height},getBasePixel:function(){return this.getPixelForValue(this.getBaseValue())},getBaseValue:function(){var t=this,e=t.min,n=t.max;return t.beginAtZero?0:e<0&&n<0?n:e>0&&n>0?e:0},_autoSkip:function(t){var e,n,i,a,r=this,o=r.isHorizontal(),l=r.options.ticks.minor,u=t.length,d=s.toRadians(r.labelRotation),c=Math.cos(d),h=r.longestLabelWidth*c,f=[];for(l.maxTicksLimit&&(a=l.maxTicksLimit),o&&(e=!1,(h+l.autoSkipPadding)*u>r.width-(r.paddingLeft+r.paddingRight)&&(e=1+Math.floor((h+l.autoSkipPadding)*u/(r.width-(r.paddingLeft+r.paddingRight)))),a&&u>a&&(e=Math.max(e,Math.floor(u/a)))),n=0;n1&&n%e>0||n%e==0&&n+e>=u)&&n!==u-1&&delete i.label,f.push(i);return f},draw:function(t){var e=this,i=e.options;if(i.display){var o=e.ctx,u=r.global,d=i.ticks.minor,c=i.ticks.major||d,h=i.gridLines,f=i.scaleLabel,g=0!==e.labelRotation,m=e.isHorizontal(),p=d.autoSkip?e._autoSkip(e.getTicks()):e.getTicks(),v=s.valueOrDefault(d.fontColor,u.defaultFontColor),y=n(d),b=s.valueOrDefault(c.fontColor,u.defaultFontColor),x=n(c),_=h.drawTicks?h.tickMarkLength:0,k=s.valueOrDefault(f.fontColor,u.defaultFontColor),w=n(f),M=s.options.toPadding(f.padding),S=s.toRadians(e.labelRotation),D=[],C="right"===i.position?e.left:e.right-_,P="right"===i.position?e.left+_:e.right,T="bottom"===i.position?e.top:e.bottom-_,A="bottom"===i.position?e.top+_:e.bottom;if(s.each(p,function(n,r){if(!s.isNullOrUndef(n.label)){var o,l,c,f,v=n.label;r===e.zeroLineIndex&&i.offset===h.offsetGridLines?(o=h.zeroLineWidth,l=h.zeroLineColor,c=h.zeroLineBorderDash,f=h.zeroLineBorderDashOffset):(o=s.valueAtIndexOrDefault(h.lineWidth,r),l=s.valueAtIndexOrDefault(h.color,r),c=s.valueOrDefault(h.borderDash,u.borderDash),f=s.valueOrDefault(h.borderDashOffset,u.borderDashOffset));var y,b,x,k,w,M,I,O,F,R,L="middle",W="middle",Y=d.padding;if(m){var N=_+Y;"bottom"===i.position?(W=g?"middle":"top",L=g?"right":"center",R=e.top+N):(W=g?"middle":"bottom",L=g?"left":"center",R=e.bottom-N);var z=a(e,r,h.offsetGridLines&&p.length>1);z1);H0)n=t.stepSize;else{var r=i.niceNum(e.max-e.min,!1);n=i.niceNum(r/(t.maxTicks-1),!0)}var o=Math.floor(e.min/n)*n,s=Math.ceil(e.max/n)*n;t.min&&t.max&&t.stepSize&&i.almostWhole((t.max-t.min)/t.stepSize,n/1e3)&&(o=t.min,s=t.max);var l=(s-o)/n;l=i.almostEquals(l,Math.round(l),n/1e3)?Math.round(l):Math.ceil(l),a.push(void 0!==t.min?t.min:o);for(var u=1;u3?n[2]-n[1]:n[1]-n[0];Math.abs(a)>1&&t!==Math.floor(t)&&(a=t-Math.floor(t));var r=i.log10(Math.abs(a)),o="";if(0!==t){var s=-1*Math.floor(r);s=Math.max(Math.min(s,20),0),o=t.toFixed(s)}else o="0";return o},logarithmic:function(t,e,n){var a=t/Math.pow(10,Math.floor(i.log10(t)));return 0===t?"0":1===a||2===a||5===a||0===e||e===n.length-1?t.toExponential():""}}}},{45:45}],35:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{tooltips:{enabled:!0,custom:null,mode:"nearest",position:"average",intersect:!0,backgroundColor:"rgba(0,0,0,0.8)",titleFontStyle:"bold",titleSpacing:2,titleMarginBottom:6,titleFontColor:"#fff",titleAlign:"left",bodySpacing:2,bodyFontColor:"#fff",bodyAlign:"left",footerFontStyle:"bold",footerSpacing:2,footerMarginTop:6,footerFontColor:"#fff",footerAlign:"left",yPadding:6,xPadding:6,caretPadding:2,caretSize:5,cornerRadius:6,multiKeyBackground:"#fff",displayColors:!0,borderColor:"rgba(0,0,0,0)",borderWidth:0,callbacks:{beforeTitle:r.noop,title:function(t,e){var n="",i=e.labels,a=i?i.length:0;if(t.length>0){var r=t[0];r.xLabel?n=r.xLabel:a>0&&r.indexi.height-e.height&&(o="bottom");var s,l,u,d,c,h=(a.left+a.right)/2,f=(a.top+a.bottom)/2;"center"===o?(s=function(t){return t<=h},l=function(t){return t>h}):(s=function(t){return t<=e.width/2},l=function(t){return t>=i.width-e.width/2}),u=function(t){return t+e.width>i.width},d=function(t){return t-e.width<0},c=function(t){return t<=f?"top":"bottom"},s(n.x)?(r="left",u(n.x)&&(r="center",o=c(n.y))):l(n.x)&&(r="right",d(n.x)&&(r="center",o=c(n.y)));var g=t._options;return{xAlign:g.xAlign?g.xAlign:r,yAlign:g.yAlign?g.yAlign:o}}function d(t,e,n){var i=t.x,a=t.y,r=t.caretSize,o=t.caretPadding,s=t.cornerRadius,l=n.xAlign,u=n.yAlign,d=r+o,c=s+o;return"right"===l?i-=e.width:"center"===l&&(i-=e.width/2),"top"===u?a+=d:a-="bottom"===u?e.height+d:e.height/2,"center"===u?"left"===l?i+=d:"right"===l&&(i-=d):"left"===l?i-=c:"right"===l&&(i+=c),{x:i,y:a}}t.Tooltip=a.extend({initialize:function(){this._model=s(this._options),this._lastActive=[]},getTitle:function(){var t=this,e=t._options.callbacks,i=e.beforeTitle.apply(t,arguments),a=e.title.apply(t,arguments),r=e.afterTitle.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},getBeforeBody:function(){var t=this._options.callbacks.beforeBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getBody:function(t,e){var i=this,a=i._options.callbacks,o=[];return r.each(t,function(t){var r={before:[],lines:[],after:[]};n(r.before,a.beforeLabel.call(i,t,e)),n(r.lines,a.label.call(i,t,e)),n(r.after,a.afterLabel.call(i,t,e)),o.push(r)}),o},getAfterBody:function(){var t=this._options.callbacks.afterBody.apply(this,arguments);return r.isArray(t)?t:void 0!==t?[t]:[]},getFooter:function(){var t=this,e=t._options.callbacks,i=e.beforeFooter.apply(t,arguments),a=e.footer.apply(t,arguments),r=e.afterFooter.apply(t,arguments),o=[];return o=n(o,i),o=n(o,a),o=n(o,r)},update:function(e){var n,i,a=this,c=a._options,h=a._model,f=a._model=s(c),g=a._active,m=a._data,p={xAlign:h.xAlign,yAlign:h.yAlign},v={x:h.x,y:h.y},y={width:h.width,height:h.height},b={x:h.caretX,y:h.caretY};if(g.length){f.opacity=1;var x=[],_=[];b=t.Tooltip.positioners[c.position].call(a,g,a._eventPosition);var k=[];for(n=0,i=g.length;n0&&i.stroke()},draw:function(){var t=this._chart.ctx,e=this._view;if(0!==e.opacity){var n={width:e.width,height:e.height},i={x:e.x,y:e.y},a=Math.abs(e.opacity<.001)?0:e.opacity,r=e.title.length||e.beforeBody.length||e.body.length||e.afterBody.length||e.footer.length;this._options.enabled&&r&&(this.drawBackground(i,e,t,n,a),i.x+=e.xPadding,i.y+=e.yPadding,this.drawTitle(i,e,t,a),this.drawBody(i,e,t,a),this.drawFooter(i,e,t,a))}},handleEvent:function(t){var e=this,n=e._options,i=!1;if(e._lastActive=e._lastActive||[],"mouseout"===t.type?e._active=[]:e._active=e._chart.getElementsAtEventForMode(t,n.mode,n),!(i=!r.arrayEquals(e._active,e._lastActive)))return!1;if(e._lastActive=e._active,n.enabled||n.custom){e._eventPosition={x:t.x,y:t.y};var a=e._model;e.update(!0),e.pivot(),i|=a.x!==e._model.x||a.y!==e._model.y}return i}}),t.Tooltip.positioners={average:function(t){if(!t.length)return!1;var e,n,i=0,a=0,r=0;for(e=0,n=t.length;el;)a-=2*Math.PI;for(;a=s&&a<=l,d=o>=n.innerRadius&&o<=n.outerRadius;return u&&d}return!1},getCenterPoint:function(){var t=this._view,e=(t.startAngle+t.endAngle)/2,n=(t.innerRadius+t.outerRadius)/2;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},getArea:function(){var t=this._view;return Math.PI*((t.endAngle-t.startAngle)/(2*Math.PI))*(Math.pow(t.outerRadius,2)-Math.pow(t.innerRadius,2))},tooltipPosition:function(){var t=this._view,e=t.startAngle+(t.endAngle-t.startAngle)/2,n=(t.outerRadius-t.innerRadius)/2+t.innerRadius;return{x:t.x+Math.cos(e)*n,y:t.y+Math.sin(e)*n}},draw:function(){var t=this._chart.ctx,e=this._view,n=e.startAngle,i=e.endAngle;t.beginPath(),t.arc(e.x,e.y,e.outerRadius,n,i),t.arc(e.x,e.y,e.innerRadius,i,n,!0),t.closePath(),t.strokeStyle=e.borderColor,t.lineWidth=e.borderWidth,t.fillStyle=e.backgroundColor,t.fill(),t.lineJoin="bevel",e.borderWidth&&t.stroke()}})},{25:25,26:26,45:45}],37:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45),o=i.global;i._set("global",{elements:{line:{tension:.4,backgroundColor:o.defaultColor,borderWidth:3,borderColor:o.defaultColor,borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",capBezierPoints:!0,fill:!0}}}),e.exports=a.extend({draw:function(){var t,e,n,i,a=this,s=a._view,l=a._chart.ctx,u=s.spanGaps,d=a._children.slice(),c=o.elements.line,h=-1;for(a._loop&&d.length&&d.push(d[0]),l.save(),l.lineCap=s.borderCapStyle||c.borderCapStyle,l.setLineDash&&l.setLineDash(s.borderDash||c.borderDash),l.lineDashOffset=s.borderDashOffset||c.borderDashOffset,l.lineJoin=s.borderJoinStyle||c.borderJoinStyle,l.lineWidth=s.borderWidth||c.borderWidth,l.strokeStyle=s.borderColor||o.defaultColor,l.beginPath(),h=-1,t=0;te?1:-1,o=1,s=u.borderSkipped||"left"):(e=u.x-u.width/2,n=u.x+u.width/2,i=u.y,r=1,o=(a=u.base)>i?1:-1,s=u.borderSkipped||"bottom"),d){var c=Math.min(Math.abs(e-n),Math.abs(i-a)),h=(d=d>c?c:d)/2,f=e+("left"!==s?h*r:0),g=n+("right"!==s?-h*r:0),m=i+("top"!==s?h*o:0),p=a+("bottom"!==s?-h*o:0);f!==g&&(i=m,a=p),m!==p&&(e=f,n=g)}l.beginPath(),l.fillStyle=u.backgroundColor,l.strokeStyle=u.borderColor,l.lineWidth=d;var v=[[e,a],[e,i],[n,i],[n,a]],y=["bottom","left","top","right"].indexOf(s,0);-1===y&&(y=0);var b=t(0);l.moveTo(b[0],b[1]);for(var x=1;x<4;x++)b=t(x),l.lineTo(b[0],b[1]);l.fill(),d&&l.stroke()},height:function(){var t=this._view;return t.base-t.y},inRange:function(t,e){var n=!1;if(this._view){var i=a(this);n=t>=i.left&&t<=i.right&&e>=i.top&&e<=i.bottom}return n},inLabelRange:function(t,e){var n=this;if(!n._view)return!1;var r=a(n);return i(n)?t>=r.left&&t<=r.right:e>=r.top&&e<=r.bottom},inXRange:function(t){var e=a(this);return t>=e.left&&t<=e.right},inYRange:function(t){var e=a(this);return t>=e.top&&t<=e.bottom},getCenterPoint:function(){var t,e,n=this._view;return i(this)?(t=n.x,e=(n.y+n.base)/2):(t=(n.x+n.base)/2,e=n.y),{x:t,y:e}},getArea:function(){var t=this._view;return t.width*Math.abs(t.y-t.base)},tooltipPosition:function(){var t=this._view;return{x:t.x,y:t.y}}})},{25:25,26:26}],40:[function(t,e,n){"use strict";e.exports={},e.exports.Arc=t(36),e.exports.Line=t(37),e.exports.Point=t(38),e.exports.Rectangle=t(39)},{36:36,37:37,38:38,39:39}],41:[function(t,e,n){"use strict";var i=t(42),n=e.exports={clear:function(t){t.ctx.clearRect(0,0,t.width,t.height)},roundedRect:function(t,e,n,i,a,r){if(r){var o=Math.min(r,i/2),s=Math.min(r,a/2);t.moveTo(e+o,n),t.lineTo(e+i-o,n),t.quadraticCurveTo(e+i,n,e+i,n+s),t.lineTo(e+i,n+a-s),t.quadraticCurveTo(e+i,n+a,e+i-o,n+a),t.lineTo(e+o,n+a),t.quadraticCurveTo(e,n+a,e,n+a-s),t.lineTo(e,n+s),t.quadraticCurveTo(e,n,e+o,n)}else t.rect(e,n,i,a)},drawPoint:function(t,e,n,i,a){var r,o,s,l,u,d;if(!e||"object"!=typeof e||"[object HTMLImageElement]"!==(r=e.toString())&&"[object HTMLCanvasElement]"!==r){if(!(isNaN(n)||n<=0)){switch(e){default:t.beginPath(),t.arc(i,a,n,0,2*Math.PI),t.closePath(),t.fill();break;case"triangle":t.beginPath(),u=(o=3*n/Math.sqrt(3))*Math.sqrt(3)/2,t.moveTo(i-o/2,a+u/3),t.lineTo(i+o/2,a+u/3),t.lineTo(i,a-2*u/3),t.closePath(),t.fill();break;case"rect":d=1/Math.SQRT2*n,t.beginPath(),t.fillRect(i-d,a-d,2*d,2*d),t.strokeRect(i-d,a-d,2*d,2*d);break;case"rectRounded":var c=n/Math.SQRT2,h=i-c,f=a-c,g=Math.SQRT2*n;t.beginPath(),this.roundedRect(t,h,f,g,g,n/2),t.closePath(),t.fill();break;case"rectRot":d=1/Math.SQRT2*n,t.beginPath(),t.moveTo(i-d,a),t.lineTo(i,a+d),t.lineTo(i+d,a),t.lineTo(i,a-d),t.closePath(),t.fill();break;case"cross":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"crossRot":t.beginPath(),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"star":t.beginPath(),t.moveTo(i,a+n),t.lineTo(i,a-n),t.moveTo(i-n,a),t.lineTo(i+n,a),s=Math.cos(Math.PI/4)*n,l=Math.sin(Math.PI/4)*n,t.moveTo(i-s,a-l),t.lineTo(i+s,a+l),t.moveTo(i-s,a+l),t.lineTo(i+s,a-l),t.closePath();break;case"line":t.beginPath(),t.moveTo(i-n,a),t.lineTo(i+n,a),t.closePath();break;case"dash":t.beginPath(),t.moveTo(i,a),t.lineTo(i+n,a),t.closePath()}t.stroke()}}else t.drawImage(e,i-e.width/2,a-e.height/2,e.width,e.height)},clipArea:function(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()},unclipArea:function(t){t.restore()},lineTo:function(t,e,n,i){if(n.steppedLine)return"after"===n.steppedLine&&!i||"after"!==n.steppedLine&&i?t.lineTo(e.x,n.y):t.lineTo(n.x,e.y),void t.lineTo(n.x,n.y);n.tension?t.bezierCurveTo(i?e.controlPointPreviousX:e.controlPointNextX,i?e.controlPointPreviousY:e.controlPointNextY,i?n.controlPointNextX:n.controlPointPreviousX,i?n.controlPointNextY:n.controlPointPreviousY,n.x,n.y):t.lineTo(n.x,n.y)}};i.clear=n.clear,i.drawRoundedRectangle=function(t){t.beginPath(),n.roundedRect.apply(n,arguments),t.closePath()}},{42:42}],42:[function(t,e,n){"use strict";var i={noop:function(){},uid:function(){var t=0;return function(){return t++}}(),isNullOrUndef:function(t){return null===t||void 0===t},isArray:Array.isArray?Array.isArray:function(t){return"[object Array]"===Object.prototype.toString.call(t)},isObject:function(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)},valueOrDefault:function(t,e){return void 0===t?e:t},valueAtIndexOrDefault:function(t,e,n){return i.valueOrDefault(i.isArray(t)?t[e]:t,n)},callback:function(t,e,n){if(t&&"function"==typeof t.call)return t.apply(n,e)},each:function(t,e,n,a){var r,o,s;if(i.isArray(t))if(o=t.length,a)for(r=o-1;r>=0;r--)e.call(n,t[r],r);else for(r=0;r=1?t:-(Math.sqrt(1-t*t)-1)},easeOutCirc:function(t){return Math.sqrt(1-(t-=1)*t)},easeInOutCirc:function(t){return(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1)},easeInElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),-i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n))},easeOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:1===t?1:(n||(n=.3),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),i*Math.pow(2,-10*t)*Math.sin((t-e)*(2*Math.PI)/n)+1)},easeInOutElastic:function(t){var e=1.70158,n=0,i=1;return 0===t?0:2==(t/=.5)?1:(n||(n=.45),i<1?(i=1,e=n/4):e=n/(2*Math.PI)*Math.asin(1/i),t<1?i*Math.pow(2,10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*-.5:i*Math.pow(2,-10*(t-=1))*Math.sin((t-e)*(2*Math.PI)/n)*.5+1)},easeInBack:function(t){var e=1.70158;return t*t*((e+1)*t-e)},easeOutBack:function(t){var e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack:function(t){var e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:function(t){return 1-a.easeOutBounce(1-t)},easeOutBounce:function(t){return t<1/2.75?7.5625*t*t:t<2/2.75?7.5625*(t-=1.5/2.75)*t+.75:t<2.5/2.75?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375},easeInOutBounce:function(t){return t<.5?.5*a.easeInBounce(2*t):.5*a.easeOutBounce(2*t-1)+.5}};e.exports={effects:a},i.easingEffects=a},{42:42}],44:[function(t,e,n){"use strict";var i=t(42);e.exports={toLineHeight:function(t,e){var n=(""+t).match(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);if(!n||"normal"===n[1])return 1.2*e;switch(t=+n[2],n[3]){case"px":return t;case"%":t/=100}return e*t},toPadding:function(t){var e,n,a,r;return i.isObject(t)?(e=+t.top||0,n=+t.right||0,a=+t.bottom||0,r=+t.left||0):e=n=a=r=+t||0,{top:e,right:n,bottom:a,left:r,height:e+a,width:r+n}},resolve:function(t,e,n){var a,r,o;for(a=0,r=t.length;a
';var a=e.childNodes[0],o=e.childNodes[1];e._reset=function(){a.scrollLeft=1e6,a.scrollTop=1e6,o.scrollLeft=1e6,o.scrollTop=1e6};var s=function(){e._reset(),t()};return r(a,"scroll",s.bind(a,"expand")),r(o,"scroll",s.bind(o,"shrink")),e}function c(t,e){var n=t[v]||(t[v]={}),i=n.renderProxy=function(t){t.animationName===x&&e()};p.each(_,function(e){r(t,e,i)}),n.reflow=!!t.offsetParent,t.classList.add(b)}function h(t){var e=t[v]||{},n=e.renderProxy;n&&(p.each(_,function(e){o(t,e,n)}),delete e.renderProxy),t.classList.remove(b)}function f(t,e,n){var i=t[v]||(t[v]={}),a=i.resizer=d(u(function(){if(i.resizer)return e(s("resize",n))}));c(t,function(){if(i.resizer){var e=t.parentNode;e&&e!==a.parentNode&&e.insertBefore(a,e.firstChild),a._reset()}})}function g(t){var e=t[v]||{},n=e.resizer;delete e.resizer,h(t),n&&n.parentNode&&n.parentNode.removeChild(n)}function m(t,e){var n=t._style||document.createElement("style");t._style||(t._style=n,e="/* Chart.js */\n"+e,n.setAttribute("type","text/css"),document.getElementsByTagName("head")[0].appendChild(n)),n.appendChild(document.createTextNode(e))}var p=t(45),v="$chartjs",y="chartjs-",b=y+"render-monitor",x=y+"render-animation",_=["animationstart","webkitAnimationStart"],k={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},w=!!function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("e",null,e)}catch(t){}return t}()&&{passive:!0};e.exports={_enabled:"undefined"!=typeof window&&"undefined"!=typeof document,initialize:function(){var t="from{opacity:0.99}to{opacity:1}";m(this,"@-webkit-keyframes "+x+"{"+t+"}@keyframes "+x+"{"+t+"}."+b+"{-webkit-animation:"+x+" 0.001s;animation:"+x+" 0.001s;}")},acquireContext:function(t,e){"string"==typeof t?t=document.getElementById(t):t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas);var n=t&&t.getContext&&t.getContext("2d");return n&&n.canvas===t?(a(t,e),n):null},releaseContext:function(t){var e=t.canvas;if(e[v]){var n=e[v].initial;["height","width"].forEach(function(t){var i=n[t];p.isNullOrUndef(i)?e.removeAttribute(t):e.setAttribute(t,i)}),p.each(n.style||{},function(t,n){e.style[n]=t}),e.width=e.width,delete e[v]}},addEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=n[v]||(n[v]={});r(i,e,(a.proxies||(a.proxies={}))[t.id+"_"+e]=function(e){n(l(e,t))})}else f(i,n,t)},removeEventListener:function(t,e,n){var i=t.canvas;if("resize"!==e){var a=((n[v]||{}).proxies||{})[t.id+"_"+e];a&&o(i,e,a)}else g(i)}},p.addEvent=r,p.removeEvent=o},{45:45}],48:[function(t,e,n){"use strict";var i=t(45),a=t(46),r=t(47),o=r._enabled?r:a;e.exports=i.extend({initialize:function(){},acquireContext:function(){},releaseContext:function(){},addEventListener:function(){},removeEventListener:function(){}},o)},{45:45,46:46,47:47}],49:[function(t,e,n){"use strict";var i=t(25),a=t(40),r=t(45);i._set("global",{plugins:{filler:{propagate:!0}}}),e.exports=function(){function t(t,e,n){var i,a=t._model||{},r=a.fill;if(void 0===r&&(r=!!a.backgroundColor),!1===r||null===r)return!1;if(!0===r)return"origin";if(i=parseFloat(r,10),isFinite(i)&&Math.floor(i)===i)return"-"!==r[0]&&"+"!==r[0]||(i=e+i),!(i===e||i<0||i>=n)&&i;switch(r){case"bottom":return"start";case"top":return"end";case"zero":return"origin";case"origin":case"start":case"end":return r;default:return!1}}function e(t){var e,n=t.el._model||{},i=t.el._scale||{},a=t.fill,r=null;if(isFinite(a))return null;if("start"===a?r=void 0===n.scaleBottom?i.bottom:n.scaleBottom:"end"===a?r=void 0===n.scaleTop?i.top:n.scaleTop:void 0!==n.scaleZero?r=n.scaleZero:i.getBasePosition?r=i.getBasePosition():i.getBasePixel&&(r=i.getBasePixel()),void 0!==r&&null!==r){if(void 0!==r.x&&void 0!==r.y)return r;if("number"==typeof r&&isFinite(r))return e=i.isHorizontal(),{x:e?r:null,y:e?null:r}}return null}function n(t,e,n){var i,a=t[e].fill,r=[e];if(!n)return a;for(;!1!==a&&-1===r.indexOf(a);){if(!isFinite(a))return a;if(!(i=t[a]))return!1;if(i.visible)return a;r.push(a),a=i.fill}return!1}function o(t){var e=t.fill,n="dataset";return!1===e?null:(isFinite(e)||(n="boundary"),d[n](t))}function s(t){return t&&!t.skip}function l(t,e,n,i,a){var o;if(i&&a){for(t.moveTo(e[0].x,e[0].y),o=1;o0;--o)r.canvas.lineTo(t,n[o],n[o-1],!0)}}function u(t,e,n,i,a,r){var o,u,d,c,h,f,g,m=e.length,p=i.spanGaps,v=[],y=[],b=0,x=0;for(t.beginPath(),o=0,u=m+!!r;o');for(var n=0;n'),t.data.datasets[n].label&&e.push(t.data.datasets[n].label),e.push("");return e.push(""),e.join("")}}),e.exports=function(t){function e(t,e){return t.usePointStyle?e*Math.SQRT2:t.boxWidth}function n(e,n){var i=new t.Legend({ctx:e.ctx,options:n,chart:e});o.configure(e,i,n),o.addBox(e,i),e.legend=i}var o=t.layoutService,s=r.noop;return t.Legend=a.extend({initialize:function(t){r.extend(this,t),this.legendHitBoxes=[],this.doughnutMode=!1},beforeUpdate:s,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:s,beforeSetDimensions:s,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:s,beforeBuildLabels:s,buildLabels:function(){var t=this,e=t.options.labels||{},n=r.callback(e.generateLabels,[t.chart],t)||[];e.filter&&(n=n.filter(function(n){return e.filter(n,t.chart.data)})),t.options.reverse&&n.reverse(),t.legendItems=n},afterBuildLabels:s,beforeFit:s,fit:function(){var t=this,n=t.options,a=n.labels,o=n.display,s=t.ctx,l=i.global,u=r.valueOrDefault,d=u(a.fontSize,l.defaultFontSize),c=u(a.fontStyle,l.defaultFontStyle),h=u(a.fontFamily,l.defaultFontFamily),f=r.fontString(d,c,h),g=t.legendHitBoxes=[],m=t.minSize,p=t.isHorizontal();if(p?(m.width=t.maxWidth,m.height=o?10:0):(m.width=o?10:0,m.height=t.maxHeight),o)if(s.font=f,p){var v=t.lineWidths=[0],y=t.legendItems.length?d+a.padding:0;s.textAlign="left",s.textBaseline="top",r.each(t.legendItems,function(n,i){var r=e(a,d)+d/2+s.measureText(n.text).width;v[v.length-1]+r+a.padding>=t.width&&(y+=d+a.padding,v[v.length]=t.left),g[i]={left:0,top:0,width:r,height:d},v[v.length-1]+=r+a.padding}),m.height+=y}else{var b=a.padding,x=t.columnWidths=[],_=a.padding,k=0,w=0,M=d+b;r.each(t.legendItems,function(t,n){var i=e(a,d)+d/2+s.measureText(t.text).width;w+M>m.height&&(_+=k+a.padding,x.push(k),k=0,w=0),k=Math.max(k,i),w+=M,g[n]={left:0,top:0,width:i,height:d}}),_+=k,x.push(k),m.width+=_}t.width=m.width,t.height=m.height},afterFit:s,isHorizontal:function(){return"top"===this.options.position||"bottom"===this.options.position},draw:function(){var t=this,n=t.options,a=n.labels,o=i.global,s=o.elements.line,l=t.width,u=t.lineWidths;if(n.display){var d,c=t.ctx,h=r.valueOrDefault,f=h(a.fontColor,o.defaultFontColor),g=h(a.fontSize,o.defaultFontSize),m=h(a.fontStyle,o.defaultFontStyle),p=h(a.fontFamily,o.defaultFontFamily),v=r.fontString(g,m,p);c.textAlign="left",c.textBaseline="middle",c.lineWidth=.5,c.strokeStyle=f,c.fillStyle=f,c.font=v;var y=e(a,g),b=t.legendHitBoxes,x=function(t,e,i){if(!(isNaN(y)||y<=0)){c.save(),c.fillStyle=h(i.fillStyle,o.defaultColor),c.lineCap=h(i.lineCap,s.borderCapStyle),c.lineDashOffset=h(i.lineDashOffset,s.borderDashOffset),c.lineJoin=h(i.lineJoin,s.borderJoinStyle),c.lineWidth=h(i.lineWidth,s.borderWidth),c.strokeStyle=h(i.strokeStyle,o.defaultColor);var a=0===h(i.lineWidth,s.borderWidth);if(c.setLineDash&&c.setLineDash(h(i.lineDash,s.borderDash)),n.labels&&n.labels.usePointStyle){var l=g*Math.SQRT2/2,u=l/Math.SQRT2,d=t+u,f=e+u;r.canvas.drawPoint(c,i.pointStyle,l,d,f)}else a||c.strokeRect(t,e,y,g),c.fillRect(t,e,y,g);c.restore()}},_=function(t,e,n,i){var a=g/2,r=y+a+t,o=e+a;c.fillText(n.text,r,o),n.hidden&&(c.beginPath(),c.lineWidth=2,c.moveTo(r,o),c.lineTo(r+i,o),c.stroke())},k=t.isHorizontal();d=k?{x:t.left+(l-u[0])/2,y:t.top+a.padding,line:0}:{x:t.left+a.padding,y:t.top+a.padding,line:0};var w=g+a.padding;r.each(t.legendItems,function(e,n){var i=c.measureText(e.text).width,r=y+g/2+i,o=d.x,s=d.y;k?o+r>=l&&(s=d.y+=w,d.line++,o=d.x=t.left+(l-u[d.line])/2):s+w>t.bottom&&(o=d.x=o+t.columnWidths[d.line]+a.padding,s=d.y=t.top+a.padding,d.line++),x(o,s,e),b[n].left=o,b[n].top=s,_(o,s,e,i),k?d.x+=r+a.padding:d.y+=w})}},handleEvent:function(t){var e=this,n=e.options,i="mouseup"===t.type?"click":t.type,a=!1;if("mousemove"===i){if(!n.onHover)return}else{if("click"!==i)return;if(!n.onClick)return}var r=t.x,o=t.y;if(r>=e.left&&r<=e.right&&o>=e.top&&o<=e.bottom)for(var s=e.legendHitBoxes,l=0;l=u.left&&r<=u.left+u.width&&o>=u.top&&o<=u.top+u.height){if("click"===i){n.onClick.call(e,t.native,e.legendItems[l]),a=!0;break}if("mousemove"===i){n.onHover.call(e,t.native,e.legendItems[l]),a=!0;break}}}return a}}),{id:"legend",beforeInit:function(t){var e=t.options.legend;e&&n(t,e)},beforeUpdate:function(t){var e=t.options.legend,a=t.legend;e?(r.mergeIf(e,i.global.legend),a?(o.configure(t,a,e),a.options=e):n(t,e)):a&&(o.removeBox(t,a),delete t.legend)},afterEvent:function(t,e){var n=t.legend;n&&n.handleEvent(e)}}}},{25:25,26:26,45:45}],51:[function(t,e,n){"use strict";var i=t(25),a=t(26),r=t(45);i._set("global",{title:{display:!1,fontStyle:"bold",fullWidth:!0,lineHeight:1.2,padding:10,position:"top",text:"",weight:2e3}}),e.exports=function(t){function e(e,i){var a=new t.Title({ctx:e.ctx,options:i,chart:e});n.configure(e,a,i),n.addBox(e,a),e.titleBlock=a}var n=t.layoutService,o=r.noop;return t.Title=a.extend({initialize:function(t){var e=this;r.extend(e,t),e.legendHitBoxes=[]},beforeUpdate:o,update:function(t,e,n){var i=this;return i.beforeUpdate(),i.maxWidth=t,i.maxHeight=e,i.margins=n,i.beforeSetDimensions(),i.setDimensions(),i.afterSetDimensions(),i.beforeBuildLabels(),i.buildLabels(),i.afterBuildLabels(),i.beforeFit(),i.fit(),i.afterFit(),i.afterUpdate(),i.minSize},afterUpdate:o,beforeSetDimensions:o,setDimensions:function(){var t=this;t.isHorizontal()?(t.width=t.maxWidth,t.left=0,t.right=t.width):(t.height=t.maxHeight,t.top=0,t.bottom=t.height),t.paddingLeft=0,t.paddingTop=0,t.paddingRight=0,t.paddingBottom=0,t.minSize={width:0,height:0}},afterSetDimensions:o,beforeBuildLabels:o,buildLabels:o,afterBuildLabels:o,beforeFit:o,fit:function(){var t=this,e=r.valueOrDefault,n=t.options,a=n.display,o=e(n.fontSize,i.global.defaultFontSize),s=t.minSize,l=r.isArray(n.text)?n.text.length:1,u=r.options.toLineHeight(n.lineHeight,o),d=a?l*u+2*n.padding:0;t.isHorizontal()?(s.width=t.maxWidth,s.height=d):(s.width=d,s.height=t.maxHeight),t.width=s.width,t.height=s.height},afterFit:o,isHorizontal:function(){var t=this.options.position;return"top"===t||"bottom"===t},draw:function(){var t=this,e=t.ctx,n=r.valueOrDefault,a=t.options,o=i.global;if(a.display){var s,l,u,d=n(a.fontSize,o.defaultFontSize),c=n(a.fontStyle,o.defaultFontStyle),h=n(a.fontFamily,o.defaultFontFamily),f=r.fontString(d,c,h),g=r.options.toLineHeight(a.lineHeight,d),m=g/2+a.padding,p=0,v=t.top,y=t.left,b=t.bottom,x=t.right;e.fillStyle=n(a.fontColor,o.defaultFontColor),e.font=f,t.isHorizontal()?(l=y+(x-y)/2,u=v+m,s=x-y):(l="left"===a.position?y+m:x-m,u=v+(b-v)/2,s=b-v,p=Math.PI*("left"===a.position?-.5:.5)),e.save(),e.translate(l,u),e.rotate(p),e.textAlign="center",e.textBaseline="middle";var _=a.text;if(r.isArray(_))for(var k=0,w=0;w<_.length;++w)e.fillText(_[w],0,k,s),k+=g;else e.fillText(_,0,0,s);e.restore()}}}),{id:"title",beforeInit:function(t){var n=t.options.title;n&&e(t,n)},beforeUpdate:function(a){var o=a.options.title,s=a.titleBlock;o?(r.mergeIf(o,i.global.title),s?(n.configure(a,s,o),s.options=o):e(a,o)):s&&(t.layoutService.removeBox(a,s),delete a.titleBlock)}}}},{25:25,26:26,45:45}],52:[function(t,e,n){"use strict";e.exports=function(t){var e=t.Scale.extend({getLabels:function(){var t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels},determineDataLimits:function(){var t=this,e=t.getLabels();t.minIndex=0,t.maxIndex=e.length-1;var n;void 0!==t.options.ticks.min&&(n=e.indexOf(t.options.ticks.min),t.minIndex=-1!==n?n:t.minIndex),void 0!==t.options.ticks.max&&(n=e.indexOf(t.options.ticks.max),t.maxIndex=-1!==n?n:t.maxIndex),t.min=e[t.minIndex],t.max=e[t.maxIndex]},buildTicks:function(){var t=this,e=t.getLabels();t.ticks=0===t.minIndex&&t.maxIndex===e.length-1?e:e.slice(t.minIndex,t.maxIndex+1)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.isHorizontal();return i.yLabels&&!a?n.getRightValue(i.datasets[e].data[t]):n.ticks[t-n.minIndex]},getPixelForValue:function(t,e){var n,i=this,a=i.options.offset,r=Math.max(i.maxIndex+1-i.minIndex-(a?0:1),1);if(void 0!==t&&null!==t&&(n=i.isHorizontal()?t.x:t.y),void 0!==n||void 0!==t&&isNaN(e)){var o=i.getLabels();t=n||t;var s=o.indexOf(t);e=-1!==s?s:e}if(i.isHorizontal()){var l=i.width/r,u=l*(e-i.minIndex);return a&&(u+=l/2),i.left+Math.round(u)}var d=i.height/r,c=d*(e-i.minIndex);return a&&(c+=d/2),i.top+Math.round(c)},getPixelForTick:function(t){return this.getPixelForValue(this.ticks[t],t+this.minIndex,null)},getValueForPixel:function(t){var e=this,n=e.options.offset,i=Math.max(e._ticks.length-(n?0:1),1),a=e.isHorizontal(),r=(a?e.width:e.height)/i;return t-=a?e.left:e.top,n&&(t-=r/2),(t<=0?0:Math.round(t/r))+e.minIndex},getBasePixel:function(){return this.bottom}});t.scaleService.registerScaleType("category",e,{position:"bottom"})}},{}],53:[function(t,e,n){"use strict";var i=t(25),a=t(45),r=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:r.formatters.linear}},n=t.LinearScaleBase.extend({determineDataLimits:function(){function t(t){return o?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,i=e.chart,r=i.data.datasets,o=e.isHorizontal();e.min=null,e.max=null;var s=n.stacked;if(void 0===s&&a.each(r,function(e,n){if(!s){var a=i.getDatasetMeta(n);i.isDatasetVisible(n)&&t(a)&&void 0!==a.stack&&(s=!0)}}),n.stacked||s){var l={};a.each(r,function(r,o){var s=i.getDatasetMeta(o),u=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");void 0===l[u]&&(l[u]={positiveValues:[],negativeValues:[]});var d=l[u].positiveValues,c=l[u].negativeValues;i.isDatasetVisible(o)&&t(s)&&a.each(r.data,function(t,i){var a=+e.getRightValue(t);isNaN(a)||s.data[i].hidden||(d[i]=d[i]||0,c[i]=c[i]||0,n.relativePoints?d[i]=100:a<0?c[i]+=a:d[i]+=a)})}),a.each(l,function(t){var n=t.positiveValues.concat(t.negativeValues),i=a.min(n),r=a.max(n);e.min=null===e.min?i:Math.min(e.min,i),e.max=null===e.max?r:Math.max(e.max,r)})}else a.each(r,function(n,r){var o=i.getDatasetMeta(r);i.isDatasetVisible(r)&&t(o)&&a.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:ie.max&&(e.max=i))})});e.min=isFinite(e.min)&&!isNaN(e.min)?e.min:0,e.max=isFinite(e.max)&&!isNaN(e.max)?e.max:1,this.handleTickRangeOptions()},getTickLimit:function(){var t,e=this,n=e.options.ticks;if(e.isHorizontal())t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.width/50));else{var r=a.valueOrDefault(n.fontSize,i.global.defaultFontSize);t=Math.min(n.maxTicksLimit?n.maxTicksLimit:11,Math.ceil(e.height/(2*r)))}return t},handleDirectionalChanges:function(){this.isHorizontal()||this.ticks.reverse()},getLabelForIndex:function(t,e){return+this.getRightValue(this.chart.data.datasets[e].data[t])},getPixelForValue:function(t){var e,n=this,i=n.start,a=+n.getRightValue(t),r=n.end-i;return n.isHorizontal()?(e=n.left+n.width/r*(a-i),Math.round(e)):(e=n.bottom-n.height/r*(a-i),Math.round(e))},getValueForPixel:function(t){var e=this,n=e.isHorizontal(),i=n?e.width:e.height,a=(n?t-e.left:e.bottom-t)/i;return e.start+(e.end-e.start)*a},getPixelForTick:function(t){return this.getPixelForValue(this.ticksAsNumbers[t])}});t.scaleService.registerScaleType("linear",n,e)}},{25:25,34:34,45:45}],54:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e=i.noop;t.LinearScaleBase=t.Scale.extend({getRightValue:function(e){return"string"==typeof e?+e:t.Scale.prototype.getRightValue.call(this,e)},handleTickRangeOptions:function(){var t=this,e=t.options.ticks;if(e.beginAtZero){var n=i.sign(t.min),a=i.sign(t.max);n<0&&a<0?t.max=0:n>0&&a>0&&(t.min=0)}var r=void 0!==e.min||void 0!==e.suggestedMin,o=void 0!==e.max||void 0!==e.suggestedMax;void 0!==e.min?t.min=e.min:void 0!==e.suggestedMin&&(null===t.min?t.min=e.suggestedMin:t.min=Math.min(t.min,e.suggestedMin)),void 0!==e.max?t.max=e.max:void 0!==e.suggestedMax&&(null===t.max?t.max=e.suggestedMax:t.max=Math.max(t.max,e.suggestedMax)),r!==o&&t.min>=t.max&&(r?t.max=t.min+1:t.min=t.max-1),t.min===t.max&&(t.max++,e.beginAtZero||t.min--)},getTickLimit:e,handleDirectionalChanges:e,buildTicks:function(){var t=this,e=t.options.ticks,n=t.getTickLimit(),r={maxTicks:n=Math.max(2,n),min:e.min,max:e.max,stepSize:i.valueOrDefault(e.fixedStepSize,e.stepSize)},o=t.ticks=a.generators.linear(r,t);t.handleDirectionalChanges(),t.max=i.max(o),t.min=i.min(o),e.reverse?(o.reverse(),t.start=t.max,t.end=t.min):(t.start=t.min,t.end=t.max)},convertTicksToLabels:function(){var e=this;e.ticksAsNumbers=e.ticks.slice(),e.zeroLineIndex=e.ticks.indexOf(0),t.Scale.prototype.convertTicksToLabels.call(e)}})}},{34:34,45:45}],55:[function(t,e,n){"use strict";var i=t(45),a=t(34);e.exports=function(t){var e={position:"left",ticks:{callback:a.formatters.logarithmic}},n=t.Scale.extend({determineDataLimits:function(){function t(t){return l?t.xAxisID===e.id:t.yAxisID===e.id}var e=this,n=e.options,a=n.ticks,r=e.chart,o=r.data.datasets,s=i.valueOrDefault,l=e.isHorizontal();e.min=null,e.max=null,e.minNotZero=null;var u=n.stacked;if(void 0===u&&i.each(o,function(e,n){if(!u){var i=r.getDatasetMeta(n);r.isDatasetVisible(n)&&t(i)&&void 0!==i.stack&&(u=!0)}}),n.stacked||u){var d={};i.each(o,function(a,o){var s=r.getDatasetMeta(o),l=[s.type,void 0===n.stacked&&void 0===s.stack?o:"",s.stack].join(".");r.isDatasetVisible(o)&&t(s)&&(void 0===d[l]&&(d[l]=[]),i.each(a.data,function(t,i){var a=d[l],r=+e.getRightValue(t);isNaN(r)||s.data[i].hidden||(a[i]=a[i]||0,n.relativePoints?a[i]=100:a[i]+=r)}))}),i.each(d,function(t){var n=i.min(t),a=i.max(t);e.min=null===e.min?n:Math.min(e.min,n),e.max=null===e.max?a:Math.max(e.max,a)})}else i.each(o,function(n,a){var o=r.getDatasetMeta(a);r.isDatasetVisible(a)&&t(o)&&i.each(n.data,function(t,n){var i=+e.getRightValue(t);isNaN(i)||o.data[n].hidden||(null===e.min?e.min=i:ie.max&&(e.max=i),0!==i&&(null===e.minNotZero||ia?{start:e-n-5,end:e}:{start:e,end:e+n+5}}function l(t){var i,r,l,u=n(t),d=Math.min(t.height/2,t.width/2),c={r:t.width,l:0,t:t.height,b:0},h={};t.ctx.font=u.font,t._pointLabelSizes=[];var f=e(t);for(i=0;ic.r&&(c.r=p.end,h.r=g),v.startc.b&&(c.b=v.end,h.b=g)}t.setReductions(d,c,h)}function u(t){var e=Math.min(t.height/2,t.width/2);t.drawingArea=Math.round(e),t.setCenterPoint(0,0,0,0)}function d(t){return 0===t||180===t?"center":t<180?"left":"right"}function c(t,e,n,i){if(a.isArray(e))for(var r=n.y,o=1.5*i,s=0;s270||t<90)&&(n.y-=e.h)}function f(t){var i=t.ctx,r=a.valueOrDefault,o=t.options,s=o.angleLines,l=o.pointLabels;i.lineWidth=s.lineWidth,i.strokeStyle=s.color;var u=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max),f=n(t);i.textBaseline="top";for(var g=e(t)-1;g>=0;g--){if(s.display){var m=t.getPointPosition(g,u);i.beginPath(),i.moveTo(t.xCenter,t.yCenter),i.lineTo(m.x,m.y),i.stroke(),i.closePath()}if(l.display){var v=t.getPointPosition(g,u+5),y=r(l.fontColor,p.defaultFontColor);i.font=f.font,i.fillStyle=y;var b=t.getIndexAngle(g),x=a.toDegrees(b);i.textAlign=d(x),h(x,t._pointLabelSizes[g],v),c(i,t.pointLabels[g]||"",v,f.size)}}}function g(t,n,i,r){var o=t.ctx;if(o.strokeStyle=a.valueAtIndexOrDefault(n.color,r-1),o.lineWidth=a.valueAtIndexOrDefault(n.lineWidth,r-1),t.options.gridLines.circular)o.beginPath(),o.arc(t.xCenter,t.yCenter,i,0,2*Math.PI),o.closePath(),o.stroke();else{var s=e(t);if(0===s)return;o.beginPath();var l=t.getPointPosition(0,i);o.moveTo(l.x,l.y);for(var u=1;u0&&n>0?e:0)},draw:function(){var t=this,e=t.options,n=e.gridLines,i=e.ticks,r=a.valueOrDefault;if(e.display){var o=t.ctx,s=this.getIndexAngle(0),l=r(i.fontSize,p.defaultFontSize),u=r(i.fontStyle,p.defaultFontStyle),d=r(i.fontFamily,p.defaultFontFamily),c=a.fontString(l,u,d);a.each(t.ticks,function(e,a){if(a>0||i.reverse){var u=t.getDistanceFromCenterForValue(t.ticksAsNumbers[a]);if(n.display&&0!==a&&g(t,n,u,a),i.display){var d=r(i.fontColor,p.defaultFontColor);if(o.font=c,o.save(),o.translate(t.xCenter,t.yCenter),o.rotate(s),i.showLabelBackdrop){var h=o.measureText(e).width;o.fillStyle=i.backdropColor,o.fillRect(-h/2-i.backdropPaddingX,-u-l/2-i.backdropPaddingY,h+2*i.backdropPaddingX,l+2*i.backdropPaddingY)}o.textAlign="center",o.textBaseline="middle",o.fillStyle=d,o.fillText(e,0,-u),o.restore()}}}),(e.angleLines.display||e.pointLabels.display)&&f(t)}}});t.scaleService.registerScaleType("radialLinear",y,v)}},{25:25,34:34,45:45}],57:[function(t,e,n){"use strict";function i(t,e){return t-e}function a(t){var e,n,i,a={},r=[];for(e=0,n=t.length;ee&&s=0&&o<=s;){if(i=o+s>>1,a=t[i-1]||null,r=t[i],!a)return{lo:null,hi:r};if(r[e]n))return{lo:a,hi:r};s=i-1}}return{lo:r,hi:null}}function s(t,e,n,i){var a=o(t,e,n),r=a.lo?a.hi?a.lo:t[t.length-2]:t[0],s=a.lo?a.hi?a.hi:t[t.length-1]:t[1],l=s[e]-r[e],u=l?(n-r[e])/l:0,d=(s[i]-r[i])*u;return r[i]+d}function l(t,e){var n=e.parser,i=e.parser||e.format;return"function"==typeof n?n(t):"string"==typeof t&&"string"==typeof i?v(t,i):(t instanceof v||(t=v(t)),t.isValid()?t:"function"==typeof i?i(t):t)}function u(t,e){if(b.isNullOrUndef(t))return null;var n=e.options.time,i=l(e.getRightValue(t),n);return i.isValid()?(n.round&&i.startOf(n.round),i.valueOf()):null}function d(t,e,n,i){var a,r,o,s=e-t,l=k[n],u=l.size,d=l.steps;if(!d)return Math.ceil(s/((i||1)*u));for(a=0,r=d.length;a=w.indexOf(e);a--)if(r=w[a],k[r].common&&o.as(r)>=t.length)return r;return w[e?w.indexOf(e):0]}function f(t){for(var e=w.indexOf(t)+1,n=w.length;e1?e[1]:i,o=e[0],l=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2),a.time.max||(r=e[e.length-1],o=e.length>1?e[e.length-2]:n,u=(s(t,"time",r,"pos")-s(t,"time",o,"pos"))/2)),{left:l,right:u}}function p(t,e){var n,i,a,r,o=[];for(n=0,i=t.length;n=a&&n<=o&&c.push(n);return i.min=a,i.max=o,i._unit=l.unit||h(c,l.minUnit,i.min,i.max),i._majorUnit=f(i._unit),i._table=r(i._timestamps.data,a,o,s.distribution),i._offsets=m(i._table,c,a,o,s),p(c,i._majorUnit)},getLabelForIndex:function(t,e){var n=this,i=n.chart.data,a=n.options.time,r=i.labels&&t=0&&t0){this.$element.data("active",items[0])}else{this.$element.data("active",null)}if(this.options.addItem){items.push(this.options.addItem)}if(this.options.items=="all"){return this.render(items).show()}else{return this.render(items.slice(0,this.options.items)).show()}},matcher:function(item){var it=this.displayText(item);return~it.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(items){var beginswith=[];var caseSensitive=[];var caseInsensitive=[];var item;while(item=items.shift()){var it=this.displayText(item);if(!it.toLowerCase().indexOf(this.query.toLowerCase()))beginswith.push(item);else if(~it.indexOf(this.query))caseSensitive.push(item);else caseInsensitive.push(item)}return beginswith.concat(caseSensitive,caseInsensitive)},highlighter:function(item){var html=$("
");var query=this.query;var i=item.toLowerCase().indexOf(query.toLowerCase());var len=query.length;var leftPart;var middlePart;var rightPart;var strong;if(len===0){return html.text(item).html()}while(i>-1){leftPart=item.substr(0,i);middlePart=item.substr(i,len);rightPart=item.substr(i+len);strong=$("").text(middlePart);html.append(document.createTextNode(leftPart)).append(strong);item=rightPart;i=item.toLowerCase().indexOf(query.toLowerCase())}return html.append(document.createTextNode(item)).html()},render:function(items){var that=this;var self=this;var activeFound=false;var data=[];var _category=that.options.separator;$.each(items,function(key,value){if(key>0&&value[_category]!==items[key-1][_category]){data.push({__type:"divider"})}if(value[_category]&&(key===0||value[_category]!==items[key-1][_category])){data.push({__type:"category",name:value[_category]})}data.push(value)});items=$(data).map(function(i,item){if((item.__type||false)=="category"){return $(that.options.headerHtml).text(item.name)[0]}if((item.__type||false)=="divider"){return $(that.options.headerDivider)[0]}var text=self.displayText(item);i=$(that.options.item).data("value",item);i.find("a").html(that.highlighter(text,item));if(text==self.$element.val()){i.addClass("active");self.$element.data("active",item);activeFound=true}return i[0]});if(this.autoSelect&&!activeFound){items.filter(":not(.dropdown-header)").first().addClass("active");this.$element.data("active",items.first().data("value"))}this.$menu.html(items);return this},displayText:function(item){return typeof item!=="undefined"&&typeof item.name!="undefined"&&item.name||item},next:function(event){var active=this.$menu.find(".active").removeClass("active");var next=active.next();if(!next.length){next=$(this.$menu.find("li")[0])}next.addClass("active")},prev:function(event){var active=this.$menu.find(".active").removeClass("active");var prev=active.prev();if(!prev.length){prev=this.$menu.find("li").last()}prev.addClass("active")},listen:function(){this.$element.on("focus",$.proxy(this.focus,this)).on("blur",$.proxy(this.blur,this)).on("keypress",$.proxy(this.keypress,this)).on("input",$.proxy(this.input,this)).on("keyup",$.proxy(this.keyup,this));if(this.eventSupported("keydown")){this.$element.on("keydown",$.proxy(this.keydown,this))}this.$menu.on("click",$.proxy(this.click,this)).on("mouseenter","li",$.proxy(this.mouseenter,this)).on("mouseleave","li",$.proxy(this.mouseleave,this)).on("mousedown",$.proxy(this.mousedown,this))},destroy:function(){this.$element.data("typeahead",null);this.$element.data("active",null);this.$element.off("focus").off("blur").off("keypress").off("input").off("keyup");if(this.eventSupported("keydown")){this.$element.off("keydown")}this.$menu.remove();this.destroyed=true},eventSupported:function(eventName){var isSupported=eventName in this.$element;if(!isSupported){this.$element.setAttribute(eventName,"return;");isSupported=typeof this.$element[eventName]==="function"}return isSupported},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:if(e.shiftKey)return;e.preventDefault();this.prev();break;case 40:if(e.shiftKey)return;e.preventDefault();this.next();break}},keydown:function(e){this.suppressKeyPressRepeat=~$.inArray(e.keyCode,[40,38,9,13,27]);if(!this.shown&&e.keyCode==40){this.lookup()}else{this.move(e)}},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},input:function(e){var currentValue=this.$element.val()||this.$element.text();if(this.value!==currentValue){this.value=currentValue;this.lookup()}},keyup:function(e){if(this.destroyed){return}switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break}},focus:function(e){if(!this.focused){this.focused=true;if(this.options.showHintOnFocus&&this.skipShowHintOnFocus!==true){if(this.options.showHintOnFocus==="all"){this.lookup("")}else{this.lookup()}}}if(this.skipShowHintOnFocus){this.skipShowHintOnFocus=false}},blur:function(e){if(!this.mousedover&&!this.mouseddown&&this.shown){this.hide();this.focused=false}else if(this.mouseddown){this.skipShowHintOnFocus=true;this.$element.focus();this.mouseddown=false}},click:function(e){e.preventDefault();this.skipShowHintOnFocus=true;this.select();this.$element.focus();this.hide()},mouseenter:function(e){this.mousedover=true;this.$menu.find(".active").removeClass("active");$(e.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=false;if(!this.focused&&this.shown)this.hide()},mousedown:function(e){this.mouseddown=true;this.$menu.one("mouseup",function(e){this.mouseddown=false}.bind(this))}};var old=$.fn.typeahead;$.fn.typeahead=function(option){var arg=arguments;if(typeof option=="string"&&option=="getActive"){return this.data("active")}return this.each(function(){var $this=$(this);var data=$this.data("typeahead");var options=typeof option=="object"&&option;if(!data)$this.data("typeahead",data=new Typeahead(this,options));if(typeof option=="string"&&data[option]){if(arg.length>1){data[option].apply(data,Array.prototype.slice.call(arg,1))}else{data[option]()}}})};$.fn.typeahead.defaults={source:[],items:8,menu:'',item:'
  • ',minLength:1,scrollHeight:0,autoSelect:true,afterSelect:$.noop,addItem:false,delay:0,separator:"category",headerHtml:'',headerDivider:''};$.fn.typeahead.Constructor=Typeahead;$.fn.typeahead.noConflict=function(){$.fn.typeahead=old;return this};$(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(e){var $this=$(this);if($this.data("typeahead"))return;$this.typeahead($this.data())})}); +!function(a,b){"use strict";"undefined"!=typeof module&&module.exports?module.exports=b(require("jquery")):"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):b(a.jQuery)}(this,function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.defaults,d),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.select=this.options.select||this.select,this.autoSelect="boolean"!=typeof this.options.autoSelect||this.options.autoSelect,this.highlighter=this.options.highlighter||this.highlighter,this.render=this.options.render||this.render,this.updater=this.options.updater||this.updater,this.displayText=this.options.displayText||this.displayText,this.itemLink=this.options.itemLink||this.itemLink,this.followLinkOnSelect=this.options.followLinkOnSelect||this.followLinkOnSelect,this.source=this.options.source,this.delay=this.options.delay,this.$menu=a(this.options.menu),this.$appendTo=this.options.appendTo?a(this.options.appendTo):null,this.fitToElement="boolean"==typeof this.options.fitToElement&&this.options.fitToElement,this.shown=!1,this.listen(),this.showHintOnFocus=("boolean"==typeof this.options.showHintOnFocus||"all"===this.options.showHintOnFocus)&&this.options.showHintOnFocus,this.afterSelect=this.options.afterSelect,this.afterEmptySelect=this.options.afterEmptySelect,this.addItem=!1,this.value=this.$element.val()||this.$element.text(),this.keyPressed=!1,this.focused=this.$element.is(":focus")};b.prototype={constructor:b,setDefault:function(a){if(this.$element.data("active",a),this.autoSelect||a){var b=this.updater(a);b||(b=""),this.$element.val(this.displayText(b)||b).text(this.displayText(b)||b).change(),this.afterSelect(b)}return this.hide()},select:function(){var a=this.$menu.find(".active").data("value");if(this.$element.data("active",a),this.autoSelect||a){var b=this.updater(a);b||(b=""),this.$element.val(this.displayText(b)||b).text(this.displayText(b)||b).change(),this.afterSelect(b),this.followLinkOnSelect&&this.itemLink(a)?(document.location=this.itemLink(a),this.afterSelect(b)):this.followLinkOnSelect&&!this.itemLink(a)?this.afterEmptySelect(b):this.afterSelect(b)}else this.afterEmptySelect(b);return this.hide()},updater:function(a){return a},setSource:function(a){this.source=a},show:function(){var b,c=a.extend({},this.$element.position(),{height:this.$element[0].offsetHeight}),d="function"==typeof this.options.scrollHeight?this.options.scrollHeight.call():this.options.scrollHeight;if(this.shown?b=this.$menu:this.$appendTo?(b=this.$menu.appendTo(this.$appendTo),this.hasSameParent=this.$appendTo.is(this.$element.parent())):(b=this.$menu.insertAfter(this.$element),this.hasSameParent=!0),!this.hasSameParent){b.css("position","fixed");var e=this.$element.offset();c.top=e.top,c.left=e.left}var f=a(b).parent().hasClass("dropup"),g=f?"auto":c.top+c.height+d,h=a(b).hasClass("dropdown-menu-right"),i=h?"auto":c.left;return b.css({top:g,left:i}).show(),!0===this.options.fitToElement&&b.css("width",this.$element.outerWidth()+"px"),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(b){if(this.query=void 0!==b&&null!==b?b:this.$element.val(),this.query.length0?this.$element.data("active",b[0]):this.$element.data("active",null),"all"!=this.options.items&&(b=b.slice(0,this.options.items)),this.options.addItem&&b.push(this.options.addItem),this.render(b).show()):this.shown?this.hide():this},matcher:function(a){return~this.displayText(a).toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(a){for(var b,c=[],d=[],e=[];b=a.shift();){var f=this.displayText(b);f.toLowerCase().indexOf(this.query.toLowerCase())?~f.indexOf(this.query)?d.push(b):e.push(b):c.push(b)}return c.concat(d,e)},highlighter:function(a){var b=this.query;if(""===b)return a;var c,d=a.match(/(>)([^<]*)(<)/g),e=[],f=[];if(d&&d.length)for(c=0;c2&&e.push(d[c]);else e=[],e.push(a);b=b.replace(/[\(\)\/\.\*\+\?\[\]]/g,function(a){return"\\"+a});var g,h=new RegExp(b,"g");for(c=0;c0&&f.push(e[c]);for(c=0;c$&"));return a},render:function(b){var c=this,d=this,e=!1,f=[],g=c.options.separator;return a.each(b,function(a,c){a>0&&c[g]!==b[a-1][g]&&f.push({__type:"divider"}),!c[g]||0!==a&&c[g]===b[a-1][g]||f.push({__type:"category",name:c[g]}),f.push(c)}),b=a(f).map(function(b,f){if("category"==(f.__type||!1))return a(c.options.headerHtml).text(f.name)[0];if("divider"==(f.__type||!1))return a(c.options.headerDivider)[0];var g=d.displayText(f);return b=a(c.options.item).data("value",f),b.find(c.options.itemContentSelector).addBack(c.options.itemContentSelector).html(c.highlighter(g,f)),this.followLinkOnSelect&&b.find("a").attr("href",d.itemLink(f)),g==d.$element.val()&&(b.addClass("active"),d.$element.data("active",f),e=!0),b[0]}),this.autoSelect&&!e&&(b.filter(":not(.dropdown-header)").first().addClass("active"),this.$element.data("active",b.first().data("value"))),this.$menu.html(b),this},displayText:function(a){return void 0!==a&&void 0!==a.name?a.name:a},itemLink:function(a){return null},next:function(b){var c=this.$menu.find(".active").removeClass("active"),d=c.next();d.length||(d=a(this.$menu.find("li")[0])),d.addClass("active");var e=this.updater(d.data("value"));this.$element.val(this.displayText(e)||e)},prev:function(a){var b=this.$menu.find(".active").removeClass("active"),c=b.prev();c.length||(c=this.$menu.find("li").last()),c.addClass("active");var d=this.updater(c.data("value"));this.$element.val(this.displayText(d)||d)},listen:function(){this.$element.on("focus.bootstrap3Typeahead",a.proxy(this.focus,this)).on("blur.bootstrap3Typeahead",a.proxy(this.blur,this)).on("keypress.bootstrap3Typeahead",a.proxy(this.keypress,this)).on("propertychange.bootstrap3Typeahead input.bootstrap3Typeahead",a.proxy(this.input,this)).on("keyup.bootstrap3Typeahead",a.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown.bootstrap3Typeahead",a.proxy(this.keydown,this)),"ontouchstart"in document.documentElement?this.$menu.on("touchstart","li",a.proxy(this.touchstart,this)).on("touchend","li",a.proxy(this.click,this)):this.$menu.on("click",a.proxy(this.click,this)).on("mouseenter","li",a.proxy(this.mouseenter,this)).on("mouseleave","li",a.proxy(this.mouseleave,this)).on("mousedown",a.proxy(this.mousedown,this))},destroy:function(){this.$element.data("typeahead",null),this.$element.data("active",null),this.$element.unbind("focus.bootstrap3Typeahead").unbind("blur.bootstrap3Typeahead").unbind("keypress.bootstrap3Typeahead").unbind("propertychange.bootstrap3Typeahead input.bootstrap3Typeahead").unbind("keyup.bootstrap3Typeahead"),this.eventSupported("keydown")&&this.$element.unbind("keydown.bootstrap3-typeahead"),this.$menu.remove(),this.destroyed=!0},eventSupported:function(a){var b=a in this.$element;return b||(this.$element.setAttribute(a,"return;"),b="function"==typeof this.$element[a]),b},move:function(a){if(this.shown)switch(a.keyCode){case 9:case 13:case 27:a.preventDefault();break;case 38:if(a.shiftKey)return;a.preventDefault(),this.prev();break;case 40:if(a.shiftKey)return;a.preventDefault(),this.next()}},keydown:function(b){this.keyPressed=!0,this.suppressKeyPressRepeat=~a.inArray(b.keyCode,[40,38,9,13,27]),this.shown||40!=b.keyCode?this.move(b):this.lookup()},keypress:function(a){this.suppressKeyPressRepeat||this.move(a)},input:function(a){var b=this.$element.val()||this.$element.text();this.value!==b&&(this.value=b,this.lookup())},keyup:function(a){if(!this.destroyed)switch(a.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:if(!this.shown||this.showHintOnFocus&&!this.keyPressed)return;this.select();break;case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide()}},focus:function(a){this.focused||(this.focused=!0,this.keyPressed=!1,this.options.showHintOnFocus&&!0!==this.skipShowHintOnFocus&&("all"===this.options.showHintOnFocus?this.lookup(""):this.lookup())),this.skipShowHintOnFocus&&(this.skipShowHintOnFocus=!1)},blur:function(a){this.mousedover||this.mouseddown||!this.shown?this.mouseddown&&(this.skipShowHintOnFocus=!0,this.$element.focus(),this.mouseddown=!1):(this.select(),this.hide(),this.focused=!1,this.keyPressed=!1)},click:function(a){a.preventDefault(),this.skipShowHintOnFocus=!0,this.select(),this.$element.focus(),this.hide()},mouseenter:function(b){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},mouseleave:function(a){this.mousedover=!1,!this.focused&&this.shown&&this.hide()},mousedown:function(a){this.mouseddown=!0,this.$menu.one("mouseup",function(a){this.mouseddown=!1}.bind(this))},touchstart:function(b){b.preventDefault(),this.$menu.find(".active").removeClass("active"),a(b.currentTarget).addClass("active")},touchend:function(a){a.preventDefault(),this.select(),this.$element.focus()}};var c=a.fn.typeahead;a.fn.typeahead=function(c){var d=arguments;return"string"==typeof c&&"getActive"==c?this.data("active"):this.each(function(){var e=a(this),f=e.data("typeahead"),g="object"==typeof c&&c;f||e.data("typeahead",f=new b(this,g)),"string"==typeof c&&f[c]&&(d.length>1?f[c].apply(f,Array.prototype.slice.call(d,1)):f[c]())})},b.defaults={source:[],items:8,menu:'',item:'
  • ',itemContentSelector:"a",minLength:1,scrollHeight:0,autoSelect:!0,afterSelect:a.noop,afterEmptySelect:a.noop,addItem:!1,followLinkOnSelect:!1,delay:0,separator:"category",headerHtml:'',headerDivider:''},a.fn.typeahead.Constructor=b,a.fn.typeahead.noConflict=function(){return a.fn.typeahead=c,this},a(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(b){var c=a(this);c.data("typeahead")||c.typeahead(c.data())})}); \ No newline at end of file diff --git a/public/js/lib/daterangepicker.js b/public/js/lib/daterangepicker.js index fdf10f9f44..822afc9a80 100755 --- a/public/js/lib/daterangepicker.js +++ b/public/js/lib/daterangepicker.js @@ -1,5 +1,5 @@ /** - * @version: 2.1.25 + * @version: 2.1.30 * @author: Dan Grossman http://www.dangrossman.info/ * @copyright: Copyright (c) 2012-2017 Dan Grossman. All rights reserved. * @license: Licensed under the MIT license. See http://www.opensource.org/licenses/mit-license.php @@ -11,7 +11,7 @@ // AMD. Make globaly available as well define(['moment', 'jquery'], function (moment, jquery) { if (!jquery.fn) jquery.fn = {}; // webpack server rendering - return (root.daterangepicker = factory(moment, jquery)); + return factory(moment, jquery); }); } else if (typeof module === 'object' && module.exports) { // Node / Browserify @@ -27,8 +27,8 @@ // Browser globals root.daterangepicker = factory(root.moment, root.jQuery); } -}(this, function (moment, $) { - var DateRangePicker = function (element, options, cb) { +}(this, function(moment, $) { + var DateRangePicker = function(element, options, cb) { //default settings for options this.parentEl = 'body'; @@ -78,8 +78,7 @@ firstDay: moment.localeData().firstDayOfWeek() }; - this.callback = function () { - }; + this.callback = function() { }; //some state information this.isShowing = false; @@ -163,7 +162,7 @@ if (typeof options.locale.weekLabel === 'string') this.locale.weekLabel = options.locale.weekLabel; - if (typeof options.locale.customRangeLabel === 'string') { + if (typeof options.locale.customRangeLabel === 'string'){ //Support unicode chars in the custom range name. var elem = document.createElement('textarea'); elem.innerHTML = options.locale.customRangeLabel; @@ -288,7 +287,7 @@ //if no start/end dates set, check if an input element contains initial values if (typeof options.startDate === 'undefined' && typeof options.endDate === 'undefined') { if ($(this.element).is('input[type=text]')) { - var val = $(this.element).val(), + var val = $(this.element).val(), split = val.split(this.locale.separator); start = end = null; @@ -397,7 +396,7 @@ //swap the position of the predefined ranges if opens right if (typeof options.ranges !== 'undefined' && this.opens == 'right') { - this.container.find('.ranges').prependTo(this.container.find('.calendar.left').parent()); + this.container.find('.ranges').prependTo( this.container.find('.calendar.left').parent() ); } //apply CSS classes and labels to buttons @@ -425,7 +424,8 @@ .on('click.daterangepicker', '.daterangepicker_input input', $.proxy(this.showCalendars, this)) .on('focus.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsFocused, this)) .on('blur.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsBlurred, this)) - .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this)); + .on('change.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsChanged, this)) + .on('keydown.daterangepicker', '.daterangepicker_input input', $.proxy(this.formInputsKeydown, this)); this.container.find('.ranges') .on('click.daterangepicker', 'button.applyBtn', $.proxy(this.clickApply, this)) @@ -439,10 +439,11 @@ 'click.daterangepicker': $.proxy(this.show, this), 'focus.daterangepicker': $.proxy(this.show, this), 'keyup.daterangepicker': $.proxy(this.elementChanged, this), - 'keydown.daterangepicker': $.proxy(this.keydown, this) + 'keydown.daterangepicker': $.proxy(this.keydown, this) //IE 11 compatibility }); } else { this.element.on('click.daterangepicker', $.proxy(this.toggle, this)); + this.element.on('keydown.daterangepicker', $.proxy(this.toggle, this)); } // @@ -463,7 +464,7 @@ constructor: DateRangePicker, - setStartDate: function (startDate) { + setStartDate: function(startDate) { if (typeof startDate === 'string') this.startDate = moment(startDate, this.locale.format); @@ -494,7 +495,7 @@ this.updateMonthsInView(); }, - setEndDate: function (endDate) { + setEndDate: function(endDate) { if (typeof endDate === 'string') this.endDate = moment(endDate, this.locale.format); @@ -502,7 +503,7 @@ this.endDate = moment(endDate); if (!this.timePicker) - this.endDate = this.endDate.endOf('day'); + this.endDate = this.endDate.add(1,'d').startOf('day').subtract(1,'second'); if (this.timePicker && this.timePickerIncrement) this.endDate.minute(Math.round(this.endDate.minute() / this.timePickerIncrement) * this.timePickerIncrement); @@ -524,15 +525,15 @@ this.updateMonthsInView(); }, - isInvalidDate: function () { + isInvalidDate: function() { return false; }, - isCustomDate: function () { + isCustomDate: function() { return false; }, - updateView: function () { + updateView: function() { if (this.timePicker) { this.renderTimePicker('left'); this.renderTimePicker('right'); @@ -554,7 +555,7 @@ this.updateFormInputs(); }, - updateMonthsInView: function () { + updateMonthsInView: function() { if (this.endDate) { //if both dates are visible already, do nothing @@ -585,7 +586,7 @@ } }, - updateCalendars: function () { + updateCalendars: function() { if (this.timePicker) { var hour, minute, second; @@ -626,7 +627,7 @@ this.calculateChosenLabel(); }, - renderCalendar: function (side) { + renderCalendar: function(side) { // // Build the matrix of dates that will populate the calendar @@ -763,7 +764,7 @@ if (this.showWeekNumbers || this.showISOWeekNumbers) html += '' + this.locale.weekLabel + ''; - $.each(this.locale.daysOfWeek, function (index, dayOfWeek) { + $.each(this.locale.daysOfWeek, function(index, dayOfWeek) { html += '' + dayOfWeek + ''; }); @@ -860,7 +861,7 @@ }, - renderTimePicker: function (side) { + renderTimePicker: function(side) { // Don't bother updating the time picker if it's currently disabled // because an end date hasn't been clicked yet @@ -1021,7 +1022,7 @@ }, - updateFormInputs: function () { + updateFormInputs: function() { //ignore mouse movements while an above-calendar text input has focus if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) @@ -1039,8 +1040,8 @@ }, - move: function () { - var parentOffset = {top: 0, left: 0}, + move: function() { + var parentOffset = { top: 0, left: 0 }, containerTop; var parentRightEdge = $(window).width(); if (!this.parentEl.is('body')) { @@ -1097,13 +1098,11 @@ } }, - show: function (e) { + show: function(e) { if (this.isShowing) return; // Create a click proxy that is private to this instance of datepicker, for unbinding - this._outsideClickProxy = $.proxy(function (e) { - this.outsideClick(e); - }, this); + this._outsideClickProxy = $.proxy(function(e) { this.outsideClick(e); }, this); // Bind global datepicker mousedown for hiding and $(document) @@ -1116,9 +1115,7 @@ .on('focusin.daterangepicker', this._outsideClickProxy); // Reposition the picker if the window is resized while it's open - $(window).on('resize.daterangepicker', $.proxy(function (e) { - this.move(e); - }, this)); + $(window).on('resize.daterangepicker', $.proxy(function(e) { this.move(e); }, this)); this.oldStartDate = this.startDate.clone(); this.oldEndDate = this.endDate.clone(); @@ -1131,7 +1128,7 @@ this.isShowing = true; }, - hide: function (e) { + hide: function(e) { if (!this.isShowing) return; //incomplete date selection, revert to last values @@ -1154,7 +1151,7 @@ this.isShowing = false; }, - toggle: function (e) { + toggle: function(e) { if (this.isShowing) { this.hide(); } else { @@ -1162,7 +1159,7 @@ } }, - outsideClick: function (e) { + outsideClick: function(e) { var target = $(e.target); // if the page is clicked anywhere except within the daterangerpicker/button // itself then call this.hide() @@ -1177,18 +1174,18 @@ this.element.trigger('outsideClick.daterangepicker', this); }, - showCalendars: function () { + showCalendars: function() { this.container.addClass('show-calendar'); this.move(); this.element.trigger('showCalendar.daterangepicker', this); }, - hideCalendars: function () { + hideCalendars: function() { this.container.removeClass('show-calendar'); this.element.trigger('hideCalendar.daterangepicker', this); }, - hoverRange: function (e) { + hoverRange: function(e) { //ignore mouse movements while an above-calendar text input has focus if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) @@ -1206,7 +1203,7 @@ }, - clickRange: function (e) { + clickRange: function(e) { var label = e.target.getAttribute('data-range-key'); this.chosenLabel = label; if (label == this.locale.customRangeLabel) { @@ -1227,7 +1224,7 @@ } }, - clickPrev: function (e) { + clickPrev: function(e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.subtract(1, 'month'); @@ -1239,7 +1236,7 @@ this.updateCalendars(); }, - clickNext: function (e) { + clickNext: function(e) { var cal = $(e.target).parents('.calendar'); if (cal.hasClass('left')) { this.leftCalendar.month.add(1, 'month'); @@ -1251,7 +1248,7 @@ this.updateCalendars(); }, - hoverDate: function (e) { + hoverDate: function(e) { //ignore mouse movements while an above-calendar text input has focus //if (this.container.find('input[name=daterangepicker_start]').is(":focus") || this.container.find('input[name=daterangepicker_end]').is(":focus")) @@ -1278,7 +1275,7 @@ var rightCalendar = this.rightCalendar; var startDate = this.startDate; if (!this.endDate) { - this.container.find('.calendar tbody td').each(function (index, el) { + this.container.find('.calendar tbody td').each(function(index, el) { //skip week numbers, only look at dates if ($(el).hasClass('week')) return; @@ -1300,7 +1297,7 @@ }, - clickDate: function (e) { + clickDate: function(e) { if (!$(e.target).hasClass('available')) return; @@ -1378,7 +1375,9 @@ var i = 0; for (var range in this.ranges) { if (this.timePicker) { - if (this.startDate.isSame(this.ranges[range][0]) && this.endDate.isSame(this.ranges[range][1])) { + var format = this.timePickerSeconds ? "YYYY-MM-DD hh:mm:ss" : "YYYY-MM-DD hh:mm"; + //ignore times when comparing dates if time picker seconds is not enabled + if (this.startDate.format(format) == this.ranges[range][0].format(format) && this.endDate.format(format) == this.ranges[range][1].format(format)) { customRange = false; this.chosenLabel = this.container.find('.ranges li:eq(' + i + ')').addClass('active').html(); break; @@ -1403,22 +1402,22 @@ } }, - clickApply: function (e) { + clickApply: function(e) { this.hide(); this.element.trigger('apply.daterangepicker', this); }, - clickCancel: function (e) { + clickCancel: function(e) { this.startDate = this.oldStartDate; this.endDate = this.oldEndDate; this.hide(); this.element.trigger('cancel.daterangepicker', this); }, - monthOrYearChanged: function (e) { - var isLeft = $(e.target).closest('.calendar').hasClass('left'), + monthOrYearChanged: function(e) { + var isLeft = $(e.target).closest('.calendar').hasClass('left'), leftOrRight = isLeft ? 'left' : 'right', - cal = this.container.find('.calendar.' + leftOrRight); + cal = this.container.find('.calendar.'+leftOrRight); // Month must be Number for new moment versions var month = parseInt(cal.find('.monthselect').val(), 10); @@ -1457,9 +1456,9 @@ this.updateCalendars(); }, - timeChanged: function (e) { + timeChanged: function(e) { - var cal = $(e.target).closest('.calendar'), + var cal = $(e.target).closest('.calendar'), isLeft = cal.hasClass('left'); var hour = parseInt(cal.find('.hourselect').val(), 10); @@ -1505,7 +1504,7 @@ }, - formInputsChanged: function (e) { + formInputsChanged: function(e) { var isRight = $(e.target).closest('.calendar').hasClass('right'); var start = moment(this.container.find('input[name="daterangepicker_start"]').val(), this.locale.format); var end = moment(this.container.find('input[name="daterangepicker_end"]').val(), this.locale.format); @@ -1529,13 +1528,13 @@ this.updateView(); }, - formInputsFocused: function (e) { + formInputsFocused: function(e) { // Highlight the focused input this.container.find('input[name="daterangepicker_start"], input[name="daterangepicker_end"]').removeClass('active'); $(e.target).addClass('active'); - // Set the state such that if the user goes back to using a mouse, + // Set the state such that if the user goes back to using a mouse, // the calendars are aware we're selecting the end of the range, not // the start. This allows someone to edit the end of a date range without // re-selecting the beginning, by clicking on the end date input then @@ -1549,7 +1548,7 @@ }, - formInputsBlurred: function (e) { + formInputsBlurred: function(e) { // this function has one purpose right now: if you tab from the first // text input to the second in the UI, the endDate is nulled so that @@ -1567,14 +1566,26 @@ }, - elementChanged: function () { + formInputsKeydown: function(e) { + // This function ensures that if the 'enter' key was pressed in the input, then the calendars + // are updated with the startDate and endDate. + // This behaviour is automatic in Chrome/Firefox/Edge but not in IE 11 hence why this exists. + // Other browsers and versions of IE are untested and the behaviour is unknown. + if (e.keyCode === 13) { + // Prevent the calendar from being updated twice on Chrome/Firefox/Edge + e.preventDefault(); + this.formInputsChanged(e); + } + }, + + + elementChanged: function() { if (!this.element.is('input')) return; if (!this.element.val().length) return; - if (this.element.val().length < this.locale.format.length) return; var dateString = this.element.val().split(this.locale.separator), - start = null, - end = null; + start = null, + end = null; if (dateString.length === 2) { start = moment(dateString[0], this.locale.format); @@ -1593,14 +1604,22 @@ this.updateView(); }, - keydown: function (e) { + keydown: function(e) { //hide on tab or enter if ((e.keyCode === 9) || (e.keyCode === 13)) { this.hide(); } + + //hide on esc and prevent propagation + if (e.keyCode === 27) { + e.preventDefault(); + e.stopPropagation(); + + this.hide(); + } }, - updateElement: function () { + updateElement: function() { if (this.element.is('input') && !this.singleDatePicker && this.autoUpdateInput) { this.element.val(this.startDate.format(this.locale.format) + this.locale.separator + this.endDate.format(this.locale.format)); this.element.trigger('change'); @@ -1610,7 +1629,7 @@ } }, - remove: function () { + remove: function() { this.container.remove(); this.element.off('.daterangepicker'); this.element.removeData(); @@ -1618,16 +1637,17 @@ }; - $.fn.daterangepicker = function (options, callback) { - this.each(function () { + $.fn.daterangepicker = function(options, callback) { + var implementOptions = $.extend(true, {}, $.fn.daterangepicker.defaultOptions, options); + this.each(function() { var el = $(this); if (el.data('daterangepicker')) el.data('daterangepicker').remove(); - el.data('daterangepicker', new DateRangePicker(el, options, callback)); + el.data('daterangepicker', new DateRangePicker(el, implementOptions, callback)); }); return this; }; return DateRangePicker; -})); +})); \ No newline at end of file diff --git a/public/js/lib/jquery-3.1.1.min.js b/public/js/lib/jquery-3.1.1.min.js deleted file mode 100644 index 4c5be4c0fb..0000000000 --- a/public/js/lib/jquery-3.1.1.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v3.1.1 | (c) jQuery Foundation | jquery.org/license */ -!function(a,b){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){"use strict";var c=[],d=a.document,e=Object.getPrototypeOf,f=c.slice,g=c.concat,h=c.push,i=c.indexOf,j={},k=j.toString,l=j.hasOwnProperty,m=l.toString,n=m.call(Object),o={};function p(a,b){b=b||d;var c=b.createElement("script");c.text=a,b.head.appendChild(c).parentNode.removeChild(c)}var q="3.1.1",r=function(a,b){return new r.fn.init(a,b)},s=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,t=/^-ms-/,u=/-([a-z])/g,v=function(a,b){return b.toUpperCase()};r.fn=r.prototype={jquery:q,constructor:r,length:0,toArray:function(){return f.call(this)},get:function(a){return null==a?f.call(this):a<0?this[a+this.length]:this[a]},pushStack:function(a){var b=r.merge(this.constructor(),a);return b.prevObject=this,b},each:function(a){return r.each(this,a)},map:function(a){return this.pushStack(r.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(f.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(a<0?b:0);return this.pushStack(c>=0&&c0&&b-1 in a)}var x=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+1*new Date,v=a.document,w=0,x=0,y=ha(),z=ha(),A=ha(),B=function(a,b){return a===b&&(l=!0),0},C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=function(a,b){for(var c=0,d=a.length;c+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(N),U=new RegExp("^"+L+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L+"|[*])"),ATTR:new RegExp("^"+M),PSEUDO:new RegExp("^"+N),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),aa=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:d<0?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)},ba=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ca=function(a,b){return b?"\0"===a?"\ufffd":a.slice(0,-1)+"\\"+a.charCodeAt(a.length-1).toString(16)+" ":"\\"+a},da=function(){m()},ea=ta(function(a){return a.disabled===!0&&("form"in a||"label"in a)},{dir:"parentNode",next:"legend"});try{G.apply(D=H.call(v.childNodes),v.childNodes),D[v.childNodes.length].nodeType}catch(fa){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function ga(a,b,d,e){var f,h,j,k,l,o,r,s=b&&b.ownerDocument,w=b?b.nodeType:9;if(d=d||[],"string"!=typeof a||!a||1!==w&&9!==w&&11!==w)return d;if(!e&&((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,p)){if(11!==w&&(l=Z.exec(a)))if(f=l[1]){if(9===w){if(!(j=b.getElementById(f)))return d;if(j.id===f)return d.push(j),d}else if(s&&(j=s.getElementById(f))&&t(b,j)&&j.id===f)return d.push(j),d}else{if(l[2])return G.apply(d,b.getElementsByTagName(a)),d;if((f=l[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(f)),d}if(c.qsa&&!A[a+" "]&&(!q||!q.test(a))){if(1!==w)s=b,r=a;else if("object"!==b.nodeName.toLowerCase()){(k=b.getAttribute("id"))?k=k.replace(ba,ca):b.setAttribute("id",k=u),o=g(a),h=o.length;while(h--)o[h]="#"+k+" "+sa(o[h]);r=o.join(","),s=$.test(a)&&qa(b.parentNode)||b}if(r)try{return G.apply(d,s.querySelectorAll(r)),d}catch(x){}finally{k===u&&b.removeAttribute("id")}}}return i(a.replace(P,"$1"),b,d,e)}function ha(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function ia(a){return a[u]=!0,a}function ja(a){var b=n.createElement("fieldset");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function ka(a,b){var c=a.split("|"),e=c.length;while(e--)d.attrHandle[c[e]]=b}function la(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&a.sourceIndex-b.sourceIndex;if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function ma(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function na(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function oa(a){return function(b){return"form"in b?b.parentNode&&b.disabled===!1?"label"in b?"label"in b.parentNode?b.parentNode.disabled===a:b.disabled===a:b.isDisabled===a||b.isDisabled!==!a&&ea(b)===a:b.disabled===a:"label"in b&&b.disabled===a}}function pa(a){return ia(function(b){return b=+b,ia(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function qa(a){return a&&"undefined"!=typeof a.getElementsByTagName&&a}c=ga.support={},f=ga.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return!!b&&"HTML"!==b.nodeName},m=ga.setDocument=function(a){var b,e,g=a?a.ownerDocument||a:v;return g!==n&&9===g.nodeType&&g.documentElement?(n=g,o=n.documentElement,p=!f(n),v!==n&&(e=n.defaultView)&&e.top!==e&&(e.addEventListener?e.addEventListener("unload",da,!1):e.attachEvent&&e.attachEvent("onunload",da)),c.attributes=ja(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ja(function(a){return a.appendChild(n.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(n.getElementsByClassName),c.getById=ja(function(a){return o.appendChild(a).id=u,!n.getElementsByName||!n.getElementsByName(u).length}),c.getById?(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){return a.getAttribute("id")===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c=b.getElementById(a);return c?[c]:[]}}):(d.filter.ID=function(a){var b=a.replace(_,aa);return function(a){var c="undefined"!=typeof a.getAttributeNode&&a.getAttributeNode("id");return c&&c.value===b}},d.find.ID=function(a,b){if("undefined"!=typeof b.getElementById&&p){var c,d,e,f=b.getElementById(a);if(f){if(c=f.getAttributeNode("id"),c&&c.value===a)return[f];e=b.getElementsByName(a),d=0;while(f=e[d++])if(c=f.getAttributeNode("id"),c&&c.value===a)return[f]}return[]}}),d.find.TAG=c.getElementsByTagName?function(a,b){return"undefined"!=typeof b.getElementsByTagName?b.getElementsByTagName(a):c.qsa?b.querySelectorAll(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){if("undefined"!=typeof b.getElementsByClassName&&p)return b.getElementsByClassName(a)},r=[],q=[],(c.qsa=Y.test(n.querySelectorAll))&&(ja(function(a){o.appendChild(a).innerHTML="",a.querySelectorAll("[msallowcapture^='']").length&&q.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll("[id~="+u+"-]").length||q.push("~="),a.querySelectorAll(":checked").length||q.push(":checked"),a.querySelectorAll("a#"+u+"+*").length||q.push(".#.+[+~]")}),ja(function(a){a.innerHTML="";var b=n.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+K+"*[*^$|!~]?="),2!==a.querySelectorAll(":enabled").length&&q.push(":enabled",":disabled"),o.appendChild(a).disabled=!0,2!==a.querySelectorAll(":disabled").length&&q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=Y.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ja(function(a){c.disconnectedMatch=s.call(a,"*"),s.call(a,"[s!='']:x"),r.push("!=",N)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=Y.test(o.compareDocumentPosition),t=b||Y.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===n||a.ownerDocument===v&&t(v,a)?-1:b===n||b.ownerDocument===v&&t(v,b)?1:k?I(k,a)-I(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,e=a.parentNode,f=b.parentNode,g=[a],h=[b];if(!e||!f)return a===n?-1:b===n?1:e?-1:f?1:k?I(k,a)-I(k,b):0;if(e===f)return la(a,b);c=a;while(c=c.parentNode)g.unshift(c);c=b;while(c=c.parentNode)h.unshift(c);while(g[d]===h[d])d++;return d?la(g[d],h[d]):g[d]===v?-1:h[d]===v?1:0},n):n},ga.matches=function(a,b){return ga(a,null,null,b)},ga.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(S,"='$1']"),c.matchesSelector&&p&&!A[b+" "]&&(!r||!r.test(b))&&(!q||!q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return ga(b,n,null,[a]).length>0},ga.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},ga.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},ga.escape=function(a){return(a+"").replace(ba,ca)},ga.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},ga.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=ga.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=ga.selectors={cacheLength:50,createPseudo:ia,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(_,aa),a[3]=(a[3]||a[4]||a[5]||"").replace(_,aa),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||ga.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&ga.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return V.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&T.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(_,aa).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||"undefined"!=typeof a.getAttribute&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=ga.attr(d,a);return null==e?"!="===b:!b||(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e.replace(O," ")+" ").indexOf(c)>-1:"|="===b&&(e===c||e.slice(0,c.length+1)===c+"-"))}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h,t=!1;if(q){if(f){while(p){m=b;while(m=m[p])if(h?m.nodeName.toLowerCase()===r:1===m.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){m=q,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n&&j[2],m=n&&q.childNodes[n];while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if(1===m.nodeType&&++t&&m===b){k[a]=[w,n,t];break}}else if(s&&(m=b,l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),j=k[a]||[],n=j[0]===w&&j[1],t=n),t===!1)while(m=++n&&m&&m[p]||(t=n=0)||o.pop())if((h?m.nodeName.toLowerCase()===r:1===m.nodeType)&&++t&&(s&&(l=m[u]||(m[u]={}),k=l[m.uniqueID]||(l[m.uniqueID]={}),k[a]=[w,t]),m===b))break;return t-=e,t===d||t%d===0&&t/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||ga.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?ia(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:ia(function(a){var b=[],c=[],d=h(a.replace(P,"$1"));return d[u]?ia(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),b[0]=null,!c.pop()}}),has:ia(function(a){return function(b){return ga(a,b).length>0}}),contains:ia(function(a){return a=a.replace(_,aa),function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:ia(function(a){return U.test(a||"")||ga.error("unsupported lang: "+a),a=a.replace(_,aa).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:oa(!1),disabled:oa(!0),checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:pa(function(){return[0]}),last:pa(function(a,b){return[b-1]}),eq:pa(function(a,b,c){return[c<0?c+b:c]}),even:pa(function(a,b){for(var c=0;c=0;)a.push(d);return a}),gt:pa(function(a,b,c){for(var d=c<0?c+b:c;++d1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function va(a,b,c){for(var d=0,e=b.length;d-1&&(f[j]=!(g[j]=l))}}else r=wa(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ya(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=ta(function(a){return a===b},h,!0),l=ta(function(a){return I(b,a)>-1},h,!0),m=[function(a,c,d){var e=!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d));return b=null,e}];i1&&ua(m),i>1&&sa(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(P,"$1"),c,i0,e=a.length>0,f=function(f,g,h,i,k){var l,o,q,r=0,s="0",t=f&&[],u=[],v=j,x=f||e&&d.find.TAG("*",k),y=w+=null==v?1:Math.random()||.1,z=x.length;for(k&&(j=g===n||g||k);s!==z&&null!=(l=x[s]);s++){if(e&&l){o=0,g||l.ownerDocument===n||(m(l),h=!p);while(q=a[o++])if(q(l,g||n,h)){i.push(l);break}k&&(w=y)}c&&((l=!q&&l)&&r--,f&&t.push(l))}if(r+=s,c&&s!==r){o=0;while(q=b[o++])q(t,u,g,h);if(f){if(r>0)while(s--)t[s]||u[s]||(u[s]=E.call(i));u=wa(u)}G.apply(i,u),k&&!f&&u.length>0&&r+b.length>1&&ga.uniqueSort(i)}return k&&(w=y,j=v),t};return c?ia(f):f}return h=ga.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=ya(b[c]),f[u]?d.push(f):e.push(f);f=A(a,za(e,d)),f.selector=a}return f},i=ga.select=function(a,b,c,e){var f,i,j,k,l,m="function"==typeof a&&a,n=!e&&g(a=m.selector||a);if(c=c||[],1===n.length){if(i=n[0]=n[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&9===b.nodeType&&p&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(_,aa),b)||[])[0],!b)return c;m&&(b=b.parentNode),a=a.slice(i.shift().value.length)}f=V.needsContext.test(a)?0:i.length;while(f--){if(j=i[f],d.relative[k=j.type])break;if((l=d.find[k])&&(e=l(j.matches[0].replace(_,aa),$.test(i[0].type)&&qa(b.parentNode)||b))){if(i.splice(f,1),a=e.length&&sa(i),!a)return G.apply(c,e),c;break}}}return(m||h(a,n))(e,b,!p,c,!b||$.test(a)&&qa(b.parentNode)||b),c},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ja(function(a){return 1&a.compareDocumentPosition(n.createElement("fieldset"))}),ja(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||ka("type|href|height|width",function(a,b,c){if(!c)return a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ja(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||ka("value",function(a,b,c){if(!c&&"input"===a.nodeName.toLowerCase())return a.defaultValue}),ja(function(a){return null==a.getAttribute("disabled")})||ka(J,function(a,b,c){var d;if(!c)return a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),ga}(a);r.find=x,r.expr=x.selectors,r.expr[":"]=r.expr.pseudos,r.uniqueSort=r.unique=x.uniqueSort,r.text=x.getText,r.isXMLDoc=x.isXML,r.contains=x.contains,r.escapeSelector=x.escape;var y=function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&r(a).is(c))break;d.push(a)}return d},z=function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c},A=r.expr.match.needsContext,B=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,C=/^.[^:#\[\.,]*$/;function D(a,b,c){return r.isFunction(b)?r.grep(a,function(a,d){return!!b.call(a,d,a)!==c}):b.nodeType?r.grep(a,function(a){return a===b!==c}):"string"!=typeof b?r.grep(a,function(a){return i.call(b,a)>-1!==c}):C.test(b)?r.filter(b,a,c):(b=r.filter(b,a),r.grep(a,function(a){return i.call(b,a)>-1!==c&&1===a.nodeType}))}r.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?r.find.matchesSelector(d,a)?[d]:[]:r.find.matches(a,r.grep(b,function(a){return 1===a.nodeType}))},r.fn.extend({find:function(a){var b,c,d=this.length,e=this;if("string"!=typeof a)return this.pushStack(r(a).filter(function(){for(b=0;b1?r.uniqueSort(c):c},filter:function(a){return this.pushStack(D(this,a||[],!1))},not:function(a){return this.pushStack(D(this,a||[],!0))},is:function(a){return!!D(this,"string"==typeof a&&A.test(a)?r(a):a||[],!1).length}});var E,F=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,G=r.fn.init=function(a,b,c){var e,f;if(!a)return this;if(c=c||E,"string"==typeof a){if(e="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:F.exec(a),!e||!e[1]&&b)return!b||b.jquery?(b||c).find(a):this.constructor(b).find(a);if(e[1]){if(b=b instanceof r?b[0]:b,r.merge(this,r.parseHTML(e[1],b&&b.nodeType?b.ownerDocument||b:d,!0)),B.test(e[1])&&r.isPlainObject(b))for(e in b)r.isFunction(this[e])?this[e](b[e]):this.attr(e,b[e]);return this}return f=d.getElementById(e[2]),f&&(this[0]=f,this.length=1),this}return a.nodeType?(this[0]=a,this.length=1,this):r.isFunction(a)?void 0!==c.ready?c.ready(a):a(r):r.makeArray(a,this)};G.prototype=r.fn,E=r(d);var H=/^(?:parents|prev(?:Until|All))/,I={children:!0,contents:!0,next:!0,prev:!0};r.fn.extend({has:function(a){var b=r(a,this),c=b.length;return this.filter(function(){for(var a=0;a-1:1===c.nodeType&&r.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?r.uniqueSort(f):f)},index:function(a){return a?"string"==typeof a?i.call(r(a),this[0]):i.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(r.uniqueSort(r.merge(this.get(),r(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function J(a,b){while((a=a[b])&&1!==a.nodeType);return a}r.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return y(a,"parentNode")},parentsUntil:function(a,b,c){return y(a,"parentNode",c)},next:function(a){return J(a,"nextSibling")},prev:function(a){return J(a,"previousSibling")},nextAll:function(a){return y(a,"nextSibling")},prevAll:function(a){return y(a,"previousSibling")},nextUntil:function(a,b,c){return y(a,"nextSibling",c)},prevUntil:function(a,b,c){return y(a,"previousSibling",c)},siblings:function(a){return z((a.parentNode||{}).firstChild,a)},children:function(a){return z(a.firstChild)},contents:function(a){return a.contentDocument||r.merge([],a.childNodes)}},function(a,b){r.fn[a]=function(c,d){var e=r.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=r.filter(d,e)),this.length>1&&(I[a]||r.uniqueSort(e),H.test(a)&&e.reverse()),this.pushStack(e)}});var K=/[^\x20\t\r\n\f]+/g;function L(a){var b={};return r.each(a.match(K)||[],function(a,c){b[c]=!0}),b}r.Callbacks=function(a){a="string"==typeof a?L(a):r.extend({},a);var b,c,d,e,f=[],g=[],h=-1,i=function(){for(e=a.once,d=b=!0;g.length;h=-1){c=g.shift();while(++h-1)f.splice(c,1),c<=h&&h--}),this},has:function(a){return a?r.inArray(a,f)>-1:f.length>0},empty:function(){return f&&(f=[]),this},disable:function(){return e=g=[],f=c="",this},disabled:function(){return!f},lock:function(){return e=g=[],c||b||(f=c=""),this},locked:function(){return!!e},fireWith:function(a,c){return e||(c=c||[],c=[a,c.slice?c.slice():c],g.push(c),b||i()),this},fire:function(){return j.fireWith(this,arguments),this},fired:function(){return!!d}};return j};function M(a){return a}function N(a){throw a}function O(a,b,c){var d;try{a&&r.isFunction(d=a.promise)?d.call(a).done(b).fail(c):a&&r.isFunction(d=a.then)?d.call(a,b,c):b.call(void 0,a)}catch(a){c.call(void 0,a)}}r.extend({Deferred:function(b){var c=[["notify","progress",r.Callbacks("memory"),r.Callbacks("memory"),2],["resolve","done",r.Callbacks("once memory"),r.Callbacks("once memory"),0,"resolved"],["reject","fail",r.Callbacks("once memory"),r.Callbacks("once memory"),1,"rejected"]],d="pending",e={state:function(){return d},always:function(){return f.done(arguments).fail(arguments),this},"catch":function(a){return e.then(null,a)},pipe:function(){var a=arguments;return r.Deferred(function(b){r.each(c,function(c,d){var e=r.isFunction(a[d[4]])&&a[d[4]];f[d[1]](function(){var a=e&&e.apply(this,arguments);a&&r.isFunction(a.promise)?a.promise().progress(b.notify).done(b.resolve).fail(b.reject):b[d[0]+"With"](this,e?[a]:arguments)})}),a=null}).promise()},then:function(b,d,e){var f=0;function g(b,c,d,e){return function(){var h=this,i=arguments,j=function(){var a,j;if(!(b=f&&(d!==N&&(h=void 0,i=[a]),c.rejectWith(h,i))}};b?k():(r.Deferred.getStackHook&&(k.stackTrace=r.Deferred.getStackHook()),a.setTimeout(k))}}return r.Deferred(function(a){c[0][3].add(g(0,a,r.isFunction(e)?e:M,a.notifyWith)),c[1][3].add(g(0,a,r.isFunction(b)?b:M)),c[2][3].add(g(0,a,r.isFunction(d)?d:N))}).promise()},promise:function(a){return null!=a?r.extend(a,e):e}},f={};return r.each(c,function(a,b){var g=b[2],h=b[5];e[b[1]]=g.add,h&&g.add(function(){d=h},c[3-a][2].disable,c[0][2].lock),g.add(b[3].fire),f[b[0]]=function(){return f[b[0]+"With"](this===f?void 0:this,arguments),this},f[b[0]+"With"]=g.fireWith}),e.promise(f),b&&b.call(f,f),f},when:function(a){var b=arguments.length,c=b,d=Array(c),e=f.call(arguments),g=r.Deferred(),h=function(a){return function(c){d[a]=this,e[a]=arguments.length>1?f.call(arguments):c,--b||g.resolveWith(d,e)}};if(b<=1&&(O(a,g.done(h(c)).resolve,g.reject),"pending"===g.state()||r.isFunction(e[c]&&e[c].then)))return g.then();while(c--)O(e[c],h(c),g.reject);return g.promise()}});var P=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;r.Deferred.exceptionHook=function(b,c){a.console&&a.console.warn&&b&&P.test(b.name)&&a.console.warn("jQuery.Deferred exception: "+b.message,b.stack,c)},r.readyException=function(b){a.setTimeout(function(){throw b})};var Q=r.Deferred();r.fn.ready=function(a){return Q.then(a)["catch"](function(a){r.readyException(a)}),this},r.extend({isReady:!1,readyWait:1,holdReady:function(a){a?r.readyWait++:r.ready(!0)},ready:function(a){(a===!0?--r.readyWait:r.isReady)||(r.isReady=!0,a!==!0&&--r.readyWait>0||Q.resolveWith(d,[r]))}}),r.ready.then=Q.then;function R(){d.removeEventListener("DOMContentLoaded",R), -a.removeEventListener("load",R),r.ready()}"complete"===d.readyState||"loading"!==d.readyState&&!d.documentElement.doScroll?a.setTimeout(r.ready):(d.addEventListener("DOMContentLoaded",R),a.addEventListener("load",R));var S=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===r.type(c)){e=!0;for(h in c)S(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,r.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(r(a),c)})),b))for(;h1,null,!0)},removeData:function(a){return this.each(function(){W.remove(this,a)})}}),r.extend({queue:function(a,b,c){var d;if(a)return b=(b||"fx")+"queue",d=V.get(a,b),c&&(!d||r.isArray(c)?d=V.access(a,b,r.makeArray(c)):d.push(c)),d||[]},dequeue:function(a,b){b=b||"fx";var c=r.queue(a,b),d=c.length,e=c.shift(),f=r._queueHooks(a,b),g=function(){r.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return V.get(a,c)||V.access(a,c,{empty:r.Callbacks("once memory").add(function(){V.remove(a,[b+"queue",c])})})}}),r.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length\x20\t\r\n\f]+)/i,ka=/^$|\/(?:java|ecma)script/i,la={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};la.optgroup=la.option,la.tbody=la.tfoot=la.colgroup=la.caption=la.thead,la.th=la.td;function ma(a,b){var c;return c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[],void 0===b||b&&r.nodeName(a,b)?r.merge([a],c):c}function na(a,b){for(var c=0,d=a.length;c-1)e&&e.push(f);else if(j=r.contains(f.ownerDocument,f),g=ma(l.appendChild(f),"script"),j&&na(g),c){k=0;while(f=g[k++])ka.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),o.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",o.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var qa=d.documentElement,ra=/^key/,sa=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,ta=/^([^.]*)(?:\.(.+)|)/;function ua(){return!0}function va(){return!1}function wa(){try{return d.activeElement}catch(a){}}function xa(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)xa(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=va;else if(!e)return a;return 1===f&&(g=e,e=function(a){return r().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=r.guid++)),a.each(function(){r.event.add(this,b,e,d,c)})}r.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.get(a);if(q){c.handler&&(f=c,c=f.handler,e=f.selector),e&&r.find.matchesSelector(qa,e),c.guid||(c.guid=r.guid++),(i=q.events)||(i=q.events={}),(g=q.handle)||(g=q.handle=function(b){return"undefined"!=typeof r&&r.event.triggered!==b.type?r.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(K)||[""],j=b.length;while(j--)h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n&&(l=r.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=r.event.special[n]||{},k=r.extend({type:n,origType:p,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&r.expr.match.needsContext.test(e),namespace:o.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,o,g)!==!1||a.addEventListener&&a.addEventListener(n,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),r.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,o,p,q=V.hasData(a)&&V.get(a);if(q&&(i=q.events)){b=(b||"").match(K)||[""],j=b.length;while(j--)if(h=ta.exec(b[j])||[],n=p=h[1],o=(h[2]||"").split(".").sort(),n){l=r.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+o.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&p!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,o,q.handle)!==!1||r.removeEvent(a,n,q.handle),delete i[n])}else for(n in i)r.event.remove(a,n+b[j],c,d,!0);r.isEmptyObject(i)&&V.remove(a,"handle events")}},dispatch:function(a){var b=r.event.fix(a),c,d,e,f,g,h,i=new Array(arguments.length),j=(V.get(this,"events")||{})[b.type]||[],k=r.event.special[b.type]||{};for(i[0]=b,c=1;c=1))for(;j!==this;j=j.parentNode||this)if(1===j.nodeType&&("click"!==a.type||j.disabled!==!0)){for(f=[],g={},c=0;c-1:r.find(e,this,null,[j]).length),g[e]&&f.push(d);f.length&&h.push({elem:j,handlers:f})}return j=this,i\x20\t\r\n\f]*)[^>]*)\/>/gi,za=/\s*$/g;function Da(a,b){return r.nodeName(a,"table")&&r.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a:a}function Ea(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function Fa(a){var b=Ba.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ga(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(V.hasData(a)&&(f=V.access(a),g=V.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;c1&&"string"==typeof q&&!o.checkClone&&Aa.test(q))return a.each(function(e){var f=a.eq(e);s&&(b[0]=q.call(this,e,f.html())),Ia(f,b,c,d)});if(m&&(e=pa(b,a[0].ownerDocument,!1,a,d),f=e.firstChild,1===e.childNodes.length&&(e=f),f||d)){for(h=r.map(ma(e,"script"),Ea),i=h.length;l")},clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=r.contains(a.ownerDocument,a);if(!(o.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||r.isXMLDoc(a)))for(g=ma(h),f=ma(a),d=0,e=f.length;d0&&na(g,!i&&ma(a,"script")),h},cleanData:function(a){for(var b,c,d,e=r.event.special,f=0;void 0!==(c=a[f]);f++)if(T(c)){if(b=c[V.expando]){if(b.events)for(d in b.events)e[d]?r.event.remove(c,d):r.removeEvent(c,d,b.handle);c[V.expando]=void 0}c[W.expando]&&(c[W.expando]=void 0)}}}),r.fn.extend({detach:function(a){return Ja(this,a,!0)},remove:function(a){return Ja(this,a)},text:function(a){return S(this,function(a){return void 0===a?r.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=a)})},null,a,arguments.length)},append:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.appendChild(a)}})},prepend:function(){return Ia(this,arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=Da(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return Ia(this,arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(r.cleanData(ma(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null!=a&&a,b=null==b?a:b,this.map(function(){return r.clone(this,a,b)})},html:function(a){return S(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!za.test(a)&&!la[(ja.exec(a)||["",""])[1].toLowerCase()]){a=r.htmlPrefilter(a);try{for(;c1)}});function Ya(a,b,c,d,e){return new Ya.prototype.init(a,b,c,d,e)}r.Tween=Ya,Ya.prototype={constructor:Ya,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||r.easing._default,this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(r.cssNumber[c]?"":"px")},cur:function(){var a=Ya.propHooks[this.prop];return a&&a.get?a.get(this):Ya.propHooks._default.get(this)},run:function(a){var b,c=Ya.propHooks[this.prop];return this.options.duration?this.pos=b=r.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):this.pos=b=a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Ya.propHooks._default.set(this),this}},Ya.prototype.init.prototype=Ya.prototype,Ya.propHooks={_default:{get:function(a){var b;return 1!==a.elem.nodeType||null!=a.elem[a.prop]&&null==a.elem.style[a.prop]?a.elem[a.prop]:(b=r.css(a.elem,a.prop,""),b&&"auto"!==b?b:0)},set:function(a){r.fx.step[a.prop]?r.fx.step[a.prop](a):1!==a.elem.nodeType||null==a.elem.style[r.cssProps[a.prop]]&&!r.cssHooks[a.prop]?a.elem[a.prop]=a.now:r.style(a.elem,a.prop,a.now+a.unit)}}},Ya.propHooks.scrollTop=Ya.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},r.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2},_default:"swing"},r.fx=Ya.prototype.init,r.fx.step={};var Za,$a,_a=/^(?:toggle|show|hide)$/,ab=/queueHooks$/;function bb(){$a&&(a.requestAnimationFrame(bb),r.fx.tick())}function cb(){return a.setTimeout(function(){Za=void 0}),Za=r.now()}function db(a,b){var c,d=0,e={height:a};for(b=b?1:0;d<4;d+=2-b)c=ba[d],e["margin"+c]=e["padding"+c]=a;return b&&(e.opacity=e.width=a),e}function eb(a,b,c){for(var d,e=(hb.tweeners[b]||[]).concat(hb.tweeners["*"]),f=0,g=e.length;f1)},removeAttr:function(a){return this.each(function(){r.removeAttr(this,a)})}}),r.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return"undefined"==typeof a.getAttribute?r.prop(a,b,c):(1===f&&r.isXMLDoc(a)||(e=r.attrHooks[b.toLowerCase()]||(r.expr.match.bool.test(b)?ib:void 0)), -void 0!==c?null===c?void r.removeAttr(a,b):e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:(a.setAttribute(b,c+""),c):e&&"get"in e&&null!==(d=e.get(a,b))?d:(d=r.find.attr(a,b),null==d?void 0:d))},attrHooks:{type:{set:function(a,b){if(!o.radioValue&&"radio"===b&&r.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}},removeAttr:function(a,b){var c,d=0,e=b&&b.match(K);if(e&&1===a.nodeType)while(c=e[d++])a.removeAttribute(c)}}),ib={set:function(a,b,c){return b===!1?r.removeAttr(a,c):a.setAttribute(c,c),c}},r.each(r.expr.match.bool.source.match(/\w+/g),function(a,b){var c=jb[b]||r.find.attr;jb[b]=function(a,b,d){var e,f,g=b.toLowerCase();return d||(f=jb[g],jb[g]=e,e=null!=c(a,b,d)?g:null,jb[g]=f),e}});var kb=/^(?:input|select|textarea|button)$/i,lb=/^(?:a|area)$/i;r.fn.extend({prop:function(a,b){return S(this,r.prop,a,b,arguments.length>1)},removeProp:function(a){return this.each(function(){delete this[r.propFix[a]||a]})}}),r.extend({prop:function(a,b,c){var d,e,f=a.nodeType;if(3!==f&&8!==f&&2!==f)return 1===f&&r.isXMLDoc(a)||(b=r.propFix[b]||b,e=r.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=r.find.attr(a,"tabindex");return b?parseInt(b,10):kb.test(a.nodeName)||lb.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),o.optSelected||(r.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}}),r.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){r.propFix[this.toLowerCase()]=this});function mb(a){var b=a.match(K)||[];return b.join(" ")}function nb(a){return a.getAttribute&&a.getAttribute("class")||""}r.fn.extend({addClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).addClass(a.call(this,b,nb(this)))});if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])d.indexOf(" "+f+" ")<0&&(d+=f+" ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},removeClass:function(a){var b,c,d,e,f,g,h,i=0;if(r.isFunction(a))return this.each(function(b){r(this).removeClass(a.call(this,b,nb(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof a&&a){b=a.match(K)||[];while(c=this[i++])if(e=nb(c),d=1===c.nodeType&&" "+mb(e)+" "){g=0;while(f=b[g++])while(d.indexOf(" "+f+" ")>-1)d=d.replace(" "+f+" "," ");h=mb(d),e!==h&&c.setAttribute("class",h)}}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):r.isFunction(a)?this.each(function(c){r(this).toggleClass(a.call(this,c,nb(this),b),b)}):this.each(function(){var b,d,e,f;if("string"===c){d=0,e=r(this),f=a.match(K)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else void 0!==a&&"boolean"!==c||(b=nb(this),b&&V.set(this,"__className__",b),this.setAttribute&&this.setAttribute("class",b||a===!1?"":V.get(this,"__className__")||""))})},hasClass:function(a){var b,c,d=0;b=" "+a+" ";while(c=this[d++])if(1===c.nodeType&&(" "+mb(nb(c))+" ").indexOf(b)>-1)return!0;return!1}});var ob=/\r/g;r.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=r.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,r(this).val()):a,null==e?e="":"number"==typeof e?e+="":r.isArray(e)&&(e=r.map(e,function(a){return null==a?"":a+""})),b=r.valHooks[this.type]||r.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=r.valHooks[e.type]||r.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(ob,""):null==c?"":c)}}}),r.extend({valHooks:{option:{get:function(a){var b=r.find.attr(a,"value");return null!=b?b:mb(r.text(a))}},select:{get:function(a){var b,c,d,e=a.options,f=a.selectedIndex,g="select-one"===a.type,h=g?null:[],i=g?f+1:e.length;for(d=f<0?i:g?f:0;d-1)&&(c=!0);return c||(a.selectedIndex=-1),f}}}}),r.each(["radio","checkbox"],function(){r.valHooks[this]={set:function(a,b){if(r.isArray(b))return a.checked=r.inArray(r(a).val(),b)>-1}},o.checkOn||(r.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var pb=/^(?:focusinfocus|focusoutblur)$/;r.extend(r.event,{trigger:function(b,c,e,f){var g,h,i,j,k,m,n,o=[e||d],p=l.call(b,"type")?b.type:b,q=l.call(b,"namespace")?b.namespace.split("."):[];if(h=i=e=e||d,3!==e.nodeType&&8!==e.nodeType&&!pb.test(p+r.event.triggered)&&(p.indexOf(".")>-1&&(q=p.split("."),p=q.shift(),q.sort()),k=p.indexOf(":")<0&&"on"+p,b=b[r.expando]?b:new r.Event(p,"object"==typeof b&&b),b.isTrigger=f?2:3,b.namespace=q.join("."),b.rnamespace=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=e),c=null==c?[b]:r.makeArray(c,[b]),n=r.event.special[p]||{},f||!n.trigger||n.trigger.apply(e,c)!==!1)){if(!f&&!n.noBubble&&!r.isWindow(e)){for(j=n.delegateType||p,pb.test(j+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),i=h;i===(e.ownerDocument||d)&&o.push(i.defaultView||i.parentWindow||a)}g=0;while((h=o[g++])&&!b.isPropagationStopped())b.type=g>1?j:n.bindType||p,m=(V.get(h,"events")||{})[b.type]&&V.get(h,"handle"),m&&m.apply(h,c),m=k&&h[k],m&&m.apply&&T(h)&&(b.result=m.apply(h,c),b.result===!1&&b.preventDefault());return b.type=p,f||b.isDefaultPrevented()||n._default&&n._default.apply(o.pop(),c)!==!1||!T(e)||k&&r.isFunction(e[p])&&!r.isWindow(e)&&(i=e[k],i&&(e[k]=null),r.event.triggered=p,e[p](),r.event.triggered=void 0,i&&(e[k]=i)),b.result}},simulate:function(a,b,c){var d=r.extend(new r.Event,c,{type:a,isSimulated:!0});r.event.trigger(d,null,b)}}),r.fn.extend({trigger:function(a,b){return this.each(function(){r.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];if(c)return r.event.trigger(a,b,c,!0)}}),r.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(a,b){r.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),r.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),o.focusin="onfocusin"in a,o.focusin||r.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){r.event.simulate(b,a.target,r.event.fix(a))};r.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=V.access(d,b);e||d.addEventListener(a,c,!0),V.access(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=V.access(d,b)-1;e?V.access(d,b,e):(d.removeEventListener(a,c,!0),V.remove(d,b))}}});var qb=a.location,rb=r.now(),sb=/\?/;r.parseXML=function(b){var c;if(!b||"string"!=typeof b)return null;try{c=(new a.DOMParser).parseFromString(b,"text/xml")}catch(d){c=void 0}return c&&!c.getElementsByTagName("parsererror").length||r.error("Invalid XML: "+b),c};var tb=/\[\]$/,ub=/\r?\n/g,vb=/^(?:submit|button|image|reset|file)$/i,wb=/^(?:input|select|textarea|keygen)/i;function xb(a,b,c,d){var e;if(r.isArray(b))r.each(b,function(b,e){c||tb.test(a)?d(a,e):xb(a+"["+("object"==typeof e&&null!=e?b:"")+"]",e,c,d)});else if(c||"object"!==r.type(b))d(a,b);else for(e in b)xb(a+"["+e+"]",b[e],c,d)}r.param=function(a,b){var c,d=[],e=function(a,b){var c=r.isFunction(b)?b():b;d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(null==c?"":c)};if(r.isArray(a)||a.jquery&&!r.isPlainObject(a))r.each(a,function(){e(this.name,this.value)});else for(c in a)xb(c,a[c],b,e);return d.join("&")},r.fn.extend({serialize:function(){return r.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=r.prop(this,"elements");return a?r.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!r(this).is(":disabled")&&wb.test(this.nodeName)&&!vb.test(a)&&(this.checked||!ia.test(a))}).map(function(a,b){var c=r(this).val();return null==c?null:r.isArray(c)?r.map(c,function(a){return{name:b.name,value:a.replace(ub,"\r\n")}}):{name:b.name,value:c.replace(ub,"\r\n")}}).get()}});var yb=/%20/g,zb=/#.*$/,Ab=/([?&])_=[^&]*/,Bb=/^(.*?):[ \t]*([^\r\n]*)$/gm,Cb=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Db=/^(?:GET|HEAD)$/,Eb=/^\/\//,Fb={},Gb={},Hb="*/".concat("*"),Ib=d.createElement("a");Ib.href=qb.href;function Jb(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(K)||[];if(r.isFunction(c))while(d=f[e++])"+"===d[0]?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Kb(a,b,c,d){var e={},f=a===Gb;function g(h){var i;return e[h]=!0,r.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Lb(a,b){var c,d,e=r.ajaxSettings.flatOptions||{};for(c in b)void 0!==b[c]&&((e[c]?a:d||(d={}))[c]=b[c]);return d&&r.extend(!0,a,d),a}function Mb(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===d&&(d=a.mimeType||b.getResponseHeader("Content-Type"));if(d)for(e in h)if(h[e]&&h[e].test(d)){i.unshift(e);break}if(i[0]in c)f=i[0];else{for(e in c){if(!i[0]||a.converters[e+" "+i[0]]){f=e;break}g||(g=e)}f=f||g}if(f)return f!==i[0]&&i.unshift(f),c[f]}function Nb(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}r.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:qb.href,type:"GET",isLocal:Cb.test(qb.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Hb,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":r.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Lb(Lb(a,r.ajaxSettings),b):Lb(r.ajaxSettings,a)},ajaxPrefilter:Jb(Fb),ajaxTransport:Jb(Gb),ajax:function(b,c){"object"==typeof b&&(c=b,b=void 0),c=c||{};var e,f,g,h,i,j,k,l,m,n,o=r.ajaxSetup({},c),p=o.context||o,q=o.context&&(p.nodeType||p.jquery)?r(p):r.event,s=r.Deferred(),t=r.Callbacks("once memory"),u=o.statusCode||{},v={},w={},x="canceled",y={readyState:0,getResponseHeader:function(a){var b;if(k){if(!h){h={};while(b=Bb.exec(g))h[b[1].toLowerCase()]=b[2]}b=h[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return k?g:null},setRequestHeader:function(a,b){return null==k&&(a=w[a.toLowerCase()]=w[a.toLowerCase()]||a,v[a]=b),this},overrideMimeType:function(a){return null==k&&(o.mimeType=a),this},statusCode:function(a){var b;if(a)if(k)y.always(a[y.status]);else for(b in a)u[b]=[u[b],a[b]];return this},abort:function(a){var b=a||x;return e&&e.abort(b),A(0,b),this}};if(s.promise(y),o.url=((b||o.url||qb.href)+"").replace(Eb,qb.protocol+"//"),o.type=c.method||c.type||o.method||o.type,o.dataTypes=(o.dataType||"*").toLowerCase().match(K)||[""],null==o.crossDomain){j=d.createElement("a");try{j.href=o.url,j.href=j.href,o.crossDomain=Ib.protocol+"//"+Ib.host!=j.protocol+"//"+j.host}catch(z){o.crossDomain=!0}}if(o.data&&o.processData&&"string"!=typeof o.data&&(o.data=r.param(o.data,o.traditional)),Kb(Fb,o,c,y),k)return y;l=r.event&&o.global,l&&0===r.active++&&r.event.trigger("ajaxStart"),o.type=o.type.toUpperCase(),o.hasContent=!Db.test(o.type),f=o.url.replace(zb,""),o.hasContent?o.data&&o.processData&&0===(o.contentType||"").indexOf("application/x-www-form-urlencoded")&&(o.data=o.data.replace(yb,"+")):(n=o.url.slice(f.length),o.data&&(f+=(sb.test(f)?"&":"?")+o.data,delete o.data),o.cache===!1&&(f=f.replace(Ab,"$1"),n=(sb.test(f)?"&":"?")+"_="+rb++ +n),o.url=f+n),o.ifModified&&(r.lastModified[f]&&y.setRequestHeader("If-Modified-Since",r.lastModified[f]),r.etag[f]&&y.setRequestHeader("If-None-Match",r.etag[f])),(o.data&&o.hasContent&&o.contentType!==!1||c.contentType)&&y.setRequestHeader("Content-Type",o.contentType),y.setRequestHeader("Accept",o.dataTypes[0]&&o.accepts[o.dataTypes[0]]?o.accepts[o.dataTypes[0]]+("*"!==o.dataTypes[0]?", "+Hb+"; q=0.01":""):o.accepts["*"]);for(m in o.headers)y.setRequestHeader(m,o.headers[m]);if(o.beforeSend&&(o.beforeSend.call(p,y,o)===!1||k))return y.abort();if(x="abort",t.add(o.complete),y.done(o.success),y.fail(o.error),e=Kb(Gb,o,c,y)){if(y.readyState=1,l&&q.trigger("ajaxSend",[y,o]),k)return y;o.async&&o.timeout>0&&(i=a.setTimeout(function(){y.abort("timeout")},o.timeout));try{k=!1,e.send(v,A)}catch(z){if(k)throw z;A(-1,z)}}else A(-1,"No Transport");function A(b,c,d,h){var j,m,n,v,w,x=c;k||(k=!0,i&&a.clearTimeout(i),e=void 0,g=h||"",y.readyState=b>0?4:0,j=b>=200&&b<300||304===b,d&&(v=Mb(o,y,d)),v=Nb(o,v,y,j),j?(o.ifModified&&(w=y.getResponseHeader("Last-Modified"),w&&(r.lastModified[f]=w),w=y.getResponseHeader("etag"),w&&(r.etag[f]=w)),204===b||"HEAD"===o.type?x="nocontent":304===b?x="notmodified":(x=v.state,m=v.data,n=v.error,j=!n)):(n=x,!b&&x||(x="error",b<0&&(b=0))),y.status=b,y.statusText=(c||x)+"",j?s.resolveWith(p,[m,x,y]):s.rejectWith(p,[y,x,n]),y.statusCode(u),u=void 0,l&&q.trigger(j?"ajaxSuccess":"ajaxError",[y,o,j?m:n]),t.fireWith(p,[y,x]),l&&(q.trigger("ajaxComplete",[y,o]),--r.active||r.event.trigger("ajaxStop")))}return y},getJSON:function(a,b,c){return r.get(a,b,c,"json")},getScript:function(a,b){return r.get(a,void 0,b,"script")}}),r.each(["get","post"],function(a,b){r[b]=function(a,c,d,e){return r.isFunction(c)&&(e=e||d,d=c,c=void 0),r.ajax(r.extend({url:a,type:b,dataType:e,data:c,success:d},r.isPlainObject(a)&&a))}}),r._evalUrl=function(a){return r.ajax({url:a,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},r.fn.extend({wrapAll:function(a){var b;return this[0]&&(r.isFunction(a)&&(a=a.call(this[0])),b=r(a,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstElementChild)a=a.firstElementChild;return a}).append(this)),this},wrapInner:function(a){return r.isFunction(a)?this.each(function(b){r(this).wrapInner(a.call(this,b))}):this.each(function(){var b=r(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=r.isFunction(a);return this.each(function(c){r(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(a){return this.parent(a).not("body").each(function(){r(this).replaceWith(this.childNodes)}),this}}),r.expr.pseudos.hidden=function(a){return!r.expr.pseudos.visible(a)},r.expr.pseudos.visible=function(a){return!!(a.offsetWidth||a.offsetHeight||a.getClientRects().length)},r.ajaxSettings.xhr=function(){try{return new a.XMLHttpRequest}catch(b){}};var Ob={0:200,1223:204},Pb=r.ajaxSettings.xhr();o.cors=!!Pb&&"withCredentials"in Pb,o.ajax=Pb=!!Pb,r.ajaxTransport(function(b){var c,d;if(o.cors||Pb&&!b.crossDomain)return{send:function(e,f){var g,h=b.xhr();if(h.open(b.type,b.url,b.async,b.username,b.password),b.xhrFields)for(g in b.xhrFields)h[g]=b.xhrFields[g];b.mimeType&&h.overrideMimeType&&h.overrideMimeType(b.mimeType),b.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest");for(g in e)h.setRequestHeader(g,e[g]);c=function(a){return function(){c&&(c=d=h.onload=h.onerror=h.onabort=h.onreadystatechange=null,"abort"===a?h.abort():"error"===a?"number"!=typeof h.status?f(0,"error"):f(h.status,h.statusText):f(Ob[h.status]||h.status,h.statusText,"text"!==(h.responseType||"text")||"string"!=typeof h.responseText?{binary:h.response}:{text:h.responseText},h.getAllResponseHeaders()))}},h.onload=c(),d=h.onerror=c("error"),void 0!==h.onabort?h.onabort=d:h.onreadystatechange=function(){4===h.readyState&&a.setTimeout(function(){c&&d()})},c=c("abort");try{h.send(b.hasContent&&b.data||null)}catch(i){if(c)throw i}},abort:function(){c&&c()}}}),r.ajaxPrefilter(function(a){a.crossDomain&&(a.contents.script=!1)}),r.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(a){return r.globalEval(a),a}}}),r.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET")}),r.ajaxTransport("script",function(a){if(a.crossDomain){var b,c;return{send:function(e,f){b=r(" diff --git a/resources/views/partials/breadcrumbs.twig b/resources/views/partials/breadcrumbs.twig new file mode 100644 index 0000000000..8aa74ca38c --- /dev/null +++ b/resources/views/partials/breadcrumbs.twig @@ -0,0 +1,16 @@ + +{% if breadcrumbs|length > 0 %} + + +{% endif %} + + + diff --git a/resources/views/reports/default/multi-year.twig b/resources/views/reports/default/multi-year.twig index 26b116700b..5cf206ed6e 100644 --- a/resources/views/reports/default/multi-year.twig +++ b/resources/views/reports/default/multi-year.twig @@ -9,7 +9,7 @@ {# charts #}
    -
    +

    {{ 'incomeVsExpenses'|_ }}

    @@ -19,7 +19,7 @@
    -
    +

    {{ 'incomeVsExpenses'|_ }}

    @@ -59,8 +59,9 @@
    + + {# block with income #}
    - {# block with income #}
    diff --git a/resources/views/reports/default/year.twig b/resources/views/reports/default/year.twig index c7fbf97539..fa702a12e4 100644 --- a/resources/views/reports/default/year.twig +++ b/resources/views/reports/default/year.twig @@ -24,11 +24,12 @@

    {{ 'incomeVsExpenses'|_ }}

    - +
    + {# balances and inc vs exp #}
    diff --git a/resources/views/tags/index.twig b/resources/views/tags/index.twig index e611b43801..6aee84d08b 100644 --- a/resources/views/tags/index.twig +++ b/resources/views/tags/index.twig @@ -8,6 +8,13 @@ {% if count == 0 %} {% include 'partials.empty' with {what: 'default', type: 'tags',route: route('tags.create')} %} {% else %} + {% for period,entries in clouds %} {% if entries|length > 0 %}
    @@ -31,59 +38,13 @@
    {% endif %} {% endfor %} - {# - -
    - - {% for type in types %} - {% if counts[type] > 0 %} -
    -
    -
    -

    {{ ('tag_title_'~type)|_ }}

    -
    -
    - {% for year,months in collection[type] %} -

    {{ year }}

    - - {% for month,tags in months %} -
    {{ month }}
    -

    - {% for tag in tags %} - - {% if tag.tagMode == 'nothing' %} - - {% endif %} - {% if tag.tagMode == 'balancingAct' %} - - {% endif %} - {% if tag.tagMode == 'advancePayment' %} - - {% endif %} - {{ tag.tag }} - - {% endfor %} -

    - {% endfor %} - {% endfor %} - - -
    - -
    -
    - {% endif %} - {% endfor %} - + - #} {% endif %} {% endblock %} diff --git a/resources/views/transactions/bulk/edit.twig b/resources/views/transactions/bulk/edit.twig new file mode 100644 index 0000000000..4957e9eeb8 --- /dev/null +++ b/resources/views/transactions/bulk/edit.twig @@ -0,0 +1,147 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.render(Route.getCurrentRoute.getName, journals) }} +{% endblock %} + +{% block content %} +
    + +
    +
    +
    +
    +

    {{ 'mass_bulk_journals'|_ }}

    +
    +
    +

    + {{ 'mass_bulk_journals_explain'|_ }} +

    +
    +
    + + + + + + + + + + + + + {% for journal in journals %} + {% if journal.transaction_count == 2 %} + + + + + + + + + + {% endif %} + {% endfor %} + +
    {{ trans('list.description') }}{{ trans('list.amount') }}{{ trans('list.date') }}{{ trans('list.category') }}{{ trans('list.budget') }}{{ trans('list.tags') }}
    + + {{ journal.description }}{{ journal|journalTotalAmount }}{{ journal.date.formatLocalized(monthAndDayFormat) }} + {% set cat = journal.categories.first %} + {% if cat %} + {{ cat.name }} + {% endif %} + + {% set bud = journal.budgets.first %} + {% if bud %} + {{ bud.name }} + {% endif %} + + {% for tag in journal.tags %} + + {{ tag.tag }} + {% endfor %} +
    +
    +
    +

    + {{ 'bulk_set_new_values'|_ }} +

    +
    +
    + + + + + + + + + + + + + + + + + +
    {{ trans('list.category') }} + + +
    + +
    +
    {{ trans('list.budget') }} + + +
    + +
    +
    {{ trans('list.tags') }} + + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +{% endblock %} +{% block scripts %} + + + + +{% endblock %} +{% block styles %} + +{% endblock %} diff --git a/resources/views/transactions/mass-delete.twig b/resources/views/transactions/mass/delete.twig similarity index 99% rename from resources/views/transactions/mass-delete.twig rename to resources/views/transactions/mass/delete.twig index b038ab16be..ce6ae5c185 100644 --- a/resources/views/transactions/mass-delete.twig +++ b/resources/views/transactions/mass/delete.twig @@ -44,7 +44,6 @@ {{ journal|journalTotalAmount }} - {{ journal.date.formatLocalized(monthAndDayFormat) }} diff --git a/resources/views/transactions/mass/edit.twig b/resources/views/transactions/mass/edit.twig index 9f834d26e5..5f46ef6e47 100644 --- a/resources/views/transactions/mass/edit.twig +++ b/resources/views/transactions/mass/edit.twig @@ -19,7 +19,6 @@ {{ 'cannot_edit_other_fields'|_ }}

    - diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php index e8237cd6e0..5e29693372 100644 --- a/routes/breadcrumbs.php +++ b/routes/breadcrumbs.php @@ -990,6 +990,25 @@ Breadcrumbs::register( } ); +// BULK EDIT +Breadcrumbs::register( + 'transactions.bulk.edit', + function (BreadCrumbsGenerator $breadcrumbs, Collection $journals): void { + if ($journals->count() > 0) { + $journalIds = $journals->pluck('id')->toArray(); + $what = strtolower($journals->first()->transactionType->type); + $breadcrumbs->parent('transactions.index', $what, '(nothing)', new Carbon, new Carbon); + $breadcrumbs->push(trans('firefly.mass_bulk_journals'), route('transactions.bulk.edit', $journalIds)); + + return; + } + + $breadcrumbs->parent('index'); + + return; + } +); + // SPLIT Breadcrumbs::register( 'transactions.split.edit', diff --git a/routes/web.php b/routes/web.php index e368b4fc71..cbc6293852 100755 --- a/routes/web.php +++ b/routes/web.php @@ -58,7 +58,7 @@ Route::group( Route::any('logout', ['uses' => 'Auth\LoginController@logout', 'as' => 'logout']); Route::get('flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); Route::get('routes', ['uses' => 'HomeController@routes', 'as' => 'routes']); - Route::get('debug', 'HomeController@displayDebug')->name('debug'); + Route::get('debug', 'DebugController@index')->name('debug'); } ); @@ -784,12 +784,23 @@ Route::group( Route::group( ['middleware' => 'user-full-auth', 'namespace' => 'Transaction', 'prefix' => 'transactions/mass', 'as' => 'transactions.mass.'], function () { Route::get('edit/{journalList}', ['uses' => 'MassController@edit', 'as' => 'edit']); + Route::get('edit/bulk/{journalList}', ['uses' => 'MassController@editBulk', 'as' => 'edit-bulk']); Route::get('delete/{journalList}', ['uses' => 'MassController@delete', 'as' => 'delete']); Route::post('update', ['uses' => 'MassController@update', 'as' => 'update']); Route::post('destroy', ['uses' => 'MassController@destroy', 'as' => 'destroy']); } ); +/** + * Transaction Bulk Controller + */ +Route::group( + ['middleware' => 'user-full-auth', 'namespace' => 'Transaction', 'prefix' => 'transactions/bulk', 'as' => 'transactions.bulk.'], function () { + Route::get('edit/{journalList}', ['uses' => 'BulkController@edit', 'as' => 'edit']); + Route::post('update', ['uses' => 'BulkController@update', 'as' => 'update']); +} +); + /** * Transaction Split Controller */ diff --git a/tests/Feature/Controllers/AccountControllerTest.php b/tests/Feature/Controllers/AccountControllerTest.php index ea3e97106e..058918f408 100644 --- a/tests/Feature/Controllers/AccountControllerTest.php +++ b/tests/Feature/Controllers/AccountControllerTest.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; +use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; @@ -114,12 +115,16 @@ class AccountControllerTest extends TestCase */ public function testEdit() { + $note = new Note(); + $note->text = 'This is a test'; // mock stuff $journalRepos = $this->mock(JournalRepositoryInterface::class); $repository = $this->mock(CurrencyRepositoryInterface::class); + $accountRepos = $this->mock(AccountRepositoryInterface::class); $repository->shouldReceive('get')->andReturn(new Collection); $journalRepos->shouldReceive('first')->once()->andReturn(new TransactionJournal); $repository->shouldReceive('find')->once()->andReturn(new TransactionCurrency()); + $accountRepos->shouldReceive('getNote')->andReturn($note)->once(); $this->be($this->user()); $account = $this->user()->accounts()->where('account_type_id', 3)->whereNull('deleted_at')->first(); @@ -127,6 +132,7 @@ class AccountControllerTest extends TestCase $response->assertStatus(200); // has bread crumb $response->assertSee('
      {{ trans('list.description') }}