diff --git a/.env.docker b/.env.docker index 6da4c14359..e9d78a6f5f 100644 --- a/.env.docker +++ b/.env.docker @@ -3,10 +3,10 @@ APP_ENV=${FF_APP_ENV} # Set to true if you want to see debug information in error screens. -APP_DEBUG=false +APP_DEBUG=${APP_DEBUG} # This should be your email address -SITE_OWNER=mail@example.com +SITE_OWNER=${SITE_OWNER} # The encryption key for your database and sessions. Keep this very secure. # If you generate a new one all existing data must be considered LOST. @@ -29,13 +29,13 @@ DB_PASSWORD=${FF_DB_PASSWORD} # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. # Several other options exist. You can use 'single' for one big fat error log (not recommended). # Also available are 'syslog' and 'errorlog' which will log to the system itself. -APP_LOG=daily +APP_LOG=syslog # Log level. You can set this from least severe to most severe: # debug, info, notice, warning, error, critical, alert, emergency # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably # nothing will get logged, ever. -APP_LOG_LEVEL=warning +APP_LOG_LEVEL=info # If you're looking for performance improvements, you could install memcached. CACHE_DRIVER=file @@ -47,23 +47,23 @@ COOKIE_DOMAIN= COOKIE_SECURE=false # If you want Firefly III to mail you, update these settings -MAIL_DRIVER=smtp -MAIL_HOST=smtp.mailtrap.io -MAIL_PORT=2525 -MAIL_FROM=changeme@example.com -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null +MAIL_DRIVER=${MAIL_DRIVER} +MAIL_HOST=${MAIL_HOST} +MAIL_PORT=${MAIL_PORT} +MAIL_FROM=${MAIL_FROM} +MAIL_USERNAME=${MAIL_USERNAME} +MAIL_PASSWORD=${MAIL_PASSWORD} +MAIL_ENCRYPTION=${MAIL_ENCRYPTION} # Firefly III can send you the following messages SEND_REGISTRATION_MAIL=true -SEND_ERROR_MESSAGE=true +SEND_ERROR_MESSAGE=false # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. -MAPBOX_API_KEY= +MAPBOX_API_KEY=${MAPBOX_API_KEY} # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. -ANALYTICS_ID= +ANALYTICS_ID=${ANALYTICS_ID} # Most parts of the database are encrypted by default, but you can turn this off if you want to. # This makes it easier to migrate your database. Not that some fields will never be decrypted. diff --git a/.env.testing b/.env.testing index 6187db58e2..e33729c196 100644 --- a/.env.testing +++ b/.env.testing @@ -27,7 +27,7 @@ REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 -MAIL_DRIVER=smtp +MAIL_DRIVER=log MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_FROM=changeme@example.com @@ -36,7 +36,7 @@ MAIL_PASSWORD=null MAIL_ENCRYPTION=null SEND_REGISTRATION_MAIL=true -SEND_ERROR_MESSAGE=true +SEND_ERROR_MESSAGE=false CACHE_PREFIX=firefly diff --git a/.sandstorm/changelog.md b/.sandstorm/changelog.md index ff618d2761..c48ae8ed54 100644 --- a/.sandstorm/changelog.md +++ b/.sandstorm/changelog.md @@ -1,3 +1,19 @@ +# 4.7.1 +- A brand new API. Read about it in the [documentation](http://firefly-iii.readthedocs.io/en/latest/). +- Add support for Spanish. [issue 1194](https://github.com/firefly-iii/firefly-iii/issues/1194) +- Some custom preferences are selected by default for a better user experience. +- Some new currencies [issue 1211](https://github.com/firefly-iii/firefly-iii/issues/1211) +- Fixed [issue 1155](https://github.com/firefly-iii/firefly-iii/issues/1155) (reported by [ndandanov](https://github.com/ndandanov)) +- [Issue 1156](https://github.com/firefly-iii/firefly-iii/issues/1156) [issue 1182](https://github.com/firefly-iii/firefly-iii/issues/1182) and other issues related to SQLite databases. +- Multi-page budget overview was broken (reported by [jinformatique](https://github.com/jinformatique)) +- Importing CSV files with semi-colons in them did not work [issue 1172](https://github.com/firefly-iii/firefly-iii/issues/1172) [issue 1183](https://github.com/firefly-iii/firefly-iii/issues/1183) [issue 1210](https://github.com/firefly-iii/firefly-iii/issues/1210) +- Could not use account number that was in use by a deleted account [issue 1174](https://github.com/firefly-iii/firefly-iii/issues/1174) +- Fixed spelling error that lead to 404's [issue 1175](https://github.com/firefly-iii/firefly-iii/issues/1175) [issue 1190](https://github.com/firefly-iii/firefly-iii/issues/1190) +- Fixed tag autocomplete [issue 1178](https://github.com/firefly-iii/firefly-iii/issues/1178) +- Better links for "new transaction" buttons [issue 1185](https://github.com/firefly-iii/firefly-iii/issues/1185) +- Cache errors in budget charts [issue 1192](https://github.com/firefly-iii/firefly-iii/issues/1192) +- Deleting transactions that are linked to other other transactions would lead to errors [issue 1209](https://github.com/firefly-iii/firefly-iii/issues/1209) + # 4.7.0 - Support for Russian and Portuguese (Brazil) - Support for the Spectre API (Salt Edge) diff --git a/.sandstorm/sandstorm-files.list b/.sandstorm/sandstorm-files.list index 5b20a43693..a79d0bb307 100644 --- a/.sandstorm/sandstorm-files.list +++ b/.sandstorm/sandstorm-files.list @@ -202,6 +202,7 @@ lib/x86_64-linux-gnu/libz.so.1.2.8 lib64/ld-linux-x86-64.so.2 opt/app/.codeclimate.yml opt/app/.env +opt/app/.env.current opt/app/.env.docker opt/app/.env.example opt/app/.env.heroku @@ -240,6 +241,17 @@ opt/app/.sandstorm/setup.sh opt/app/.sandstorm/stack opt/app/LICENSE opt/app/app.json +opt/app/app/Api/V1/Controllers/AboutController.php +opt/app/app/Api/V1/Controllers/AccountController.php +opt/app/app/Api/V1/Controllers/BillController.php +opt/app/app/Api/V1/Controllers/Controller.php +opt/app/app/Api/V1/Controllers/TransactionController.php +opt/app/app/Api/V1/Controllers/UserController.php +opt/app/app/Api/V1/Requests/AccountRequest.php +opt/app/app/Api/V1/Requests/BillRequest.php +opt/app/app/Api/V1/Requests/Request.php +opt/app/app/Api/V1/Requests/TransactionRequest.php +opt/app/app/Api/V1/Requests/UserRequest.php opt/app/app/Console/Commands/CreateExport.php opt/app/app/Console/Commands/CreateImport.php opt/app/app/Console/Commands/DecryptAttachment.php @@ -274,6 +286,19 @@ opt/app/app/Export/Exporter/BasicExporter.php opt/app/app/Export/Exporter/CsvExporter.php opt/app/app/Export/Exporter/ExporterInterface.php opt/app/app/Export/ProcessorInterface.php +opt/app/app/Factory/AccountFactory.php +opt/app/app/Factory/AccountMetaFactory.php +opt/app/app/Factory/BillFactory.php +opt/app/app/Factory/BudgetFactory.php +opt/app/app/Factory/CategoryFactory.php +opt/app/app/Factory/PiggyBankEventFactory.php +opt/app/app/Factory/PiggyBankFactory.php +opt/app/app/Factory/TagFactory.php +opt/app/app/Factory/TransactionCurrencyFactory.php +opt/app/app/Factory/TransactionFactory.php +opt/app/app/Factory/TransactionJournalFactory.php +opt/app/app/Factory/TransactionJournalMetaFactory.php +opt/app/app/Factory/TransactionTypeFactory.php opt/app/app/Generator/Chart/Basic/ChartJsGenerator.php opt/app/app/Generator/Chart/Basic/GeneratorInterface.php opt/app/app/Generator/Report/Account/MonthReportGenerator.php @@ -437,7 +462,8 @@ opt/app/app/Http/Requests/MassEditJournalRequest.php opt/app/app/Http/Requests/NewUserFormRequest.php opt/app/app/Http/Requests/PiggyBankFormRequest.php opt/app/app/Http/Requests/ProfileFormRequest.php -opt/app/app/Http/Requests/ReconciliationFormRequest.php +opt/app/app/Http/Requests/ReconciliationStoreRequest.php +opt/app/app/Http/Requests/ReconciliationUpdateRequest.php opt/app/app/Http/Requests/ReportFormRequest.php opt/app/app/Http/Requests/Request.php opt/app/app/Http/Requests/RuleFormRequest.php @@ -577,13 +603,10 @@ opt/app/app/Repositories/ExportJob/ExportJobRepository.php opt/app/app/Repositories/ExportJob/ExportJobRepositoryInterface.php opt/app/app/Repositories/ImportJob/ImportJobRepository.php opt/app/app/Repositories/ImportJob/ImportJobRepositoryInterface.php -opt/app/app/Repositories/Journal/CreateJournalsTrait.php opt/app/app/Repositories/Journal/JournalRepository.php opt/app/app/Repositories/Journal/JournalRepositoryInterface.php opt/app/app/Repositories/Journal/JournalTasker.php opt/app/app/Repositories/Journal/JournalTaskerInterface.php -opt/app/app/Repositories/Journal/SupportJournalsTrait.php -opt/app/app/Repositories/Journal/UpdateJournalsTrait.php opt/app/app/Repositories/LinkType/LinkTypeRepository.php opt/app/app/Repositories/LinkType/LinkTypeRepositoryInterface.php opt/app/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -594,8 +617,13 @@ opt/app/app/Repositories/RuleGroup/RuleGroupRepository.php opt/app/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php opt/app/app/Repositories/Tag/TagRepository.php opt/app/app/Repositories/Tag/TagRepositoryInterface.php +opt/app/app/Repositories/TransactionType/TransactionTypeRepository.php +opt/app/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php opt/app/app/Repositories/User/UserRepository.php opt/app/app/Repositories/User/UserRepositoryInterface.php +opt/app/app/Rules/BelongsUser.php +opt/app/app/Rules/UniqueIban.php +opt/app/app/Rules/ValidTransactions.php opt/app/app/Services/Bunq/Id/BunqId.php opt/app/app/Services/Bunq/Id/DeviceServerId.php opt/app/app/Services/Bunq/Id/DeviceSessionId.php @@ -630,6 +658,17 @@ opt/app/app/Services/Github/Object/GithubObject.php opt/app/app/Services/Github/Object/Release.php opt/app/app/Services/Github/Request/GithubRequest.php opt/app/app/Services/Github/Request/UpdateRequest.php +opt/app/app/Services/Internal/Destroy/AccountDestroyService.php +opt/app/app/Services/Internal/Destroy/BillDestroyService.php +opt/app/app/Services/Internal/Destroy/JournalDestroyService.php +opt/app/app/Services/Internal/Support/AccountServiceTrait.php +opt/app/app/Services/Internal/Support/BillServiceTrait.php +opt/app/app/Services/Internal/Support/JournalServiceTrait.php +opt/app/app/Services/Internal/Support/TransactionServiceTrait.php +opt/app/app/Services/Internal/Update/AccountUpdateService.php +opt/app/app/Services/Internal/Update/BillUpdateService.php +opt/app/app/Services/Internal/Update/JournalUpdateService.php +opt/app/app/Services/Internal/Update/TransactionUpdateService.php opt/app/app/Services/Password/PwndVerifier.php opt/app/app/Services/Password/Verifier.php opt/app/app/Services/Spectre/Exception/DuplicatedCustomerException.php @@ -754,6 +793,17 @@ opt/app/app/TransactionRules/Triggers/ToAccountStarts.php opt/app/app/TransactionRules/Triggers/TransactionType.php opt/app/app/TransactionRules/Triggers/TriggerInterface.php opt/app/app/TransactionRules/Triggers/UserAction.php +opt/app/app/Transformers/AccountTransformer.php +opt/app/app/Transformers/AttachmentTransformer.php +opt/app/app/Transformers/BillTransformer.php +opt/app/app/Transformers/BudgetTransformer.php +opt/app/app/Transformers/CategoryTransformer.php +opt/app/app/Transformers/JournalMetaTransformer.php +opt/app/app/Transformers/PiggyBankEventTransformer.php +opt/app/app/Transformers/PiggyBankTransformer.php +opt/app/app/Transformers/TagTransformer.php +opt/app/app/Transformers/TransactionTransformer.php +opt/app/app/Transformers/UserTransformer.php opt/app/app/User.php opt/app/app/Validation/FireflyValidator.php opt/app/artisan @@ -798,6 +848,11 @@ opt/app/database/migrations/2017_04_13_163623_changes_for_v440.php opt/app/database/migrations/2017_06_02_105232_changes_for_v450.php opt/app/database/migrations/2017_08_20_062014_changes_for_v470.php opt/app/database/migrations/2017_11_04_170844_changes_for_v470a.php +opt/app/database/migrations/2018_01_01_000001_create_oauth_auth_codes_table.php +opt/app/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php +opt/app/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php +opt/app/database/migrations/2018_01_01_000004_create_oauth_clients_table.php +opt/app/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php opt/app/database/seeds/AccountTypeSeeder.php opt/app/database/seeds/DatabaseSeeder.php opt/app/database/seeds/LinkTypeSeeder.php @@ -806,11 +861,13 @@ opt/app/database/seeds/TransactionCurrencySeeder.php opt/app/database/seeds/TransactionTypeSeeder.php opt/app/docker-compose.yml opt/app/index.php +opt/app/package-lock.json opt/app/public/.htaccess opt/app/public/android-chrome-192x192.png opt/app/public/android-chrome-512x512.png opt/app/public/apple-touch-icon.png opt/app/public/browserconfig.xml +opt/app/public/css/app.css opt/app/public/css/bootstrap-multiselect.css opt/app/public/css/bootstrap-sortable.css opt/app/public/css/bootstrap-tagsinput.css @@ -944,6 +1001,16 @@ opt/app/public/fonts/lato-100.woff opt/app/public/fonts/lato-100.woff2 opt/app/public/fonts/roboto-light-300.woff opt/app/public/fonts/roboto-light-300.woff2 +opt/app/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot +opt/app/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.svg +opt/app/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf +opt/app/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff +opt/app/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2 +opt/app/public/fonts/vendor/font-awesome/fontawesome-webfont.eot +opt/app/public/fonts/vendor/font-awesome/fontawesome-webfont.svg +opt/app/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf +opt/app/public/fonts/vendor/font-awesome/fontawesome-webfont.woff +opt/app/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2 opt/app/public/images/error.png opt/app/public/images/image.png opt/app/public/images/loading-small.gif @@ -956,6 +1023,7 @@ opt/app/public/images/logos/spectre.png opt/app/public/images/page_green.png opt/app/public/images/page_white_acrobat.png opt/app/public/index.php +opt/app/public/js/app.js opt/app/public/js/ff/accounts/create.js opt/app/public/js/ff/accounts/edit-reconciliation.js opt/app/public/js/ff/accounts/edit.js @@ -1019,8 +1087,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.2.1.min.js -opt/app/public/js/lib/jquery-3.2.1.min.map opt/app/public/js/lib/jquery-ui.min.js opt/app/public/js/lib/jquery.color-2.1.2.min.js opt/app/public/js/lib/modernizr-custom.js @@ -1033,22 +1099,6 @@ opt/app/public/lib/adminlte/css/skins/skin-blue-light.min.css opt/app/public/lib/adminlte/img/icons.png opt/app/public/lib/adminlte/js/app.js opt/app/public/lib/adminlte/js/app.min.js -opt/app/public/lib/bootstrap/config.json -opt/app/public/lib/bootstrap/css/bootstrap.min.css -opt/app/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot -opt/app/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg -opt/app/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf -opt/app/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff -opt/app/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 -opt/app/public/lib/bootstrap/js/bootstrap.min.js -opt/app/public/lib/font-awesome/css/font-awesome.css -opt/app/public/lib/font-awesome/css/font-awesome.min.css -opt/app/public/lib/font-awesome/fonts/FontAwesome.otf -opt/app/public/lib/font-awesome/fonts/fontawesome-webfont.eot -opt/app/public/lib/font-awesome/fonts/fontawesome-webfont.svg -opt/app/public/lib/font-awesome/fonts/fontawesome-webfont.ttf -opt/app/public/lib/font-awesome/fonts/fontawesome-webfont.woff -opt/app/public/lib/font-awesome/fonts/fontawesome-webfont.woff2 opt/app/public/lib/intro/intro.min.js opt/app/public/lib/intro/introjs-rtl.min.css opt/app/public/lib/intro/introjs.min.css @@ -1063,15 +1113,28 @@ opt/app/public/lib/leaflet/leaflet.css opt/app/public/lib/leaflet/leaflet.js opt/app/public/lib/leaflet/leaflet.js.map opt/app/public/manifest.json +opt/app/public/mix-manifest.json opt/app/public/mstile-150x150.png opt/app/public/report.html opt/app/public/robots.txt opt/app/public/safari-pinned-tab.svg opt/app/public/web.config opt/app/readme.md +opt/app/resources/assets/js/app.js +opt/app/resources/assets/js/bootstrap.js +opt/app/resources/assets/js/components/ExampleComponent.vue +opt/app/resources/assets/js/components/bills/Index.vue +opt/app/resources/assets/js/components/passport/AuthorizedClients.vue +opt/app/resources/assets/js/components/passport/Clients.vue +opt/app/resources/assets/js/components/passport/PersonalAccessTokens.vue +opt/app/resources/assets/js/lang.js +opt/app/resources/assets/js/messages.js +opt/app/resources/assets/sass/_variables.scss +opt/app/resources/assets/sass/app.scss opt/app/resources/lang/de_DE/auth.php opt/app/resources/lang/de_DE/bank.php opt/app/resources/lang/de_DE/breadcrumbs.php +opt/app/resources/lang/de_DE/components.php opt/app/resources/lang/de_DE/config.php opt/app/resources/lang/de_DE/csv.php opt/app/resources/lang/de_DE/demo.php @@ -1087,6 +1150,7 @@ opt/app/resources/lang/de_DE/validation.php opt/app/resources/lang/en_US/auth.php opt/app/resources/lang/en_US/bank.php opt/app/resources/lang/en_US/breadcrumbs.php +opt/app/resources/lang/en_US/components.php opt/app/resources/lang/en_US/config.php opt/app/resources/lang/en_US/csv.php opt/app/resources/lang/en_US/demo.php @@ -1098,9 +1162,25 @@ opt/app/resources/lang/en_US/list.php opt/app/resources/lang/en_US/pagination.php opt/app/resources/lang/en_US/passwords.php opt/app/resources/lang/en_US/validation.php +opt/app/resources/lang/es_ES/auth.php +opt/app/resources/lang/es_ES/bank.php +opt/app/resources/lang/es_ES/breadcrumbs.php +opt/app/resources/lang/es_ES/components.php +opt/app/resources/lang/es_ES/config.php +opt/app/resources/lang/es_ES/csv.php +opt/app/resources/lang/es_ES/demo.php +opt/app/resources/lang/es_ES/firefly.php +opt/app/resources/lang/es_ES/form.php +opt/app/resources/lang/es_ES/import.php +opt/app/resources/lang/es_ES/intro.php +opt/app/resources/lang/es_ES/list.php +opt/app/resources/lang/es_ES/pagination.php +opt/app/resources/lang/es_ES/passwords.php +opt/app/resources/lang/es_ES/validation.php opt/app/resources/lang/fr_FR/auth.php opt/app/resources/lang/fr_FR/bank.php opt/app/resources/lang/fr_FR/breadcrumbs.php +opt/app/resources/lang/fr_FR/components.php opt/app/resources/lang/fr_FR/config.php opt/app/resources/lang/fr_FR/csv.php opt/app/resources/lang/fr_FR/demo.php @@ -1116,6 +1196,7 @@ opt/app/resources/lang/fr_FR/validation.php opt/app/resources/lang/id_ID/auth.php opt/app/resources/lang/id_ID/bank.php opt/app/resources/lang/id_ID/breadcrumbs.php +opt/app/resources/lang/id_ID/components.php opt/app/resources/lang/id_ID/config.php opt/app/resources/lang/id_ID/csv.php opt/app/resources/lang/id_ID/demo.php @@ -1130,6 +1211,7 @@ opt/app/resources/lang/id_ID/validation.php opt/app/resources/lang/nl_NL/auth.php opt/app/resources/lang/nl_NL/bank.php opt/app/resources/lang/nl_NL/breadcrumbs.php +opt/app/resources/lang/nl_NL/components.php opt/app/resources/lang/nl_NL/config.php opt/app/resources/lang/nl_NL/csv.php opt/app/resources/lang/nl_NL/demo.php @@ -1145,6 +1227,7 @@ opt/app/resources/lang/nl_NL/validation.php opt/app/resources/lang/pl_PL/auth.php opt/app/resources/lang/pl_PL/bank.php opt/app/resources/lang/pl_PL/breadcrumbs.php +opt/app/resources/lang/pl_PL/components.php opt/app/resources/lang/pl_PL/config.php opt/app/resources/lang/pl_PL/csv.php opt/app/resources/lang/pl_PL/demo.php @@ -1160,6 +1243,7 @@ opt/app/resources/lang/pl_PL/validation.php opt/app/resources/lang/pt_BR/auth.php opt/app/resources/lang/pt_BR/bank.php opt/app/resources/lang/pt_BR/breadcrumbs.php +opt/app/resources/lang/pt_BR/components.php opt/app/resources/lang/pt_BR/config.php opt/app/resources/lang/pt_BR/csv.php opt/app/resources/lang/pt_BR/demo.php @@ -1174,6 +1258,7 @@ opt/app/resources/lang/pt_BR/validation.php opt/app/resources/lang/ru_RU/auth.php opt/app/resources/lang/ru_RU/bank.php opt/app/resources/lang/ru_RU/breadcrumbs.php +opt/app/resources/lang/ru_RU/components.php opt/app/resources/lang/ru_RU/config.php opt/app/resources/lang/ru_RU/csv.php opt/app/resources/lang/ru_RU/demo.php @@ -1188,6 +1273,7 @@ opt/app/resources/lang/ru_RU/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/components.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 @@ -1431,6 +1517,7 @@ opt/app/resources/views/transactions/single/create.twig opt/app/resources/views/transactions/single/delete.twig opt/app/resources/views/transactions/single/edit.twig opt/app/resources/views/transactions/split/edit.twig +opt/app/resources/views/vendor/passport/authorize.twig opt/app/routes/api.php opt/app/routes/breadcrumbs.php opt/app/routes/channels.php @@ -1501,6 +1588,7 @@ opt/app/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/TextTest.php opt/app/vendor/bacon/bacon-qr-code/tests/bootstrap.php opt/app/vendor/bin/commonmark opt/app/vendor/bin/doctrine-dbal +opt/app/vendor/bin/generate-defuse-key opt/app/vendor/composer/ClassLoader.php opt/app/vendor/composer/LICENSE opt/app/vendor/composer/autoload_classmap.php @@ -1528,6 +1616,39 @@ opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/bulma.blade.php opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/foundation6.blade.php opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/json-ld.php opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/materialize.blade.php +opt/app/vendor/defuse/php-encryption/.php_cs +opt/app/vendor/defuse/php-encryption/LICENSE +opt/app/vendor/defuse/php-encryption/README.md +opt/app/vendor/defuse/php-encryption/bin/generate-defuse-key +opt/app/vendor/defuse/php-encryption/composer.json +opt/app/vendor/defuse/php-encryption/dist/Makefile +opt/app/vendor/defuse/php-encryption/dist/box.json +opt/app/vendor/defuse/php-encryption/dist/signingkey.asc +opt/app/vendor/defuse/php-encryption/docs/CryptoDetails.md +opt/app/vendor/defuse/php-encryption/docs/FAQ.md +opt/app/vendor/defuse/php-encryption/docs/InstallingAndVerifying.md +opt/app/vendor/defuse/php-encryption/docs/InternalDeveloperDocs.md +opt/app/vendor/defuse/php-encryption/docs/Tutorial.md +opt/app/vendor/defuse/php-encryption/docs/UpgradingFromV1.2.md +opt/app/vendor/defuse/php-encryption/docs/classes/Crypto.md +opt/app/vendor/defuse/php-encryption/docs/classes/File.md +opt/app/vendor/defuse/php-encryption/docs/classes/Key.md +opt/app/vendor/defuse/php-encryption/docs/classes/KeyProtectedByPassword.md +opt/app/vendor/defuse/php-encryption/psalm.xml +opt/app/vendor/defuse/php-encryption/src/Core.php +opt/app/vendor/defuse/php-encryption/src/Crypto.php +opt/app/vendor/defuse/php-encryption/src/DerivedKeys.php +opt/app/vendor/defuse/php-encryption/src/Encoding.php +opt/app/vendor/defuse/php-encryption/src/Exception/BadFormatException.php +opt/app/vendor/defuse/php-encryption/src/Exception/CryptoException.php +opt/app/vendor/defuse/php-encryption/src/Exception/EnvironmentIsBrokenException.php +opt/app/vendor/defuse/php-encryption/src/Exception/IOException.php +opt/app/vendor/defuse/php-encryption/src/Exception/WrongKeyOrModifiedCiphertextException.php +opt/app/vendor/defuse/php-encryption/src/File.php +opt/app/vendor/defuse/php-encryption/src/Key.php +opt/app/vendor/defuse/php-encryption/src/KeyOrPassword.php +opt/app/vendor/defuse/php-encryption/src/KeyProtectedByPassword.php +opt/app/vendor/defuse/php-encryption/src/RuntimeTests.php opt/app/vendor/doctrine/annotations/CHANGELOG.md opt/app/vendor/doctrine/annotations/LICENSE opt/app/vendor/doctrine/annotations/README.md @@ -1995,6 +2116,101 @@ opt/app/vendor/fideloper/proxy/composer.json opt/app/vendor/fideloper/proxy/config/trustedproxy.php opt/app/vendor/fideloper/proxy/src/TrustProxies.php opt/app/vendor/fideloper/proxy/src/TrustedProxyServiceProvider.php +opt/app/vendor/firebase/php-jwt/LICENSE +opt/app/vendor/firebase/php-jwt/README.md +opt/app/vendor/firebase/php-jwt/composer.json +opt/app/vendor/firebase/php-jwt/src/BeforeValidException.php +opt/app/vendor/firebase/php-jwt/src/ExpiredException.php +opt/app/vendor/firebase/php-jwt/src/JWT.php +opt/app/vendor/firebase/php-jwt/src/SignatureInvalidException.php +opt/app/vendor/guzzlehttp/guzzle/CHANGELOG.md +opt/app/vendor/guzzlehttp/guzzle/LICENSE +opt/app/vendor/guzzlehttp/guzzle/README.md +opt/app/vendor/guzzlehttp/guzzle/UPGRADING.md +opt/app/vendor/guzzlehttp/guzzle/composer.json +opt/app/vendor/guzzlehttp/guzzle/src/Client.php +opt/app/vendor/guzzlehttp/guzzle/src/ClientInterface.php +opt/app/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +opt/app/vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +opt/app/vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +opt/app/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +opt/app/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/SeekException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +opt/app/vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +opt/app/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +opt/app/vendor/guzzlehttp/guzzle/src/HandlerStack.php +opt/app/vendor/guzzlehttp/guzzle/src/MessageFormatter.php +opt/app/vendor/guzzlehttp/guzzle/src/Middleware.php +opt/app/vendor/guzzlehttp/guzzle/src/Pool.php +opt/app/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +opt/app/vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +opt/app/vendor/guzzlehttp/guzzle/src/RequestOptions.php +opt/app/vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +opt/app/vendor/guzzlehttp/guzzle/src/TransferStats.php +opt/app/vendor/guzzlehttp/guzzle/src/UriTemplate.php +opt/app/vendor/guzzlehttp/guzzle/src/functions.php +opt/app/vendor/guzzlehttp/guzzle/src/functions_include.php +opt/app/vendor/guzzlehttp/promises/CHANGELOG.md +opt/app/vendor/guzzlehttp/promises/LICENSE +opt/app/vendor/guzzlehttp/promises/Makefile +opt/app/vendor/guzzlehttp/promises/README.md +opt/app/vendor/guzzlehttp/promises/composer.json +opt/app/vendor/guzzlehttp/promises/src/AggregateException.php +opt/app/vendor/guzzlehttp/promises/src/CancellationException.php +opt/app/vendor/guzzlehttp/promises/src/Coroutine.php +opt/app/vendor/guzzlehttp/promises/src/EachPromise.php +opt/app/vendor/guzzlehttp/promises/src/FulfilledPromise.php +opt/app/vendor/guzzlehttp/promises/src/Promise.php +opt/app/vendor/guzzlehttp/promises/src/PromiseInterface.php +opt/app/vendor/guzzlehttp/promises/src/PromisorInterface.php +opt/app/vendor/guzzlehttp/promises/src/RejectedPromise.php +opt/app/vendor/guzzlehttp/promises/src/RejectionException.php +opt/app/vendor/guzzlehttp/promises/src/TaskQueue.php +opt/app/vendor/guzzlehttp/promises/src/TaskQueueInterface.php +opt/app/vendor/guzzlehttp/promises/src/functions.php +opt/app/vendor/guzzlehttp/promises/src/functions_include.php +opt/app/vendor/guzzlehttp/psr7/CHANGELOG.md +opt/app/vendor/guzzlehttp/psr7/LICENSE +opt/app/vendor/guzzlehttp/psr7/README.md +opt/app/vendor/guzzlehttp/psr7/composer.json +opt/app/vendor/guzzlehttp/psr7/src/AppendStream.php +opt/app/vendor/guzzlehttp/psr7/src/BufferStream.php +opt/app/vendor/guzzlehttp/psr7/src/CachingStream.php +opt/app/vendor/guzzlehttp/psr7/src/DroppingStream.php +opt/app/vendor/guzzlehttp/psr7/src/FnStream.php +opt/app/vendor/guzzlehttp/psr7/src/InflateStream.php +opt/app/vendor/guzzlehttp/psr7/src/LazyOpenStream.php +opt/app/vendor/guzzlehttp/psr7/src/LimitStream.php +opt/app/vendor/guzzlehttp/psr7/src/MessageTrait.php +opt/app/vendor/guzzlehttp/psr7/src/MultipartStream.php +opt/app/vendor/guzzlehttp/psr7/src/NoSeekStream.php +opt/app/vendor/guzzlehttp/psr7/src/PumpStream.php +opt/app/vendor/guzzlehttp/psr7/src/Request.php +opt/app/vendor/guzzlehttp/psr7/src/Response.php +opt/app/vendor/guzzlehttp/psr7/src/ServerRequest.php +opt/app/vendor/guzzlehttp/psr7/src/Stream.php +opt/app/vendor/guzzlehttp/psr7/src/StreamDecoratorTrait.php +opt/app/vendor/guzzlehttp/psr7/src/StreamWrapper.php +opt/app/vendor/guzzlehttp/psr7/src/UploadedFile.php +opt/app/vendor/guzzlehttp/psr7/src/Uri.php +opt/app/vendor/guzzlehttp/psr7/src/UriNormalizer.php +opt/app/vendor/guzzlehttp/psr7/src/UriResolver.php +opt/app/vendor/guzzlehttp/psr7/src/functions.php +opt/app/vendor/guzzlehttp/psr7/src/functions_include.php opt/app/vendor/laravel/framework/LICENSE.md opt/app/vendor/laravel/framework/README.md opt/app/vendor/laravel/framework/composer.json @@ -2894,6 +3110,70 @@ opt/app/vendor/laravel/framework/src/Illuminate/View/ViewFinderInterface.php opt/app/vendor/laravel/framework/src/Illuminate/View/ViewName.php opt/app/vendor/laravel/framework/src/Illuminate/View/ViewServiceProvider.php opt/app/vendor/laravel/framework/src/Illuminate/View/composer.json +opt/app/vendor/laravel/passport/LICENSE.txt +opt/app/vendor/laravel/passport/composer.json +opt/app/vendor/laravel/passport/database/migrations/2016_06_01_000001_create_oauth_auth_codes_table.php +opt/app/vendor/laravel/passport/database/migrations/2016_06_01_000002_create_oauth_access_tokens_table.php +opt/app/vendor/laravel/passport/database/migrations/2016_06_01_000003_create_oauth_refresh_tokens_table.php +opt/app/vendor/laravel/passport/database/migrations/2016_06_01_000004_create_oauth_clients_table.php +opt/app/vendor/laravel/passport/database/migrations/2016_06_01_000005_create_oauth_personal_access_clients_table.php +opt/app/vendor/laravel/passport/readme.md +opt/app/vendor/laravel/passport/resources/assets/js/components/AuthorizedClients.vue +opt/app/vendor/laravel/passport/resources/assets/js/components/Clients.vue +opt/app/vendor/laravel/passport/resources/assets/js/components/PersonalAccessTokens.vue +opt/app/vendor/laravel/passport/resources/views/authorize.blade.php +opt/app/vendor/laravel/passport/src/ApiTokenCookieFactory.php +opt/app/vendor/laravel/passport/src/AuthCode.php +opt/app/vendor/laravel/passport/src/Bridge/AccessToken.php +opt/app/vendor/laravel/passport/src/Bridge/AccessTokenRepository.php +opt/app/vendor/laravel/passport/src/Bridge/AuthCode.php +opt/app/vendor/laravel/passport/src/Bridge/AuthCodeRepository.php +opt/app/vendor/laravel/passport/src/Bridge/Client.php +opt/app/vendor/laravel/passport/src/Bridge/ClientRepository.php +opt/app/vendor/laravel/passport/src/Bridge/FormatsScopesForStorage.php +opt/app/vendor/laravel/passport/src/Bridge/PersonalAccessGrant.php +opt/app/vendor/laravel/passport/src/Bridge/RefreshToken.php +opt/app/vendor/laravel/passport/src/Bridge/RefreshTokenRepository.php +opt/app/vendor/laravel/passport/src/Bridge/Scope.php +opt/app/vendor/laravel/passport/src/Bridge/ScopeRepository.php +opt/app/vendor/laravel/passport/src/Bridge/User.php +opt/app/vendor/laravel/passport/src/Bridge/UserRepository.php +opt/app/vendor/laravel/passport/src/Client.php +opt/app/vendor/laravel/passport/src/ClientRepository.php +opt/app/vendor/laravel/passport/src/Console/ClientCommand.php +opt/app/vendor/laravel/passport/src/Console/InstallCommand.php +opt/app/vendor/laravel/passport/src/Console/KeysCommand.php +opt/app/vendor/laravel/passport/src/Events/AccessTokenCreated.php +opt/app/vendor/laravel/passport/src/Events/RefreshTokenCreated.php +opt/app/vendor/laravel/passport/src/Exceptions/MissingScopeException.php +opt/app/vendor/laravel/passport/src/Guards/TokenGuard.php +opt/app/vendor/laravel/passport/src/HasApiTokens.php +opt/app/vendor/laravel/passport/src/Http/Controllers/AccessTokenController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/ApproveAuthorizationController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/AuthorizationController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/AuthorizedAccessTokenController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/ClientController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/ConvertsPsrResponses.php +opt/app/vendor/laravel/passport/src/Http/Controllers/DenyAuthorizationController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/HandlesOAuthErrors.php +opt/app/vendor/laravel/passport/src/Http/Controllers/PersonalAccessTokenController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/RetrievesAuthRequestFromSession.php +opt/app/vendor/laravel/passport/src/Http/Controllers/ScopeController.php +opt/app/vendor/laravel/passport/src/Http/Controllers/TransientTokenController.php +opt/app/vendor/laravel/passport/src/Http/Middleware/CheckClientCredentials.php +opt/app/vendor/laravel/passport/src/Http/Middleware/CheckForAnyScope.php +opt/app/vendor/laravel/passport/src/Http/Middleware/CheckScopes.php +opt/app/vendor/laravel/passport/src/Http/Middleware/CreateFreshApiToken.php +opt/app/vendor/laravel/passport/src/Passport.php +opt/app/vendor/laravel/passport/src/PassportServiceProvider.php +opt/app/vendor/laravel/passport/src/PersonalAccessClient.php +opt/app/vendor/laravel/passport/src/PersonalAccessTokenFactory.php +opt/app/vendor/laravel/passport/src/PersonalAccessTokenResult.php +opt/app/vendor/laravel/passport/src/RouteRegistrar.php +opt/app/vendor/laravel/passport/src/Scope.php +opt/app/vendor/laravel/passport/src/Token.php +opt/app/vendor/laravel/passport/src/TokenRepository.php +opt/app/vendor/laravel/passport/src/TransientToken.php opt/app/vendor/laravelcollective/html/CONTRIBUTING.md opt/app/vendor/laravelcollective/html/LICENSE.txt opt/app/vendor/laravelcollective/html/composer.json @@ -2906,6 +3186,83 @@ opt/app/vendor/laravelcollective/html/src/HtmlBuilder.php opt/app/vendor/laravelcollective/html/src/HtmlFacade.php opt/app/vendor/laravelcollective/html/src/HtmlServiceProvider.php opt/app/vendor/laravelcollective/html/src/helpers.php +opt/app/vendor/lcobucci/jwt/LICENSE +opt/app/vendor/lcobucci/jwt/README.md +opt/app/vendor/lcobucci/jwt/composer.json +opt/app/vendor/lcobucci/jwt/composer.lock +opt/app/vendor/lcobucci/jwt/phpunit.xml.dist +opt/app/vendor/lcobucci/jwt/src/Builder.php +opt/app/vendor/lcobucci/jwt/src/Claim.php +opt/app/vendor/lcobucci/jwt/src/Claim/Basic.php +opt/app/vendor/lcobucci/jwt/src/Claim/EqualsTo.php +opt/app/vendor/lcobucci/jwt/src/Claim/Factory.php +opt/app/vendor/lcobucci/jwt/src/Claim/GreaterOrEqualsTo.php +opt/app/vendor/lcobucci/jwt/src/Claim/LesserOrEqualsTo.php +opt/app/vendor/lcobucci/jwt/src/Claim/Validatable.php +opt/app/vendor/lcobucci/jwt/src/Parser.php +opt/app/vendor/lcobucci/jwt/src/Parsing/Decoder.php +opt/app/vendor/lcobucci/jwt/src/Parsing/Encoder.php +opt/app/vendor/lcobucci/jwt/src/Signature.php +opt/app/vendor/lcobucci/jwt/src/Signer.php +opt/app/vendor/lcobucci/jwt/src/Signer/BaseSigner.php +opt/app/vendor/lcobucci/jwt/src/Signer/Ecdsa.php +opt/app/vendor/lcobucci/jwt/src/Signer/Ecdsa/KeyParser.php +opt/app/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha256.php +opt/app/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha384.php +opt/app/vendor/lcobucci/jwt/src/Signer/Ecdsa/Sha512.php +opt/app/vendor/lcobucci/jwt/src/Signer/Hmac.php +opt/app/vendor/lcobucci/jwt/src/Signer/Hmac/Sha256.php +opt/app/vendor/lcobucci/jwt/src/Signer/Hmac/Sha384.php +opt/app/vendor/lcobucci/jwt/src/Signer/Hmac/Sha512.php +opt/app/vendor/lcobucci/jwt/src/Signer/Key.php +opt/app/vendor/lcobucci/jwt/src/Signer/Keychain.php +opt/app/vendor/lcobucci/jwt/src/Signer/Rsa.php +opt/app/vendor/lcobucci/jwt/src/Signer/Rsa/Sha256.php +opt/app/vendor/lcobucci/jwt/src/Signer/Rsa/Sha384.php +opt/app/vendor/lcobucci/jwt/src/Signer/Rsa/Sha512.php +opt/app/vendor/lcobucci/jwt/src/Token.php +opt/app/vendor/lcobucci/jwt/src/ValidationData.php +opt/app/vendor/lcobucci/jwt/test/functional/EcdsaTokenTest.php +opt/app/vendor/lcobucci/jwt/test/functional/HmacTokenTest.php +opt/app/vendor/lcobucci/jwt/test/functional/Keys.php +opt/app/vendor/lcobucci/jwt/test/functional/RsaTokenTest.php +opt/app/vendor/lcobucci/jwt/test/functional/UnsignedTokenTest.php +opt/app/vendor/lcobucci/jwt/test/functional/ecdsa/private.key +opt/app/vendor/lcobucci/jwt/test/functional/ecdsa/private2.key +opt/app/vendor/lcobucci/jwt/test/functional/ecdsa/public1.key +opt/app/vendor/lcobucci/jwt/test/functional/ecdsa/public2.key +opt/app/vendor/lcobucci/jwt/test/functional/ecdsa/public3.key +opt/app/vendor/lcobucci/jwt/test/functional/rsa/encrypted-private.key +opt/app/vendor/lcobucci/jwt/test/functional/rsa/encrypted-public.key +opt/app/vendor/lcobucci/jwt/test/functional/rsa/private.key +opt/app/vendor/lcobucci/jwt/test/functional/rsa/public.key +opt/app/vendor/lcobucci/jwt/test/unit/BuilderTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Claim/BasicTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Claim/EqualsToTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Claim/FactoryTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Claim/GreaterOrEqualsToTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Claim/LesserOrEqualsToTest.php +opt/app/vendor/lcobucci/jwt/test/unit/ParserTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Parsing/DecoderTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Parsing/EncoderTest.php +opt/app/vendor/lcobucci/jwt/test/unit/SignatureTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/BaseSignerTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Ecdsa/KeyParserTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Ecdsa/Sha256Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Ecdsa/Sha384Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Ecdsa/Sha512Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/EcdsaTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Hmac/Sha256Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Hmac/Sha384Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Hmac/Sha512Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/HmacTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/KeyTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/KeychainTest.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Rsa/Sha256Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Rsa/Sha384Test.php +opt/app/vendor/lcobucci/jwt/test/unit/Signer/Rsa/Sha512Test.php +opt/app/vendor/lcobucci/jwt/test/unit/TokenTest.php +opt/app/vendor/lcobucci/jwt/test/unit/ValidationDataTest.php opt/app/vendor/league/commonmark/.styleci.yml opt/app/vendor/league/commonmark/CHANGELOG.md opt/app/vendor/league/commonmark/CONDUCT.md @@ -3043,47 +3400,28 @@ opt/app/vendor/league/csv/src/Writer.php opt/app/vendor/league/csv/src/XMLConverter.php opt/app/vendor/league/csv/src/functions.php opt/app/vendor/league/csv/src/functions_include.php +opt/app/vendor/league/event/LICENCE +opt/app/vendor/league/event/composer.json +opt/app/vendor/league/event/src/AbstractEvent.php +opt/app/vendor/league/event/src/AbstractListener.php +opt/app/vendor/league/event/src/CallbackListener.php +opt/app/vendor/league/event/src/Emitter.php +opt/app/vendor/league/event/src/EmitterAwareInterface.php +opt/app/vendor/league/event/src/EmitterAwareTrait.php +opt/app/vendor/league/event/src/EmitterInterface.php +opt/app/vendor/league/event/src/EmitterTrait.php +opt/app/vendor/league/event/src/Event.php +opt/app/vendor/league/event/src/EventInterface.php +opt/app/vendor/league/event/src/Generator.php +opt/app/vendor/league/event/src/GeneratorInterface.php +opt/app/vendor/league/event/src/GeneratorTrait.php +opt/app/vendor/league/event/src/ListenerAcceptor.php +opt/app/vendor/league/event/src/ListenerAcceptorInterface.php +opt/app/vendor/league/event/src/ListenerInterface.php +opt/app/vendor/league/event/src/ListenerProviderInterface.php +opt/app/vendor/league/event/src/OneTimeListener.php opt/app/vendor/league/flysystem/LICENSE opt/app/vendor/league/flysystem/composer.json -opt/app/vendor/league/flysystem/docs/CNAME -opt/app/vendor/league/flysystem/docs/_data/images.yml -opt/app/vendor/league/flysystem/docs/_data/menu.yml -opt/app/vendor/league/flysystem/docs/_data/project.yml -opt/app/vendor/league/flysystem/docs/_layouts/default.html -opt/app/vendor/league/flysystem/docs/adapter/aws-s3-v2.md -opt/app/vendor/league/flysystem/docs/adapter/aws-s3-v3.md -opt/app/vendor/league/flysystem/docs/adapter/azure.md -opt/app/vendor/league/flysystem/docs/adapter/copy.md -opt/app/vendor/league/flysystem/docs/adapter/digitalocean-spaces.md -opt/app/vendor/league/flysystem/docs/adapter/dropbox.md -opt/app/vendor/league/flysystem/docs/adapter/ftp.md -opt/app/vendor/league/flysystem/docs/adapter/gridfs.md -opt/app/vendor/league/flysystem/docs/adapter/local.md -opt/app/vendor/league/flysystem/docs/adapter/memory.md -opt/app/vendor/league/flysystem/docs/adapter/null-test.md -opt/app/vendor/league/flysystem/docs/adapter/phpcr.md -opt/app/vendor/league/flysystem/docs/adapter/rackspace.md -opt/app/vendor/league/flysystem/docs/adapter/replicate.md -opt/app/vendor/league/flysystem/docs/adapter/sftp.md -opt/app/vendor/league/flysystem/docs/adapter/webdav.md -opt/app/vendor/league/flysystem/docs/adapter/zip-archive.md -opt/app/vendor/league/flysystem/docs/api.md -opt/app/vendor/league/flysystem/docs/caching.md -opt/app/vendor/league/flysystem/docs/core-concepts.md -opt/app/vendor/league/flysystem/docs/creating-an-adapter.md -opt/app/vendor/league/flysystem/docs/index.md -opt/app/vendor/league/flysystem/docs/installation.md -opt/app/vendor/league/flysystem/docs/integrations.md -opt/app/vendor/league/flysystem/docs/logo/become_a_patron_button.png -opt/app/vendor/league/flysystem/docs/logo/become_a_patron_button@2x.png -opt/app/vendor/league/flysystem/docs/logo/become_a_patron_button@3x.png -opt/app/vendor/league/flysystem/docs/logo/laravel.svg -opt/app/vendor/league/flysystem/docs/mount-manager.md -opt/app/vendor/league/flysystem/docs/performance.md -opt/app/vendor/league/flysystem/docs/plugins.md -opt/app/vendor/league/flysystem/docs/recipes.md -opt/app/vendor/league/flysystem/docs/sponsors.md -opt/app/vendor/league/flysystem/docs/upgrade-to-1.0.0.md opt/app/vendor/league/flysystem/src/Adapter/AbstractAdapter.php opt/app/vendor/league/flysystem/src/Adapter/AbstractFtpAdapter.php opt/app/vendor/league/flysystem/src/Adapter/CanOverwriteFiles.php @@ -3130,7 +3468,81 @@ opt/app/vendor/league/flysystem/src/Util.php opt/app/vendor/league/flysystem/src/Util/ContentListingFormatter.php opt/app/vendor/league/flysystem/src/Util/MimeType.php opt/app/vendor/league/flysystem/src/Util/StreamHasher.php -opt/app/vendor/league/flysystem/wait_for_ftp_service.php +opt/app/vendor/league/fractal/LICENSE +opt/app/vendor/league/fractal/composer.json +opt/app/vendor/league/fractal/src/Manager.php +opt/app/vendor/league/fractal/src/Pagination/Cursor.php +opt/app/vendor/league/fractal/src/Pagination/CursorInterface.php +opt/app/vendor/league/fractal/src/Pagination/DoctrinePaginatorAdapter.php +opt/app/vendor/league/fractal/src/Pagination/IlluminatePaginatorAdapter.php +opt/app/vendor/league/fractal/src/Pagination/PagerfantaPaginatorAdapter.php +opt/app/vendor/league/fractal/src/Pagination/PaginatorInterface.php +opt/app/vendor/league/fractal/src/Pagination/PhalconFrameworkPaginatorAdapter.php +opt/app/vendor/league/fractal/src/Pagination/ZendFrameworkPaginatorAdapter.php +opt/app/vendor/league/fractal/src/ParamBag.php +opt/app/vendor/league/fractal/src/Resource/Collection.php +opt/app/vendor/league/fractal/src/Resource/Item.php +opt/app/vendor/league/fractal/src/Resource/NullResource.php +opt/app/vendor/league/fractal/src/Resource/Primitive.php +opt/app/vendor/league/fractal/src/Resource/ResourceAbstract.php +opt/app/vendor/league/fractal/src/Resource/ResourceInterface.php +opt/app/vendor/league/fractal/src/Scope.php +opt/app/vendor/league/fractal/src/ScopeFactory.php +opt/app/vendor/league/fractal/src/ScopeFactoryInterface.php +opt/app/vendor/league/fractal/src/Serializer/ArraySerializer.php +opt/app/vendor/league/fractal/src/Serializer/DataArraySerializer.php +opt/app/vendor/league/fractal/src/Serializer/JsonApiSerializer.php +opt/app/vendor/league/fractal/src/Serializer/Serializer.php +opt/app/vendor/league/fractal/src/Serializer/SerializerAbstract.php +opt/app/vendor/league/fractal/src/TransformerAbstract.php +opt/app/vendor/league/oauth2-server/.styleci.yml +opt/app/vendor/league/oauth2-server/CONDUCT.md +opt/app/vendor/league/oauth2-server/LICENSE +opt/app/vendor/league/oauth2-server/composer.json +opt/app/vendor/league/oauth2-server/src/AuthorizationServer.php +opt/app/vendor/league/oauth2-server/src/AuthorizationValidators/AuthorizationValidatorInterface.php +opt/app/vendor/league/oauth2-server/src/AuthorizationValidators/BearerTokenValidator.php +opt/app/vendor/league/oauth2-server/src/CryptKey.php +opt/app/vendor/league/oauth2-server/src/CryptTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/AccessTokenEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/AuthCodeEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/ClientEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/RefreshTokenEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/ScopeEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/TokenInterface.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/AccessTokenTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/AuthCodeTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/ClientTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/EntityTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/RefreshTokenTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/Traits/TokenEntityTrait.php +opt/app/vendor/league/oauth2-server/src/Entities/UserEntityInterface.php +opt/app/vendor/league/oauth2-server/src/Exception/OAuthServerException.php +opt/app/vendor/league/oauth2-server/src/Exception/UniqueTokenIdentifierConstraintViolationException.php +opt/app/vendor/league/oauth2-server/src/Grant/AbstractAuthorizeGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/AbstractGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/AuthCodeGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/ClientCredentialsGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/GrantTypeInterface.php +opt/app/vendor/league/oauth2-server/src/Grant/ImplicitGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/PasswordGrant.php +opt/app/vendor/league/oauth2-server/src/Grant/RefreshTokenGrant.php +opt/app/vendor/league/oauth2-server/src/Middleware/AuthorizationServerMiddleware.php +opt/app/vendor/league/oauth2-server/src/Middleware/ResourceServerMiddleware.php +opt/app/vendor/league/oauth2-server/src/Repositories/AccessTokenRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/AuthCodeRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/ClientRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/RefreshTokenRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/RepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/ScopeRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/Repositories/UserRepositoryInterface.php +opt/app/vendor/league/oauth2-server/src/RequestEvent.php +opt/app/vendor/league/oauth2-server/src/RequestTypes/AuthorizationRequest.php +opt/app/vendor/league/oauth2-server/src/ResourceServer.php +opt/app/vendor/league/oauth2-server/src/ResponseTypes/AbstractResponseType.php +opt/app/vendor/league/oauth2-server/src/ResponseTypes/BearerTokenResponse.php +opt/app/vendor/league/oauth2-server/src/ResponseTypes/RedirectResponse.php +opt/app/vendor/league/oauth2-server/src/ResponseTypes/ResponseTypeInterface.php opt/app/vendor/monolog/monolog/.php_cs opt/app/vendor/monolog/monolog/CHANGELOG.md opt/app/vendor/monolog/monolog/LICENSE @@ -3342,6 +3754,7 @@ opt/app/vendor/nesbot/carbon/src/Carbon/CarbonInterval.php opt/app/vendor/nesbot/carbon/src/Carbon/Exceptions/InvalidDateException.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/af.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ar.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ar_Shakl.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/az.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/bg.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/bn.php @@ -3349,6 +3762,7 @@ opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ca.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/cs.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/da.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/de.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/dv_MV.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/el.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/en.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/eo.php @@ -3368,15 +3782,18 @@ opt/app/vendor/nesbot/carbon/src/Carbon/Lang/id.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/it.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ja.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ka.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/kk.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/km.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ko.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/lt.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/lv.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/mk.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/mn.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ms.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/nl.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/no.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/pl.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ps.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/pt.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/pt_BR.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/ro.php @@ -3385,6 +3802,7 @@ opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sk.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sl.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sq.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sr.php +opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sr_Cyrl_ME.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sr_Latn_ME.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/sr_ME.php @@ -3397,6 +3815,7 @@ opt/app/vendor/nesbot/carbon/src/Carbon/Lang/uz.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/vi.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/zh.php opt/app/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php +opt/app/vendor/nesbot/carbon/trigger opt/app/vendor/paragonie/constant_time_encoding/LICENSE.txt opt/app/vendor/paragonie/constant_time_encoding/README.md opt/app/vendor/paragonie/constant_time_encoding/composer.json @@ -3440,6 +3859,36 @@ opt/app/vendor/paragonie/random_compat/lib/random_int.php opt/app/vendor/paragonie/random_compat/other/build_phar.php opt/app/vendor/paragonie/random_compat/psalm-autoload.php opt/app/vendor/paragonie/random_compat/psalm.xml +opt/app/vendor/phpseclib/phpseclib/AUTHORS +opt/app/vendor/phpseclib/phpseclib/LICENSE +opt/app/vendor/phpseclib/phpseclib/README.md +opt/app/vendor/phpseclib/phpseclib/composer.json +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Base.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/File/ANSI.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/File/X509.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Net/SCP.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Net/SSH1.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php +opt/app/vendor/phpseclib/phpseclib/phpseclib/openssl.cnf opt/app/vendor/pragmarx/google2fa-laravel/LICENSE opt/app/vendor/pragmarx/google2fa-laravel/changelog.md opt/app/vendor/pragmarx/google2fa-laravel/composer.json @@ -3487,6 +3936,17 @@ opt/app/vendor/psr/container/composer.json opt/app/vendor/psr/container/src/ContainerExceptionInterface.php opt/app/vendor/psr/container/src/ContainerInterface.php opt/app/vendor/psr/container/src/NotFoundExceptionInterface.php +opt/app/vendor/psr/http-message/CHANGELOG.md +opt/app/vendor/psr/http-message/LICENSE +opt/app/vendor/psr/http-message/README.md +opt/app/vendor/psr/http-message/composer.json +opt/app/vendor/psr/http-message/src/MessageInterface.php +opt/app/vendor/psr/http-message/src/RequestInterface.php +opt/app/vendor/psr/http-message/src/ResponseInterface.php +opt/app/vendor/psr/http-message/src/ServerRequestInterface.php +opt/app/vendor/psr/http-message/src/StreamInterface.php +opt/app/vendor/psr/http-message/src/UploadedFileInterface.php +opt/app/vendor/psr/http-message/src/UriInterface.php opt/app/vendor/psr/log/LICENSE opt/app/vendor/psr/log/Psr/Log/AbstractLogger.php opt/app/vendor/psr/log/Psr/Log/InvalidArgumentException.php @@ -4998,8 +5458,10 @@ opt/app/vendor/symfony/polyfill-util/Binary.php opt/app/vendor/symfony/polyfill-util/BinaryNoFuncOverload.php opt/app/vendor/symfony/polyfill-util/BinaryOnFuncOverload.php opt/app/vendor/symfony/polyfill-util/LICENSE +opt/app/vendor/symfony/polyfill-util/LegacyTestListener.php opt/app/vendor/symfony/polyfill-util/README.md opt/app/vendor/symfony/polyfill-util/TestListener.php +opt/app/vendor/symfony/polyfill-util/TestListenerTrait.php opt/app/vendor/symfony/polyfill-util/composer.json opt/app/vendor/symfony/process/CHANGELOG.md opt/app/vendor/symfony/process/Exception/ExceptionInterface.php @@ -5033,6 +5495,23 @@ opt/app/vendor/symfony/process/Tests/ProcessUtilsTest.php opt/app/vendor/symfony/process/Tests/SignalListener.php opt/app/vendor/symfony/process/composer.json opt/app/vendor/symfony/process/phpunit.xml.dist +opt/app/vendor/symfony/psr-http-message-bridge/CHANGELOG +opt/app/vendor/symfony/psr-http-message-bridge/Factory/DiactorosFactory.php +opt/app/vendor/symfony/psr-http-message-bridge/Factory/HttpFoundationFactory.php +opt/app/vendor/symfony/psr-http-message-bridge/HttpFoundationFactoryInterface.php +opt/app/vendor/symfony/psr-http-message-bridge/HttpMessageFactoryInterface.php +opt/app/vendor/symfony/psr-http-message-bridge/LICENSE +opt/app/vendor/symfony/psr-http-message-bridge/README.md +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Factory/DiactorosFactoryTest.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Factory/HttpFoundationFactoryTest.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Message.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Response.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/ServerRequest.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Stream.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/UploadedFile.php +opt/app/vendor/symfony/psr-http-message-bridge/Tests/Fixtures/Uri.php +opt/app/vendor/symfony/psr-http-message-bridge/composer.json +opt/app/vendor/symfony/psr-http-message-bridge/phpunit.xml.dist opt/app/vendor/symfony/routing/Annotation/Route.php opt/app/vendor/symfony/routing/CHANGELOG.md opt/app/vendor/symfony/routing/CompiledRoute.php @@ -5063,6 +5542,7 @@ opt/app/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php opt/app/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php opt/app/vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php opt/app/vendor/symfony/routing/Loader/DirectoryLoader.php +opt/app/vendor/symfony/routing/Loader/GlobFileLoader.php opt/app/vendor/symfony/routing/Loader/ObjectRouteLoader.php opt/app/vendor/symfony/routing/Loader/PhpFileLoader.php opt/app/vendor/symfony/routing/Loader/XmlFileLoader.php @@ -5175,10 +5655,13 @@ opt/app/vendor/symfony/routing/Tests/Loader/AnnotationDirectoryLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/AnnotationFileLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/ClosureLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/DirectoryLoaderTest.php +opt/app/vendor/symfony/routing/Tests/Loader/GlobFileLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/ObjectRouteLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/PhpFileLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/XmlFileLoaderTest.php opt/app/vendor/symfony/routing/Tests/Loader/YamlFileLoaderTest.php +opt/app/vendor/symfony/routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php +opt/app/vendor/symfony/routing/Tests/Matcher/DumpedUrlMatcherTest.php opt/app/vendor/symfony/routing/Tests/Matcher/Dumper/DumperCollectionTest.php opt/app/vendor/symfony/routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php opt/app/vendor/symfony/routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php @@ -5337,6 +5820,7 @@ opt/app/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/packagelist opt/app/vendor/symfony/translation/Tests/fixtures/resourcebundle/dat/resources.dat opt/app/vendor/symfony/translation/Tests/fixtures/resourcebundle/res/en.res opt/app/vendor/symfony/translation/Tests/fixtures/resources-2.0-clean.xlf +opt/app/vendor/symfony/translation/Tests/fixtures/resources-2.0-multi-segment-unit.xlf opt/app/vendor/symfony/translation/Tests/fixtures/resources-2.0.xlf opt/app/vendor/symfony/translation/Tests/fixtures/resources-clean.xlf opt/app/vendor/symfony/translation/Tests/fixtures/resources-notes-meta.xlf @@ -5931,6 +6415,7 @@ opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_wit opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test +opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/strict_comparison_operator.test opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_parent.test @@ -6301,6 +6786,47 @@ 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/vendor/zendframework/zend-diactoros/.coveralls.yml +opt/app/vendor/zendframework/zend-diactoros/CHANGELOG.md +opt/app/vendor/zendframework/zend-diactoros/CONDUCT.md +opt/app/vendor/zendframework/zend-diactoros/CONTRIBUTING.md +opt/app/vendor/zendframework/zend-diactoros/LICENSE.md +opt/app/vendor/zendframework/zend-diactoros/README.md +opt/app/vendor/zendframework/zend-diactoros/composer.json +opt/app/vendor/zendframework/zend-diactoros/composer.lock +opt/app/vendor/zendframework/zend-diactoros/mkdocs.yml +opt/app/vendor/zendframework/zend-diactoros/src/AbstractSerializer.php +opt/app/vendor/zendframework/zend-diactoros/src/CallbackStream.php +opt/app/vendor/zendframework/zend-diactoros/src/Exception/DeprecatedMethodException.php +opt/app/vendor/zendframework/zend-diactoros/src/Exception/ExceptionInterface.php +opt/app/vendor/zendframework/zend-diactoros/src/HeaderSecurity.php +opt/app/vendor/zendframework/zend-diactoros/src/MessageTrait.php +opt/app/vendor/zendframework/zend-diactoros/src/PhpInputStream.php +opt/app/vendor/zendframework/zend-diactoros/src/RelativeStream.php +opt/app/vendor/zendframework/zend-diactoros/src/Request.php +opt/app/vendor/zendframework/zend-diactoros/src/Request/ArraySerializer.php +opt/app/vendor/zendframework/zend-diactoros/src/Request/Serializer.php +opt/app/vendor/zendframework/zend-diactoros/src/RequestTrait.php +opt/app/vendor/zendframework/zend-diactoros/src/Response.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/ArraySerializer.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/EmitterInterface.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/EmptyResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/HtmlResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/InjectContentTypeTrait.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/JsonResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/RedirectResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/SapiEmitter.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/SapiEmitterTrait.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/SapiStreamEmitter.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/Serializer.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/TextResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Response/XmlResponse.php +opt/app/vendor/zendframework/zend-diactoros/src/Server.php +opt/app/vendor/zendframework/zend-diactoros/src/ServerRequest.php +opt/app/vendor/zendframework/zend-diactoros/src/ServerRequestFactory.php +opt/app/vendor/zendframework/zend-diactoros/src/Stream.php +opt/app/vendor/zendframework/zend-diactoros/src/UploadedFile.php +opt/app/vendor/zendframework/zend-diactoros/src/Uri.php proc/cpuinfo sandstorm-http-bridge sandstorm-http-bridge-config diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp index 10848c2abd..5f865b44c0 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 = 8, - appMarketingVersion = (defaultText = "4.7.0"), + appVersion = 9, + appMarketingVersion = (defaultText = "4.7.1"), actions = [ # Define your "new document" handlers here. diff --git a/.travis.yml b/.travis.yml index d2a3ff064d..33f7a18921 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - 7.1 - - 7.2 cache: directories: diff --git a/app/Api/V1/Controllers/AboutController.php b/app/Api/V1/Controllers/AboutController.php new file mode 100644 index 0000000000..4529802743 --- /dev/null +++ b/app/Api/V1/Controllers/AboutController.php @@ -0,0 +1,88 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use DB; +use FireflyIII\Transformers\UserTransformer; +use Illuminate\Http\Request; +use League\Fractal\Manager; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; + + +/** + * Class AboutController + */ +class AboutController extends Controller +{ + /** + * AccountController constructor. + * + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function __construct() + { + parent::__construct(); + + } + + /** + * @return \Illuminate\Http\JsonResponse + */ + public function about() + { + $search = ['~', '#']; + $replace = ['\~', '# ']; + $phpVersion = str_replace($search, $replace, PHP_VERSION); + $phpOs = str_replace($search, $replace, php_uname()); + $currentDriver = DB::getDriverName(); + $data + = [ + 'version' => config('firefly.version'), + 'api_version' => config('firefly.api_version'), + 'php_version' => $phpVersion, + 'os' => $phpOs, + 'driver' => $currentDriver, + + ]; + + return response()->json(['data' => $data], 200)->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function user(Request $request) + { + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/AccountController.php b/app/Api/V1/Controllers/AccountController.php new file mode 100644 index 0000000000..861d3e4aff --- /dev/null +++ b/app/Api/V1/Controllers/AccountController.php @@ -0,0 +1,263 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Api\V1\Requests\AccountRequest; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Transformers\AccountTransformer; +use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; +use Preferences; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ + + /** @var CurrencyRepositoryInterface */ + private $currencyRepository; + /** @var AccountRepositoryInterface */ + private $repository; + + /** + * AccountController constructor. + * + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var AccountRepositoryInterface repository */ + $this->repository = app(AccountRepositoryInterface::class); + $this->repository->setUser(auth()->user()); + + $this->currencyRepository = app(CurrencyRepositoryInterface::class); + $this->currencyRepository->setUser(auth()->user()); + + return $next($request); + } + ); + } + + /** + * Remove the specified resource from storage. + * + * @param \FireflyIII\Models\Account $account + * + * @return \Illuminate\Http\Response + */ + public function delete(Account $account) + { + $this->repository->destroy($account, null); + + return response()->json([], 204); + } + + /** + * Display a listing of the resource. + * + * @param Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function index(Request $request) + { + // create some objects: + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + + // read type from URI + $type = $request->get('type') ?? 'all'; + $this->parameters->set('type', $type); + + // types to get, page size: + $types = $this->mapTypes($this->parameters->get('type')); + $pageSize = intval(Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data); + + // get list of accounts. Count it and split it. + $collection = $this->repository->getAccountsByType($types); + $count = $collection->count(); + $accounts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.accounts.index') . $this->buildParams()); + + // present to user. + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new FractalCollection($accounts, new AccountTransformer($this->parameters), 'accounts'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param Request $request + * @param Account $account + * + * @return \Illuminate\Http\JsonResponse + */ + public function show(Request $request, Account $account) + { + $manager = new Manager(); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param AccountRequest $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function store(AccountRequest $request) + { + $data = $request->getAll(); + // if currency ID is 0, find the currency by the code: + if ($data['currency_id'] === 0) { + $currency = $this->currencyRepository->findByCodeNull($data['currency_code']); + $data['currency_id'] = is_null($currency) ? 0 : $currency->id; + } + $account = $this->repository->store($data); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * Update account. + * + * @param AccountRequest $request + * @param Account $account + * + * @return \Illuminate\Http\JsonResponse + */ + public function update(AccountRequest $request, Account $account) + { + $data = $request->getAll(); + // if currency ID is 0, find the currency by the code: + if ($data['currency_id'] === 0) { + $currency = $this->currencyRepository->findByCodeNull($data['currency_code']); + $data['currency_id'] = is_null($currency) ? 0 : $currency->id; + } + // set correct type: + $data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type); + $this->repository->update($account, $data); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param string $type + * + * @return array + */ + private function mapTypes(string $type): array + { + $types = [ + 'all' => [ + AccountType::DEFAULT, + AccountType::CASH, + AccountType::ASSET, + AccountType::EXPENSE, + AccountType::REVENUE, + AccountType::INITIAL_BALANCE, + AccountType::BENEFICIARY, + AccountType::IMPORT, + AccountType::RECONCILIATION, + AccountType::LOAN, + ], + 'asset' => [ + AccountType::DEFAULT, + AccountType::ASSET, + ], + 'cash' => [ + AccountType::CASH, + ], + 'expense' => [ + AccountType::EXPENSE, + AccountType::BENEFICIARY, + ], + 'revenue' => [ + AccountType::REVENUE, + ], + 'special' => [ + AccountType::CASH, + AccountType::INITIAL_BALANCE, + AccountType::IMPORT, + AccountType::RECONCILIATION, + AccountType::LOAN, + ], + 'hidden' => [ + AccountType::INITIAL_BALANCE, + AccountType::IMPORT, + AccountType::RECONCILIATION, + AccountType::LOAN, + ], + AccountType::DEFAULT => [AccountType::DEFAULT], + AccountType::CASH => [AccountType::CASH], + AccountType::ASSET => [AccountType::ASSET], + AccountType::EXPENSE => [AccountType::EXPENSE], + AccountType::REVENUE => [AccountType::REVENUE], + AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE], + AccountType::BENEFICIARY => [AccountType::BENEFICIARY], + AccountType::IMPORT => [AccountType::IMPORT], + AccountType::RECONCILIATION => [AccountType::RECONCILIATION], + AccountType::LOAN => [AccountType::LOAN], + ]; + if (isset($types[$type])) { + return $types[$type]; + } + + return $types['all']; // @codeCoverageIgnore + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/BillController.php b/app/Api/V1/Controllers/BillController.php new file mode 100644 index 0000000000..6e62d6e906 --- /dev/null +++ b/app/Api/V1/Controllers/BillController.php @@ -0,0 +1,164 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Api\V1\Requests\BillRequest; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Bill; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Transformers\BillTransformer; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; +use Preferences; + +/** + * Class BillController + */ +class BillController extends Controller +{ + /** @var BillRepositoryInterface */ + private $repository; + + /** + * BillController constructor. + * + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var BillRepositoryInterface repository */ + $this->repository = app(BillRepositoryInterface::class); + $this->repository->setUser(auth()->user()); + + return $next($request); + } + ); + } + + /** + * Remove the specified resource from storage. + * + * @param \FireflyIII\Models\Bill $bill + * + * @return \Illuminate\Http\Response + */ + public function delete(Bill $bill) + { + $this->repository->destroy($bill); + + return response()->json([], 204); + } + + /** + * Display a listing of the resource. + * + * @param Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function index(Request $request) + { + $pageSize = intval(Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data); + $paginator = $this->repository->getPaginator($pageSize); + /** @var Collection $bills */ + $bills = $paginator->getCollection(); + + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + + /** + * @param Request $request + * @param Bill $bill + * + * @return \Illuminate\Http\JsonResponse + */ + public function show(Request $request, Bill $bill) + { + $manager = new Manager(); + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param BillRequest $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function store(BillRequest $request) + { + $bill = $this->repository->store($request->getAll()); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + + /** + * @param BillRequest $request + * @param Bill $bill + * + * @return \Illuminate\Http\JsonResponse + */ + public function update(BillRequest $request, Bill $bill) + { + $data = $request->getAll(); + $bill = $this->repository->update($bill, $data); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } +} diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php new file mode 100644 index 0000000000..91145d63b8 --- /dev/null +++ b/app/Api/V1/Controllers/Controller.php @@ -0,0 +1,121 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use Carbon\Carbon; +use Carbon\Exceptions\InvalidDateException; +use FireflyConfig; +use FireflyIII\Exceptions\FireflyException; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; +use Illuminate\Foundation\Bus\DispatchesJobs; +use Illuminate\Foundation\Validation\ValidatesRequests; +use Illuminate\Routing\Controller as BaseController; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class Controller. + * @codeCoverageIgnore + */ +class Controller extends BaseController +{ + use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + + /** @var ParameterBag */ + protected $parameters; + + /** + * Controller constructor. + * + * @throws FireflyException + */ + public function __construct() + { + // is site a demo site? + $isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data; + + // do not expose API on demo site: + if (true === $isDemoSite) { + throw new FireflyException('The API is not available on the demo site.'); + } + + // get global parameters + $this->parameters = $this->getParameters(); + } + + /** + * @return string + */ + protected function buildParams(): string + { + $return = '?'; + $params = []; + foreach ($this->parameters as $key => $value) { + if($key === 'page') { + continue; + } + if ($value instanceof Carbon) { + $params[$key] = $value->format('Y-m-d'); + } + if (!$value instanceof Carbon) { + $params[$key] = $value; + } + } + $return .= http_build_query($params); + if (strlen($return) === 1) { + return ''; + } + + return $return; + } + + /** + * @return ParameterBag + */ + private function getParameters(): ParameterBag + { + $bag = new ParameterBag; + $page = (int)request()->get('page'); + if ($page === 0) { + $page = 1; + } + $bag->set('page', $page); + + // some date fields: + $dates = ['start', 'end', 'date']; + foreach ($dates as $field) { + $date = request()->get($field); + $obj = null; + if (!is_null($date)) { + try { + $obj = new Carbon($date); + } catch (InvalidDateException $e) { + // don't care + } + } + $bag->set($field, $obj); + } + + return $bag; + + } +} diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php new file mode 100644 index 0000000000..9490a190b1 --- /dev/null +++ b/app/Api/V1/Controllers/TransactionController.php @@ -0,0 +1,333 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Api\V1\Requests\TransactionRequest; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Helpers\Filter\InternalTransferFilter; +use FireflyIII\Helpers\Filter\NegativeAmountFilter; +use FireflyIII\Helpers\Filter\PositiveAmountFilter; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Transformers\TransactionTransformer; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; +use Log; +use Preferences; + +/** + * Class TransactionController + */ +class TransactionController extends Controller +{ + + /** @var JournalRepositoryInterface */ + private $repository; + + /** + * TransactionController constructor. + * + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var JournalRepositoryInterface repository */ + $this->repository = app(JournalRepositoryInterface::class); + $this->repository->setUser(auth()->user()); + + return $next($request); + } + ); + } + + /** + * Remove the specified resource from storage. + * + * @param \FireflyIII\Models\Transaction $transaction + * + * @return \Illuminate\Http\Response + */ + public function delete(Transaction $transaction) + { + $journal = $transaction->transactionJournal; + $this->repository->destroy($journal); + + return response()->json([], 204); + } + + /** + * @param Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function index(Request $request) + { + $pageSize = intval(Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data); + + // read type from URI + $type = $request->get('type') ?? 'default'; + $this->parameters->set('type', $type); + + // types to get, page size: + $types = $this->mapTypes($this->parameters->get('type')); + + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // collect transactions using the journal collector + $collector = app(JournalCollectorInterface::class); + $collector->setUser(auth()->user()); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + $collector->setAllAssetAccounts(); + + // remove internal transfer filter: + if (in_array(TransactionType::TRANSFER, $types)) { + $collector->removeFilter(InternalTransferFilter::class); + } + + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $collector->setTypes($types); + $paginator = $collector->getPaginatedJournals(); + $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); + $transactions = $paginator->getCollection(); + + + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + + /** + * @param Request $request + * @param Transaction $transaction + * + * @return \Illuminate\Http\JsonResponse + */ + public function show(Request $request, Transaction $transaction) + { + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // collect transactions using the journal collector + $collector = app(JournalCollectorInterface::class); + $collector->setUser(auth()->user()); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + // filter on specific journals. + $collector->setJournals(new Collection([$transaction->transactionJournal])); + + // add filter to remove transactions: + $transactionType = $transaction->transactionJournal->transactionType->type; + if ($transactionType === TransactionType::WITHDRAWAL) { + $collector->addFilter(PositiveAmountFilter::class); + } + if (!($transactionType === TransactionType::WITHDRAWAL)) { + $collector->addFilter(NegativeAmountFilter::class); + } + + $transactions = $collector->getJournals(); + $resource = new Item($transactions->first(), new TransactionTransformer($this->parameters), 'transactions'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param TransactionRequest $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function store(TransactionRequest $request, JournalRepositoryInterface $repository) + { + $data = $request->getAll(); + $data['user'] = auth()->user()->id; + $journal = $repository->store($data); + + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // collect transactions using the journal collector + $collector = app(JournalCollectorInterface::class); + $collector->setUser(auth()->user()); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + // filter on specific journals. + $collector->setJournals(new Collection([$journal])); + + // add filter to remove transactions: + $transactionType = $journal->transactionType->type; + if ($transactionType === TransactionType::WITHDRAWAL) { + $collector->addFilter(PositiveAmountFilter::class); + } + if (!($transactionType === TransactionType::WITHDRAWAL)) { + $collector->addFilter(NegativeAmountFilter::class); + } + + $transactions = $collector->getJournals(); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + + /** + * @param TransactionRequest $request + * @param JournalRepositoryInterface $repository + * @param Transaction $transaction + * + * @return \Illuminate\Http\JsonResponse + */ + public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction) + { + $data = $request->getAll(); + $data['user'] = auth()->user()->id; + + Log::debug('Inside transaction update'); + + $journal = $repository->update($transaction->transactionJournal, $data); + + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // needs a lot of extra data to match the journal collector. Or just expand that one. + // collect transactions using the journal collector + $collector = app(JournalCollectorInterface::class); + $collector->setUser(auth()->user()); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + // filter on specific journals. + $collector->setJournals(new Collection([$journal])); + + // add filter to remove transactions: + $transactionType = $journal->transactionType->type; + if ($transactionType === TransactionType::WITHDRAWAL) { + $collector->addFilter(PositiveAmountFilter::class); + } + if (!($transactionType === TransactionType::WITHDRAWAL)) { + $collector->addFilter(NegativeAmountFilter::class); + } + + $transactions = $collector->getJournals(); + $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + + /** + * @param string $type + * + * @return array + */ + private function mapTypes(string $type): array + { + $types = [ + 'all' => [ + TransactionType::WITHDRAWAL, + TransactionType::DEPOSIT, + TransactionType::TRANSFER, + TransactionType::OPENING_BALANCE, + TransactionType::RECONCILIATION, + ], + 'withdrawal' => [ + TransactionType::WITHDRAWAL, + ], + 'withdrawals' => [ + TransactionType::WITHDRAWAL, + ], + 'expense' => [ + TransactionType::WITHDRAWAL, + ], + 'income' => [ + TransactionType::DEPOSIT, + ], + 'deposit' => [ + TransactionType::DEPOSIT, + ], + 'deposits' => [ + TransactionType::DEPOSIT, + ], + 'transfer' => [ + TransactionType::TRANSFER, + ], + 'transfers' => [ + TransactionType::TRANSFER, + ], + 'opening_balance' => [ + TransactionType::OPENING_BALANCE, + ], + 'reconciliation' => [ + TransactionType::RECONCILIATION, + ], + 'reconciliations' => [ + TransactionType::RECONCILIATION, + ], + 'special' => [ + TransactionType::OPENING_BALANCE, + TransactionType::RECONCILIATION, + ], + 'specials' => [ + TransactionType::OPENING_BALANCE, + TransactionType::RECONCILIATION, + ], + 'default' => [ + TransactionType::WITHDRAWAL, + TransactionType::DEPOSIT, + TransactionType::TRANSFER, + ], + ]; + if (isset($types[$type])) { + return $types[$type]; + } + + return $types['default']; // @codeCoverageIgnore + + } +} \ No newline at end of file diff --git a/app/Api/V1/Controllers/UserController.php b/app/Api/V1/Controllers/UserController.php new file mode 100644 index 0000000000..29acb5307e --- /dev/null +++ b/app/Api/V1/Controllers/UserController.php @@ -0,0 +1,192 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers; + +use FireflyIII\Api\V1\Requests\UserRequest; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Transformers\UserTransformer; +use FireflyIII\User; +use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; +use Preferences; +use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; + +/** + * Class UserController + */ +class UserController extends Controller +{ + + /** @var UserRepositoryInterface */ + private $repository; + + /** + * UserController constructor. + * + * @throws \FireflyIII\Exceptions\FireflyException + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @var UserRepositoryInterface repository */ + $this->repository = app(UserRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** + * Remove the specified resource from storage. + * + * @param \FireflyIII\User $user + * + * @return \Illuminate\Http\Response + */ + public function delete(User $user) + { + if (auth()->user()->hasRole('owner')) { + $this->repository->destroy($user); + + return response()->json([], 204); + } + throw new AccessDeniedException(''); // @codeCoverageIgnore + } + + /** + * Display a listing of the resource. + * + * @param Request $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function index(Request $request) + { + // user preferences + $pageSize = intval(Preferences::getForUser(auth()->user(), 'listPageSize', 50)->data); + + // make manager + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // build collection + $collection = $this->repository->all(); + $count = $collection->count(); + $users = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); + + // make paginator: + $paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page')); + $paginator->setPath(route('api.v1.users.index') . $this->buildParams()); + + // make resource + $resource = new FractalCollection($users, new UserTransformer($this->parameters), 'users'); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param Request $request + * @param User $user + * + * @return \Illuminate\Http\JsonResponse + */ + public function show(Request $request, User $user) + { + // make manager + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // make resource + $resource = new Item($user, new UserTransformer($this->parameters), 'users'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param UserRequest $request + * + * @return \Illuminate\Http\JsonResponse + */ + public function store(UserRequest $request) + { + $data = $request->getAll(); + $user = $this->repository->store($data); + + // make manager + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // make resource + $resource = new Item($user, new UserTransformer($this->parameters), 'users'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + } + + /** + * @param UserRequest $request + * @param User $user + * + * @return \Illuminate\Http\JsonResponse + */ + public function update(UserRequest $request, User $user) + { + $data = $request->getAll(); + $user = $this->repository->update($user, $data); + + // make manager + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + // add include parameter: + $include = $request->get('include') ?? ''; + $manager->parseIncludes($include); + + // make resource + $resource = new Item($user, new UserTransformer($this->parameters), 'users'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); + + } + +} \ No newline at end of file diff --git a/app/Api/V1/Requests/AccountRequest.php b/app/Api/V1/Requests/AccountRequest.php new file mode 100644 index 0000000000..649d21c29c --- /dev/null +++ b/app/Api/V1/Requests/AccountRequest.php @@ -0,0 +1,107 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +/** + * Class AccountRequest + */ +class AccountRequest extends Request +{ + + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow authenticated users + return auth()->check(); + } + + /** + * @return array + */ + public function getAll(): array + { + $data = [ + 'name' => $this->string('name'), + 'active' => $this->boolean('active'), + 'accountType' => $this->string('type'), + 'account_type_id' => null, + 'currency_id' => $this->integer('currency_id'), + 'currency_code' => $this->string('currency_code'), + 'virtualBalance' => $this->string('virtual_balance'), + 'iban' => $this->string('iban'), + 'BIC' => $this->string('bic'), + 'accountNumber' => $this->string('account_number'), + 'accountRole' => $this->string('account_role'), + 'openingBalance' => $this->string('opening_balance'), + 'openingBalanceDate' => $this->date('opening_balance_date'), + 'ccType' => $this->string('cc_type'), + 'ccMonthlyPaymentDate' => $this->string('cc_monthly_payment_date'), + 'notes' => $this->string('notes'), + ]; + + return $data; + } + + /** + * @return array + */ + public function rules(): array + { + $accountRoles = join(',', config('firefly.accountRoles')); + $types = join(',', array_keys(config('firefly.subTitlesByIdentifier'))); + $ccPaymentTypes = join(',', array_keys(config('firefly.ccTypes'))); + $rules = [ + 'name' => 'required|min:1|uniqueAccountForUser', + 'opening_balance' => 'numeric|required_with:opening_balance_date|nullable', + 'opening_balance_date' => 'date|required_with:opening_balance|nullable', + 'iban' => 'iban|nullable', + 'bic' => 'bic|nullable', + 'virtual_balance' => 'numeric|nullable', + 'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code', + 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', + 'account_number' => 'between:1,255|nullable|uniqueAccountNumberForUser', + 'account_role' => 'in:' . $accountRoles . '|required_if:type,asset', + 'active' => 'required|boolean', + 'cc_type' => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset', + 'cc_monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:cc_type,monthlyFull', + 'type' => 'required|in:' . $types, + 'notes' => 'min:0|max:65536', + ]; + switch ($this->method()) { + default: + break; + case 'PUT': + case 'PATCH': + $account = $this->route()->parameter('account'); + $rules['name'] .= ':' . $account->id; + $rules['account_number'] .= ':' . $account->id; + $rules['type'] = 'in:' . $types; + break; + } + + return $rules; + } +} \ No newline at end of file diff --git a/app/Api/V1/Requests/BillRequest.php b/app/Api/V1/Requests/BillRequest.php new file mode 100644 index 0000000000..881364a3e9 --- /dev/null +++ b/app/Api/V1/Requests/BillRequest.php @@ -0,0 +1,119 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +use Illuminate\Validation\Validator; + +/** + * Class BillRequest + */ +class BillRequest extends Request +{ + + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow authenticated users + return auth()->check(); + } + + /** + * @return array + */ + public function getAll(): array + { + $data = [ + 'name' => $this->string('name'), + 'match' => $this->string('match'), + 'amount_min' => $this->string('amount_min'), + 'amount_max' => $this->string('amount_max'), + //'currency_id' => $this->integer('currency_id'), + //'currency_code' => $this->string('currency_code'), + 'date' => $this->date('date'), + 'repeat_freq' => $this->string('repeat_freq'), + 'skip' => $this->integer('skip'), + 'automatch' => $this->boolean('automatch'), + 'active' => $this->boolean('active'), + 'notes' => $this->string('notes'), + ]; + + return $data; + } + + /** + * @return array + */ + public function rules(): array + { + $rules = [ + 'name' => 'required|between:1,255|uniqueObjectForUser:bills,name', + 'match' => 'required|between:1,255|uniqueObjectForUser:bills,match', + 'amount_min' => 'required|numeric|more:0', + 'amount_max' => 'required|numeric|more:0', + //'currency_id' => 'numeric|exists:transaction_currencies,id|required_without:currency_code', + //'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', + 'date' => 'required|date', + 'repeat_freq' => 'required|in:weekly,monthly,quarterly,half-year,yearly', + 'skip' => 'required|between:0,31', + 'automatch' => 'required|boolean', + 'active' => 'required|boolean', + 'notes' => 'between:1,65536', + ]; + switch ($this->method()) { + default: + break; + case 'PUT': + case 'PATCH': + $bill = $this->route()->parameter('bill'); + $rules['name'] .= ',' . $bill->id; + $rules['match'] .= ',' . $bill->id; + break; + } + + return $rules; + } + + /** + * Configure the validator instance. + * + * @param Validator $validator + * + * @return void + */ + public function withValidator(Validator $validator): void + { + $validator->after( + function (Validator $validator) { + $data = $validator->getData(); + $min = floatval($data['amount_min'] ?? 0); + $max = floatval($data['amount_max'] ?? 0); + if ($min > $max) { + $validator->errors()->add('amount_min', trans('validation.amount_min_over_max')); + } + } + ); + } +} \ No newline at end of file diff --git a/app/Api/V1/Requests/Request.php b/app/Api/V1/Requests/Request.php new file mode 100644 index 0000000000..198680635b --- /dev/null +++ b/app/Api/V1/Requests/Request.php @@ -0,0 +1,32 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +use FireflyIII\Http\Requests\Request as FireflyIIIRequest; +/** + * Class Request. + */ +class Request extends FireflyIIIRequest +{ + +} diff --git a/app/Api/V1/Requests/TransactionRequest.php b/app/Api/V1/Requests/TransactionRequest.php new file mode 100644 index 0000000000..17a46633c7 --- /dev/null +++ b/app/Api/V1/Requests/TransactionRequest.php @@ -0,0 +1,500 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Transaction; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Rules\BelongsUser; +use Illuminate\Validation\Validator; + + +/** + * Class TransactionRequest + */ +class TransactionRequest extends Request +{ + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow authenticated users + return auth()->check(); + } + + /** + * @return array + */ + public function getAll(): array + { + $data = [ + // basic fields for journal: + 'type' => $this->string('type'), + 'date' => $this->date('date'), + 'description' => $this->string('description'), + 'piggy_bank_id' => $this->integer('piggy_bank_id'), + 'piggy_bank_name' => $this->string('piggy_bank_name'), + 'bill_id' => $this->integer('bill_id'), + 'bill_name' => $this->string('bill_name'), + 'tags' => explode(',', $this->string('tags')), + + // then, custom fields for journal + 'interest_date' => $this->date('interest_date'), + 'book_date' => $this->date('book_date'), + 'process_date' => $this->date('process_date'), + 'due_date' => $this->date('due_date'), + 'payment_date' => $this->date('payment_date'), + 'invoice_date' => $this->date('invoice_date'), + 'internal_reference' => $this->string('internal_reference'), + 'notes' => $this->string('notes'), + + // then, transactions (see below). + 'transactions' => [], + + ]; + foreach ($this->get('transactions') as $index => $transaction) { + $array = [ + 'description' => $transaction['description'] ?? null, + 'amount' => $transaction['amount'], + 'currency_id' => isset($transaction['currency_id']) ? intval($transaction['currency_id']) : null, + 'currency_code' => isset($transaction['currency_code']) ? $transaction['currency_code'] : null, + 'foreign_amount' => $transaction['foreign_amount'] ?? null, + 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? intval($transaction['foreign_currency_id']) : null, + 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, + 'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : null, + 'budget_name' => $transaction['budget_name'] ?? null, + 'category_id' => isset($transaction['category_id']) ? intval($transaction['category_id']) : null, + 'category_name' => $transaction['category_name'] ?? null, + 'source_id' => isset($transaction['source_id']) ? intval($transaction['source_id']) : null, + 'source_name' => isset($transaction['source_name']) ? strval($transaction['source_name']) : null, + 'destination_id' => isset($transaction['destination_id']) ? intval($transaction['destination_id']) : null, + 'destination_name' => isset($transaction['destination_name']) ? strval($transaction['destination_name']) : null, + 'reconciled' => $transaction['reconciled'] ?? false, + 'identifier' => $index, + ]; + $data['transactions'][] = $array; + } + + return $data; + } + + /** + * @return array + */ + public function rules(): array + { + $rules = [ + // basic fields for journal: + 'type' => 'required|in:withdrawal,deposit,transfer', + 'date' => 'required|date', + 'description' => 'between:1,255', + 'piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], + 'piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser], + 'bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], + 'bill_name' => ['between:1,255', 'nullable', new BelongsUser], + 'tags' => 'between:1,255', + + // then, custom fields for journal + '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', + + // transaction rules (in array for splits): + 'transactions.*.description' => 'nullable|between:1,255', + 'transactions.*.amount' => 'required|numeric|more:0', + 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code', + 'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id', + 'transactions.*.foreign_amount' => 'numeric|more:0', + 'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id', + 'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', + 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser], + 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], + 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser], + 'transactions.*.category_name' => 'between:1,255|nullable', + 'transactions.*.reconciled' => 'boolean|nullable', + // basic rules will be expanded later. + 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.source_name' => 'between:1,255|nullable', + 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.destination_name' => 'between:1,255|nullable', + ]; + + switch ($this->method()) { + default: + break; + case 'PUT': + case 'PATCH': + unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']); + break; + } + + return $rules; + + + } + + /** + * Configure the validator instance. + * + * @param Validator $validator + * + * @return void + */ + public function withValidator(Validator $validator): void + { + $validator->after( + function (Validator $validator) { + $this->atLeastOneTransaction($validator); + $this->checkValidDescriptions($validator); + $this->equalToJournalDescription($validator); + $this->emptySplitDescriptions($validator); + $this->foreignCurrencyInformation($validator); + $this->validateAccountInformation($validator); + $this->validateSplitAccounts($validator); + } + ); + } + + /** + * Throws an error when this asset account is invalid. + * + * @param Validator $validator + * @param int|null $accountId + * @param null|string $accountName + * @param string $idField + * @param string $nameField + */ + protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): void + { + + $accountId = intval($accountId); + $accountName = strval($accountName); + // both empty? hard exit. + if ($accountId < 1 && strlen($accountName) === 0) { + $validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField])); + + return; + } + // ID belongs to user and is asset account: + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setUser(auth()->user()); + $set = $repository->getAccountsById([$accountId]); + if ($set->count() === 1) { + /** @var Account $first */ + $first = $set->first(); + if ($first->accountType->type !== AccountType::ASSET) { + $validator->errors()->add($idField, trans('validation.belongs_user')); + + return; + } + + // we ignore the account name at this point. + return; + } + + $account = $repository->findByName($accountName, [AccountType::ASSET]); + if (is_null($account)) { + $validator->errors()->add($nameField, trans('validation.belongs_user')); + } + + return; + } + + /** + * Adds an error to the validator when there are no transactions in the array of data. + * + * @param Validator $validator + */ + protected function atLeastOneTransaction(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + // need at least one transaction + if (count($transactions) === 0) { + $validator->errors()->add('description', trans('validation.at_least_one_transaction')); + } + } + + /** + * Adds an error to the "description" field when the user has submitted no descriptions and no + * journal description. + * + * @param Validator $validator + */ + protected function checkValidDescriptions(Validator $validator) + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + $journalDescription = strval($data['description'] ?? ''); + $validDescriptions = 0; + foreach ($transactions as $index => $transaction) { + if (strlen(strval($transaction['description'] ?? '')) > 0) { + $validDescriptions++; + } + } + + // no valid descriptions and empty journal description? error. + if ($validDescriptions === 0 && strlen($journalDescription) === 0) { + $validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')])); + } + + } + + /** + * Adds an error to the validator when the user submits a split transaction (more than 1 transactions) + * but does not give them a description. + * + * @param Validator $validator + */ + protected function emptySplitDescriptions(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + foreach ($transactions as $index => $transaction) { + $description = strval($transaction['description'] ?? ''); + // filled description is mandatory for split transactions. + if (count($transactions) > 1 && strlen($description) === 0) { + $validator->errors()->add( + 'transactions.' . $index . '.description', + trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')]) + ); + } + } + } + + /** + * Adds an error to the validator when any transaction descriptions are equal to the journal description. + * + * @param Validator $validator + */ + protected function equalToJournalDescription(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + $journalDescription = strval($data['description'] ?? ''); + foreach ($transactions as $index => $transaction) { + $description = strval($transaction['description'] ?? ''); + // description cannot be equal to journal description. + if ($description === $journalDescription) { + $validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description')); + } + } + } + + /** + * If the transactions contain foreign amounts, there must also be foreign currency information. + * + * @param Validator $validator + */ + protected function foreignCurrencyInformation(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + foreach ($transactions as $index => $transaction) { + // must have currency info. + if (isset($transaction['foreign_amount']) + && !(isset($transaction['foreign_currency_id']) + || isset($transaction['foreign_currency_code']))) { + $validator->errors()->add( + 'transactions.' . $index . '.foreign_amount', + trans('validation.require_currency_info') + ); + } + } + } + + /** + * Throws an error when the given opposing account (of type $type) is invalid. + * Empty data is allowed, system will default to cash. + * + * @param Validator $validator + * @param string $type + * @param int|null $accountId + * @param null|string $accountName + * @param string $idField + */ + protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): void { + $accountId = intval($accountId); + $accountName = strval($accountName); + // both empty? done! + if ($accountId < 1 && strlen($accountName) === 0) { + return; + } + if ($accountId !== 0) { + // ID belongs to user and is $type account: + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setUser(auth()->user()); + $set = $repository->getAccountsById([$accountId]); + if ($set->count() === 1) { + /** @var Account $first */ + $first = $set->first(); + if ($first->accountType->type !== $type) { + $validator->errors()->add($idField, trans('validation.belongs_user')); + + return; + } + + // we ignore the account name at this point. + return; + } + } + + // not having an opposing account by this name is NOT a problem. + return; + } + + /** + * Validates the given account information. Switches on given transaction type. + * + * @param Validator $validator + * + * @throws FireflyException + */ + protected function validateAccountInformation(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + if (!isset($data['type'])) { + // the journal may exist in the request: + /** @var Transaction $transaction */ + $transaction = $this->route()->parameter('transaction'); + if (is_null($transaction)) { + return; // @codeCoverageIgnore + } + $data['type'] = strtolower($transaction->transactionJournal->transactionType->type); + } + foreach ($transactions as $index => $transaction) { + $sourceId = isset($transaction['source_id']) ? intval($transaction['source_id']) : null; + $sourceName = $transaction['source_name'] ?? null; + $destinationId = isset($transaction['destination_id']) ? intval($transaction['destination_id']) : null; + $destinationName = $transaction['destination_name'] ?? null; + + switch ($data['type']) { + case 'withdrawal': + $idField = 'transactions.' . $index . '.source_id'; + $nameField = 'transactions.' . $index . '.source_name'; + $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); + + $idField = 'transactions.' . $index . '.destination_id'; + $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField); + break; + case 'deposit': + $idField = 'transactions.' . $index . '.source_id'; + $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField); + + $idField = 'transactions.' . $index . '.destination_id'; + $nameField = 'transactions.' . $index . '.destination_name'; + $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); + break; + case 'transfer': + $idField = 'transactions.' . $index . '.source_id'; + $nameField = 'transactions.' . $index . '.source_name'; + $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); + + $idField = 'transactions.' . $index . '.destination_id'; + $nameField = 'transactions.' . $index . '.destination_name'; + $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); + break; + default: + throw new FireflyException(sprintf('The validator cannot handle transaction type "%s" in validateAccountInformation().', $data['type'])); + + } + } + } + + /** + * @param Validator $validator + * + * @throws FireflyException + */ + protected function validateSplitAccounts(Validator $validator) + { + $data = $validator->getData(); + $count = isset($data['transactions']) ? count($data['transactions']) : 0; + if ($count < 2) { + return; + } + // this is pretty much impossible: + // @codeCoverageIgnoreStart + if (!isset($data['type'])) { + // the journal may exist in the request: + /** @var Transaction $transaction */ + $transaction = $this->route()->parameter('transaction'); + if (is_null($transaction)) { + return; + } + $data['type'] = strtolower($transaction->transactionJournal->transactionType->type); + } + // @codeCoverageIgnoreEnd + + // collect all source ID's and destination ID's, if present: + $sources = []; + $destinations = []; + + foreach ($data['transactions'] as $transaction) { + $sources[] = isset($transaction['source_id']) ? intval($transaction['source_id']) : 0; + $destinations[] = isset($transaction['destination_id']) ? intval($transaction['destination_id']) : 0; + } + $destinations = array_unique($destinations); + $sources = array_unique($sources); + // switch on type: + switch ($data['type']) { + case 'withdrawal': + if (count($sources) > 1) { + $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); + } + break; + case 'deposit': + if (count($destinations) > 1) { + $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); + } + break; + case 'transfer': + if (count($sources) > 1 || count($destinations) > 1) { + $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); + } + break; + default: + // @codeCoverageIgnoreStart + throw new FireflyException( + sprintf('The validator cannot handle transaction type "%s" in validateSplitAccounts().', $data['type']) + ); + // @codeCoverageIgnoreEnd + } + + return; + } + +} \ No newline at end of file diff --git a/app/Api/V1/Requests/UserRequest.php b/app/Api/V1/Requests/UserRequest.php new file mode 100644 index 0000000000..9be50cef8c --- /dev/null +++ b/app/Api/V1/Requests/UserRequest.php @@ -0,0 +1,89 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Requests; + +use FireflyIII\User; + + +/** + * Class UserRequest + */ +class UserRequest extends Request +{ + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow authenticated users + if (!auth()->check()) { + return false; // @codeCoverageIgnore + } + /** @var User $user */ + $user = auth()->user(); + if (!$user->hasRole('owner')) { + return false; // @codeCoverageIgnore + } + + return true; + } + + /** + * @return array + */ + public function getAll(): array + { + $data = [ + 'email' => $this->string('email'), + 'blocked' => $this->boolean('blocked'), + 'blocked_code' => $this->string('blocked_code'), + ]; + + return $data; + } + + /** + * @return array + */ + public function rules(): array + { + $rules = [ + 'email' => 'required|email|unique:users,email,', + 'blocked' => 'required|boolean', + 'blocked_code' => 'in:email_changed', + ]; + switch ($this->method()) { + default: + break; + case 'PUT': + case 'PATCH': + $user = $this->route()->parameter('user'); + $rules['email'] = 'required|email|unique:users,email,' . $user->id; + break; + } + + return $rules; + } + +} \ No newline at end of file diff --git a/app/Console/Commands/Import.php b/app/Console/Commands/Import.php index 65ae256332..7d7a735c82 100644 --- a/app/Console/Commands/Import.php +++ b/app/Console/Commands/Import.php @@ -85,8 +85,8 @@ class Import extends Command $monolog->pushHandler($handler); // actually start job: - $type = 'csv' === $job->file_type ? 'file' : $job->file_type; - $key = sprintf('import.routine.%s', $type); + $type = 'csv' === $job->file_type ? 'file' : $job->file_type; + $key = sprintf('import.routine.%s', $type); $className = config($key); if (null === $className || !class_exists($className)) { throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index f5e1097fb7..2dc4e0320c 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -25,8 +25,11 @@ namespace FireflyIII\Exceptions; use ErrorException; use Exception; use FireflyIII\Jobs\MailError; +use Illuminate\Auth\AuthenticationException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; +use Illuminate\Validation\ValidationException; use Request; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class Handler @@ -62,6 +65,36 @@ class Handler extends ExceptionHandler */ public function render($request, Exception $exception) { + if ($exception instanceof ValidationException && $request->expectsJson()) { + // ignore it: controller will handle it. + return parent::render($request, $exception); + } + if ($exception instanceof NotFoundHttpException && $request->expectsJson()) { + return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404); + } + + if ($exception instanceof AuthenticationException && $request->expectsJson()) { + return response()->json(['message' => 'Unauthenticated', 'exception' => 'AuthenticationException'], 401); + } + + + if ($request->expectsJson()) { + $isDebug = config('app.debug', false); + if ($isDebug) { + return response()->json( + [ + 'message' => $exception->getMessage(), + 'exception' => get_class($exception), + 'line' => $exception->getLine(), + 'file' => $exception->getFile(), + 'trace' => $exception->getTrace(), + ], 500 + ); + } + + return response()->json(['message' => 'Internal Firefly III Exception. See log files.', 'exception' => get_class($exception)], 500); + } + if ($exception instanceof FireflyException || $exception instanceof ErrorException) { $isDebug = env('APP_DEBUG', false); diff --git a/app/Factory/AccountFactory.php b/app/Factory/AccountFactory.php new file mode 100644 index 0000000000..88adfd287c --- /dev/null +++ b/app/Factory/AccountFactory.php @@ -0,0 +1,171 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Services\Internal\Support\AccountServiceTrait; +use FireflyIII\User; + +/** + * Factory to create or return accounts. + * + * Class AccountFactory + */ +class AccountFactory +{ + use AccountServiceTrait; + /** @var User */ + private $user; + + /** + * @param array $data + * + * @return Account + */ + public function create(array $data): Account + { + $type = $this->getAccountType($data['account_type_id'], $data['accountType']); + $data['iban'] = $this->filterIban($data['iban']); + + + // account may exist already: + $existingAccount = $this->find($data['name'], $type->type); + if (null !== $existingAccount) { + return $existingAccount; + } + + + // create it: + $databaseData + = [ + 'user_id' => $this->user->id, + 'account_type_id' => $type->id, + 'name' => $data['name'], + 'virtual_balance' => strlen(strval($data['virtualBalance'])) === 0 ? '0' : $data['virtualBalance'], + 'active' => true === $data['active'] ? true : false, + 'iban' => $data['iban'], + ]; + + // remove virtual balance when not an asset account: + if ($type->type !== AccountType::ASSET) { + $databaseData['virtual_balance'] = '0'; + } + + $newAccount = Account::create($databaseData); + $this->updateMetadata($newAccount, $data); + + if ($this->validIBData($data) && $type->type === AccountType::ASSET) { + $this->updateIB($newAccount, $data); + } + if (!$this->validIBData($data) && $type->type === AccountType::ASSET) { + $this->deleteIB($newAccount); + } + // update note: + if (isset($data['notes'])) { + $this->updateNote($newAccount, $data['notes']); + } + + return $newAccount; + } + + /** + * @param string $accountName + * @param string $accountType + * + * @return Account|null + */ + public function find(string $accountName, string $accountType): ?Account + { + $type = AccountType::whereType($accountType)->first(); + $accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']); + + /** @var Account $object */ + foreach ($accounts as $object) { + if ($object->name === $accountName) { + return $object; + } + } + + return null; + } + + /** + * @param string $accountName + * @param string $accountType + * + * @return Account + */ + public function findOrCreate(string $accountName, string $accountType): Account + { + $type = AccountType::whereType($accountType)->first(); + $accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']); + + /** @var Account $object */ + foreach ($accounts as $object) { + if ($object->name === $accountName) { + return $object; + } + } + + return $this->create( + [ + 'user_id' => $this->user->id, + 'name' => $accountName, + 'account_type_id' => $type->id, + 'accountType' => null, + 'virtualBalance' => '0', + 'iban' => null, + 'active' => true, + ] + ); + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param int|null $accountTypeId + * @param null|string $accountType + * + * @return AccountType|null + */ + protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType + { + $accountTypeId = intval($accountTypeId); + if ($accountTypeId > 0) { + return AccountType::find($accountTypeId); + } + $type = config('firefly.accountTypeByIdentifier.' . strval($accountType)); + + return AccountType::whereType($type)->first(); + + } + +} \ No newline at end of file diff --git a/app/Factory/AccountMetaFactory.php b/app/Factory/AccountMetaFactory.php new file mode 100644 index 0000000000..12290e08a7 --- /dev/null +++ b/app/Factory/AccountMetaFactory.php @@ -0,0 +1,43 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\AccountMeta; + +/** + * Class AccountMetaFactory + */ +class AccountMetaFactory +{ + /** + * @param array $data + * + * @return AccountMeta|null + */ + public function create(array $data): ?AccountMeta + { + return AccountMeta::create($data); + } + +} \ No newline at end of file diff --git a/app/Factory/BillFactory.php b/app/Factory/BillFactory.php new file mode 100644 index 0000000000..087ae39912 --- /dev/null +++ b/app/Factory/BillFactory.php @@ -0,0 +1,137 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\Bill; +use FireflyIII\Services\Internal\Support\BillServiceTrait; +use FireflyIII\User; +use Illuminate\Support\Collection; +use Log; + +/** + * Class BillFactory + */ +class BillFactory +{ + use BillServiceTrait; + /** @var User */ + private $user; + + /** + * @param array $data + * + * @return Bill|null + */ + public function create(array $data): ?Bill + { + $matchArray = explode(',', $data['match']); + $matchArray = array_unique($matchArray); + $match = join(',', $matchArray); + + /** @var Bill $bill */ + $bill = Bill::create( + [ + 'name' => $data['name'], + 'match' => $match, + 'amount_min' => $data['amount_min'], + 'user_id' => $this->user->id, + 'amount_max' => $data['amount_max'], + 'date' => $data['date'], + 'repeat_freq' => $data['repeat_freq'], + 'skip' => $data['skip'], + 'automatch' => $data['automatch'], + 'active' => $data['active'], + ] + ); + + // update note: + if (isset($data['notes'])) { + $this->updateNote($bill, $data['notes']); + } + + return $bill; + } + + /** + * @param int|null $billId + * @param null|string $billName + * + * @return Bill|null + */ + public function find(?int $billId, ?string $billName): ?Bill + { + $billId = intval($billId); + $billName = strval($billName); + + // first find by ID: + if ($billId > 0) { + /** @var Bill $bill */ + $bill = $this->user->bills()->find($billId); + if (!is_null($bill)) { + return $bill; + } + } + + // then find by name: + if (strlen($billName) > 0) { + $bill = $this->findByName($billName); + if (!is_null($bill)) { + return $bill; + } + } + + return null; + + } + + /** + * @param string $name + * + * @return Bill|null + */ + public function findByName(string $name): ?Bill + { + /** @var Collection $collection */ + $collection = $this->user->bills()->get(); + /** @var Bill $bill */ + foreach ($collection as $bill) { + Log::debug(sprintf('"%s" vs. "%s"', $bill->name, $name)); + if ($bill->name === $name) { + return $bill; + } + } + Log::debug(sprintf('Bill::Find by name returns NULL based on "%s"', $name)); + + return null; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + } + +} \ No newline at end of file diff --git a/app/Factory/BudgetFactory.php b/app/Factory/BudgetFactory.php new file mode 100644 index 0000000000..135663bb59 --- /dev/null +++ b/app/Factory/BudgetFactory.php @@ -0,0 +1,100 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\Budget; +use FireflyIII\User; +use Illuminate\Support\Collection; + +/** + * Class BudgetFactory + */ +class BudgetFactory +{ + /** @var User */ + private $user; + + + /** + * @param int|null $budgetId + * @param null|string $budgetName + * + * @return Budget|null + */ + public function find(?int $budgetId, ?string $budgetName): ?Budget + { + $budgetId = intval($budgetId); + $budgetName = strval($budgetName); + + if (strlen($budgetName) === 0 && $budgetId === 0) { + return null; + } + + // first by ID: + if ($budgetId > 0) { + /** @var Budget $budget */ + $budget = $this->user->budgets()->find($budgetId); + if (!is_null($budget)) { + return $budget; + } + } + + if (strlen($budgetName) > 0) { + $budget = $this->findByName($budgetName); + if (!is_null($budget)) { + return $budget; + } + } + + return null; + } + + /** + * @param string $name + * + * @return Budget|null + */ + public function findByName(string $name): ?Budget + { + /** @var Collection $collection */ + $collection = $this->user->budgets()->get(); + /** @var Budget $budget */ + foreach ($collection as $budget) { + if ($budget->name === $name) { + return $budget; + } + } + + return null; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + } + +} \ No newline at end of file diff --git a/app/Factory/CategoryFactory.php b/app/Factory/CategoryFactory.php new file mode 100644 index 0000000000..ccc136eeed --- /dev/null +++ b/app/Factory/CategoryFactory.php @@ -0,0 +1,109 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + + +use FireflyIII\Models\Category; +use FireflyIII\User; +use Illuminate\Support\Collection; +use Log; + +/** + * Class CategoryFactory + */ +class CategoryFactory +{ + /** @var User */ + private $user; + + /** + * @param string $name + * + * @return Category|null + */ + public function findByName(string $name): ?Category + { + /** @var Collection $collection */ + $collection = $this->user->categories()->get(); + /** @var Category $category */ + foreach ($collection as $category) { + if ($category->name === $name) { + return $category; + } + } + + return null; + } + + /** + * @param int|null $categoryId + * @param null|string $categoryName + * + * @return Category|null + */ + public function findOrCreate(?int $categoryId, ?string $categoryName): ?Category + { + $categoryId = intval($categoryId); + $categoryName = strval($categoryName); + + Log::debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName)); + + if (strlen($categoryName) === 0 && $categoryId === 0) { + return null; + } + // first by ID: + if ($categoryId > 0) { + /** @var Category $category */ + $category = $this->user->categories()->find($categoryId); + if (!is_null($category)) { + return $category; + } + } + + if (strlen($categoryName) > 0) { + $category = $this->findByName($categoryName); + if (!is_null($category)) { + return $category; + } + + return Category::create( + [ + 'user_id' => $this->user->id, + 'name' => $categoryName, + ] + ); + } + + return null; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + } + +} \ No newline at end of file diff --git a/app/Factory/PiggyBankEventFactory.php b/app/Factory/PiggyBankEventFactory.php new file mode 100644 index 0000000000..ca4d301e6f --- /dev/null +++ b/app/Factory/PiggyBankEventFactory.php @@ -0,0 +1,88 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\PiggyBank; +use FireflyIII\Models\PiggyBankEvent; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use Log; + +/** + * Create piggy bank events. + * + * Class PiggyBankEventFactory + */ +class PiggyBankEventFactory +{ + /** + * @param TransactionJournal $journal + * @param PiggyBank|null $piggyBank + * + * @return PiggyBankEvent|null + */ + public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): ?PiggyBankEvent + { + Log::debug(sprintf('Now in PiggyBankEventCreate for a %s', $journal->transactionType->type)); + if (is_null($piggyBank)) { + return null; + } + + // is a transfer? + if (!(TransactionType::TRANSFER === $journal->transactionType->type)) { + Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id)); + + return null; + } + + /** @var PiggyBankRepositoryInterface $piggyRepos */ + $piggyRepos = app(PiggyBankRepositoryInterface::class); + $piggyRepos->setUser($journal->user); + + // repetition exists? + $repetition = $piggyRepos->getRepetition($piggyBank, $journal->date); + if (null === $repetition->id) { + Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d'))); + + return null; + } + + // get the amount + $amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal); + if (0 === bccomp($amount, '0')) { + Log::debug('Amount is zero, will not create event.'); + + return null; + } + + // update amount + $piggyRepos->addAmountToRepetition($repetition, $amount); + $event = $piggyRepos->createEventWithJournal($piggyBank, $amount, $journal); + + Log::debug(sprintf('Created piggy bank event #%d', $event->id)); + + return $event; + } +} \ No newline at end of file diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php new file mode 100644 index 0000000000..3ded4bfe3c --- /dev/null +++ b/app/Factory/PiggyBankFactory.php @@ -0,0 +1,100 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + + +use FireflyIII\Models\PiggyBank; +use FireflyIII\User; + +/** + * Class PiggyBankFactory + */ +class PiggyBankFactory +{ + /** @var User */ + private $user; + + /** + * @param int|null $piggyBankId + * @param null|string $piggyBankName + * + * @return PiggyBank|null + */ + public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank + { + $piggyBankId = intval($piggyBankId); + $piggyBankName = strval($piggyBankName); + if (strlen($piggyBankName) === 0 && $piggyBankId === 0) { + return null; + } + // first find by ID: + if ($piggyBankId > 0) { + /** @var PiggyBank $piggyBank */ + $piggyBank = $this->user->piggyBanks()->find($piggyBankId); + if (!is_null($piggyBank)) { + return $piggyBank; + } + } + + // then find by name: + if (strlen($piggyBankName) > 0) { + /** @var PiggyBank $piggyBank */ + $piggyBank = $this->findByName($piggyBankName); + if (!is_null($piggyBank)) { + return $piggyBank; + } + } + + return null; + + } + + /** + * @param string $name + * + * @return PiggyBank|null + */ + public function findByName(string $name): ?PiggyBank + { + $set = $this->user->piggyBanks()->get(); + /** @var PiggyBank $piggy */ + foreach ($set as $piggy) { + if ($piggy->name === $name) { + return $piggy; + } + } + + return null; + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + + } + +} \ No newline at end of file diff --git a/app/Factory/TagFactory.php b/app/Factory/TagFactory.php new file mode 100644 index 0000000000..0fc74c2a0e --- /dev/null +++ b/app/Factory/TagFactory.php @@ -0,0 +1,102 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\Tag; +use FireflyIII\User; +use Illuminate\Support\Collection; + +/** + * Class TagFactory + */ +class TagFactory +{ + /** @var Collection */ + private $tags; + /** @var User */ + private $user; + + /** + * @param array $data + * + * @return Tag|null + */ + public function create(array $data): ?Tag + { + return Tag::create( + [ + 'user_id' => $this->user->id, + 'tag' => $data['tag'], + 'tagMode' => 'nothing', + 'date' => $data['date'], + 'description' => $data['description'], + 'latitude' => $data['latitude'], + 'longitude ' => $data['longitude'], + 'zoomLevel' => $data['zoom_level'], + ] + ); + } + + /** + * @param string $tag + * + * @return Tag|null + */ + public function findOrCreate(string $tag): ?Tag + { + if (is_null($this->tags)) { + $this->tags = $this->user->tags()->get(); + } + + /** @var Tag $object */ + foreach ($this->tags as $object) { + if ($object->tag === $tag) { + return $object; + } + } + + $newTag = $this->create( + [ + 'tag' => $tag, + 'date' => null, + 'description' => null, + 'latitude' => null, + 'longitude' => null, + 'zoom_level' => null, + ] + ); + $this->tags->push($newTag); + + return $newTag; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + +} \ No newline at end of file diff --git a/app/Factory/TransactionCurrencyFactory.php b/app/Factory/TransactionCurrencyFactory.php new file mode 100644 index 0000000000..0c66c2942a --- /dev/null +++ b/app/Factory/TransactionCurrencyFactory.php @@ -0,0 +1,67 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\TransactionCurrency; + +/** + * Class TransactionCurrencyFactory + */ +class TransactionCurrencyFactory +{ + /** + * @param int|null $currencyId + * @param null|string $currencyCode + * + * @return TransactionCurrency|null + */ + public function find(?int $currencyId, ?string $currencyCode): ?TransactionCurrency + { + $currencyCode = strval($currencyCode); + $currencyId = intval($currencyId); + + if (strlen($currencyCode) === 0 && intval($currencyId) === 0) { + return null; + } + + // first by ID: + if ($currencyId > 0) { + $currency = TransactionCurrency::find($currencyId); + if (!is_null($currency)) { + return $currency; + } + } + // then by code: + if (strlen($currencyCode) > 0) { + $currency = TransactionCurrency::whereCode($currencyCode)->first(); + if (!is_null($currency)) { + return $currency; + } + } + + return null; + } + + +} \ No newline at end of file diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php new file mode 100644 index 0000000000..50cf0b99b5 --- /dev/null +++ b/app/Factory/TransactionFactory.php @@ -0,0 +1,148 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + + +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Services\Internal\Support\TransactionServiceTrait; +use FireflyIII\User; +use Illuminate\Support\Collection; + +/** + * Class TransactionFactory + */ +class TransactionFactory +{ + use TransactionServiceTrait; + + /** @var User */ + private $user; + + /** + * @param array $data + * + * @return Transaction + */ + public function create(array $data): Transaction + { + $currencyId = isset($data['currency']) ? $data['currency']->id : $data['currency_id']; + + return Transaction::create( + [ + 'reconciled' => $data['reconciled'], + 'account_id' => $data['account']->id, + 'transaction_journal_id' => $data['transaction_journal']->id, + 'description' => $data['description'], + 'transaction_currency_id' => $currencyId, + 'amount' => $data['amount'], + 'foreign_amount' => $data['foreign_amount'], + 'foreign_currency_id' => null, + 'identifier' => $data['identifier'], + ] + ); + } + + /** + * Create a pair of transactions based on the data given in the array. + * + * @param TransactionJournal $journal + * @param array $data + * + * @return Collection + */ + public function createPair(TransactionJournal $journal, array $data): Collection + { + // all this data is the same for both transactions: + $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); + $description = $journal->description === $data['description'] ? null : $data['description']; + + // type of source account depends on journal type: + $sourceType = $this->accountType($journal, 'source'); + $sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']); + + // same for destination account: + $destinationType = $this->accountType($journal, 'destination'); + $destinationAccount = $this->findAccount($destinationType, $data['destination_id'], $data['destination_name']); + // first make a "negative" (source) transaction based on the data in the array. + $source = $this->create( + [ + 'description' => $description, + 'amount' => app('steam')->negative(strval($data['amount'])), + 'foreign_amount' => null, + 'currency' => $currency, + 'account' => $sourceAccount, + 'transaction_journal' => $journal, + 'reconciled' => $data['reconciled'], + 'identifier' => $data['identifier'], + ] + ); + // then make a "positive" transaction based on the data in the array. + $dest = $this->create( + [ + 'description' => $description, + 'amount' => app('steam')->positive(strval($data['amount'])), + 'foreign_amount' => null, + 'currency' => $currency, + 'account' => $destinationAccount, + 'transaction_journal' => $journal, + 'reconciled' => $data['reconciled'], + 'identifier' => $data['identifier'], + ] + ); + + // set foreign currency + $foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']); + $this->setForeignCurrency($source, $foreign); + $this->setForeignCurrency($dest, $foreign); + + // set foreign amount: + if (!is_null($data['foreign_amount'])) { + $this->setForeignAmount($source, app('steam')->negative(strval($data['foreign_amount']))); + $this->setForeignAmount($dest, app('steam')->positive(strval($data['foreign_amount']))); + } + + // set budget: + $budget = $this->findBudget($data['budget_id'], $data['budget_name']); + $this->setBudget($source, $budget); + $this->setBudget($dest, $budget); + + // set category + $category = $this->findCategory($data['category_id'], $data['category_name']); + $this->setCategory($source, $category); + $this->setCategory($dest, $category); + + return new Collection([$source, $dest]); + } + + /** + * @param User $user + */ + public function setUser(User $user) + { + $this->user = $user; + } + + +} \ No newline at end of file diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php new file mode 100644 index 0000000000..77c9828a78 --- /dev/null +++ b/app/Factory/TransactionJournalFactory.php @@ -0,0 +1,154 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use FireflyIII\Services\Internal\Support\JournalServiceTrait; +use FireflyIII\User; +use Log; + +/** + * Class TransactionJournalFactory + */ +class TransactionJournalFactory +{ + use JournalServiceTrait; + /** @var User */ + private $user; + + /** + * Create a new transaction journal and associated transactions. + * + * @param array $data + * + * @return TransactionJournal + * @throws FireflyException + */ + public function create(array $data): TransactionJournal + { + Log::debug('Start of TransactionJournalFactory::create()'); + // store basic journal first. + $type = $this->findTransactionType($data['type']); + $defaultCurrency = app('amount')->getDefaultCurrencyByUser($this->user); + $journal = TransactionJournal::create( + [ + 'user_id' => $data['user'], + 'transaction_type_id' => $type->id, + 'bill_id' => null, + 'transaction_currency_id' => $defaultCurrency->id, + 'description' => $data['description'], + 'date' => $data['date']->format('Y-m-d'), + 'order' => 0, + 'tag_count' => 0, + 'completed' => 0, + ] + ); + + // store basic transactions: + $factory = app(TransactionFactory::class); + $factory->setUser($this->user); + + /** @var array $trData */ + foreach ($data['transactions'] as $trData) { + $factory->createPair($journal, $trData); + } + $journal->completed = true; + $journal->save(); + + // link bill: + $this->connectBill($journal, $data); + + // link piggy bank (if transfer) + $this->connectPiggyBank($journal, $data); + + // link tags: + $this->connectTags($journal, $data); + + // store note: + $this->storeNote($journal, strval($data['notes'])); + + // store date meta fields (if present): + $this->storeMeta($journal, $data, 'interest_date'); + $this->storeMeta($journal, $data, 'book_date'); + $this->storeMeta($journal, $data, 'process_date'); + $this->storeMeta($journal, $data, 'due_date'); + $this->storeMeta($journal, $data, 'payment_date'); + $this->storeMeta($journal, $data, 'invoice_date'); + $this->storeMeta($journal, $data, 'internal_reference'); + Log::debug('End of TransactionJournalFactory::create()'); + + return $journal; + } + + /** + * Set the user. + * + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param TransactionJournal $journal + * @param array $data + */ + protected function connectPiggyBank(TransactionJournal $journal, array $data): void + { + /** @var PiggyBankFactory $factory */ + $factory = app(PiggyBankFactory::class); + $factory->setUser($this->user); + + $piggyBank = $factory->find($data['piggy_bank_id'], $data['piggy_bank_name']); + if (!is_null($piggyBank)) { + /** @var PiggyBankEventFactory $factory */ + $factory = app(PiggyBankEventFactory::class); + $factory->create($journal, $piggyBank); + } + } + + /** + * Get the transaction type. Since this is mandatory, will throw an exception when nothing comes up. Will always + * use TransactionType repository. + * + * @param string $type + * + * @return TransactionType + * @throws FireflyException + */ + protected function findTransactionType(string $type): TransactionType + { + $factory = app(TransactionTypeFactory::class); + $transactionType = $factory->find($type); + if (is_null($transactionType)) { + throw new FireflyException(sprintf('Could not find transaction type for "%s"', $type)); // @codeCoverageIgnore + } + + return $transactionType; + } + +} \ No newline at end of file diff --git a/app/Factory/TransactionJournalMetaFactory.php b/app/Factory/TransactionJournalMetaFactory.php new file mode 100644 index 0000000000..999d4fb3d2 --- /dev/null +++ b/app/Factory/TransactionJournalMetaFactory.php @@ -0,0 +1,72 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use Carbon\Carbon; +use Exception; +use FireflyIII\Models\TransactionJournalMeta; +use Log; + +/** + * Class TransactionJournalMetaFactory + */ +class TransactionJournalMetaFactory +{ + /** + * @param array $data + * + * @return TransactionJournalMeta|null + */ + public function updateOrCreate(array $data): ?TransactionJournalMeta + { + $value = $data['data']; + /** @var TransactionJournalMeta $entry */ + $entry = $data['journal']->transactionJournalMeta()->where('name', $data['name'])->first(); + if (is_null($value) && !is_null($entry)) { + try { + $entry->delete(); + } catch (Exception $e) { // @codeCoverageIgnore + Log::error(sprintf('Could not delete transaction journal meta: %s', $e->getMessage())); // @codeCoverageIgnore + } + + return null; + } + + if ($data['data'] instanceof Carbon) { + $value = $data['data']->toW3cString(); + } + + + if (null === $entry) { + $entry = new TransactionJournalMeta(); + $entry->transactionJournal()->associate($data['journal']); + $entry->name = $data['name']; + } + $entry->data = $value; + $entry->save(); + + return $entry; + } + +} \ No newline at end of file diff --git a/app/Factory/TransactionTypeFactory.php b/app/Factory/TransactionTypeFactory.php new file mode 100644 index 0000000000..178dc21d6c --- /dev/null +++ b/app/Factory/TransactionTypeFactory.php @@ -0,0 +1,44 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Factory; + +use FireflyIII\Models\TransactionType; + +/** + * @codeCoverageIgnore + * Class TransactionTypeFactory + */ +class TransactionTypeFactory +{ + /** + * @param string $type + * + * @return TransactionType|null + */ + public function find(string $type): ?TransactionType + { + return TransactionType::whereType(ucfirst($type))->first(); + } + +} \ No newline at end of file diff --git a/app/Handlers/Events/StoredJournalEventHandler.php b/app/Handlers/Events/StoredJournalEventHandler.php index b05a4f09c5..ef6a26bcc0 100644 --- a/app/Handlers/Events/StoredJournalEventHandler.php +++ b/app/Handlers/Events/StoredJournalEventHandler.php @@ -61,61 +61,6 @@ class StoredJournalEventHandler $this->ruleGroupRepository = $ruleGroupRepository; } - /** - * This method connects a new transfer to a piggy bank. - * - * @param StoredTransactionJournal $event - * - * @return bool - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function connectToPiggyBank(StoredTransactionJournal $event): bool - { - $journal = $event->journal; - $piggyBankId = $event->piggyBankId; - $piggyBank = $this->repository->find($piggyBankId); - - // is a transfer? - if (!$this->journalRepository->isTransfer($journal)) { - Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id)); - - return true; - } - - // piggy exists? - if (null === $piggyBank->id) { - Log::error(sprintf('There is no piggy bank with ID #%d', $piggyBankId)); - - return true; - } - - // repetition exists? - $repetition = $this->repository->getRepetition($piggyBank, $journal->date); - if (null === $repetition->id) { - Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d'))); - - return true; - } - - // get the amount - $amount = $this->repository->getExactAmount($piggyBank, $repetition, $journal); - if (0 === bccomp($amount, '0')) { - Log::debug('Amount is zero, will not create event.'); - - return true; - } - - // update amount - $this->repository->addAmountToRepetition($repetition, $amount); - $event = $this->repository->createEventWithJournal($piggyBank, $amount, $journal); - - Log::debug(sprintf('Created piggy bank event #%d', $event->id)); - - return true; - } - /** * This method grabs all the users rules and processes them. * diff --git a/app/Handlers/Events/UpdatedJournalEventHandler.php b/app/Handlers/Events/UpdatedJournalEventHandler.php index 20e446ea5e..a99a078374 100644 --- a/app/Handlers/Events/UpdatedJournalEventHandler.php +++ b/app/Handlers/Events/UpdatedJournalEventHandler.php @@ -51,6 +51,7 @@ class UpdatedJournalEventHandler /** * This method will check all the rules when a journal is updated. + * TODO move to factory. * * @param UpdatedTransactionJournal $updatedJournalEvent * @@ -81,6 +82,7 @@ class UpdatedJournalEventHandler /** * This method calls a special bill scanner that will check if the updated journal is part of a bill. + * TODO move to factory. * * @param UpdatedTransactionJournal $updatedJournalEvent * diff --git a/app/Helpers/Attachments/AttachmentHelper.php b/app/Helpers/Attachments/AttachmentHelper.php index 1e6e0e6986..cdc3df2c85 100644 --- a/app/Helpers/Attachments/AttachmentHelper.php +++ b/app/Helpers/Attachments/AttachmentHelper.php @@ -50,8 +50,9 @@ class AttachmentHelper implements AttachmentHelperInterface /** @var \Illuminate\Contracts\Filesystem\Filesystem */ protected $uploadDisk; + /** - * + * AttachmentHelper constructor. */ public function __construct() { diff --git a/app/Helpers/Chart/MetaPieChart.php b/app/Helpers/Chart/MetaPieChart.php index 8fccc9d81f..931b996360 100644 --- a/app/Helpers/Chart/MetaPieChart.php +++ b/app/Helpers/Chart/MetaPieChart.php @@ -79,6 +79,9 @@ class MetaPieChart implements MetaPieChartInterface /** @var User */ protected $user; + /** + * MetaPieChart constructor. + */ public function __construct() { $this->accounts = new Collection; @@ -273,11 +276,13 @@ class MetaPieChart implements MetaPieChartInterface $collector->setBudgets($this->budgets); $collector->setCategories($this->categories); + // @codeCoverageIgnoreStart if ($this->tags->count() > 0) { $collector->setTags($this->tags); $collector->withCategoryInformation(); $collector->withBudgetInformation(); } + // @codeCoverageIgnoreEnd return $collector->getJournals(); } @@ -294,7 +299,7 @@ class MetaPieChart implements MetaPieChartInterface { if (0 === count($fields) && $this->tags->count() > 0) { // do a special group on tags: - return $this->groupByTag($set); + return $this->groupByTag($set); // @codeCoverageIgnore } $grouped = []; @@ -338,6 +343,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * @codeCoverageIgnore + * * @param Collection $set * * @return array diff --git a/app/Helpers/Collector/JournalCollector.php b/app/Helpers/Collector/JournalCollector.php index 3e04a2217d..f4fa3d2e6e 100644 --- a/app/Helpers/Collector/JournalCollector.php +++ b/app/Helpers/Collector/JournalCollector.php @@ -69,6 +69,8 @@ class JournalCollector implements JournalCollectorInterface 'transaction_journals.description', 'transaction_journals.date', 'transaction_journals.encrypted', + 'transaction_journals.created_at', + 'transaction_journals.updated_at', 'transaction_types.type as transaction_type_type', 'transaction_journals.bill_id', 'transaction_journals.updated_at', @@ -252,6 +254,7 @@ class JournalCollector implements JournalCollectorInterface $cache->addProperty($key); if ($cache->has()) { Log::debug(sprintf('Return cache of query with ID "%s".', $key)); + return $cache->get(); // @codeCoverageIgnore } @@ -270,10 +273,19 @@ class JournalCollector implements JournalCollectorInterface if (null !== $transaction->bill_name) { $transaction->bill_name = Steam::decrypt(intval($transaction->bill_name_encrypted), $transaction->bill_name); } + $transaction->account_name = app('steam')->tryDecrypt($transaction->account_name); $transaction->opposing_account_name = app('steam')->tryDecrypt($transaction->opposing_account_name); $transaction->account_iban = app('steam')->tryDecrypt($transaction->account_iban); $transaction->opposing_account_iban = app('steam')->tryDecrypt($transaction->opposing_account_iban); + + // budget name + $transaction->transaction_journal_budget_name = app('steam')->tryDecrypt($transaction->transaction_journal_budget_name); + $transaction->transaction_budget_name = app('steam')->tryDecrypt($transaction->transaction_budget_name); + // category name: + $transaction->transaction_journal_category_name = app('steam')->tryDecrypt($transaction->transaction_journal_category_name); + $transaction->transaction_category_name = app('steam')->tryDecrypt($transaction->transaction_category_name); } + ); Log::debug(sprintf('Cached query with ID "%s".', $key)); $cache->store($set); @@ -342,7 +354,7 @@ class JournalCollector implements JournalCollectorInterface */ public function setAfter(Carbon $after): JournalCollectorInterface { - $afterStr = $after->format('Y-m-d'); + $afterStr = $after->format('Y-m-d 00:00:00'); $this->query->where('transaction_journals.date', '>=', $afterStr); Log::debug(sprintf('JournalCollector range is now after %s (inclusive)', $afterStr)); @@ -378,7 +390,7 @@ class JournalCollector implements JournalCollectorInterface */ public function setBefore(Carbon $before): JournalCollectorInterface { - $beforeStr = $before->format('Y-m-d'); + $beforeStr = $before->format('Y-m-d 00:00:00'); $this->query->where('transaction_journals.date', '<=', $beforeStr); Log::debug(sprintf('JournalCollector range is now before %s (inclusive)', $beforeStr)); @@ -485,6 +497,23 @@ class JournalCollector implements JournalCollectorInterface return $this; } + /** + * @param Collection $journals + * + * @return JournalCollectorInterface + */ + public function setJournals(Collection $journals): JournalCollectorInterface + { + $ids = $journals->pluck('id')->toArray(); + $this->query->where( + function (EloquentBuilder $q) use ($ids) { + $q->whereIn('transaction_journals.id', $ids); + } + ); + + return $this; + } + /** * @param int $limit * @@ -565,8 +594,8 @@ class JournalCollector implements JournalCollectorInterface public function setRange(Carbon $start, Carbon $end): JournalCollectorInterface { if ($start <= $end) { - $startStr = $start->format('Y-m-d'); - $endStr = $end->format('Y-m-d'); + $startStr = $start->format('Y-m-d 00:00:00'); + $endStr = $end->format('Y-m-d 23:59:59'); $this->query->where('transaction_journals.date', '>=', $startStr); $this->query->where('transaction_journals.date', '<=', $endStr); Log::debug(sprintf('JournalCollector range is now %s - %s (inclusive)', $startStr, $endStr)); diff --git a/app/Helpers/Collector/JournalCollectorInterface.php b/app/Helpers/Collector/JournalCollectorInterface.php index 30243ac6db..eef1662e03 100644 --- a/app/Helpers/Collector/JournalCollectorInterface.php +++ b/app/Helpers/Collector/JournalCollectorInterface.php @@ -27,7 +27,6 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Tag; use FireflyIII\User; -use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -43,6 +42,13 @@ interface JournalCollectorInterface */ public function addFilter(string $filter): JournalCollectorInterface; + /** + * @param Collection $journals + * + * @return JournalCollectorInterface + */ + public function setJournals(Collection $journals): JournalCollectorInterface; + /** * @param string $amount * diff --git a/app/Helpers/Report/PopupReport.php b/app/Helpers/Report/PopupReport.php index 40f9be6dc7..e55db58a4e 100644 --- a/app/Helpers/Report/PopupReport.php +++ b/app/Helpers/Report/PopupReport.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Support\Collection; /** @@ -182,6 +183,9 @@ class PopupReport implements PopupReportInterface */ public function byIncome(Account $account, array $attributes): Collection { + /** @var JournalRepositoryInterface $repository */ + $repository = app(JournalRepositoryInterface::class); + $repository->setUser($account->user); /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate']) @@ -191,9 +195,10 @@ class PopupReport implements PopupReportInterface // filter the set so the destinations outside of $attributes['accounts'] are not included. $journals = $journals->filter( - function (Transaction $transaction) use ($report) { + function (Transaction $transaction) use ($report, $repository) { // get the destinations: - $destinations = $transaction->transactionJournal->destinationAccountList()->pluck('id')->toArray(); + $journal = $transaction->transactionJournal; + $destinations = $repository->getJournalDestinationAccounts($journal)->pluck('id')->toArray(); // do these intersect with the current list? return !empty(array_intersect($report, $destinations)); diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index 9c810fc77a..1a690f11e3 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -24,9 +24,11 @@ namespace FireflyIII\Http\Controllers\Account; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Factory\TransactionJournalFactory; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Http\Requests\ReconciliationFormRequest; +use FireflyIII\Http\Requests\ReconciliationStoreRequest; +use FireflyIII\Http\Requests\ReconciliationUpdateRequest; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; @@ -35,8 +37,10 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Services\Internal\Update\TransactionUpdateService; use Illuminate\Http\Request; use Illuminate\Support\Collection; +use Log; use Preferences; use Response; use Session; @@ -48,6 +52,9 @@ use Session; */ class ReconcileController extends Controller { + /** @var JournalRepositoryInterface */ + private $repository; + /** * */ @@ -60,6 +67,7 @@ class ReconcileController extends Controller function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); app('view')->share('title', trans('firefly.accounts')); + $this->repository = app(JournalRepositoryInterface::class); return $next($request); } @@ -80,10 +88,10 @@ class ReconcileController extends Controller $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); // journal related code - $pTransaction = $journal->positiveTransaction(); + $pTransaction = $this->repository->getFirstPosTransaction($journal); $preFilled = [ - 'date' => $journal->dateAsString(), - 'category' => $journal->categoryAsString(), + 'date' => $this->repository->getJournalDate($journal, null), + 'category' => $this->repository->getJournalCategoryName($journal), 'tags' => join(',', $journal->tags->pluck('tag')->toArray()), 'amount' => $pTransaction->amount, ]; @@ -126,10 +134,8 @@ class ReconcileController extends Controller $clearedAmount = '0'; $route = route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]); // get sum of transaction amounts: - /** @var JournalRepositoryInterface $repository */ - $repository = app(JournalRepositoryInterface::class); - $transactions = $repository->getTransactionsById($transactionIds); - $cleared = $repository->getTransactionsById($clearedIds); + $transactions = $this->repository->getTransactionsById($transactionIds); + $cleared = $this->repository->getTransactionsById($clearedIds); $countCleared = 0; /** @var Transaction $transaction */ @@ -182,7 +188,7 @@ class ReconcileController extends Controller /** @var CurrencyRepositoryInterface $currencyRepos */ $currencyRepos = app(CurrencyRepositoryInterface::class); $currencyId = intval($account->getMeta('currency_id')); - $currency = $currencyRepos->find($currencyId); + $currency = $currencyRepos->findNull($currencyId); if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore } @@ -220,71 +226,105 @@ class ReconcileController extends Controller } /** - * @param JournalRepositoryInterface $repository - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View */ - public function show(JournalRepositoryInterface $repository, TransactionJournal $journal) + public function show(TransactionJournal $journal) { + if (TransactionType::RECONCILIATION !== $journal->transactionType->type) { return redirect(route('transactions.show', [$journal->id])); } $subTitle = trans('firefly.reconciliation') . ' "' . $journal->description . '"'; // get main transaction: - $transaction = $repository->getAssetTransaction($journal); + $transaction = $this->repository->getAssetTransaction($journal); $account = $transaction->account; return view('accounts.reconcile.show', compact('journal', 'subTitle', 'transaction', 'account')); } /** - * @param Request $request - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param ReconciliationStoreRequest $request + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws FireflyException */ - public function submit(Request $request, Account $account, Carbon $start, Carbon $end) + public function submit(ReconciliationStoreRequest $request, JournalRepositoryInterface $repository, Account $account, Carbon $start, Carbon $end) { - /** @var JournalRepositoryInterface $repository */ - $repository = app(JournalRepositoryInterface::class); - $transactions = $repository->getTransactionsById($request->get('transactions') ?? []); + Log::debug('In ReconcileController::submit()'); + $data = $request->getAll(); + /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $repository->reconcile($transaction); // mark as reconciled. + foreach ($data['transactions'] as $transactionId) { + $repository->reconcileById(intval($transactionId)); } + Log::debug('Reconciled all transactions.'); // create reconciliation transaction (if necessary): - if ('create' === $request->get('reconcile')) { + if ('create' === $data['reconcile']) { + // get "opposing" account. /** @var AccountRepositoryInterface $accountRepos */ $accountRepos = app(AccountRepositoryInterface::class); $reconciliation = $accountRepos->getReconciliation($account); - $difference = $request->get('difference'); - // store journal between these two. - $data = [ - 'what' => 'Reconciliation', - 'source' => $account, - 'destination' => $reconciliation, - 'category' => '', - 'budget_id' => 0, - 'amount' => $difference, - 'currency_id' => $account->getMeta('currency_id'), - 'description' => trans( - 'firefly.reconcilliation_transaction_title', - ['from' => $start->formatLocalized($this->monthAndDayFormat), 'to' => $end->formatLocalized($this->monthAndDayFormat)] - ), - 'date' => $request->get('end'), - 'notes' => join(',', $transactions->pluck('id')->toArray()), + + $difference = $data['difference']; + $source = $reconciliation; + $destination = $account; + if (bccomp($difference, '0') === 1) { + // amount is positive. Add it to reconciliation? + $source = $account; + $destination = $reconciliation; + + } + + // data for journal + $description = trans( + 'firefly.reconcilliation_transaction_title', + ['from' => $start->formatLocalized($this->monthAndDayFormat), 'to' => $end->formatLocalized($this->monthAndDayFormat)] + ); + $journalData = [ + 'type' => 'Reconciliation', + 'description' => $description, + 'user' => auth()->user()->id, + 'date' => $data['end'], + 'bill_id' => null, + 'bill_name' => null, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'tags' => null, + 'interest_date' => null, + 'transactions' => [[ + 'currency_id' => intval($account->getMeta('currency_id')), + 'currency_code' => null, + 'description' => null, + 'amount' => app('steam')->positive($difference), + 'source_id' => $source->id, + 'source_name' => null, + 'destination_id' => $destination->id, + 'destination_name' => null, + 'reconciled' => true, + 'identifier' => 0, + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'budget_id' => null, + 'budget_name' => null, + 'category_id' => null, + 'category_name' => null, + ], + ], + 'notes' => join(', ', $data['transactions']), ]; - $journal = $repository->store($data); - // reconcile this transaction too: - $transaction = $journal->transactions()->first(); - $repository->reconcile($transaction); + + $journal = $repository->store($journalData); } + Log::debug('End of routine.'); Session::flash('success', trans('firefly.reconciliation_stored')); @@ -313,7 +353,7 @@ class ReconcileController extends Controller /** @var CurrencyRepositoryInterface $currencyRepos */ $currencyRepos = app(CurrencyRepositoryInterface::class); $currencyId = intval($account->getMeta('currency_id')); - $currency = $currencyRepos->find($currencyId); + $currency = $currencyRepos->findNull($currencyId); if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore } @@ -339,13 +379,12 @@ class ReconcileController extends Controller } /** - * @param ReconciliationFormRequest $request - * @param AccountRepositoryInterface $repository - * @param TransactionJournal $journal + * @param ReconciliationUpdateRequest $request + * @param TransactionJournal $journal * * @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function update(ReconciliationFormRequest $request, AccountRepositoryInterface $repository, TransactionJournal $journal) + public function update(ReconciliationUpdateRequest $request, TransactionJournal $journal) { if (TransactionType::RECONCILIATION !== $journal->transactionType->type) { return redirect(route('transactions.show', [$journal->id])); @@ -356,8 +395,53 @@ class ReconcileController extends Controller return redirect(route('accounts.reconcile.edit', [$journal->id]))->withInput(); } // update journal using account repository. Keep it consistent. - $data = $request->getJournalData(); - $repository->updateReconciliation($journal, $data); + $submitted = $request->getJournalData(); + + // amount pos neg influences the accounts: + $source = $this->repository->getJournalSourceAccounts($journal)->first(); + $destination = $this->repository->getJournalDestinationAccounts($journal)->first(); + if (bccomp($submitted['amount'], '0') === 1) { + // amount is positive, switch accounts: + list($source, $destination) = [$destination, $source]; + + } + // expand data with journal data: + $data = [ + 'type' => $journal->transactionType->type, + 'description' => $journal->description, + 'user' => $journal->user_id, + 'date' => $journal->date, + 'bill_id' => null, + 'bill_name' => null, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'tags' => $submitted['tags'], + 'interest_date' => null, + 'book_date' => null, + 'transactions' => [[ + 'currency_id' => intval($journal->transaction_currency_id), + 'currency_code' => null, + 'description' => null, + 'amount' => app('steam')->positive($submitted['amount']), + 'source_id' => $source->id, + 'source_name' => null, + 'destination_id' => $destination->id, + 'destination_name' => null, + 'reconciled' => true, + 'identifier' => 0, + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'budget_id' => null, + 'budget_name' => null, + 'category_id' => null, + 'category_name' => $submitted['category'], + ], + ], + 'notes' => $this->repository->getNoteText($journal), + ]; + + $this->repository->update($journal, $data); // @codeCoverageIgnoreStart if (1 === intval($request->get('return_to_edit'))) { diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 49e40a182e..98f3c8f978 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -139,7 +139,7 @@ class AccountController extends Controller $type = $account->accountType->type; $typeName = config('firefly.shortNamesByFullName.' . $type); $name = $account->name; - $moveTo = $this->repository->find(intval($request->get('move_account_before_delete'))); + $moveTo = $this->repository->findNull(intval($request->get('move_account_before_delete'))); $this->repository->destroy($account, $moveTo); @@ -162,7 +162,7 @@ class AccountController extends Controller * * @throws FireflyException */ - public function edit(Request $request, Account $account) + public function edit(Request $request, Account $account, AccountRepositoryInterface $repository) { $what = config('firefly.shortNamesByFullName')[$account->accountType->type]; $subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]); @@ -183,11 +183,9 @@ class AccountController extends Controller // pre fill some useful values. // the opening balance is tricky: - $openingBalanceAmount = $account->getOpeningBalanceAmount(); - $openingBalanceAmount = '0' === $account->getOpeningBalanceAmount() ? '' : $openingBalanceAmount; - $openingBalanceDate = $account->getOpeningBalanceDate(); - $openingBalanceDate = 1900 === $openingBalanceDate->year ? null : $openingBalanceDate->format('Y-m-d'); - $currency = $this->currencyRepos->find(intval($account->getMeta('currency_id'))); + $openingBalanceAmount = strval($repository->getOpeningBalanceAmount($account)); + $openingBalanceDate = $repository->getOpeningBalanceDate($account); + $currency = $this->currencyRepos->findNull(intval($account->getMeta('currency_id'))); $preFilled = [ 'accountNumber' => $account->getMeta('accountNumber'), @@ -200,6 +198,7 @@ class AccountController extends Controller 'virtualBalance' => $account->virtual_balance, 'currency_id' => $currency->id, 'notes' => '', + 'active' => $account->active, ]; /** @var Note $note */ $note = $this->repository->getNote($account); @@ -285,68 +284,46 @@ class AccountController extends Controller * * @throws FireflyException */ - public function show(Request $request, Account $account, string $moment = '') + public function show(Request $request, Account $account, Carbon $start = null, Carbon $end = null) { if (AccountType::INITIAL_BALANCE === $account->accountType->type) { return $this->redirectToOriginalAccount($account); } - $range = Preferences::get('viewRange', '1M')->data; + $range = Preferences::get('viewRange', '1M')->data; + if (null === $start) { + $start = session('start'); + } + if (null === $end) { + $end = app('navigation')->endOfPeriod($start, $range); + } + if ($end < $start) { + throw new FireflyException('End is after start!'); // @codeCoverageIgnore + } + $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type); $page = intval($request->get('page')); $pageSize = intval(Preferences::get('listPageSize', 50)->data); - $chartUri = route('chart.account.single', [$account->id]); - $start = null; - $end = null; - $periods = new Collection; $currencyId = intval($account->getMeta('currency_id')); - $currency = $this->currencyRepos->find($currencyId); + $currency = $this->currencyRepos->findNull($currencyId); if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore } - - // prep for "all" view. - if ('all' === $moment) { - $subTitle = trans('firefly.all_journals_for_account', ['name' => $account->name]); - $chartUri = route('chart.account.all', [$account->id]); - $first = $this->journalRepos->first(); - $start = $first->date ?? new Carbon; - $end = new Carbon; - } - - // prep for "specific date" view. - if (strlen($moment) > 0 && 'all' !== $moment) { - $start = new Carbon($moment); - $start = app('navigation')->startOfPeriod($start, $range); - $end = app('navigation')->endOfPeriod($start, $range); - $fStart = $start->formatLocalized($this->monthAndDayFormat); - $fEnd = $end->formatLocalized($this->monthAndDayFormat); - $subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); - $chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d')]); - $periods = $this->getPeriodOverview($account, $start); - } - - // prep for current period view - if (0 === strlen($moment)) { - $start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range)); - $end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range)); - $fStart = $start->formatLocalized($this->monthAndDayFormat); - $fEnd = $end->formatLocalized($this->monthAndDayFormat); - $subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); - $periods = $this->getPeriodOverview($account, null); - } - - // grab journals: + $fStart = $start->formatLocalized($this->monthAndDayFormat); + $fEnd = $end->formatLocalized($this->monthAndDayFormat); + $subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); + $chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); + $periods = $this->getPeriodOverview($account, $end); $collector = app(JournalCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page); if (null !== $start) { $collector->setRange($start, $end); } $transactions = $collector->getPaginatedJournals(); - $transactions->setPath(route('accounts.show', [$account->id, $moment])); + $transactions->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')])); return view( 'accounts.show', - compact('account', 'currency', 'moment', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end', 'chartUri') + compact('account', 'currency', 'periods', 'subTitleIcon', 'transactions', 'subTitle', 'start', 'end', 'chartUri') ); } @@ -439,6 +416,9 @@ class AccountController extends Controller $range = Preferences::get('viewRange', '1M')->data; $start = $this->repository->oldestJournalDate($account); $end = $date ?? new Carbon; + if ($end < $start) { + list($start, $end) = [$end, $start]; // @codeCoverageIgnore + } // properties for cache $cache = new CacheProperties; @@ -449,11 +429,8 @@ class AccountController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - - $dates = app('navigation')->blockPeriods($start, $end, $range); $entries = new Collection; - // loop dates foreach ($dates as $date) { @@ -471,15 +448,15 @@ class AccountController extends Controller ->withOpposingAccount(); $spent = strval($collector->getJournals()->sum('transaction_amount')); - $dateStr = $date['end']->format('Y-m-d'); $dateName = app('navigation')->periodShow($date['start'], $date['period']); $entries->push( [ - 'string' => $dateStr, 'name' => $dateName, 'spent' => $spent, 'earned' => $earned, - 'date' => clone $date['end'],] + 'start' => $date['start']->format('Y-m-d'), + 'end' => $date['end']->format('Y-m-d'), + ] ); } diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 1231fc749d..fe0040156d 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -75,6 +75,7 @@ class ResetPasswordController extends Controller 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/BillController.php b/app/Http/Controllers/BillController.php index 4591ebead3..24210ebf34 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -30,10 +30,14 @@ use FireflyIII\Models\Bill; use FireflyIII\Models\Note; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Transformers\BillTransformer; use Illuminate\Http\Request; -use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; +use League\Fractal\Manager; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\DataArraySerializer; use Preferences; +use Symfony\Component\HttpFoundation\ParameterBag; use URL; use View; @@ -167,36 +171,26 @@ class BillController extends Controller * * @return View */ - public function index(Request $request, BillRepositoryInterface $repository) + public function index(BillRepositoryInterface $repository) { - /** @var Carbon $start */ - $start = session('start'); - /** @var Carbon $end */ + $start = session('start'); $end = session('end'); - $page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page')); $pageSize = intval(Preferences::get('listPageSize', 50)->data); - $collection = $repository->getBills(); - $total = $collection->count(); - $collection = $collection->slice(($page - 1) * $pageSize, $pageSize); - - $collection->each( - function (Bill $bill) use ($repository, $start, $end) { - // paid in this period? - $bill->paidDates = $repository->getPaidDatesInRange($bill, $start, $end); - $bill->payDates = $repository->getPayDatesInRange($bill, $start, $end); - $lastPaidDate = $this->lastPaidDate($repository->getPaidDatesInRange($bill, $start, $end), $start); - if ($bill->paidDates->count() >= $bill->payDates->count()) { - // if all bills have been been paid, jump to next period. - $lastPaidDate = $end; - } - $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastPaidDate); + $paginator = $repository->getPaginator($pageSize); + $parameters = new ParameterBag(); + $parameters->set('start', $start); + $parameters->set('end', $end); + $transformer = new BillTransformer($parameters); + /** @var Collection $bills */ + $bills = $paginator->getCollection()->map( + function (Bill $bill) use ($transformer) { + return $transformer->transform($bill); } ); - // paginate bills - $bills = new LengthAwarePaginator($collection, $total, $pageSize, $page); - $bills->setPath(route('bills.index')); - return view('bills.index', compact('bills')); + $paginator->setPath(route('bills.index')); + + return view('bills.index', compact('bills', 'paginator')); } /** @@ -235,15 +229,24 @@ class BillController extends Controller */ public function show(Request $request, BillRepositoryInterface $repository, Bill $bill) { - /** @var Carbon $date */ - $date = session('start'); - /** @var Carbon $end */ + $subTitle = $bill->name; + $start = session('start'); $end = session('end'); - $year = $date->year; + $year = $start->year; $page = intval($request->get('page')); $pageSize = intval(Preferences::get('listPageSize', 50)->data); - $yearAverage = $repository->getYearAverage($bill, $date); + $yearAverage = $repository->getYearAverage($bill, $start); $overallAverage = $repository->getOverallAverage($bill); + $manager = new Manager(); + $manager->setSerializer(new DataArraySerializer()); + $manager->parseIncludes(['attachments']); + + // Make a resource out of the data and + $parameters = new ParameterBag(); + $parameters->set('start', $start); + $parameters->set('end', $end); + $resource = new Item($bill, new BillTransformer($parameters), 'bill'); + $object = $manager->createData($resource)->toArray(); // use collector: /** @var JournalCollectorInterface $collector */ @@ -253,18 +256,8 @@ class BillController extends Controller $transactions = $collector->getPaginatedJournals(); $transactions->setPath(route('bills.show', [$bill->id])); - $bill->paidDates = $repository->getPaidDatesInRange($bill, $date, $end); - $bill->payDates = $repository->getPayDatesInRange($bill, $date, $end); - $lastPaidDate = $this->lastPaidDate($repository->getPaidDatesInRange($bill, $date, $end), $date); - if ($bill->paidDates->count() >= $bill->payDates->count()) { - // if all bills have been been paid, jump to next period. - $lastPaidDate = $end; - } - $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastPaidDate); - $hideBill = true; - $subTitle = $bill->name; - return view('bills.show', compact('transactions', 'yearAverage', 'overallAverage', 'year', 'hideBill', 'bill', 'subTitle')); + return view('bills.show', compact('transactions', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle')); } /** @@ -335,28 +328,4 @@ class BillController extends Controller return redirect($this->getPreviousUri('bills.edit.uri')); } - - /** - * Returns the latest date in the set, or start when set is empty. - * - * @param Collection $dates - * @param Carbon $default - * - * @return Carbon - */ - private function lastPaidDate(Collection $dates, Carbon $default): Carbon - { - if (0 === $dates->count()) { - return $default; // @codeCoverageIgnore - } - $latest = $dates->first(); - /** @var Carbon $date */ - foreach ($dates as $date) { - if ($date->gte($latest)) { - $latest = $date; - } - } - - return $latest; - } } diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index 71f11a9630..b445ca7adc 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -82,9 +82,9 @@ class BudgetController extends Controller */ public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget) { - $amount = strval($request->get('amount')); - $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); - $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); + $amount = strval($request->get('amount')); + $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); + $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); $budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount); if (0 === bccomp($amount, '0')) { $budgetLimit = null; @@ -198,13 +198,13 @@ class BudgetController extends Controller $prev->subDay(); $prev = app('navigation')->startOfPeriod($prev, $range); $this->repository->cleanupBudgets(); - $budgets = $this->repository->getActiveBudgets(); - $total = $budgets->count(); - $budgets = $budgets->slice(($page - 1) * $pageSize, $pageSize); + $allBudgets = $this->repository->getActiveBudgets(); + $total = $allBudgets->count(); + $budgets = $allBudgets->slice(($page - 1) * $pageSize, $pageSize); $inactive = $this->repository->getInactiveBudgets(); $periodStart = $start->formatLocalized($this->monthAndDayFormat); $periodEnd = $end->formatLocalized($this->monthAndDayFormat); - $budgetInformation = $this->repository->collectBudgetInformation($budgets, $start, $end); + $budgetInformation = $this->repository->collectBudgetInformation($allBudgets, $start, $end); $defaultCurrency = app('amount')->getDefaultCurrency(); $available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end); $spent = array_sum(array_column($budgetInformation, 'spent')); @@ -252,7 +252,7 @@ class BudgetController extends Controller 'currentMonth', 'next', 'nextText', - 'prev', + 'prev', 'allBudgets', 'prevText', 'periodStart', 'periodEnd', @@ -420,11 +420,12 @@ class BudgetController extends Controller $end = Carbon::createFromFormat('Y-m-d', $request->string('end')); $defaultCurrency = app('amount')->getDefaultCurrency(); $amount = $request->get('amount'); - + $page = $request->integer('page') === 0 ? 1 : $request->integer('page'); + $this->repository->cleanupBudgets(); $this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount); Preferences::mark(); - return redirect(route('budgets.index', [$start->format('Y-m-d')])); + return redirect(route('budgets.index', [$start->format('Y-m-d')]) . '?page=' . $page); } /** @@ -503,7 +504,7 @@ class BudgetController extends Controller { $data = $request->getBudgetData(); $budget = $this->repository->store($data); - + $this->repository->cleanupBudgets(); $request->session()->flash('success', strval(trans('firefly.stored_new_budget', ['name' => $budget->name]))); Preferences::mark(); @@ -530,6 +531,7 @@ class BudgetController extends Controller $this->repository->update($budget, $data); $request->session()->flash('success', strval(trans('firefly.updated_budget', ['name' => $budget->name]))); + $this->repository->cleanupBudgets(); Preferences::mark(); if (1 === intval($request->get('return_to_edit'))) { @@ -549,13 +551,14 @@ class BudgetController extends Controller * * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function updateIncome(Carbon $start, Carbon $end) + public function updateIncome(Request $request, Carbon $start, Carbon $end) { $defaultCurrency = app('amount')->getDefaultCurrency(); $available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end); $available = round($available, $defaultCurrency->decimal_places); + $page = intval($request->get('page')); - return view('budgets.income', compact('available', 'start', 'end')); + return view('budgets.income', compact('available', 'start', 'end', 'page')); } /** diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index d559947d87..baf19747d6 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -39,7 +39,6 @@ use Illuminate\Support\Collection; use Log; use Preferences; use Response; -use Steam; /** checked * Class AccountController. @@ -58,69 +57,6 @@ class AccountController extends Controller $this->generator = app(GeneratorInterface::class); } - /** - * @param Account $account - * - * @return \Illuminate\Http\JsonResponse - */ - public function all(Account $account) - { - $cache = new CacheProperties; - $cache->addProperty('chart.account.all'); - $cache->addProperty($account->id); - if ($cache->has()) { - return Response::json($cache->get()); // @codeCoverageIgnore - } - - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $start = $repository->oldestJournalDate($account); - $end = new Carbon; - - // depending on diff, do something with range of chart. - $step = '1D'; - $months = $start->diffInMonths($end); - if ($months > 3) { - $step = '1W'; - } - if ($months > 24) { - $step = '1M'; // @codeCoverageIgnore - } - if ($months > 100) { - $step = '1Y'; // @codeCoverageIgnore - } - $chartData = []; - $current = clone $start; - switch ($step) { - case '1D': - $format = (string)trans('config.month_and_day'); - $range = Steam::balanceInRange($account, $start, $end); - $previous = array_values($range)[0]; - while ($end >= $current) { - $theDate = $current->format('Y-m-d'); - $balance = $range[$theDate] ?? $previous; - $label = $current->formatLocalized($format); - $chartData[$label] = floatval($balance); - $previous = $balance; - $current->addDay(); - } - break; - case '1W': - case '1M': // @codeCoverageIgnore - case '1Y': // @codeCoverageIgnore - while ($end >= $current) { - $balance = floatval(Steam::balance($account, $current)); - $label = app('navigation')->periodShow($current, $step); - $chartData[$label] = $balance; - $current = app('navigation')->addPeriod($current, $step, 1); - } - break; - } - $data = $this->generator->singleSet($account->name, $chartData); - $cache->store($data); - - return Response::json($data); - } /** * Shows the balances for all the user's expense accounts. @@ -143,8 +79,8 @@ class AccountController extends Controller $start->subDay(); $accounts = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]); - $startBalances = Steam::balancesByAccounts($accounts, $start); - $endBalances = Steam::balancesByAccounts($accounts, $end); + $startBalances = app('steam')->balancesByAccounts($accounts, $start); + $endBalances = app('steam')->balancesByAccounts($accounts, $end); $chartData = []; foreach ($accounts as $account) { @@ -366,34 +302,57 @@ class AccountController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function period(Account $account, Carbon $start) + public function period(Account $account, Carbon $start, Carbon $end) { - $range = Preferences::get('viewRange', '1M')->data; - $end = app('navigation')->endOfPeriod($start, $range); - $cache = new CacheProperties(); + $cache = new CacheProperties; + $cache->addProperty('chart.account.period'); $cache->addProperty($start); $cache->addProperty($end); - $cache->addProperty('chart.account.period'); $cache->addProperty($account->id); if ($cache->has()) { return Response::json($cache->get()); // @codeCoverageIgnore } - - $format = (string)trans('config.month_and_day'); - $range = Steam::balanceInRange($account, $start, $end); - $current = clone $start; - $previous = array_values($range)[0]; - $chartData = []; - - while ($end >= $current) { - $theDate = $current->format('Y-m-d'); - $balance = $range[$theDate] ?? $previous; - $label = $current->formatLocalized($format); - $chartData[$label] = $balance; - $previous = $balance; - $current->addDay(); + // depending on diff, do something with range of chart. + $step = '1D'; + $months = $start->diffInMonths($end); + if ($months > 3) { + $step = '1W'; // @codeCoverageIgnore + } + if ($months > 24) { + $step = '1M'; // @codeCoverageIgnore + } + if ($months > 100) { + $step = '1Y'; // @codeCoverageIgnore + } + $chartData = []; + $current = clone $start; + switch ($step) { + case '1D': + $format = (string)trans('config.month_and_day'); + $range = app('steam')->balanceInRange($account, $start, $end); + $previous = array_values($range)[0]; + while ($end >= $current) { + $theDate = $current->format('Y-m-d'); + $balance = $range[$theDate] ?? $previous; + $label = $current->formatLocalized($format); + $chartData[$label] = floatval($balance); + $previous = $balance; + $current->addDay(); + } + break; + // @codeCoverageIgnoreStart + case '1W': + case '1M': + case '1Y': + while ($end >= $current) { + $balance = floatval(app('steam')->balance($account, $current)); + $label = app('navigation')->periodShow($current, $step); + $chartData[$label] = $balance; + $current = app('navigation')->addPeriod($current, $step, 1); + } + break; + // @codeCoverageIgnoreEnd } - $data = $this->generator->singleSet($account->name, $chartData); $cache->store($data); @@ -436,8 +395,8 @@ class AccountController extends Controller $accounts = $repository->getAccountsByType([AccountType::REVENUE]); $start->subDay(); - $startBalances = Steam::balancesByAccounts($accounts, $start); - $endBalances = Steam::balancesByAccounts($accounts, $end); + $startBalances = app('steam')->balancesByAccounts($accounts, $start); + $endBalances = app('steam')->balancesByAccounts($accounts, $end); foreach ($accounts as $account) { $id = $account->id; @@ -457,49 +416,6 @@ class AccountController extends Controller return Response::json($data); } - /** - * Shows an account's balance for a single month. - * - * @param Account $account - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function single(Account $account) - { - $start = clone session('start', Carbon::now()->startOfMonth()); - $end = clone session('end', Carbon::now()->endOfMonth()); - - // chart properties for cache: - $cache = new CacheProperties(); - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty('chart.account.single'); - $cache->addProperty($account->id); - if ($cache->has()) { - return Response::json($cache->get()); // @codeCoverageIgnore - } - - $format = (string)trans('config.month_and_day'); - $range = Steam::balanceInRange($account, $start, $end); - $current = clone $start; - $previous = array_values($range)[0]; - $chartData = []; - - while ($end >= $current) { - $theDate = $current->format('Y-m-d'); - $balance = $range[$theDate] ?? $previous; - $label = $current->formatLocalized($format); - $chartData[$label] = $balance; - $previous = $balance; - $current->addDay(); - } - - $data = $this->generator->singleSet($account->name, $chartData); - $cache->store($data); - - return Response::json($data); - } - /** * @param Collection $accounts * @param Carbon $start @@ -525,14 +441,14 @@ class AccountController extends Controller $chartData = []; foreach ($accounts as $account) { - $currency = $repository->find(intval($account->getMeta('currency_id'))); + $currency = $repository->findNull(intval($account->getMeta('currency_id'))); $currentSet = [ 'label' => $account->name, 'currency_symbol' => $currency->symbol, 'entries' => [], ]; $currentStart = clone $start; - $range = Steam::balanceInRange($account, $start, clone $end); + $range = app('steam')->balanceInRange($account, $start, clone $end); $previous = array_values($range)[0]; while ($currentStart <= $end) { $format = $currentStart->format('Y-m-d'); diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index cbff5e05e9..b48f3c3d25 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -83,6 +83,7 @@ class BudgetController extends Controller $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.budget.budget'); + $cache->addProperty($budget->id); if ($cache->has()) { return Response::json($cache->get()); // @codeCoverageIgnore @@ -149,6 +150,7 @@ class BudgetController extends Controller $cache->addProperty($end); $cache->addProperty('chart.budget.budget.limit'); $cache->addProperty($budgetLimit->id); + $cache->addProperty($budget->id); if ($cache->has()) { return Response::json($cache->get()); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Chart/ExpenseReportController.php b/app/Http/Controllers/Chart/ExpenseReportController.php index ed9e3f98ac..03ca051730 100644 --- a/app/Http/Controllers/Chart/ExpenseReportController.php +++ b/app/Http/Controllers/Chart/ExpenseReportController.php @@ -197,7 +197,7 @@ class ExpenseReportController extends Controller $collection->push($expenseAccount); $revenue = $this->accountRepository->findByName($expenseAccount->name, [AccountType::REVENUE]); - if (!is_null($revenue->id)) { + if (!is_null($revenue)) { $collection->push($revenue); } $combined[$expenseAccount->name] = $collection; diff --git a/app/Http/Controllers/Import/IndexController.php b/app/Http/Controllers/Import/IndexController.php index 4cb9e094cb..af3704e1a8 100644 --- a/app/Http/Controllers/Import/IndexController.php +++ b/app/Http/Controllers/Import/IndexController.php @@ -100,6 +100,7 @@ class IndexController extends Controller $config['initial-config-complete'] = false; $config['has-file-upload'] = false; $config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter']; + unset($config['stage']); $result = json_encode($config, JSON_PRETTY_PRINT); $name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\')); diff --git a/app/Http/Controllers/JavascriptController.php b/app/Http/Controllers/JavascriptController.php index afdbd59db9..bb991eb100 100644 --- a/app/Http/Controllers/JavascriptController.php +++ b/app/Http/Controllers/JavascriptController.php @@ -47,7 +47,7 @@ class JavascriptController extends Controller { $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); $preference = Preferences::get('currencyPreference', config('firefly.default_currency', 'EUR')); - $default = $currencyRepository->findByCode($preference->data); + $default = $currencyRepository->findByCodeNull($preference->data); $data = ['accounts' => []]; @@ -95,13 +95,13 @@ class JavascriptController extends Controller */ public function variables(Request $request, AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository) { - $account = $repository->find(intval($request->get('account'))); + $account = $repository->findNull(intval($request->get('account'))); $currencyId = 0; if (null !== $account) { $currencyId = intval($account->getMeta('currency_id')); } /** @var TransactionCurrency $currency */ - $currency = $currencyRepository->find($currencyId); + $currency = $currencyRepository->findNull($currencyId); if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); } diff --git a/app/Http/Controllers/Json/BoxController.php b/app/Http/Controllers/Json/BoxController.php index c3f3485677..67204d993c 100644 --- a/app/Http/Controllers/Json/BoxController.php +++ b/app/Http/Controllers/Json/BoxController.php @@ -206,7 +206,7 @@ class BoxController extends Controller $balance = $balances[$account->id] ?? '0'; $currencyId = intval($account->getMeta('currency_id')); if ($currencyId !== 0) { - $accountCurrency = $currencyRepos->find($currencyId); + $accountCurrency = $currencyRepos->findNull($currencyId); } if (!isset($netWorth[$accountCurrency->id])) { $netWorth[$accountCurrency->id]['currency'] = $accountCurrency; diff --git a/app/Http/Controllers/Json/FrontpageController.php b/app/Http/Controllers/Json/FrontpageController.php index f2d549bf6d..3aa2d1a30d 100644 --- a/app/Http/Controllers/Json/FrontpageController.php +++ b/app/Http/Controllers/Json/FrontpageController.php @@ -45,9 +45,8 @@ class FrontpageController extends Controller $info = []; /** @var PiggyBank $piggyBank */ foreach ($set as $piggyBank) { - $rep = $piggyBank->currentRelevantRep(); - $amount = strval($rep->currentamount); - if (null !== $rep->id && 1 === bccomp($amount, '0')) { + $amount = $repository->getCurrentAmount($piggyBank); + if (1 === bccomp($amount, '0')) { // percentage! $pct = round(($amount / $piggyBank->targetamount) * 100); diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index be61c563b7..341c3b7852 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -85,14 +85,28 @@ class NewUserController extends Controller $this->createSavingsAccount($request, $repository); // also store currency preference from input: - $currency = $currencyRepository->find(intval($request->input('amount_currency_id_bank_balance'))); + $currency = $currencyRepository->findNull(intval($request->input('amount_currency_id_bank_balance'))); - if (null !== $currency->id) { + if (null !== $currency) { // store currency preference: Preferences::set('currencyPreference', $currency->code); Preferences::mark(); } + // set default optional fields: + $visibleFields = [ + 'interest_date' => true, + 'book_date' => false, + 'process_date' => false, + 'due_date' => false, + 'payment_date' => false, + 'invoice_date' => false, + 'internal_reference' => false, + 'notes' => true, + 'attachments' => true, + ]; + Preferences::set('transaction_journal_optional_fields', $visibleFields); + Session::flash('success', strval(trans('firefly.stored_new_accounts_new_user'))); Preferences::mark(); @@ -112,6 +126,7 @@ class NewUserController extends Controller 'iban' => null, 'accountType' => 'asset', 'virtualBalance' => 0, + 'account_type_id' => null, 'active' => true, 'accountRole' => 'defaultAsset', 'openingBalance' => $request->input('bank_balance'), @@ -136,6 +151,7 @@ class NewUserController extends Controller 'name' => $request->get('bank_name') . ' savings account', 'iban' => null, 'accountType' => 'asset', + 'account_type_id' => null, 'virtualBalance' => 0, 'active' => true, 'accountRole' => 'savingAsset', diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index 1c88fc6dc5..7ba0315b5c 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -67,12 +67,12 @@ class PiggyBankController extends Controller * * @return View */ - public function add(PiggyBank $piggyBank) + public function add(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository) { /** @var Carbon $date */ $date = session('end', Carbon::now()->endOfMonth()); $leftOnAccount = $piggyBank->leftOnAccount($date); - $savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0'; + $savedSoFar = $repository->getCurrentAmount($piggyBank); $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); $maxAmount = min($leftOnAccount, $leftToSave); @@ -86,12 +86,12 @@ class PiggyBankController extends Controller * * @return View */ - public function addMobile(PiggyBank $piggyBank) + public function addMobile(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository) { /** @var Carbon $date */ $date = session('end', Carbon::now()->endOfMonth()); $leftOnAccount = $piggyBank->leftOnAccount($date); - $savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0'; + $savedSoFar = $repository->getCurrentAmount($piggyBank); $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); $maxAmount = min($leftOnAccount, $leftToSave); @@ -212,7 +212,8 @@ class PiggyBankController extends Controller Log::debug('Looping piggues'); /** @var PiggyBank $piggyBank */ foreach ($collection as $piggyBank) { - $piggyBank->savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0'; + + $piggyBank->savedSoFar = $piggyRepository->getCurrentAmount($piggyBank); $piggyBank->percentage = 0 !== bccomp('0', $piggyBank->savedSoFar) ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0; $piggyBank->leftToSave = bcsub($piggyBank->targetamount, strval($piggyBank->savedSoFar)); $piggyBank->percentage = $piggyBank->percentage > 100 ? 100 : $piggyBank->percentage; diff --git a/app/Http/Controllers/Report/ExpenseController.php b/app/Http/Controllers/Report/ExpenseController.php index ecd36ada6a..3fb3b9b7cd 100644 --- a/app/Http/Controllers/Report/ExpenseController.php +++ b/app/Http/Controllers/Report/ExpenseController.php @@ -313,7 +313,7 @@ class ExpenseController extends Controller $collection->push($expenseAccount); $revenue = $this->accountRepository->findByName($expenseAccount->name, [AccountType::REVENUE]); - if (!is_null($revenue->id)) { + if (!is_null($revenue)) { $collection->push($revenue); } $combined[$expenseAccount->name] = $collection; diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index 2dfecca07b..10d38d0895 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -31,11 +31,11 @@ use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Services\Internal\Update\JournalUpdateService; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Log; use Preferences; -use Session; use View; /** @@ -43,6 +43,8 @@ use View; */ class BulkController extends Controller { + /** @var JournalRepositoryInterface */ + private $repository; /** @@ -54,6 +56,7 @@ class BulkController extends Controller $this->middleware( function ($request, $next) { + $this->repository = app(JournalRepositoryInterface::class); app('view')->share('title', trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-repeat'); @@ -77,8 +80,8 @@ class BulkController extends Controller $messages = []; /** @var TransactionJournal $journal */ foreach ($journals as $journal) { - $sources = $journal->sourceAccountList(); - $destinations = $journal->destinationAccountList(); + $sources = $this->repository->getJournalSourceAccounts($journal); + $destinations = $this->repository->getJournalDestinationAccounts($journal); if ($sources->count() > 1) { $messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]); continue; @@ -88,13 +91,13 @@ class BulkController extends Controller $messages[] = trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]); continue; } - if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) { + if (TransactionType::OPENING_BALANCE === $this->repository->getTransactionType($journal)) { $messages[] = trans('firefly.cannot_edit_opening_balance'); continue; } // cannot edit reconciled transactions / journals: - if ($journal->transactions->first()->reconciled) { + if ($this->repository->isJournalReconciled($journal)) { $messages[] = trans('firefly.cannot_edit_reconciled', ['description' => $journal->description, 'id' => $journal->id]); continue; } @@ -138,11 +141,14 @@ class BulkController extends Controller */ public function update(BulkEditJournalRequest $request, JournalRepositoryInterface $repository) { + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); $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; + $count = 0; + if (is_array($journalIds)) { foreach ($journalIds as $journalId) { $journal = $repository->find(intval($journalId)); @@ -152,6 +158,7 @@ class BulkController extends Controller // 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) @@ -161,7 +168,7 @@ class BulkController extends Controller } if ($ignoreTags === false) { Log::debug(sprintf('Set tags to %s', $request->string('budget_id'))); - $repository->updateTags($journal, explode(',', $request->string('tags'))); + $repository->updateTags($journal,['tags' => explode(',', $request->string('tags'))]); } // update tags if not told to ignore (and is withdrawal) } diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index 323334c9fc..9541162376 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -43,6 +43,9 @@ class ConvertController extends Controller /** @var AccountRepositoryInterface */ private $accounts; + /** @var JournalRepositoryInterface */ + private $repository; + /** * ConvertController constructor. */ @@ -53,7 +56,8 @@ class ConvertController extends Controller // some useful repositories: $this->middleware( function ($request, $next) { - $this->accounts = app(AccountRepositoryInterface::class); + $this->accounts = app(AccountRepositoryInterface::class); + $this->repository = app(JournalRepositoryInterface::class); app('view')->share('title', trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); @@ -76,8 +80,7 @@ class ConvertController extends Controller return $this->redirectToAccount($journal); } // @codeCoverageIgnoreEnd - - $positiveAmount = $journal->amountPositive(); + $positiveAmount = $this->repository->getJournalTotal($journal); $assetAccounts = ExpandedForm::makeSelectList($this->accounts->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET])); $sourceType = $journal->transactionType; $subTitle = trans('firefly.convert_to_' . $destinationType->type, ['description' => $journal->description]); @@ -98,8 +101,8 @@ class ConvertController extends Controller } // get source and destination account: - $sourceAccount = $journal->sourceAccountList()->first(); - $destinationAccount = $journal->destinationAccountList()->first(); + $sourceAccount = $this->repository->getJournalSourceAccounts($journal)->first(); + $destinationAccount = $this->repository->getJournalDestinationAccounts($journal)->first(); return view( 'transactions.convert', @@ -183,8 +186,8 @@ class ConvertController extends Controller { /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); - $sourceAccount = $journal->sourceAccountList()->first(); - $destinationAccount = $journal->destinationAccountList()->first(); + $sourceAccount = $this->repository->getJournalSourceAccounts($journal)->first(); + $destinationAccount = $this->repository->getJournalDestinationAccounts($journal)->first(); $sourceType = $journal->transactionType; $joined = $sourceType->type . '-' . $destinationType->type; switch ($joined) { @@ -196,7 +199,7 @@ class ConvertController extends Controller break; case TransactionType::WITHDRAWAL . '-' . TransactionType::TRANSFER: // two - $destination = $accountRepository->find(intval($data['destination_account_asset'])); + $destination = $accountRepository->findNull(intval($data['destination_account_asset'])); break; case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL: case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL: @@ -239,8 +242,8 @@ class ConvertController extends Controller { /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); - $sourceAccount = $journal->sourceAccountList()->first(); - $destinationAccount = $journal->destinationAccountList()->first(); + $sourceAccount = $this->repository->getJournalSourceAccounts($journal)->first(); + $destinationAccount = $this->repository->getJournalDestinationAccounts($journal)->first(); $sourceType = $journal->transactionType; $joined = $sourceType->type . '-' . $destinationType->type; switch ($joined) { @@ -273,7 +276,7 @@ class ConvertController extends Controller $source = $destinationAccount; break; case TransactionType::DEPOSIT . '-' . TransactionType::TRANSFER: - $source = $accountRepository->find(intval($data['source_account_asset'])); + $source = $accountRepository->findNull(intval($data['source_account_asset'])); break; } diff --git a/app/Http/Controllers/Transaction/LinkController.php b/app/Http/Controllers/Transaction/LinkController.php index e1fe464f18..5bd8c3ae20 100644 --- a/app/Http/Controllers/Transaction/LinkController.php +++ b/app/Http/Controllers/Transaction/LinkController.php @@ -78,7 +78,7 @@ class LinkController extends Controller } /** - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ @@ -93,8 +93,8 @@ class LinkController extends Controller } /** - * @param JournalLinkRequest $request - * @param TransactionJournal $journal + * @param JournalLinkRequest $request + * @param TransactionJournal $journal * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ @@ -123,7 +123,7 @@ class LinkController extends Controller } /** - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index cbae31b26c..c84cde082b 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -25,8 +25,8 @@ namespace FireflyIII\Http\Controllers\Transaction; 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\Http\Requests\MassEditJournalRequest; use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; @@ -43,6 +43,9 @@ use View; */ class MassController extends Controller { + /** @var JournalRepositoryInterface */ + private $repository; + /** * */ @@ -54,6 +57,7 @@ class MassController extends Controller function ($request, $next) { app('view')->share('title', trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-repeat'); + $this->repository = app(JournalRepositoryInterface::class); return $next($request); } @@ -76,12 +80,11 @@ class MassController extends Controller } /** - * @param MassDeleteJournalRequest $request - * @param JournalRepositoryInterface $repository + * @param MassDeleteJournalRequest $request * * @return mixed */ - public function destroy(MassDeleteJournalRequest $request, JournalRepositoryInterface $repository) + public function destroy(MassDeleteJournalRequest $request) { $ids = $request->get('confirm_mass_delete'); $set = new Collection; @@ -89,7 +92,7 @@ class MassController extends Controller /** @var int $journalId */ foreach ($ids as $journalId) { /** @var TransactionJournal $journal */ - $journal = $repository->find(intval($journalId)); + $journal = $this->repository->find(intval($journalId)); if (null !== $journal->id && intval($journalId) === $journal->id) { $set->push($journal); } @@ -100,7 +103,7 @@ class MassController extends Controller /** @var TransactionJournal $journal */ foreach ($set as $journal) { - $repository->delete($journal); + $this->repository->delete($journal); ++$count; } @@ -112,6 +115,8 @@ class MassController extends Controller } /** + * TODO this code is a mess. + * * @param Collection $journals * * @return View @@ -134,8 +139,8 @@ class MassController extends Controller $messages = []; /** @var TransactionJournal $journal */ foreach ($journals as $journal) { - $sources = $journal->sourceAccountList(); - $destinations = $journal->destinationAccountList(); + $sources = $this->repository->getJournalSourceAccounts($journal); + $destinations = $this->repository->getJournalDestinationAccounts($journal); if ($sources->count() > 1) { $messages[] = trans('firefly.cannot_edit_multiple_source', ['description' => $journal->description, 'id' => $journal->id]); continue; @@ -145,13 +150,13 @@ class MassController extends Controller $messages[] = trans('firefly.cannot_edit_multiple_dest', ['description' => $journal->description, 'id' => $journal->id]); continue; } - if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) { + if (TransactionType::OPENING_BALANCE === $this->repository->getTransactionType($journal)) { $messages[] = trans('firefly.cannot_edit_opening_balance'); continue; } // cannot edit reconciled transactions / journals: - if ($journal->transactions->first()->reconciled) { + if ($this->repository->isJournalReconciled($journal)) { $messages[] = trans('firefly.cannot_edit_reconciled', ['description' => $journal->description, 'id' => $journal->id]); continue; } @@ -169,11 +174,11 @@ class MassController extends Controller // collect some useful meta data for the mass edit: $filtered->each( function (TransactionJournal $journal) { - $transaction = $journal->positiveTransaction(); + $transaction = $this->repository->getFirstPosTransaction($journal); $currency = $transaction->transactionCurrency; $journal->amount = floatval($transaction->amount); - $sources = $journal->sourceAccountList(); - $destinations = $journal->destinationAccountList(); + $sources = $this->repository->getJournalSourceAccounts($journal); + $destinations = $this->repository->getJournalDestinationAccounts($journal); $journal->transaction_count = $journal->transactions()->count(); $journal->currency_symbol = $currency->symbol; $journal->transaction_type_type = $journal->transactionType->type; @@ -202,6 +207,8 @@ class MassController extends Controller } /** + * TODO this cannot work with new update service. + * * @param MassEditJournalRequest $request * @param JournalRepositoryInterface $repository * @@ -216,11 +223,12 @@ class MassController extends Controller $journal = $repository->find(intval($journalId)); if (!is_null($journal)) { // get optional fields: - $what = strtolower($journal->transactionTypeStr()); - $sourceAccountId = $request->get('source_account_id')[$journal->id] ?? 0; - $sourceAccountName = $request->get('source_account_name')[$journal->id] ?? ''; - $destAccountId = $request->get('destination_account_id')[$journal->id] ?? 0; - $destAccountName = $request->get('destination_account_name')[$journal->id] ?? ''; + $what = strtolower($this->repository->getTransactionType($journal)); + $sourceAccountId = $request->get('source_account_id')[$journal->id] ?? null; + $currencyId = $request->get('transaction_currency_id')[$journal->id] ?? 1; + $sourceAccountName = $request->get('source_account_name')[$journal->id] ?? null; + $destAccountId = $request->get('destination_account_id')[$journal->id] ?? null; + $destAccountName = $request->get('destination_account_name')[$journal->id] ?? null; $budgetId = $request->get('budget_id')[$journal->id] ?? 0; $category = $request->get('category')[$journal->id]; $tags = $journal->tags->pluck('tag')->toArray(); @@ -228,29 +236,47 @@ class MassController extends Controller $foreignAmount = isset($request->get('foreign_amount')[$journal->id]) ? round($request->get('foreign_amount')[$journal->id], 12) : null; $foreignCurrencyId = isset($request->get('foreign_currency_id')[$journal->id]) ? intval($request->get('foreign_currency_id')[$journal->id]) : null; - + $notes = $repository->getNoteText($journal); // build data array $data = [ - 'id' => $journal->id, - 'what' => $what, - 'description' => $request->get('description')[$journal->id], - 'source_account_id' => intval($sourceAccountId), - 'source_account_name' => $sourceAccountName, - 'destination_account_id' => intval($destAccountId), - 'destination_account_name' => $destAccountName, - 'amount' => $foreignAmount, - 'native_amount' => $amount, - 'source_amount' => $amount, - 'date' => new Carbon($request->get('date')[$journal->id]), - 'interest_date' => $journal->interest_date, - 'book_date' => $journal->book_date, - 'process_date' => $journal->process_date, - 'budget_id' => intval($budgetId), - 'currency_id' => $foreignCurrencyId, - 'foreign_amount' => $foreignAmount, - 'destination_amount' => $foreignAmount, - 'category' => $category, - 'tags' => $tags, + 'id' => $journal->id, + 'what' => $what, + 'description' => $request->get('description')[$journal->id], + 'date' => new Carbon($request->get('date')[$journal->id]), + 'bill_id' => null, + 'bill_name' => null, + 'notes' => $notes, + 'transactions' => [[ + + 'category_id' => null, + 'category_name' => $category, + 'budget_id' => intval($budgetId), + 'budget_name' => null, + 'source_id' => intval($sourceAccountId), + 'source_name' => $sourceAccountName, + 'destination_id' => intval($destAccountId), + 'destination_name' => $destAccountName, + 'amount' => $amount, + 'identifier' => 0, + 'reconciled' => false, + 'currency_id' => intval($currencyId), + 'currency_code' => null, + 'description' => null, + 'foreign_amount' => null, + 'foreign_currency_id' => $foreignCurrencyId, + 'foreign_currency_code' => null, + //'native_amount' => $amount, + //'source_amount' => $amount, + //'foreign_amount' => $foreignAmount, + //'destination_amount' => $foreignAmount, + //'amount' => $foreignAmount, + ]], + 'currency_id' => $foreignCurrencyId, + 'tags' => $tags, + 'interest_date' => $journal->interest_date, + 'book_date' => $journal->book_date, + 'process_date' => $journal->process_date, + ]; // call repository update function. $repository->update($journal, $data); diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index a7f350132d..8dd3023290 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -104,13 +104,13 @@ class SingleController extends Controller */ public function cloneTransaction(TransactionJournal $journal) { - $source = $journal->sourceAccountList()->first(); - $destination = $journal->destinationAccountList()->first(); - $budget = $journal->budgets()->first(); - $budgetId = null === $budget ? 0 : $budget->id; - $category = $journal->categories()->first(); - $categoryName = null === $category ? '' : $category->name; - $tags = join(',', $journal->tags()->get()->pluck('tag')->toArray()); + $source = $this->repository->getJournalSourceAccounts($journal)->first(); + $destination = $this->repository->getJournalDestinationAccounts($journal)->first(); + $budgetId = $this->repository->getJournalBudgetId($journal); + $categoryName = $this->repository->getJournalCategoryName($journal); + + $tags = join(',', $this->repository->getTags($journal)); + // todo less direct database access. Use collector? /** @var Transaction $transaction */ $transaction = $journal->transactions()->first(); $amount = app('steam')->positive($transaction->amount); @@ -171,6 +171,14 @@ class SingleController extends Controller $subTitle = trans('form.add_new_' . $what); $subTitleIcon = 'fa-plus'; $optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data; + $source = intval($request->get('source')); + + if (($what === 'withdrawal' || $what === 'transfer') && $source > 0) { + $preFilled['source_account_id'] = $source; + } + if ($what === 'deposit' && $source > 0) { + $preFilled['destination_account_id'] = $source; + } Session::put('preFilled', $preFilled); @@ -230,7 +238,7 @@ class SingleController extends Controller $type = $transactionJournal->transactionTypeStr(); Session::flash('success', strval(trans('firefly.deleted_' . strtolower($type), ['description' => $transactionJournal->description]))); - $this->repository->delete($transactionJournal); + $this->repository->destroy($transactionJournal); Preferences::mark(); @@ -242,53 +250,56 @@ class SingleController extends Controller * * @return mixed */ - public function edit(TransactionJournal $journal) + public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository) { - // @codeCoverageIgnoreStart - if ($this->isOpeningBalance($journal)) { + $transactionType = $repository->getTransactionType($journal); + + // redirect to account: + if ($transactionType === TransactionType::OPENING_BALANCE) { return $this->redirectToAccount($journal); } - // @codeCoverageIgnoreEnd + // redirect to reconcile edit: + if ($transactionType === TransactionType::RECONCILIATION) { + return redirect(route('accounts.reconcile.edit', [$journal->id])); + } + + // redirect to split edit: if ($this->isSplitJournal($journal)) { return redirect(route('transactions.split.edit', [$journal->id])); } - $what = strtolower($journal->transactionTypeStr()); + $what = strtolower($transactionType); $assetAccounts = $this->groupedAccountList(); $budgetList = ExpandedForm::makeSelectListWithEmpty($this->budgets->getBudgets()); - if (TransactionType::RECONCILIATION === $journal->transactionType->type) { - return redirect(route('accounts.reconcile.edit', [$journal->id])); - } - // view related code $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); // journal related code - $sourceAccounts = $journal->sourceAccountList(); - $destinationAccounts = $journal->destinationAccountList(); + $sourceAccounts = $repository->getJournalSourceAccounts($journal); + $destinationAccounts = $repository->getJournalDestinationAccounts($journal); $optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data; - $pTransaction = $journal->positiveTransaction(); + $pTransaction = $repository->getFirstPosTransaction($journal); $foreignCurrency = null !== $pTransaction->foreignCurrency ? $pTransaction->foreignCurrency : $pTransaction->transactionCurrency; $preFilled = [ - 'date' => $journal->dateAsString(), - 'interest_date' => $journal->dateAsString('interest_date'), - 'book_date' => $journal->dateAsString('book_date'), - 'process_date' => $journal->dateAsString('process_date'), - 'category' => $journal->categoryAsString(), - 'budget_id' => $journal->budgetId(), - 'tags' => join(',', $journal->tags->pluck('tag')->toArray()), + 'date' => $repository->getJournalDate($journal, null), // $journal->dateAsString() + 'interest_date' => $repository->getJournalDate($journal, 'interest_date'), + 'book_date' => $repository->getJournalDate($journal, 'book_date'), + 'process_date' => $repository->getJournalDate($journal, 'process_date'), + 'category' => $repository->getJournalCategoryName($journal), + 'budget_id' => $repository->getJournalBudgetId($journal), + 'tags' => join(',', $repository->getTags($journal)), 'source_account_id' => $sourceAccounts->first()->id, 'source_account_name' => $sourceAccounts->first()->edit_name, 'destination_account_id' => $destinationAccounts->first()->id, 'destination_account_name' => $destinationAccounts->first()->edit_name, // new custom fields: - 'due_date' => $journal->dateAsString('due_date'), - 'payment_date' => $journal->dateAsString('payment_date'), - 'invoice_date' => $journal->dateAsString('invoice_date'), - 'interal_reference' => $journal->getMeta('internal_reference'), - 'notes' => '', + 'due_date' => $repository->getJournalDate($journal, 'due_date'), + 'payment_date' => $repository->getJournalDate($journal, 'payment_date'), + 'invoice_date' => $repository->getJournalDate($journal, 'invoice_date'), + 'interal_reference' => $repository->getMetaField($journal, 'internal_reference'), + 'notes' => $repository->getNoteText($journal), // amount fields 'amount' => $pTransaction->amount, @@ -301,11 +312,6 @@ class SingleController extends Controller 'foreign_currency' => $foreignCurrency, 'destination_currency' => $foreignCurrency, ]; - /** @var Note $note */ - $note = $this->repository->getNote($journal); - if (null !== $note) { - $preFilled['notes'] = $note->text; - } // amounts for withdrawals and deposits: // amount, native_amount, source_amount, destination_amount @@ -340,6 +346,8 @@ class SingleController extends Controller $createAnother = 1 === intval($request->get('create_another')); $data = $request->getJournalData(); $journal = $repository->store($data); + + if (null === $journal->id) { // error! Log::error('Could not store transaction journal: ', $journal->getErrors()->toArray()); @@ -416,7 +424,7 @@ class SingleController extends Controller event(new UpdatedTransactionJournal($journal)); // update, get events by date and sort DESC - $type = strtolower($journal->transactionTypeStr()); + $type = strtolower($this->repository->getTransactionType($journal)); Session::flash('success', strval(trans('firefly.updated_' . $type, ['description' => $data['description']]))); Preferences::mark(); diff --git a/app/Http/Controllers/Transaction/SplitController.php b/app/Http/Controllers/Transaction/SplitController.php index d93e431df7..b82633bef4 100644 --- a/app/Http/Controllers/Transaction/SplitController.php +++ b/app/Http/Controllers/Transaction/SplitController.php @@ -29,7 +29,6 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\SplitJournalFormRequest; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; -use FireflyIII\Models\Note; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; @@ -37,7 +36,6 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Journal\JournalTaskerInterface; use Illuminate\Http\Request; -use Log; use Preferences; use Session; use Steam; @@ -97,7 +95,7 @@ class SplitController extends Controller public function edit(Request $request, TransactionJournal $journal) { if ($this->isOpeningBalance($journal)) { - return $this->redirectToAccount($journal); + return $this->redirectToAccount($journal); // @codeCoverageIgnore } $uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size'))); @@ -125,20 +123,11 @@ class SplitController extends Controller Session::forget('transactions.edit-split.fromUpdate'); return view( - 'transactions.split.edit', - compact( - 'subTitleIcon', - 'currencies', - 'optionalFields', - 'preFilled', - 'subTitle', - 'uploadSize', - 'assetAccounts', - 'budgets', - 'journal', - 'accountArray', - 'previous' - ) + 'transactions.split.edit', compact( + 'subTitleIcon', 'currencies', 'optionalFields', 'preFilled', 'subTitle', 'uploadSize', 'assetAccounts', 'budgets', + 'journal', 'accountArray', + 'previous' + ) ); } @@ -151,10 +140,11 @@ class SplitController extends Controller public function update(SplitJournalFormRequest $request, TransactionJournal $journal) { if ($this->isOpeningBalance($journal)) { - return $this->redirectToAccount($journal); + return $this->redirectToAccount($journal); // @codeCoverageIgnore } - $data = $this->arrayFromInput($request); - $journal = $this->repository->updateSplitJournal($journal, $data); + $data = $request->getAll(); + $journal = $this->repository->update($journal, $data); + /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; // save attachments: @@ -168,8 +158,8 @@ class SplitController extends Controller } // @codeCoverageIgnoreEnd - $type = strtolower($journal->transactionTypeStr()); - Session::flash('success', strval(trans('firefly.updated_' . $type, ['description' => $data['journal_description']]))); + $type = strtolower($this->repository->getTransactionType($journal)); + Session::flash('success', strval(trans('firefly.updated_' . $type, ['description' => $data['description']]))); Preferences::mark(); // @codeCoverageIgnoreStart @@ -185,39 +175,6 @@ class SplitController extends Controller return redirect($this->getPreviousUri('transactions.edit-split.uri')); } - /** - * @param SplitJournalFormRequest $request - * - * @return array - */ - private function arrayFromInput(SplitJournalFormRequest $request): array - { - $tags = null === $request->get('tags') ? '' : $request->get('tags'); - $array = [ - 'journal_description' => $request->get('journal_description'), - 'journal_source_account_id' => $request->get('journal_source_account_id'), - 'journal_source_account_name' => $request->get('journal_source_account_name'), - 'journal_destination_account_id' => $request->get('journal_destination_account_id'), - 'what' => $request->get('what'), - 'date' => $request->get('date'), - // all custom fields: - 'interest_date' => $request->get('interest_date'), - 'book_date' => $request->get('book_date'), - 'process_date' => $request->get('process_date'), - 'due_date' => $request->get('due_date'), - 'payment_date' => $request->get('payment_date'), - 'invoice_date' => $request->get('invoice_date'), - 'internal_reference' => $request->get('internal_reference'), - 'notes' => $request->get('notes'), - 'tags' => explode(',', $tags), - - // transactions. - 'transactions' => $this->getTransactionDataFromRequest($request), - ]; - - return $array; - } - /** * @param SplitJournalFormRequest|Request $request * @param TransactionJournal $journal @@ -226,36 +183,29 @@ class SplitController extends Controller */ private function arrayFromJournal(Request $request, TransactionJournal $journal): array { - $sourceAccounts = $journal->sourceAccountList(); - $destinationAccounts = $journal->destinationAccountList(); - $notes = ''; - /** @var Note $note */ - - $note = $this->repository->getNote($journal); - if (null !== $note) { - $notes = $note->text; - } - $array = [ + $sourceAccounts = $this->repository->getJournalSourceAccounts($journal); + $destinationAccounts = $this->repository->getJournalDestinationAccounts($journal); + $array = [ 'journal_description' => $request->old('journal_description', $journal->description), - 'journal_amount' => $journal->amountPositive(), + 'journal_amount' => $this->repository->getJournalTotal($journal), 'sourceAccounts' => $sourceAccounts, 'journal_source_account_id' => $request->old('journal_source_account_id', $sourceAccounts->first()->id), 'journal_source_account_name' => $request->old('journal_source_account_name', $sourceAccounts->first()->name), 'journal_destination_account_id' => $request->old('journal_destination_account_id', $destinationAccounts->first()->id), 'destinationAccounts' => $destinationAccounts, - 'what' => strtolower($journal->transactionTypeStr()), - 'date' => $request->old('date', $journal->date->format('Y-m-d')), + 'what' => strtolower($this->repository->getTransactionType($journal)), + 'date' => $request->old('date', $this->repository->getJournalDate($journal, null)), 'tags' => join(',', $journal->tags->pluck('tag')->toArray()), // all custom fields: - 'interest_date' => $request->old('interest_date', $journal->getMeta('interest_date')), - 'book_date' => $request->old('book_date', $journal->getMeta('book_date')), - 'process_date' => $request->old('process_date', $journal->getMeta('process_date')), - 'due_date' => $request->old('due_date', $journal->getMeta('due_date')), - 'payment_date' => $request->old('payment_date', $journal->getMeta('payment_date')), - 'invoice_date' => $request->old('invoice_date', $journal->getMeta('invoice_date')), - 'internal_reference' => $request->old('internal_reference', $journal->getMeta('internal_reference')), - 'notes' => $request->old('notes', $notes), + 'interest_date' => $request->old('interest_date', $this->repository->getMetaField($journal, 'interest_date')), + 'book_date' => $request->old('book_date', $this->repository->getMetaField($journal, 'book_date')), + 'process_date' => $request->old('process_date', $this->repository->getMetaField($journal, 'process_date')), + 'due_date' => $request->old('due_date', $this->repository->getMetaField($journal, 'due_date')), + 'payment_date' => $request->old('payment_date', $this->repository->getMetaField($journal, 'payment_date')), + 'invoice_date' => $request->old('invoice_date', $this->repository->getMetaField($journal, 'invoice_date')), + 'internal_reference' => $request->old('internal_reference', $this->repository->getMetaField($journal, 'internal_reference')), + 'notes' => $request->old('notes', $this->repository->getNoteText($journal)), // transactions. 'transactions' => $this->getTransactionDataFromJournal($journal), @@ -295,12 +245,14 @@ class SplitController extends Controller 'foreign_currency_code' => $transaction['foreign_currency_code'], 'foreign_currency_symbol' => $transaction['foreign_currency_symbol'], ]; - // set initial category and/or budget: - if (1 === count($transactions) && 0 === $index) { - $set['budget_id'] = $journal->budgetId(); - $set['category'] = $journal->categoryAsString(); + if ($set['budget_id'] === 0) { + $set['budget_id'] = $this->repository->getJournalBudgetId($journal); } + if (strlen($set['category']) === 0) { + $set['category'] = $this->repository->getJournalCategoryName($journal); + } + $return[] = $set; } @@ -308,35 +260,6 @@ class SplitController extends Controller return $return; } - /** - * @param SplitJournalFormRequest|Request $request - * - * @return array - */ - private function getTransactionDataFromRequest(SplitJournalFormRequest $request): array - { - $return = []; - $transactions = $request->get('transactions'); - foreach ($transactions as $transaction) { - $return[] = [ - 'description' => $transaction['description'], - 'source_account_id' => $transaction['source_account_id'] ?? 0, - 'source_account_name' => $transaction['source_account_name'] ?? '', - 'destination_account_id' => $transaction['destination_account_id'] ?? 0, - 'destination_account_name' => $transaction['destination_account_name'] ?? '', - 'amount' => round($transaction['amount'] ?? 0, 12), - 'foreign_amount' => !isset($transaction['foreign_amount']) ? null : round($transaction['foreign_amount'] ?? 0, 12), - 'budget_id' => isset($transaction['budget_id']) ? intval($transaction['budget_id']) : 0, - 'category' => $transaction['category'] ?? '', - 'transaction_currency_id' => intval($transaction['transaction_currency_id']), - 'foreign_currency_id' => $transaction['foreign_currency_id'] ?? null, - ]; - } - Log::debug(sprintf('Found %d splits in request data.', count($return))); - - return $return; - } - /** * @param $array * @param $old diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index a2a6205cd8..35d914499d 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -44,6 +44,7 @@ use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull; use Illuminate\Foundation\Http\Middleware\ValidatePostSize; use Illuminate\Routing\Middleware\ThrottleRequests; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Laravel\Passport\Http\Middleware\CreateFreshApiToken; /** * @codeCoverageIgnore @@ -84,7 +85,7 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, + CreateFreshApiToken::class, ], // MUST NOT be logged in. Does not care about 2FA or confirmation. @@ -95,7 +96,6 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, Binder::class, RedirectIfAuthenticated::class, ], @@ -109,7 +109,6 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, Binder::class, Authenticate::class, RedirectIfTwoFactorAuthenticated::class, @@ -125,7 +124,6 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, Binder::class, Authenticate::class, ], @@ -141,11 +139,11 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, Authenticate::class, AuthenticateTwoFactor::class, Range::class, Binder::class, + CreateFreshApiToken::class, ], // MUST be logged in // MUST have 2fa @@ -159,12 +157,12 @@ class Kernel extends HttpKernel StartFireflySession::class, ShareErrorsFromSession::class, VerifyCsrfToken::class, - //SubstituteBindings::class, Authenticate::class, AuthenticateTwoFactor::class, IsAdmin::class, Range::class, Binder::class, + CreateFreshApiToken::class, ], 'api' => [ diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index c5d91b1510..289fff1515 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -1,7 +1,7 @@ . */ -declare(strict_types=1); namespace FireflyIII\Http\Middleware; use Closure; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; -use Session; +use Illuminate\Auth\AuthenticationException; +use Illuminate\Contracts\Auth\Factory as Auth; /** - * Class Authenticate. + * Class Authenticate */ class Authenticate { + /** + * The authentication factory instance. + * + * @var \Illuminate\Contracts\Auth\Factory + */ + protected $auth; + + /** + * Create a new middleware instance. + * + * @param \Illuminate\Contracts\Auth\Factory $auth + * + * @return void + */ + public function __construct(Auth $auth) + { + $this->auth = $auth; + } + /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string[] ...$guards * * @return mixed + * + * @throws \Illuminate\Auth\AuthenticationException */ - public function handle(Request $request, Closure $next, $guard = null) + public function handle($request, Closure $next, ...$guards) { - if (Auth::guard($guard)->guest()) { - if ($request->ajax()) { - return response('Unauthorized.', 401); - } - - return redirect()->guest('login'); - } - if (1 === intval(auth()->user()->blocked)) { - $message = strval(trans('firefly.block_account_logout')); - if ('email_changed' === auth()->user()->blocked_code) { - $message = strval(trans('firefly.email_changed_logout')); - } - - Session::flash('logoutMessage', $message); - Auth::guard($guard)->logout(); - - return redirect()->guest('login'); - } + $this->authenticate($guards); return $next($request); } + + /** + * Determine if the user is logged in to any of the given guards. + * + * @param array $guards + * + * @return void + * + * @throws \Illuminate\Auth\AuthenticationException + */ + protected function authenticate(array $guards) + { + if (empty($guards)) { + // go for default guard: + if ($this->auth->check()) { + // do an extra check on user object. + $user = $this->auth->authenticate(); + if (1 === intval($user->blocked)) { + $message = strval(trans('firefly.block_account_logout')); + if ('email_changed' === $user->blocked_code) { + $message = strval(trans('firefly.email_changed_logout')); + } + app('session')->flash('logoutMessage', $message); + $this->auth->logout(); + + throw new AuthenticationException('Blocked account.', $guards); + } + } + + return $this->auth->authenticate(); + } + + // @codeCoverageIgnoreStart + foreach ($guards as $guard) { + if ($this->auth->guard($guard)->check()) { + return $this->auth->shouldUse($guard); + } + } + + throw new AuthenticationException('Unauthenticated.', $guards); + // @codeCoverageIgnoreEnd + } } diff --git a/app/Http/Middleware/AuthenticateTwoFactor.php b/app/Http/Middleware/AuthenticateTwoFactor.php index aaa026ee19..ca6879d96c 100644 --- a/app/Http/Middleware/AuthenticateTwoFactor.php +++ b/app/Http/Middleware/AuthenticateTwoFactor.php @@ -23,34 +23,49 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; use Closure; -use Illuminate\Http\Request; +use Illuminate\Contracts\Auth\Factory as Auth; use Log; -use Preferences; -use Auth; -use Session; + /** * Class AuthenticateTwoFactor. */ class AuthenticateTwoFactor { /** - * Handle an incoming request. + * The authentication factory instance. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard - * - * @return mixed + * @var \Illuminate\Contracts\Auth\Factory */ - public function handle(Request $request, Closure $next, $guard = null) - { - if (Auth::guard($guard)->guest()) { + protected $auth; + /** + * Create a new middleware instance. + * + * @param \Illuminate\Contracts\Auth\Factory $auth + * + * @return void + */ + public function __construct(Auth $auth) + { + $this->auth = $auth; + } + + /** + * @param $request + * @param Closure $next + * @param array ...$guards + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|mixed + * @throws \Illuminate\Container\EntryNotFoundException + */ + public function handle($request, Closure $next, ...$guards) + { + if ($this->auth->guest()) { return redirect()->guest('login'); } - $is2faEnabled = Preferences::get('twoFactorAuthEnabled', false)->data; - $has2faSecret = null !== Preferences::get('twoFactorAuthSecret'); + $is2faEnabled = app('preferences')->get('twoFactorAuthEnabled', false)->data; + $has2faSecret = null !== app('preferences')->get('twoFactorAuthSecret'); $is2faAuthed = 'true' === $request->cookie('twoFactorAuthenticated'); if ($is2faEnabled && $has2faSecret && !$is2faAuthed) { @@ -61,4 +76,5 @@ class AuthenticateTwoFactor return $next($request); } + } diff --git a/app/Http/Middleware/Binder.php b/app/Http/Middleware/Binder.php index 0a7bfc1bda..415dbe2474 100644 --- a/app/Http/Middleware/Binder.php +++ b/app/Http/Middleware/Binder.php @@ -1,7 +1,7 @@ binders = Domain::getBindables(); + $this->auth = $auth; } /** * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string[] ...$guards * * @return mixed + * + * @throws \Illuminate\Auth\AuthenticationException */ - public function handle(Request $request, Closure $next) + public function handle($request, Closure $next, ...$guards) { foreach ($request->route()->parameters() as $key => $value) { if (isset($this->binders[$key])) { @@ -71,7 +84,7 @@ class Binder * * @return mixed */ - private function performBinding($key, $value, $route) + private function performBinding(string $key, string $value, Route $route) { $class = $this->binders[$key]; diff --git a/app/Http/Middleware/IsDemoUser.php b/app/Http/Middleware/IsDemoUser.php index c4b1b5123f..7f704adc14 100644 --- a/app/Http/Middleware/IsDemoUser.php +++ b/app/Http/Middleware/IsDemoUser.php @@ -34,26 +34,28 @@ use Session; class IsDemoUser { /** - * Handle an incoming request. May not be a limited user (ie. Sandstorm env. or demo user). + * Handle an incoming request. * - * @param \Illuminate\Http\Request $request - * @param \Closure $next - * @param string|null $guard + * @param \Illuminate\Http\Request $request + * @param \Closure $next + * @param string[] ...$guards * * @return mixed */ - public function handle(Request $request, Closure $next, $guard = null) + public function handle(Request $request, Closure $next) { - if (Auth::guard($guard)->guest()) { - // don't care when not logged in, usual stuff applies: + /** @var User $user */ + $user = $request->user(); + if (is_null($user)) { return $next($request); } - /** @var User $user */ - $user = auth()->user(); + if ($user->hasRole('demo')) { Session::flash('info', strval(trans('firefly.not_available_demo_user'))); - return redirect($request->session()->previousUrl()); + redirect($request->session()->previousUrl()); + + return $next($request); } return $next($request); diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index 11e85836f2..15f9b10b21 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -38,35 +38,17 @@ use View; */ class Range { - /** - * The Guard implementation. - * - * @var Guard - */ - protected $auth; - - /** - * Create a new filter instance. - * - * @param Guard $auth - */ - public function __construct(Guard $auth) - { - $this->auth = $auth; - } - /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param Closure $next - * @param string|null $guard * * @return mixed */ - public function handle(Request $request, Closure $next, $guard = null) + public function handle(Request $request, Closure $next) { - if (!Auth::guard($guard)->guest()) { + if ($request->user()) { // set start, end and finish: $this->setRange(); diff --git a/app/Http/Middleware/Sandstorm.php b/app/Http/Middleware/Sandstorm.php index c119efcc97..5dce1f605a 100644 --- a/app/Http/Middleware/Sandstorm.php +++ b/app/Http/Middleware/Sandstorm.php @@ -95,8 +95,9 @@ class Sandstorm /** @var User $user */ $user = $repository->store( [ + 'blocked' => false, + 'blocked_code' => null, 'email' => $email, - 'password' => str_random(16), ] ); Auth::guard($guard)->login($user); diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index efb721d45a..c3a867f7e4 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -22,7 +22,8 @@ declare(strict_types=1); namespace FireflyIII\Http\Requests; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Models\Account; +use FireflyIII\Rules\UniqueIban; /** * Class AccountFormRequest. @@ -47,6 +48,7 @@ class AccountFormRequest extends Request 'name' => $this->string('name'), 'active' => $this->boolean('active'), 'accountType' => $this->string('what'), + 'account_type_id' => 0, 'currency_id' => $this->integer('currency_id'), 'virtualBalance' => $this->string('virtualBalance'), 'iban' => $this->string('iban'), @@ -66,25 +68,14 @@ class AccountFormRequest extends Request */ public function rules() { - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); $accountRoles = join(',', config('firefly.accountRoles')); $types = join(',', array_keys(config('firefly.subTitlesByIdentifier'))); $ccPaymentTypes = join(',', array_keys(config('firefly.ccTypes'))); - - $nameRule = 'required|min:1|uniqueAccountForUser'; - $idRule = ''; - if (null !== $repository->find(intval($this->get('id')))->id) { - $idRule = 'belongsToUser:accounts'; - $nameRule = 'required|min:1|uniqueAccountForUser:' . intval($this->get('id')); - } - - return [ - 'id' => $idRule, - 'name' => $nameRule, + $rules = [ + 'name' => 'required|min:1|uniqueAccountForUser', 'openingBalance' => 'numeric|required_with:openingBalanceDate|nullable', 'openingBalanceDate' => 'date|required_with:openingBalance|nullable', - 'iban' => 'iban|nullable', + 'iban' => ['iban', 'nullable', new UniqueIban(null)], 'BIC' => 'bic|nullable', 'virtualBalance' => 'numeric|nullable', 'currency_id' => 'exists:transaction_currencies,id', @@ -97,5 +88,16 @@ class AccountFormRequest extends Request 'amount_currency_id_virtualBalance' => 'exists:transaction_currencies,id', 'what' => 'in:' . $types, ]; + + /** @var Account $account */ + $account = $this->route()->parameter('account'); + if (!is_null($account)) { + // add rules: + $rules['id'] = 'belongsToUser:accounts'; + $rules['name'] = 'required|min:1|uniqueAccountForUser:' . intval($this->get('id')); + $rules['iban'] = ['iban', 'nullable', new UniqueIban($account)]; + } + + return $rules; } } diff --git a/app/Http/Requests/JournalFormRequest.php b/app/Http/Requests/JournalFormRequest.php index f23dcdd650..eaa39797eb 100644 --- a/app/Http/Requests/JournalFormRequest.php +++ b/app/Http/Requests/JournalFormRequest.php @@ -46,38 +46,91 @@ class JournalFormRequest extends Request */ public function getJournalData() { - $data = [ - 'what' => $this->get('what'), // type. can be 'deposit', 'withdrawal' or 'transfer' - 'date' => $this->date('date'), - 'tags' => explode(',', $this->string('tags')), - 'currency_id' => $this->integer('amount_currency_id_amount'), + $currencyId = $this->integer('amount_currency_id_amount'); + $data = [ + 'type' => $this->get('what'), // type. can be 'deposit', 'withdrawal' or 'transfer' + 'date' => $this->date('date'), + 'tags' => explode(',', $this->string('tags')), + 'user' => auth()->user()->id, // all custom fields: - 'interest_date' => $this->date('interest_date'), - 'book_date' => $this->date('book_date'), - 'process_date' => $this->date('process_date'), - 'due_date' => $this->date('due_date'), - 'payment_date' => $this->date('payment_date'), - 'invoice_date' => $this->date('invoice_date'), - 'internal_reference' => $this->string('internal_reference'), - 'notes' => $this->string('notes'), + 'interest_date' => $this->date('interest_date'), + 'book_date' => $this->date('book_date'), + 'process_date' => $this->date('process_date'), + 'due_date' => $this->date('due_date'), + 'payment_date' => $this->date('payment_date'), + 'invoice_date' => $this->date('invoice_date'), + 'internal_reference' => $this->string('internal_reference'), + 'notes' => $this->string('notes'), - // transaction / journal data: - 'description' => $this->string('description'), - 'amount' => $this->string('amount'), - 'budget_id' => $this->integer('budget_id'), - 'category' => $this->string('category'), - 'source_account_id' => $this->integer('source_account_id'), - 'source_account_name' => $this->string('source_account_name'), - 'destination_account_id' => $this->string('destination_account_id'), - 'destination_account_name' => $this->string('destination_account_name'), - 'piggy_bank_id' => $this->integer('piggy_bank_id'), + // journal data: + 'description' => $this->string('description'), + 'piggy_bank_id' => $this->integer('piggy_bank_id'), + 'piggy_bank_name' => null, + 'bill_id' => null, + 'bill_name' => null, - // native amount and stuff like that: - 'native_amount' => $this->string('native_amount'), - 'source_amount' => $this->string('source_amount'), - 'destination_amount' => $this->string('destination_amount'), + // transaction data: + 'transactions' => [ + [ + 'currency_id' => null, + 'currency_code' => null, + 'description' => null, + 'amount' => $this->string('amount'), + 'budget_id' => $this->integer('budget_id'), + 'budget_name' => null, + 'category_id' => null, + 'category_name' => $this->string('category'), + 'source_id' => $this->integer('source_account_id'), + 'source_name' => $this->string('source_account_name'), + 'destination_id' => $this->integer('destination_account_id'), + 'destination_name' => $this->string('destination_account_name'), + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'foreign_amount' => null, + 'reconciled' => false, + 'identifier' => 0, + ], + ], ]; + switch (strtolower($data['type'])) { + case 'withdrawal': + $sourceCurrency = $this->integer('source_account_currency'); + $data['transactions'][0]['currency_id'] = $sourceCurrency; + $data['transactions'][0]['destination_id'] = null; // clear destination ID (transfer) + if ($sourceCurrency !== $currencyId) { + // user has selected a foreign currency. + $data['transactions'][0]['foreign_currency_id'] = $currencyId; + $data['transactions'][0]['foreign_amount'] = $this->string('amount'); + $data['transactions'][0]['amount'] = $this->string('native_amount'); + } + + break; + case 'deposit': + $destinationCurrency = $this->integer('destination_account_currency'); + $data['transactions'][0]['currency_id'] = $destinationCurrency; + $data['transactions'][0]['source_id'] = null; // clear destination ID (transfer) + if ($destinationCurrency !== $currencyId) { + // user has selected a foreign currency. + $data['transactions'][0]['foreign_currency_id'] = $currencyId; + $data['transactions'][0]['foreign_amount'] = $this->string('amount'); + $data['transactions'][0]['amount'] = $this->string('native_amount'); + } + break; + case 'transfer': + // by default just assume source currency + $sourceCurrency = $this->integer('source_account_currency'); + $destinationCurrency = $this->integer('destination_account_currency'); + $data['transactions'][0]['currency_id'] = $sourceCurrency; + if ($sourceCurrency !== $destinationCurrency) { + // user has selected a foreign currency. + $data['transactions'][0]['foreign_currency_id'] = $destinationCurrency; + $data['transactions'][0]['foreign_amount'] = $this->string('destination_amount'); + $data['transactions'][0]['amount'] = $this->string('source_amount'); + } + break; + + } return $data; } @@ -154,7 +207,7 @@ class JournalFormRequest extends Request break; default: - throw new FireflyException('Cannot handle transaction type of type ' . e($what) . ' . '); + throw new FireflyException(sprintf('Cannot handle transaction type of type "%s"', $what)); // @codeCoverageIgnore } return $rules; diff --git a/app/Http/Requests/LinkTypeFormRequest.php b/app/Http/Requests/LinkTypeFormRequest.php index f530fc299f..79fef825ff 100644 --- a/app/Http/Requests/LinkTypeFormRequest.php +++ b/app/Http/Requests/LinkTypeFormRequest.php @@ -44,12 +44,13 @@ class LinkTypeFormRequest extends Request public function rules() { // fixed - - /** @var LinkTypeRepositoryInterface $repository */ - $repository = app(LinkTypeRepositoryInterface::class); $nameRule = 'required|min:1|unique:link_types,name'; $idRule = ''; - if (null !== $repository->find($this->integer('id'))->id) { + + // get parameter link: + $link = $this->route()->parameter('linkType'); + + if (null !== $link) { $idRule = 'exists:link_types,id'; $nameRule = 'required|min:1'; } diff --git a/app/Http/Requests/ReconciliationStoreRequest.php b/app/Http/Requests/ReconciliationStoreRequest.php new file mode 100644 index 0000000000..0c76a052d2 --- /dev/null +++ b/app/Http/Requests/ReconciliationStoreRequest.php @@ -0,0 +1,81 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Requests; + +use FireflyIII\Rules\ValidTransactions; +use Log; + +/** + * Class ReconciliationStoreRequest + */ +class ReconciliationStoreRequest extends Request +{ + /** + * @return bool + */ + public function authorize(): bool + { + // Only allow logged in users + return auth()->check(); + } + + /** + * @return array + */ + public function getAll(): array + { + $transactions = $this->get('transactions'); + if (!is_array($transactions)) { + $transactions = []; // @codeCoverageIgnore + } + $data = [ + 'start' => $this->date('start'), + 'end' => $this->date('end'), + 'start_balance' => $this->string('startBalance'), + 'end_balance' => $this->string('endBalance'), + 'difference' => $this->string('difference'), + 'transactions' => $transactions, + 'reconcile' => $this->string('reconcile'), + ]; + Log::debug('In ReconciliationStoreRequest::getAll(). Will now return data.'); + + return $data; + } + + /** + * @return array + */ + public function rules(): array + { + return [ + 'start' => 'required|date', + 'end' => 'required|date', + 'startBalance' => 'numeric', + 'endBalance' => 'numeric', + 'difference' => 'required|numeric', + 'transactions' => [new ValidTransactions], + 'reconcile' => 'required|in:create,nothing', + ]; + } +} \ No newline at end of file diff --git a/app/Http/Requests/ReconciliationFormRequest.php b/app/Http/Requests/ReconciliationUpdateRequest.php similarity index 91% rename from app/Http/Requests/ReconciliationFormRequest.php rename to app/Http/Requests/ReconciliationUpdateRequest.php index c2ea851180..7e98b79186 100644 --- a/app/Http/Requests/ReconciliationFormRequest.php +++ b/app/Http/Requests/ReconciliationUpdateRequest.php @@ -1,6 +1,6 @@ find(intval($accountId)); - if (null !== $account->id) { + $account = $repository->findNull(intval($accountId)); + if (null !== $account) { $collection->push($account); } } @@ -78,8 +78,8 @@ class ReportFormRequest extends Request $collection = new Collection; if (is_array($set)) { foreach ($set as $budgetId) { - $budget = $repository->find(intval($budgetId)); - if (null !== $budget->id) { + $budget = $repository->findNull(intval($budgetId)); + if (null !== $budget) { $collection->push($budget); } } @@ -99,8 +99,8 @@ class ReportFormRequest extends Request $collection = new Collection; if (is_array($set)) { foreach ($set as $categoryId) { - $category = $repository->find(intval($categoryId)); - if (null !== $category->id) { + $category = $repository->findNull(intval($categoryId)); + if (null !== $category) { $collection->push($category); } } @@ -122,9 +122,12 @@ class ReportFormRequest extends Request if (2 === count($parts)) { try { $date = new Carbon($parts[1]); + // @codeCoverageIgnoreStart } catch (Exception $e) { throw new FireflyException(sprintf('"%s" is not a valid date range.', $range)); + // @codeCoverageIgnoreEnd } + } return $date; @@ -142,8 +145,8 @@ class ReportFormRequest extends Request $collection = new Collection; if (is_array($set)) { foreach ($set as $accountId) { - $account = $repository->find(intval($accountId)); - if (null !== $account->id) { + $account = $repository->findNull(intval($accountId)); + if (null !== $account) { $collection->push($account); } } @@ -165,8 +168,10 @@ class ReportFormRequest extends Request if (2 === count($parts)) { try { $date = new Carbon($parts[0]); + // @codeCoverageIgnoreStart } catch (Exception $e) { throw new FireflyException(sprintf('"%s" is not a valid date range.', $range)); + // @codeCoverageIgnoreEnd } } diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index dca2d3f774..2b0406614c 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -40,6 +40,16 @@ class Request extends FormRequest return 1 === intval($this->input($field)); } + /** + * @param string $field + * + * @return int + */ + public function integer(string $field): int + { + return intval($this->get($field)); + } + /** * @param string $field * @@ -110,41 +120,4 @@ class Request extends FormRequest { return $this->get($field) ? new Carbon($this->get($field)) : null; } - - /** - * @param string $field - * - * @return float - */ - protected function float(string $field): float - { - return round($this->input($field), 12); - } - - /** - * @param string $field - * @param string $type - * - * @return array - */ - protected function getArray(string $field, string $type): array - { - $original = $this->get($field); - $return = []; - foreach ($original as $index => $value) { - $return[$index] = $this->$type($value); - } - - return $return; - } - - /** - * @param string $field - * - * @return int - */ - public function integer(string $field): int - { - return intval($this->get($field)); - } } diff --git a/app/Http/Requests/SplitJournalFormRequest.php b/app/Http/Requests/SplitJournalFormRequest.php index d2c82be9ff..303c0d7bf8 100644 --- a/app/Http/Requests/SplitJournalFormRequest.php +++ b/app/Http/Requests/SplitJournalFormRequest.php @@ -41,23 +41,63 @@ class SplitJournalFormRequest extends Request /** * @return array */ - public function getSplitData(): array + public function getAll(): array { $data = [ - 'id' => $this->integer('id'), - 'journal_description' => $this->string('journal_description'), - 'journal_currency_id' => $this->integer('journal_currency_id'), - 'journal_source_account_id' => $this->integer('journal_source_account_id'), - 'journal_source_account_name' => $this->string('journal_source_account_name'), - 'journal_destination_account_id' => $this->integer('journal_destination_account_id'), - 'journal_destination_account_name' => $this->string('journal_source_destination_name'), - 'date' => $this->date('date'), - 'what' => $this->string('what'), - 'interest_date' => $this->date('interest_date'), - 'book_date' => $this->date('book_date'), - 'process_date' => $this->date('process_date'), - 'transactions' => $this->getTransactionData(), + 'description' => $this->string('description'), + 'type' => $this->string('what'), + 'date' => $this->date('date'), + 'tags' => explode(',', $this->string('tags')), + 'bill_id' => null, + 'bill_name' => null, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'notes' => $this->string('notes'), + 'transactions' => [], ]; + // switch type to get correct source / destination info: + $sourceId = null; + $sourceName = null; + $destinationId = null; + $destinationName = null; + + foreach ($this->get('transactions') as $index => $transaction) { + switch ($data['type']) { + case 'withdrawal': + $sourceId = $this->integer('journal_source_account_id'); + $destinationName = $transaction['destination_account_name']; + break; + case 'deposit': + $sourceName = $transaction['source_account_name']; + $destinationId = $this->integer('journal_destination_account_id'); + break; + case 'transfer': + $sourceId = $this->integer('journal_source_account_id'); + $destinationId = $this->integer('journal_destination_account_id'); + break; + } + $foreignAmount = $transaction['foreign_amount'] ?? null; + $set = [ + 'source_id' => $sourceId, + 'source_name' => $sourceName, + 'destination_id' => $destinationId, + 'destination_name' => $destinationName, + 'foreign_amount' => $foreignAmount, + 'foreign_currency_id' => null, + 'foreign_currency_code' => null, + 'reconciled' => false, + 'identifier' => $index, + 'currency_id' => $this->integer('journal_currency_id'), + 'currency_code' => null, + 'description' => $transaction['description'], + 'amount' => $transaction['amount'], + 'budget_id' => intval($transaction['budget_id'] ?? 0), + 'budget_name' => null, + 'category_id' => null, + 'category_name' => $transaction['category'], + ]; + $data['transactions'][] = $set; + } return $data; } @@ -88,39 +128,4 @@ class SplitJournalFormRequest extends Request ]; } - /** - * @return array - */ - private function getTransactionData(): array - { - $descriptions = $this->getArray('description', 'string'); - $categories = $this->getArray('category', 'string'); - $amounts = $this->getArray('amount', 'float'); - $budgets = $this->getArray('amount', 'integer'); - $srcAccountIds = $this->getArray('source_account_id', 'integer'); - $srcAccountNames = $this->getArray('source_account_name', 'string'); - $dstAccountIds = $this->getArray('destination_account_id', 'integer'); - $dstAccountNames = $this->getArray('destination_account_name', 'string'); - $piggyBankIds = $this->getArray('piggy_bank_id', 'integer'); - - $return = []; - // description is leading because it is one of the mandatory fields. - foreach ($descriptions as $index => $description) { - $category = $categories[$index] ?? ''; - $transaction = [ - 'description' => $description, - 'amount' => Steam::positive($amounts[$index]), - 'budget_id' => $budgets[$index] ?? 0, - 'category' => $category, - 'source_account_id' => $srcAccountIds[$index] ?? $this->get('journal_source_account_id'), - 'source_account_name' => $srcAccountNames[$index] ?? '', - 'piggy_bank_id' => $piggyBankIds[$index] ?? 0, - 'destination_account_id' => $dstAccountIds[$index] ?? $this->get('journal_destination_account_id'), - 'destination_account_name' => $dstAccountNames[$index] ?? '', - ]; - $return[] = $transaction; - } - - return $return; - } } diff --git a/app/Import/Configuration/FileConfigurator.php b/app/Import/Configuration/FileConfigurator.php index 1cde0e8015..c5070e5f73 100644 --- a/app/Import/Configuration/FileConfigurator.php +++ b/app/Import/Configuration/FileConfigurator.php @@ -263,6 +263,7 @@ class FileConfigurator implements ConfiguratorInterface * Shorthand method to set the extended status. * * @codeCoverageIgnore + * * @param array $extended */ private function setExtendedStatus(array $extended): void diff --git a/app/Import/FileProcessor/CsvProcessor.php b/app/Import/FileProcessor/CsvProcessor.php index a0de8ca0ff..79de2ec118 100644 --- a/app/Import/FileProcessor/CsvProcessor.php +++ b/app/Import/FileProcessor/CsvProcessor.php @@ -125,6 +125,7 @@ class CsvProcessor implements FileProcessorInterface * Shorthand method to set the extended status. * * @codeCoverageIgnore + * * @param array $array */ public function setExtendedStatus(array $array) diff --git a/app/Import/Object/ImportBill.php b/app/Import/Object/ImportBill.php index 988b7b9574..f27eaaf070 100644 --- a/app/Import/Object/ImportBill.php +++ b/app/Import/Object/ImportBill.php @@ -114,7 +114,7 @@ class ImportBill Log::debug(sprintf('Finding bill with ID #%d', $this->id['value'])); /** @var Bill $bill */ $bill = $this->repository->find(intval($this->id['value'])); - if (null !== $bill->id) { + if (null !== $bill) { Log::debug(sprintf('Found unmapped bill by ID (#%d): %s', $bill->id, $bill->name)); return $bill; @@ -199,7 +199,7 @@ class ImportBill $search = intval($array['mapped']); $bill = $this->repository->find($search); - if (null === $bill->id) { + if (null === $bill) { Log::error(sprintf('There is no bill with id #%d. Invalid mapping will be ignored!', $search)); return new Bill; diff --git a/app/Import/Prerequisites/FilePrerequisites.php b/app/Import/Prerequisites/FilePrerequisites.php index e47bb4c797..e0a9219218 100644 --- a/app/Import/Prerequisites/FilePrerequisites.php +++ b/app/Import/Prerequisites/FilePrerequisites.php @@ -67,9 +67,10 @@ class FilePrerequisites implements PrerequisitesInterface */ public function hasPrerequisites(): bool { - if($this->user->hasRole('demo')) { + if ($this->user->hasRole('demo')) { throw new FireflyException('Apologies, the demo user cannot import files.'); } + return false; } diff --git a/app/Import/Routine/FileRoutine.php b/app/Import/Routine/FileRoutine.php index 828dbd5d0f..121651660f 100644 --- a/app/Import/Routine/FileRoutine.php +++ b/app/Import/Routine/FileRoutine.php @@ -114,7 +114,6 @@ class FileRoutine implements RoutineInterface Log::debug('Back in run()'); - Log::debug('Updated job...'); Log::debug(sprintf('%d journals in $storage->journals', $storage->journals->count())); $this->journals = $storage->journals; @@ -177,6 +176,16 @@ class FileRoutine implements RoutineInterface $this->repository->addStepsDone($this->job, 1); } + /** + * Shorthand + * + * @param int $steps + */ + private function addTotalSteps(int $steps) + { + $this->repository->addTotalSteps($this->job, $steps); + } + /** * */ @@ -194,7 +203,7 @@ class FileRoutine implements RoutineInterface /** @var TagRepositoryInterface $repository */ $repository = app(TagRepositoryInterface::class); $repository->setUser($this->job->user); - $data = [ + $data = [ 'tag' => trans('import.import_with_key', ['key' => $this->job->key]), 'date' => new Carbon, 'description' => null, @@ -203,7 +212,7 @@ class FileRoutine implements RoutineInterface 'zoomLevel' => null, 'tagMode' => 'nothing', ]; - $tag = $repository->store($data); + $tag = $repository->store($data); $this->addStep(); $extended = $this->getExtendedStatus(); $extended['tag'] = $tag->id; @@ -220,6 +229,7 @@ class FileRoutine implements RoutineInterface } Log::info(sprintf('Linked %d journals to tag #%d ("%s")', $this->journals->count(), $tag->id, $tag->tag)); $this->addStep(); + return $tag; } @@ -281,16 +291,6 @@ class FileRoutine implements RoutineInterface $this->repository->setTotalSteps($this->job, $steps); } - /** - * Shorthand - * - * @param int $steps - */ - private function addTotalSteps(int $steps) - { - $this->repository->addTotalSteps($this->job, $steps); - } - /** * @param Collection $objects * diff --git a/app/Import/Storage/ImportStorage.php b/app/Import/Storage/ImportStorage.php index 8990aab387..728cce920e 100644 --- a/app/Import/Storage/ImportStorage.php +++ b/app/Import/Storage/ImportStorage.php @@ -308,8 +308,8 @@ class ImportStorage return false; } - $amount = app('steam')->positive($parameters['amount']); - $names = [$parameters['asset'], $parameters['opposing']]; + $amount = app('steam')->positive($parameters['amount']); + $names = [$parameters['asset'], $parameters['opposing']]; sort($names); diff --git a/app/Models/Account.php b/app/Models/Account.php index 81ad0d8016..b70870c148 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -241,53 +241,12 @@ class Account extends Model } /** - * Returns the amount of the opening balance for this account. - * - * @return string - * - * @throws FireflyException + * @codeCoverageIgnore + * Get all of the notes. */ - public function getOpeningBalanceAmount(): string + public function notes() { - $journal = TransactionJournal::sortCorrectly() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $this->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); - if (null === $journal) { - return '0'; - } - - $count = $journal->transactions()->count(); - if (2 !== $count) { - throw new FireflyException(sprintf('Cannot use getFirstTransaction on journal #%d', $journal->id)); - } - $transaction = $journal->transactions()->where('account_id', $this->id)->first(); - if (null === $transaction) { - return '0'; - } - - return strval($transaction->amount); - } - - /** - * Returns the date of the opening balance for this account. If no date, will return 01-01-1900. - * - * @return Carbon - */ - public function getOpeningBalanceDate(): Carbon - { - $date = new Carbon('1900-01-01'); - $journal = TransactionJournal::sortCorrectly() - ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $this->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); - if (null === $journal) { - return $date; - } - - return $journal->date; + return $this->morphMany(Note::class, 'noteable'); } /** @@ -345,15 +304,6 @@ 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/BudgetLimit.php b/app/Models/BudgetLimit.php index ddab3dfab0..741e2706c3 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -43,8 +43,6 @@ class BudgetLimit extends Model 'end_date' => 'date', 'repeats' => 'boolean', ]; - /** @var array */ - protected $dates = ['start_date', 'end_date']; /** * @param string $value diff --git a/app/Models/ExportJob.php b/app/Models/ExportJob.php index 629d212b18..03ec4c5816 100644 --- a/app/Models/ExportJob.php +++ b/app/Models/ExportJob.php @@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class ExportJob. * - * @property User $user + * @property User $user * @property string $key */ class ExportJob extends Model diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php index 9ad55c7c31..e0ae998c58 100644 --- a/app/Models/ImportJob.php +++ b/app/Models/ImportJob.php @@ -65,7 +65,7 @@ class ImportJob extends Model * @throws NotFoundHttpException * @throws FireflyException */ - public static function routeBinder($value): ImportJob + public static function routeBinder(string $value): ImportJob { if (auth()->check()) { $key = trim($value); diff --git a/app/Models/Note.php b/app/Models/Note.php index b9fa882cd5..e0ca98c8f2 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Models; use Illuminate\Database\Eloquent\Model; -use League\CommonMark\CommonMarkConverter; /** * Class Note. @@ -42,18 +41,7 @@ class Note extends Model 'deleted_at' => 'datetime', ]; /** @var array */ - protected $fillable = ['title', 'text']; - - /** - * @codeCoverageIgnore - * @return string - */ - public function getMarkdownAttribute(): string - { - $converter = new CommonMarkConverter; - - return $converter->convertToHtml($this->text); - } + protected $fillable = ['title', 'text', 'noteable_id', 'noteable_type']; /** * @codeCoverageIgnore diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index 2140c33b8b..8706a4b302 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -56,7 +56,7 @@ class PiggyBank extends Model /** @var array */ protected $dates = ['startdate', 'targetdate']; /** @var array */ - protected $fillable = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate']; + protected $fillable = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate', 'active']; /** @var array */ protected $hidden = ['targetamount_encrypted', 'encrypted']; @@ -90,7 +90,7 @@ class PiggyBank extends Model /** * Grabs the PiggyBankRepetition that's currently relevant / active. - * + * @deprecated * @returns PiggyBankRepetition */ public function currentRelevantRep(): PiggyBankRepetition @@ -126,6 +126,7 @@ class PiggyBank extends Model } /** + * @deprecated * @return string */ public function getSuggestedMonthlyAmount(): string @@ -152,7 +153,7 @@ class PiggyBank extends Model /** * @param Carbon $date - * + * @deprecated * @return string */ public function leftOnAccount(Carbon $date): string diff --git a/app/Models/PiggyBankEvent.php b/app/Models/PiggyBankEvent.php index 4bd7753aa9..d937815739 100644 --- a/app/Models/PiggyBankEvent.php +++ b/app/Models/PiggyBankEvent.php @@ -26,6 +26,7 @@ use Illuminate\Database\Eloquent\Model; /** * Class PiggyBankEvent. + * @property $piggyBank */ class PiggyBankEvent extends Model { diff --git a/app/Models/Tag.php b/app/Models/Tag.php index 5f70bee39e..37bf61af66 100644 --- a/app/Models/Tag.php +++ b/app/Models/Tag.php @@ -103,24 +103,6 @@ class Tag extends Model throw new NotFoundHttpException; } - /** - * @param Tag $tag - * - * @return string - * - * @throws \FireflyIII\Exceptions\FireflyException - */ - public static function tagSum(Tag $tag): string - { - $sum = '0'; - /** @var TransactionJournal $journal */ - foreach ($tag->transactionjournals as $journal) { - bcadd($sum, $journal->amount()); - } - - return $sum; - } - /** * @codeCoverageIgnore * diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 0ac3df916e..09ab60ab42 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Watson\Validating\ValidatingTrait; /** @@ -90,7 +91,7 @@ class Transaction extends Model */ protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount', 'identifier', 'transaction_currency_id', 'foreign_currency_id', - 'foreign_amount',]; + 'foreign_amount','reconciled']; /** * @var array */ @@ -130,6 +131,25 @@ class Transaction extends Model return false; } + /** + * @param string $value + * + * @return Transaction + */ + public static function routeBinder(string $value): Transaction + { + if (auth()->check()) { + $transactionId = intval($value); + $transaction = auth()->user()->transactions()->where('transactions.id', $transactionId) + ->first(['transactions.*']); + if (!is_null($transaction)) { + return $transaction; + } + } + + throw new NotFoundHttpException; + } + use SoftDeletes, ValidatingTrait; /** diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index 12408be513..dd49eb5025 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use Crypt; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Models\TransactionJournalTrait; +use FireflyIII\User; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -38,6 +39,7 @@ use Watson\Validating\ValidatingTrait; /** * Class TransactionJournal. + * @property User $user */ class TransactionJournal extends Model { @@ -62,8 +64,7 @@ class TransactionJournal extends Model 'encrypted' => 'boolean', 'completed' => 'boolean', ]; - /** @var array */ - protected $dates = ['date', 'interest_date', 'book_date', 'process_date']; + /** @var array */ protected $fillable = ['user_id', 'transaction_type_id', 'bill_id', 'interest_date', 'book_date', 'process_date', diff --git a/app/Models/TransactionType.php b/app/Models/TransactionType.php index 5fd8972049..1ad60435b3 100644 --- a/app/Models/TransactionType.php +++ b/app/Models/TransactionType.php @@ -72,7 +72,7 @@ class TransactionType extends Model * * @return Model|null|static */ - public static function routeBinder(string $type) + public static function routeBinder(string $type): TransactionType { if (!auth()->check()) { throw new NotFoundHttpException(); diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 42fdfc5350..2e44ca0924 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -24,6 +24,7 @@ namespace FireflyIII\Providers; use Illuminate\Support\Facades\Schema; use Illuminate\Support\ServiceProvider; +use Laravel\Passport\Passport; /** * @codeCoverageIgnore @@ -44,5 +45,6 @@ class AppServiceProvider extends ServiceProvider */ public function register() { + Passport::ignoreMigrations(); } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 3c78d0b5b2..ed1d76630b 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; +use Laravel\Passport\Passport; /** * @codeCoverageIgnore @@ -46,5 +47,7 @@ class AuthServiceProvider extends ServiceProvider public function boot() { $this->registerPolicies(); + Passport::routes(); + Passport::tokensExpireIn(now()->addDays(14)); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 9cd5f2d8d5..65d703e6f4 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -77,7 +77,6 @@ class EventServiceProvider extends ServiceProvider // is a Transaction Journal related event. 'FireflyIII\Events\StoredTransactionJournal' => [ 'FireflyIII\Handlers\Events\StoredJournalEventHandler@scanBills', - 'FireflyIII\Handlers\Events\StoredJournalEventHandler@connectToPiggyBank', 'FireflyIII\Handlers\Events\StoredJournalEventHandler@processRules', ], // is a Transaction Journal related event. @@ -122,39 +121,6 @@ class EventServiceProvider extends ServiceProvider */ protected function registerDeleteEvents() { - Account::deleted( - function (Account $account) { - Log::debug('Now trigger account delete response #' . $account->id); - /** @var Transaction $transaction */ - foreach ($account->transactions()->get() as $transaction) { - Log::debug('Now at transaction #' . $transaction->id); - $journal = $transaction->transactionJournal()->first(); - if (null !== $journal) { - Log::debug('Call for deletion of journal #' . $journal->id); - $journal->delete(); - } - } - } - ); - TransactionJournal::deleted( - function (TransactionJournal $journal) { - Log::debug(sprintf('Now triggered journal delete response #%d', $journal->id)); - - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - Log::debug(sprintf('Will now delete transaction #%d', $transaction->id)); - $transaction->delete(); - } - - // also delete journal_meta entries. - - /** @var TransactionJournalMeta $meta */ - foreach ($journal->transactionJournalMeta()->get() as $meta) { - Log::debug(sprintf('Will now delete meta-entry #%d', $meta->id)); - $meta->delete(); - } - } - ); } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 5e3c5ccd2a..f04fad6fa2 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -42,6 +42,8 @@ use FireflyIII\Helpers\Report\PopupReport; use FireflyIII\Helpers\Report\PopupReportInterface; use FireflyIII\Helpers\Report\ReportHelper; use FireflyIII\Helpers\Report\ReportHelperInterface; +use FireflyIII\Repositories\TransactionType\TransactionTypeRepository; +use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface; use FireflyIII\Repositories\User\UserRepository; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Services\Password\PwndVerifier; @@ -162,6 +164,7 @@ class FireflyServiceProvider extends ServiceProvider // export: $this->app->bind(ProcessorInterface::class, ExpandedProcessor::class); $this->app->bind(UserRepositoryInterface::class, UserRepository::class); + $this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class); $this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class); // more generators: diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 8a57b746f4..f15114ac3c 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -38,7 +38,7 @@ class RouteServiceProvider extends ServiceProvider * * @var string */ - protected $namespace = 'FireflyIII\Http\Controllers'; + protected $namespace = ''; /** * Define your route model bindings, pattern filters, etc. @@ -65,8 +65,8 @@ class RouteServiceProvider extends ServiceProvider */ protected function mapApiRoutes() { - Route::prefix('api') - ->middleware('api') + Route::prefix('api/v1') + ->middleware('auth:api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); } diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 36ca48e872..6c6d5348ff 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -23,37 +23,29 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Account; use Carbon\Carbon; -use DB; +use Exception; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Factory\AccountFactory; 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; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Tag\TagRepositoryInterface; +use FireflyIII\Services\Internal\Destroy\AccountDestroyService; +use FireflyIII\Services\Internal\Update\AccountUpdateService; +use FireflyIII\Services\Internal\Update\JournalUpdateService; use FireflyIII\User; -use Log; -use Validator; /** * Class AccountRepository. */ class AccountRepository implements AccountRepositoryInterface { + use FindAccountsTrait; /** @var User */ private $user; - use FindAccountsTrait; - /** @var array */ - private $validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC']; - /** - * Moved here from account CRUD. - * * @param array $types * * @return int @@ -69,24 +61,31 @@ class AccountRepository implements AccountRepositoryInterface * Moved here from account CRUD. * * @param Account $account - * @param Account $moveTo + * @param Account|null $moveTo * * @return bool * * @throws \Exception */ - public function destroy(Account $account, Account $moveTo): bool + public function destroy(Account $account, ?Account $moveTo): bool { - if (null !== $moveTo->id) { - DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]); - } - if (null !== $account) { - $account->delete(); - } + /** @var AccountDestroyService $service */ + $service = app(AccountDestroyService::class); + $service->destroy($account, $moveTo); return true; } + /** + * @param int $accountId + * + * @return Account|null + */ + public function findNull(int $accountId): ?Account + { + return $this->user->accounts()->find($accountId); + } + /** * Return account type by string. * @@ -109,6 +108,51 @@ class AccountRepository implements AccountRepositoryInterface return $account->notes()->first(); } + /** + * Returns the amount of the opening balance for this account. + * + * @param Account $account + * + * @return string + */ + public function getOpeningBalanceAmount(Account $account): ?string + { + + $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); + if (null === $journal) { + return null; + } + $transaction = $journal->transactions()->where('account_id', $account->id)->first(); + if (null === $transaction) { + return null; + } + + return strval($transaction->amount); + } + + /** + * Return date of opening balance as string or null. + * + * @param Account $account + * + * @return null|string + */ + public function getOpeningBalanceDate(Account $account): ?string + { + $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); + if (null === $journal) { + return null; + } + + return $journal->date->format('Y-m-d'); + } + /** * Returns the date of the very last transaction in this account. * @@ -184,54 +228,32 @@ class AccountRepository implements AccountRepositoryInterface * @param array $data * * @return Account - * * @throws FireflyException + * @throws Exception */ public function store(array $data): Account { - $newAccount = $this->storeAccount($data); - $this->updateMetadata($newAccount, $data); + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($this->user); + $account = $factory->create($data); - if ($this->validOpeningBalanceData($data)) { - $this->updateInitialBalance($newAccount, $data); - - return $newAccount; - } - $this->deleteInitialBalance($newAccount); - - // update note: - if (isset($data['notes'])) { - $this->updateNote($newAccount, $data['notes']); - } - - return $newAccount; + return $account; } /** * @param Account $account * @param array $data * + * @throws FireflyException + * @throws Exception * @return Account */ public function update(Account $account, array $data): Account { - // update the account: - $account->name = $data['name']; - $account->active = $data['active']; - $account->virtual_balance = trim($data['virtualBalance']) === '' ? '0' : $data['virtualBalance']; - $account->iban = $data['iban']; - $account->save(); - - $this->updateMetadata($account, $data); - if ($this->validOpeningBalanceData($data)) { - $this->updateInitialBalance($account, $data); - } - - // update note: - if (isset($data['notes']) && null !== $data['notes']) { - $this->updateNote($account, strval($data['notes'])); - } - + /** @var AccountUpdateService $service */ + $service = app(AccountUpdateService::class); + $account = $service->update($account, $data); return $account; } @@ -241,465 +263,16 @@ class AccountRepository implements AccountRepositoryInterface * @param array $data * * @return TransactionJournal + * @throws FireflyException + * @throws Exception */ public function updateReconciliation(TransactionJournal $journal, array $data): TransactionJournal { - // update journal - // update actual journal: - $data['amount'] = strval($data['amount']); - - // unlink all categories, recreate them: - $journal->categories()->detach(); - - $this->storeCategoryWithJournal($journal, strval($data['category'])); - - // update amounts - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - $transaction->amount = bcmul($data['amount'], '-1'); - if (AccountType::ASSET === $transaction->account->accountType->type) { - $transaction->amount = $data['amount']; - } - $transaction->save(); - } - - $journal->save(); - - // update tags: - if (isset($data['tags']) && is_array($data['tags'])) { - $this->updateTags($journal, $data['tags']); - } + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); + $journal = $service->update($journal, $data); return $journal; } - /** - * @param Account $account - * - * @throws \Exception - */ - protected function deleteInitialBalance(Account $account) - { - $journal = $this->openingBalanceTransaction($account); - if (null !== $journal->id) { - $journal->delete(); - } - } - - /** - * @param Account $account - * - * @return TransactionJournal|null - */ - protected function openingBalanceTransaction(Account $account): TransactionJournal - { - $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); - if (null === $journal) { - Log::debug('Could not find a opening balance journal, return empty one.'); - - return new TransactionJournal; - } - Log::debug(sprintf('Found opening balance: journal #%d.', $journal->id)); - - return $journal; - } - - /** - * @param array $data - * - * @return Account - * - * @throws FireflyException - */ - protected function storeAccount(array $data): Account - { - $data['accountType'] = $data['accountType'] ?? 'invalid'; - $type = config('firefly.accountTypeByIdentifier.' . $data['accountType']); - $accountType = AccountType::whereType($type)->first(); - $data['iban'] = $this->filterIban($data['iban']); - // verify account type - if (null === $accountType) { - throw new FireflyException(sprintf('Account type "%s" is invalid. Cannot create account.', $data['accountType'])); - } - - // account may exist already: - $existingAccount = $this->findByName($data['name'], [$type]); - if (null !== $existingAccount->id) { - Log::warning(sprintf('There already is an account named "%s" of type "%s".', $data['name'], $type)); - - return $existingAccount; - } - - // create it: - $databaseData - = [ - 'user_id' => $this->user->id, - 'account_type_id' => $accountType->id, - 'name' => $data['name'], - 'virtual_balance' => strlen(strval($data['virtualBalance'])) === 0 ? '0' : $data['virtualBalance'], - 'active' => true === $data['active'] ? true : false, - 'iban' => $data['iban'], - ]; - $newAccount = new Account($databaseData); - Log::debug('Final account creation dataset', $databaseData); - $newAccount->save(); - // verify its creation: - if (null === $newAccount->id) { - Log::error( - sprintf('Could not create account "%s" (%d error(s))', $data['name'], $newAccount->getErrors()->count()), - $newAccount->getErrors()->toArray() - ); - throw new FireflyException(sprintf('Tried to create account named "%s" but failed. The logs have more details.', $data['name'])); - } - Log::debug(sprintf('Created new account #%d named "%s" of type %s.', $newAccount->id, $newAccount->name, $accountType->type)); - - return $newAccount; - } - - /** - * @param TransactionJournal $journal - * @param string $category - */ - protected function storeCategoryWithJournal(TransactionJournal $journal, string $category) - { - if (strlen($category) > 0) { - $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); - $journal->categories()->save($category); - } - } - - /** - * At this point strlen of amount > 0. - * - * @param Account $account - * @param array $data - * - * @return TransactionJournal - */ - protected function storeInitialBalance(Account $account, array $data): TransactionJournal - { - $amount = strval($data['openingBalance']); - Log::debug(sprintf('Submitted amount is %s', $amount)); - - if (0 === bccomp($amount, '0')) { - return new TransactionJournal; - } - - $name = $data['name']; - $currencyId = $data['currency_id']; - $opposing = $this->storeOpposingAccount($name); - $transactionType = TransactionType::whereType(TransactionType::OPENING_BALANCE)->first(); - /** @var TransactionJournal $journal */ - $journal = TransactionJournal::create( - [ - 'user_id' => $this->user->id, - 'transaction_type_id' => $transactionType->id, - 'transaction_currency_id' => $currencyId, - 'description' => strval(trans('firefly.initial_balance_description', ['account' => $account->name])), - 'completed' => true, - 'date' => $data['openingBalanceDate'], - ] - ); - Log::notice(sprintf('Created new opening balance journal: #%d', $journal->id)); - - $firstAccount = $account; - $secondAccount = $opposing; - $firstAmount = $amount; - $secondAmount = bcmul($amount, '-1'); - Log::notice(sprintf('First amount is %s, second amount is %s', $firstAmount, $secondAmount)); - - if (bccomp($amount, '0') === -1) { - Log::debug(sprintf('%s is a negative number.', $amount)); - $firstAccount = $opposing; - $secondAccount = $account; - $firstAmount = bcmul($amount, '-1'); - $secondAmount = $amount; - Log::notice(sprintf('First amount is %s, second amount is %s', $firstAmount, $secondAmount)); - } - - $one = new Transaction( - [ - 'account_id' => $firstAccount->id, - 'transaction_journal_id' => $journal->id, - 'amount' => $firstAmount, - 'transaction_currency_id' => $currencyId, - ] - ); - $one->save(); // first transaction: from - - $two = new Transaction( - [ - 'account_id' => $secondAccount->id, - 'transaction_journal_id' => $journal->id, - 'amount' => $secondAmount, - 'transaction_currency_id' => $currencyId,] - ); - $two->save(); // second transaction: to - - Log::notice(sprintf('Stored two transactions for new account, #%d and #%d', $one->id, $two->id)); - - return $journal; - } - - /** - * @param string $name - * - * @return Account - * - * @throws FireflyException - */ - protected function storeOpposingAccount(string $name): Account - { - $opposingData = [ - 'accountType' => 'initial', - 'name' => $name . ' initial balance', - 'active' => false, - 'iban' => '', - 'virtualBalance' => '0', - ]; - Log::debug('Going to create an opening balance opposing account.'); - - return $this->storeAccount($opposingData); - } - - /** - * @param Account $account - * @param array $data - * - * @return bool - */ - protected function updateInitialBalance(Account $account, array $data): bool - { - Log::debug(sprintf('updateInitialBalance() for account #%d', $account->id)); - $openingBalance = $this->openingBalanceTransaction($account); - - // no opening balance journal? create it: - if (null === $openingBalance->id) { - Log::debug('No opening balance journal yet, create journal.'); - $this->storeInitialBalance($account, $data); - - return true; - } - // opening balance data? update it! - if (null !== $openingBalance->id) { - Log::debug('Opening balance journal found, update journal.'); - $this->updateOpeningBalanceJournal($account, $openingBalance, $data); - - return true; - } - - return true; - } - - /** - * @param Account $account - * @param array $data - */ - protected function updateMetadata(Account $account, array $data) - { - foreach ($this->validFields as $field) { - /** @var AccountMeta $entry */ - $entry = $account->accountMeta()->where('name', $field)->first(); - - // if $data has field and $entry is null, create new one: - if (isset($data[$field]) && null === $entry) { - Log::debug( - sprintf( - 'Created meta-field "%s":"%s" for account #%d ("%s") ', - $field, - $data[$field], - $account->id, - $account->name - ) - ); - AccountMeta::create( - [ - 'account_id' => $account->id, - 'name' => $field, - 'data' => $data[$field], - ] - ); - } - - // if $data has field and $entry is not null, update $entry: - if (isset($data[$field]) && null !== $entry) { - $entry->data = $data[$field]; - $entry->save(); - Log::debug( - sprintf( - 'Updated meta-field "%s":"%s" for account #%d ("%s") ', - $field, - $data[$field], - $account->id, - $account->name - ) - ); - } - } - } - - /** - * @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 - * @param array $data - * - * @return bool - * - * @throws \Exception - */ - protected function updateOpeningBalanceJournal(Account $account, TransactionJournal $journal, array $data): bool - { - $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)); - - if (0 === bccomp($amount, '0')) { - Log::notice(sprintf('Amount "%s" is zero, delete opening balance.', $amount)); - $journal->delete(); - - return true; - } - - // update date: - $journal->date = $date; - $journal->transaction_currency_id = $currencyId; - $journal->save(); - - // update transactions: - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - 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 (!(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(); - } - } - Log::debug('Updated opening balance journal.'); - - return true; - } - - /** - * @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; - } - - /** - * @param array $data - * - * @return bool - */ - protected function validOpeningBalanceData(array $data): bool - { - $data['openingBalance'] = strval($data['openingBalance'] ?? ''); - if (isset($data['openingBalance']) && null !== $data['openingBalance'] && strlen($data['openingBalance']) > 0 - && isset($data['openingBalanceDate'])) { - Log::debug('Array has valid opening balance data.'); - - return true; - } - Log::debug('Array does not have valid opening balance data.'); - - return false; - } - - /** - * @param null|string $iban - * - * @return null|string - */ - private function filterIban(?string $iban) - { - if (null === $iban) { - return null; - } - $data = ['iban' => $iban]; - $rules = ['iban' => 'required|iban']; - $validator = Validator::make($data, $rules); - if ($validator->fails()) { - Log::error(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban)); - - return null; - } - - - return $iban; - } } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index eb5e70fe0a..70b74070b5 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -48,15 +48,16 @@ interface AccountRepositoryInterface * Moved here from account CRUD. * * @param Account $account - * @param Account $moveTo + * @param Account|null $moveTo * * @return bool */ - public function destroy(Account $account, Account $moveTo): bool; + public function destroy(Account $account, ?Account $moveTo): bool; /** * @param int $accountId * + * @deprecated * @return Account */ public function find(int $accountId): Account; @@ -81,9 +82,16 @@ interface AccountRepositoryInterface * @param string $name * @param array $types * - * @return Account + * @return Account|null */ - public function findByName(string $name, array $types): Account; + public function findByName(string $name, array $types): ?Account; + + /** + * @param int $accountId + * + * @return Account|null + */ + public function findNull(int $accountId): ?Account; /** * Return account type by string. @@ -127,6 +135,25 @@ interface AccountRepositoryInterface */ public function getNote(Account $account): ?Note; + /** + * Returns the amount of the opening balance for this account. + * + * @param Account $account + * + * @return string + */ + public function getOpeningBalanceAmount(Account $account): ?string; + + + /** + * Return date of opening balance as string or null. + * + * @param Account $account + * + * @return null|string + */ + public function getOpeningBalanceDate(Account $account): ?string; + /** * Find or create the opposing reconciliation account. * diff --git a/app/Repositories/Account/FindAccountsTrait.php b/app/Repositories/Account/FindAccountsTrait.php index 8214dd1157..dca6580210 100644 --- a/app/Repositories/Account/FindAccountsTrait.php +++ b/app/Repositories/Account/FindAccountsTrait.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Account; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Factory\AccountFactory; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\User; @@ -44,6 +45,7 @@ trait FindAccountsTrait */ public function find(int $accountId): Account { + /** @var Account $account */ $account = $this->user->accounts()->find($accountId); if (null === $account) { return new Account; @@ -56,6 +58,7 @@ trait FindAccountsTrait * @param string $number * @param array $types * + * @deprecated * @return Account */ public function findByAccountNumber(string $number, array $types): Account @@ -83,6 +86,7 @@ trait FindAccountsTrait * @param string $iban * @param array $types * + * @deprecated * @return Account */ public function findByIban(string $iban, array $types): Account @@ -109,9 +113,9 @@ trait FindAccountsTrait * @param string $name * @param array $types * - * @return Account + * @return Account|null */ - public function findByName(string $name, array $types): Account + public function findByName(string $name, array $types): ?Account { $query = $this->user->accounts(); @@ -132,7 +136,7 @@ trait FindAccountsTrait } Log::debug(sprintf('There is no account with name "%s" or types', $name), $types); - return new Account; + return null; } /** @@ -213,15 +217,15 @@ trait FindAccountsTrait * @return Account * * @throws FireflyException + * @throws \Exception */ public function getCashAccount(): Account { - $type = AccountType::where('type', AccountType::CASH)->first(); - $account = Account::firstOrCreateEncrypted( - ['user_id' => $this->user->id, 'account_type_id' => $type->id, 'name' => 'Cash account'] - ); - $account->active = true; - $account->save(); + $type = AccountType::where('type', AccountType::CASH)->first(); + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($this->user); + $account = $factory->findOrCreate('Cash account', $type->type); return $account; } @@ -232,6 +236,7 @@ trait FindAccountsTrait * @return Account|null * * @throws FireflyException + * @throws \Exception */ public function getReconciliation(Account $account): ?Account { @@ -247,23 +252,12 @@ trait FindAccountsTrait return $account; } } - // assume nothing was found. create it! - $data = [ - 'accountType' => 'reconcile', - 'name' => $name, - 'iban' => null, - 'virtualBalance' => '0', - 'active' => true, - ]; - $account = $this->storeAccount($data); + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($account->user); + $account = $factory->findOrCreate($name, $type->type); return $account; } - /** - * @param array $data - * - * @return Account - */ - abstract protected function storeAccount(array $data): Account; } diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 00fe9f70e3..62513a643c 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -24,17 +24,20 @@ namespace FireflyIII\Repositories\Bill; use Carbon\Carbon; use DB; +use FireflyIII\Factory\BillFactory; use FireflyIII\Models\Bill; -use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Services\Internal\Destroy\BillDestroyService; +use FireflyIII\Services\Internal\Update\BillUpdateService; use FireflyIII\Support\CacheProperties; use FireflyIII\User; use Illuminate\Database\Query\JoinClause; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; -use Navigation; /** * Class BillRepository. @@ -53,7 +56,9 @@ class BillRepository implements BillRepositoryInterface */ public function destroy(Bill $bill): bool { - $bill->delete(); + /** @var BillDestroyService $service */ + $service = app(BillDestroyService::class); + $service->destroy($bill); return true; } @@ -65,14 +70,12 @@ class BillRepository implements BillRepositoryInterface * * @return Bill */ - public function find(int $billId): Bill + public function find(int $billId): ?Bill { - $bill = $this->user->bills()->find($billId); - if (null === $bill) { - $bill = new Bill; - } + /** @var Bill $res */ + $res = $this->user->bills()->find($billId); - return $bill; + return $res; } /** @@ -82,7 +85,7 @@ class BillRepository implements BillRepositoryInterface * * @return Bill */ - public function findByName(string $name): Bill + public function findByName(string $name): ?Bill { $bills = $this->user->bills()->get(['bills.*']); @@ -93,7 +96,7 @@ class BillRepository implements BillRepositoryInterface } } - return new Bill; + return null; } /** @@ -104,12 +107,8 @@ class BillRepository implements BillRepositoryInterface /** @var Collection $set */ $set = $this->user->bills() ->where('active', 1) - ->get( - [ - 'bills.*', - DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'), - ] - )->sortBy('name'); + ->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]) + ->sortBy('name'); return $set; } @@ -222,6 +221,7 @@ class BillRepository implements BillRepositoryInterface * @param Carbon $end * * @return string + * @throws \FireflyIII\Exceptions\FireflyException */ public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string { @@ -254,12 +254,15 @@ class BillRepository implements BillRepositoryInterface */ public function getOverallAverage(Bill $bill): string { + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($this->user); $journals = $bill->transactionJournals()->get(); $sum = '0'; $count = strval($journals->count()); /** @var TransactionJournal $journal */ foreach ($journals as $journal) { - $sum = bcadd($sum, $journal->amountPositive()); + $sum = bcadd($sum, $repos->getJournalTotal($journal)); } $avg = '0'; if ($journals->count() > 0) { @@ -269,6 +272,16 @@ class BillRepository implements BillRepositoryInterface return $avg; } + /** + * @param int $size + * + * @return LengthAwarePaginator + */ + public function getPaginator(int $size): LengthAwarePaginator + { + return $this->user->bills()->paginate($size); + } + /** * The "paid dates" list is a list of dates of transaction journals that are linked to this bill. * @@ -293,6 +306,7 @@ class BillRepository implements BillRepositoryInterface * @param Carbon $end * * @return Collection + * @throws \FireflyIII\Exceptions\FireflyException */ public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection { @@ -366,15 +380,19 @@ class BillRepository implements BillRepositoryInterface */ public function getYearAverage(Bill $bill, Carbon $date): string { + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($this->user); + $journals = $bill->transactionJournals() - ->where('date', '>=', $date->year . '-01-01') - ->where('date', '<=', $date->year . '-12-31') + ->where('date', '>=', $date->year . '-01-01 00:00:00') + ->where('date', '<=', $date->year . '-12-31 23:59:59') ->get(); $sum = '0'; $count = strval($journals->count()); /** @var TransactionJournal $journal */ foreach ($journals as $journal) { - $sum = bcadd($sum, $journal->amountPositive()); + $sum = bcadd($sum, $repos->getJournalTotal($journal)); } $avg = '0'; if ($journals->count() > 0) { @@ -392,9 +410,6 @@ class BillRepository implements BillRepositoryInterface * @param Carbon $date * * @return \Carbon\Carbon - * - * @throws \FireflyIII\Support\Facades\FireflyException - * @throws \FireflyIII\Support\Facades\FireflyException */ public function nextDateMatch(Bill $bill, Carbon $date): Carbon { @@ -411,11 +426,11 @@ class BillRepository implements BillRepositoryInterface while ($start < $date) { Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d'), $date->format('Y-m-d'))); - $start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); Log::debug('Start is now ' . $start->format('Y-m-d')); } - $end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); Log::debug('nextDateMatch: Final start is ' . $start->format('Y-m-d')); Log::debug('nextDateMatch: Matching end is ' . $end->format('Y-m-d')); @@ -432,10 +447,6 @@ class BillRepository implements BillRepositoryInterface * @param Carbon $date * * @return Carbon - * - * @throws \FireflyIII\Support\Facades\FireflyException - * @throws \FireflyIII\Support\Facades\FireflyException - * @throws \FireflyIII\Support\Facades\FireflyException */ public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon { @@ -452,11 +463,11 @@ class BillRepository implements BillRepositoryInterface while ($start < $date) { Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d'), $date->format('Y-m-d'))); - $start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); Log::debug('Start is now ' . $start->format('Y-m-d')); } - $end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); // see if the bill was paid in this period. $journalCount = $bill->transactionJournals()->before($end)->after($start)->count(); @@ -465,7 +476,7 @@ class BillRepository implements BillRepositoryInterface // this period had in fact a bill. The new start is the current end, and we create a new end. Log::debug(sprintf('Journal count is %d, so start becomes %s', $journalCount, $end->format('Y-m-d'))); $start = clone $end; - $end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip); + $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); } Log::debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d')); Log::debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d')); @@ -476,9 +487,12 @@ class BillRepository implements BillRepositoryInterface } /** + * TODO move to a service. + * * @param Bill $bill * @param TransactionJournal $journal * + * @deprecated * @return bool */ public function scan(Bill $bill, TransactionJournal $journal): bool @@ -487,15 +501,20 @@ class BillRepository implements BillRepositoryInterface if (false === $journal->isWithdrawal()) { return false; } - $destinationAccounts = $journal->destinationAccountList(); - $sourceAccounts = $journal->sourceAccountList(); + + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($this->user); + + $destinationAccounts = $repos->getJournalDestinationAccounts($journal); + $sourceAccounts = $repos->getJournalDestinationAccounts($journal); $matches = explode(',', $bill->match); $description = strtolower($journal->description) . ' '; $description .= strtolower(join(' ', $destinationAccounts->pluck('name')->toArray())); $description .= strtolower(join(' ', $sourceAccounts->pluck('name')->toArray())); $wordMatch = $this->doWordMatch($matches, $description); - $amountMatch = $this->doAmountMatch($journal->amountPositive(), $bill->amount_min, $bill->amount_max); + $amountMatch = $this->doAmountMatch($repos->getJournalTotal($journal), $bill->amount_min, $bill->amount_max); // when both, update! if ($wordMatch && $amountMatch) { @@ -530,26 +549,11 @@ class BillRepository implements BillRepositoryInterface */ public function store(array $data): Bill { - /** @var Bill $bill */ - $bill = Bill::create( - [ - 'name' => $data['name'], - 'match' => $data['match'], - 'amount_min' => $data['amount_min'], - 'user_id' => $this->user->id, - 'amount_max' => $data['amount_max'], - 'date' => $data['date'], - 'repeat_freq' => $data['repeat_freq'], - 'skip' => $data['skip'], - 'automatch' => $data['automatch'], - 'active' => $data['active'], - ] - ); + /** @var BillFactory $factory */ + $factory = app(BillFactory::class); + $factory->setUser($this->user); + $bill = $factory->create($data); - // update note: - if (isset($data['notes'])) { - $this->updateNote($bill, $data['notes']); - } return $bill; } @@ -562,26 +566,15 @@ class BillRepository implements BillRepositoryInterface */ public function update(Bill $bill, array $data): Bill { - $bill->name = $data['name']; - $bill->match = $data['match']; - $bill->amount_min = $data['amount_min']; - $bill->amount_max = $data['amount_max']; - $bill->date = $data['date']; - $bill->repeat_freq = $data['repeat_freq']; - $bill->skip = $data['skip']; - $bill->automatch = $data['automatch']; - $bill->active = $data['active']; - $bill->save(); + /** @var BillUpdateService $service */ + $service = app(BillUpdateService::class); - // update note: - if (isset($data['notes']) && null !== $data['notes']) { - $this->updateNote($bill, strval($data['notes'])); - } - - return $bill; + return $service->update($bill, $data); } /** + * TODO refactor + * * @param float $amount * @param float $min * @param float $max @@ -598,6 +591,8 @@ class BillRepository implements BillRepositoryInterface } /** + * TODO refactor + * * @param array $matches * @param $description * @@ -618,31 +613,4 @@ class BillRepository implements BillRepositoryInterface return $wordMatch; } - - /** - * @param Bill $bill - * @param string $note - * - * @return bool - */ - protected function updateNote(Bill $bill, string $note): bool - { - if (0 === strlen($note)) { - $dbNote = $bill->notes()->first(); - if (null !== $dbNote) { - $dbNote->delete(); - } - - return true; - } - $dbNote = $bill->notes()->first(); - if (null === $dbNote) { - $dbNote = new Note(); - $dbNote->noteable()->associate($bill); - } - $dbNote->text = trim($note); - $dbNote->save(); - - return true; - } } diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 3a99b0fc62..1530dab099 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use FireflyIII\Models\Bill; use FireflyIII\Models\TransactionJournal; use FireflyIII\User; +use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; /** @@ -33,6 +34,7 @@ use Illuminate\Support\Collection; */ interface BillRepositoryInterface { + /** * @param Bill $bill * @@ -45,18 +47,18 @@ interface BillRepositoryInterface * * @param int $billId * - * @return Bill + * @return Bill|null */ - public function find(int $billId): Bill; + public function find(int $billId): ?Bill; /** * Find a bill by name. * * @param string $name * - * @return Bill + * @return Bill|null */ - public function findByName(string $name): Bill; + public function findByName(string $name): ?Bill; /** * @return Collection @@ -104,6 +106,13 @@ interface BillRepositoryInterface */ public function getOverallAverage(Bill $bill): string; + /** + * @param int $size + * + * @return LengthAwarePaginator + */ + public function getPaginator(int $size): LengthAwarePaginator; + /** * @param Bill $bill * @param Carbon $start diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index e448182f7e..98e91fc5af 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; -use DB; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\AccountType; use FireflyIII\Models\AvailableBudget; @@ -60,19 +59,17 @@ class BudgetRepository implements BudgetRepositoryInterface // delete limits with amount 0: BudgetLimit::where('amount', 0)->delete(); - // clean up: - $set = BudgetLimit::groupBy(['budget_id', 'start_date', 'end_date']) - ->get(['budget_id', 'start_date', 'end_date', DB::raw('COUNT(*) as ct')]); - foreach ($set as $entry) { - if ($entry->ct > 1) { - $newest = BudgetLimit::where('start_date', $entry->start_date)->where('end_date', $entry->end_date) - ->where('budget_id', $entry->budget_id)->orderBy('updated_at', 'DESC')->first(['budget_limits.*']); - if (!is_null($newest)) { - BudgetLimit::where('start_date', $entry->start_date)->where('end_date', $entry->end_date) - ->where('budget_id', $entry->budget_id) - ->where('id', '!=', $newest->id)->delete(); - } + // do the clean up by hand because Sqlite can be tricky with this. + $budgetLimits = BudgetLimit::orderBy('created_at', 'DESC')->get(['id', 'budget_id', 'start_date', 'end_date']); + $count = []; + /** @var BudgetLimit $budgetLimit */ + foreach ($budgetLimits as $budgetLimit) { + $key = $budgetLimit->budget_id . '-' . $budgetLimit->start_date->format('Y-m-d') . $budgetLimit->end_date->format('Y-m-d'); + if (isset($count[$key])) { + // delete it! + BudgetLimit::find($budgetLimit->id)->delete(); } + $count[$key] = true; } return true; @@ -194,9 +191,9 @@ class BudgetRepository implements BudgetRepositoryInterface * * @param string $name * - * @return Budget + * @return Budget|null */ - public function findByName(string $name): Budget + public function findByName(string $name): ?Budget { $budgets = $this->user->budgets()->get(['budgets.*']); /** @var Budget $budget */ @@ -206,7 +203,19 @@ class BudgetRepository implements BudgetRepositoryInterface } } - return new Budget; + return null; + } + + /** + * Find a budget or return NULL + * + * @param int $budgetId + * + * @return Budget|null + */ + public function findNull(int $budgetId): ?Budget + { + return $this->user->budgets()->find($budgetId); } /** @@ -489,8 +498,8 @@ class BudgetRepository implements BudgetRepositoryInterface $availableBudget = new AvailableBudget; $availableBudget->user()->associate($this->user); $availableBudget->transactionCurrency()->associate($currency); - $availableBudget->start_date = $start; - $availableBudget->end_date = $end; + $availableBudget->start_date = $start->format('Y-m-d 00:00:00'); + $availableBudget->end_date = $end->format('Y-m-d 00:00:00'); } $availableBudget->amount = $amount; $availableBudget->save(); @@ -617,25 +626,26 @@ class BudgetRepository implements BudgetRepositoryInterface */ public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): BudgetLimit { + $this->cleanupBudgets(); // count the limits: $limits = $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d')) - ->where('budget_limits.end_date', $end->format('Y-m-d')) + ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) + ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) ->get(['budget_limits.*'])->count(); Log::debug(sprintf('Found %d budget limits.', $limits)); // there might be a budget limit for these dates: /** @var BudgetLimit $limit */ $limit = $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d')) - ->where('budget_limits.end_date', $end->format('Y-m-d')) + ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) + ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) ->first(['budget_limits.*']); // if more than 1 limit found, delete the others: if ($limits > 1 && null !== $limit) { Log::debug(sprintf('Found more than 1, delete all except #%d', $limit->id)); $budget->budgetlimits() - ->where('budget_limits.start_date', $start->format('Y-m-d')) - ->where('budget_limits.end_date', $end->format('Y-m-d')) + ->where('budget_limits.start_date', $start->format('Y-m-d 00:00:00')) + ->where('budget_limits.end_date', $end->format('Y-m-d 00:00:00')) ->where('budget_limits.id', '!=', $limit->id)->delete(); } @@ -660,8 +670,8 @@ class BudgetRepository implements BudgetRepositoryInterface // or create one and return it. $limit = new BudgetLimit; $limit->budget()->associate($budget); - $limit->start_date = $start; - $limit->end_date = $end; + $limit->start_date = $start->format('Y-m-d 00:00:00'); + $limit->end_date = $end->format('Y-m-d 00:00:00'); $limit->amount = $amount; $limit->save(); Log::debug(sprintf('Created new budget limit with ID #%d and amount %s', $limit->id, $amount)); diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 1563d2080d..1a6ca75625 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -73,19 +73,29 @@ interface BudgetRepositoryInterface * Find a budget. * * @param int $budgetId + * @deprecated * * @return Budget */ public function find(int $budgetId): Budget; + /** + * Find a budget or return NULL + * + * @param int $budgetId + * + * @return Budget|null + */ + public function findNull(int $budgetId): ?Budget; + /** * Find a budget. * * @param string $name * - * @return Budget + * @return Budget|null */ - public function findByName(string $name): Budget; + public function findByName(string $name): ?Budget; /** * This method returns the oldest journal or transaction date known to this budget. diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 03ad9d4308..c591141a8b 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -96,9 +96,9 @@ class CategoryRepository implements CategoryRepositoryInterface * * @param string $name * - * @return Category + * @return Category|null */ - public function findByName(string $name): Category + public function findByName(string $name): ?Category { $categories = $this->user->categories()->get(['categories.*']); foreach ($categories as $category) { @@ -107,7 +107,19 @@ class CategoryRepository implements CategoryRepositoryInterface } } - return new Category; + return null; + } + + /** + * Find a category or return NULL + * + * @param int $categoryId + * + * @return Category|null + */ + public function findNull(int $categoryId): ?Category + { + return $this->user->categories()->find($categoryId); } /** diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index 5aa9c0278c..84e3f1d922 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -53,11 +53,20 @@ interface CategoryRepositoryInterface * Find a category. * * @param int $categoryId - * + * @deprecated * @return Category */ public function find(int $categoryId): Category; + /** + * Find a category or return NULL + * + * @param int $categoryId + * + * @return Category|null + */ + public function findNull(int $categoryId): ?Category; + /** * Find a category. * @@ -65,7 +74,7 @@ interface CategoryRepositoryInterface * * @return Category */ - public function findByName(string $name): Category; + public function findByName(string $name): ?Category; /** * @param Category $category diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 2dbff1614e..37af7d2f9b 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -39,6 +39,13 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** @var User */ private $user; + /** + * CurrencyRepository constructor. + */ + public function __construct() + { + } + /** * @param TransactionCurrency $currency * @@ -129,6 +136,18 @@ class CurrencyRepository implements CurrencyRepositoryInterface return $currency; } + /** + * Find by currency code, return NULL if unfound. + * + * @param string $currencyCode + * + * @return TransactionCurrency|null + */ + public function findByCodeNull(string $currencyCode): ?TransactionCurrency + { + return TransactionCurrency::where('code', $currencyCode)->first(); + } + /** * Find by currency name. * @@ -163,6 +182,21 @@ class CurrencyRepository implements CurrencyRepositoryInterface return $currency; } + /** + * Find by ID, return NULL if not found. + * + * @param int $currencyId + * + * @return TransactionCurrency|null + */ + public function findNull(int $currencyId): ?TransactionCurrency + { + /** @var TransactionCurrency $res */ + $res = TransactionCurrency::find($currencyId); + + return $res; + } + /** * @return Collection */ diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index e7d2d66eb3..60df5cf396 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -60,6 +60,7 @@ interface CurrencyRepositoryInterface * * @param int $currencyId * + * @deprecated * @return TransactionCurrency */ public function find(int $currencyId): TransactionCurrency; @@ -67,12 +68,23 @@ interface CurrencyRepositoryInterface /** * Find by currency code. * + * @deprecated + * * @param string $currencyCode * * @return TransactionCurrency */ public function findByCode(string $currencyCode): TransactionCurrency; + /** + * Find by currency code, return NULL if unfound. + * + * @param string $currencyCode + * + * @return TransactionCurrency|null + */ + public function findByCodeNull(string $currencyCode): ?TransactionCurrency; + /** * Find by currency name. * @@ -91,6 +103,15 @@ interface CurrencyRepositoryInterface */ public function findBySymbol(string $currencySymbol): TransactionCurrency; + /** + * Find by ID, return NULL if not found. + * + * @param int $currencyId + * + * @return TransactionCurrency|null + */ + public function findNull(int $currencyId): ?TransactionCurrency; + /** * @return Collection */ diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index 722bb1b1f9..9eee6714e5 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -225,11 +225,17 @@ class ImportJobRepository implements ImportJobRepositoryInterface $configFileObject = new SplFileObject($file->getRealPath()); $configRaw = $configFileObject->fread($configFileObject->getSize()); $configuration = json_decode($configRaw, true); - + Log::debug(sprintf('Raw configuration is %s', $configRaw)); if (null !== $configuration && is_array($configuration)) { Log::debug('Found configuration', $configuration); $this->setConfiguration($job, $configuration); } + if (null === $configuration) { + Log::error('Uploaded configuration is NULL'); + } + if (false === $configuration) { + Log::error('Uploaded configuration is FALSE'); + } } return true; diff --git a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php index 2c0efe97f2..5bb3a905cb 100644 --- a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php +++ b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php @@ -133,7 +133,7 @@ interface ImportJobRepositoryInterface * @param ImportJob $job * @param array $array * - * @return void + * @return ImportJob */ public function setExtendedStatus(ImportJob $job, array $array): ImportJob; @@ -147,7 +147,7 @@ interface ImportJobRepositoryInterface /** * @param ImportJob $job - * @param int $count + * @param int $steps * * @return ImportJob */ diff --git a/app/Repositories/Journal/CreateJournalsTrait.php b/app/Repositories/Journal/CreateJournalsTrait.php deleted file mode 100644 index 897d145a1c..0000000000 --- a/app/Repositories/Journal/CreateJournalsTrait.php +++ /dev/null @@ -1,240 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Repositories\Journal; - -use FireflyIII\Models\Budget; -use FireflyIII\Models\Category; -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 Log; - -/** - * @property User $user - * - * Trait CreateJournalsTrait - */ -trait CreateJournalsTrait -{ - /** - * Store accounts found in parent class. - * - * @param User $user - * @param TransactionType $type - * @param array $data - * - * @return array - */ - abstract public function storeAccounts(User $user, TransactionType $type, array $data): array; - - /** - * * Remember: a balancingAct takes at most one expense and one transfer. - * an advancePayment takes at most one expense, infinite deposits and NO transfers. - * - * @param TransactionJournal $journal - * @param array $array - * - * @return bool - */ - protected function saveTags(TransactionJournal $journal, array $array): bool - { - /** @var TagRepositoryInterface $tagRepository */ - $tagRepository = app(TagRepositoryInterface::class); - - foreach ($array as $name) { - if (strlen(trim($name)) > 0) { - $tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]); - if (null !== $tag) { - Log::debug(sprintf('Will try to connect tag #%d to journal #%d.', $tag->id, $journal->id)); - $tagRepository->connect($journal, $tag); - } - } - } - - return true; - } - - /** - * Store a budget if found. - * - * @param Transaction $transaction - * @param int $budgetId - */ - protected function storeBudgetWithTransaction(Transaction $transaction, int $budgetId) - { - if (intval($budgetId) > 0 && TransactionType::TRANSFER !== $transaction->transactionJournal->transactionType->type) { - /** @var \FireflyIII\Models\Budget $budget */ - $budget = Budget::find($budgetId); - $transaction->budgets()->save($budget); - } - } - - /** - * Store category if found. - * - * @param Transaction $transaction - * @param string $category - */ - protected function storeCategoryWithTransaction(Transaction $transaction, string $category) - { - if (strlen($category) > 0) { - $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $transaction->transactionJournal->user_id]); - $transaction->categories()->save($category); - } - } - - /** - * The reference to storeAccounts() in this function is an indication of spagetti code but alas, - * I leave it as it is. - * - * @param TransactionJournal $journal - * @param array $transaction - * @param int $identifier - * - * @return Collection - */ - protected function storeSplitTransaction(TransactionJournal $journal, array $transaction, int $identifier): Collection - { - // store source and destination accounts (depends on type) - $accounts = $this->storeAccounts($this->user, $journal->transactionType, $transaction); - - // store transaction one way: - $amount = bcmul(strval($transaction['amount']), '-1'); - $foreignAmount = null === $transaction['foreign_amount'] ? null : bcmul(strval($transaction['foreign_amount']), '-1'); - $one = $this->storeTransaction( - [ - 'journal' => $journal, - 'account' => $accounts['source'], - 'amount' => $amount, - 'transaction_currency_id' => $transaction['transaction_currency_id'], - 'foreign_amount' => $foreignAmount, - 'foreign_currency_id' => $transaction['foreign_currency_id'], - 'description' => $transaction['description'], - 'category' => null, - 'budget' => null, - 'identifier' => $identifier, - ] - ); - $this->storeCategoryWithTransaction($one, $transaction['category']); - $this->storeBudgetWithTransaction($one, $transaction['budget_id']); - - // and the other way: - $amount = strval($transaction['amount']); - $foreignAmount = null === $transaction['foreign_amount'] ? null : strval($transaction['foreign_amount']); - $two = $this->storeTransaction( - [ - 'journal' => $journal, - 'account' => $accounts['destination'], - 'amount' => $amount, - 'transaction_currency_id' => $transaction['transaction_currency_id'], - 'foreign_amount' => $foreignAmount, - 'foreign_currency_id' => $transaction['foreign_currency_id'], - 'description' => $transaction['description'], - 'category' => null, - 'budget' => null, - 'identifier' => $identifier, - ] - ); - $this->storeCategoryWithTransaction($two, $transaction['category']); - $this->storeBudgetWithTransaction($two, $transaction['budget_id']); - - return new Collection([$one, $two]); - } - - /** - * Store a transaction. - * - * @param array $data - * - * @return Transaction - */ - protected function storeTransaction(array $data): Transaction - { - $fields = [ - 'transaction_journal_id' => $data['journal']->id, - 'account_id' => $data['account']->id, - 'amount' => $data['amount'], - 'foreign_amount' => $data['foreign_amount'], - 'transaction_currency_id' => $data['transaction_currency_id'], - 'foreign_currency_id' => $data['foreign_currency_id'], - 'description' => $data['description'], - 'identifier' => $data['identifier'], - ]; - - if (null === $data['foreign_currency_id']) { - unset($fields['foreign_currency_id']); - } - if (null === $data['foreign_amount']) { - unset($fields['foreign_amount']); - } - - /** @var Transaction $transaction */ - $transaction = Transaction::create($fields); - - Log::debug(sprintf('Transaction stored with ID: %s', $transaction->id)); - - if (null !== $data['category']) { - $transaction->categories()->save($data['category']); - } - - if (null !== $data['budget']) { - $transaction->categories()->save($data['budget']); - } - - return $transaction; - } - - /** - * Update note for journal. - * - * @param TransactionJournal $journal - * @param string $note - * - * @return bool - */ - protected function updateNote(TransactionJournal $journal, string $note): bool - { - if (0 === strlen($note)) { - $dbNote = $journal->notes()->first(); - if (null !== $dbNote) { - $dbNote->delete(); - } - - return true; - } - $dbNote = $journal->notes()->first(); - if (null === $dbNote) { - $dbNote = new Note(); - $dbNote->noteable()->associate($journal); - } - $dbNote->text = trim($note); - $dbNote->save(); - - return true; - } -} diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 7bf6bb78cd..d46576e4b7 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -22,15 +22,17 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; -use DB; +use Carbon\Carbon; +use FireflyIII\Factory\TransactionJournalFactory; 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\Services\Internal\Destroy\JournalDestroyService; +use FireflyIII\Services\Internal\Update\JournalUpdateService; +use FireflyIII\Support\CacheProperties; use FireflyIII\User; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; @@ -42,12 +44,8 @@ use Preferences; */ class JournalRepository implements JournalRepositoryInterface { - use CreateJournalsTrait, UpdateJournalsTrait, SupportJournalsTrait; - /** @var User */ private $user; - /** @var array */ - private $validMetaFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date', 'internal_reference']; /** * @param TransactionJournal $journal @@ -106,9 +104,11 @@ class JournalRepository implements JournalRepositoryInterface * * @throws \Exception */ - public function delete(TransactionJournal $journal): bool + public function destroy(TransactionJournal $journal): bool { - $journal->delete(); + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + $service->destroy($journal); return true; } @@ -120,6 +120,7 @@ class JournalRepository implements JournalRepositoryInterface */ public function find(int $journalId): TransactionJournal { + /** @var TransactionJournal $journal */ $journal = $this->user->transactionJournals()->where('id', $journalId)->first(); if (null === $journal) { return new TransactionJournal; @@ -167,6 +168,7 @@ class JournalRepository implements JournalRepositoryInterface */ public function first(): TransactionJournal { + /** @var TransactionJournal $entry */ $entry = $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']); if (null === $entry) { @@ -193,6 +195,208 @@ class JournalRepository implements JournalRepositoryInterface return null; } + /** + * Returns the first positive transaction for the journal. Useful when editing journals. + * + * @param TransactionJournal $journal + * + * @return Transaction + */ + public function getFirstPosTransaction(TransactionJournal $journal): Transaction + { + /** @var Transaction $transaction */ + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + + return $transaction; + } + + /** + * Return the ID of the budget linked to the journal (if any) or the transactions (if any). + * + * @param TransactionJournal $journal + * + * @return int + */ + public function getJournalBudgetId(TransactionJournal $journal): int + { + $budget = $journal->budgets()->first(); + if (null !== $budget) { + return $budget->id; + } + $budget = $journal->transactions()->first()->budgets()->first(); + if (null !== $budget) { + return $budget->id; + } + + return 0; + } + + /** + * Return the name of the category linked to the journal (if any) or to the transactions (if any). + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getJournalCategoryName(TransactionJournal $journal): string + { + $category = $journal->categories()->first(); + if (null !== $category) { + return $category->name; + } + $category = $journal->transactions()->first()->categories()->first(); + if (null !== $category) { + return $category->name; + } + + return ''; + } + + /** + * Return requested date as string. When it's a NULL return the date of journal, + * otherwise look for meta field and return that one. + * + * @param TransactionJournal $journal + * @param null|string $field + * + * @return string + */ + public function getJournalDate(TransactionJournal $journal, ?string $field): string + { + if (is_null($field)) { + return $journal->date->format('Y-m-d'); + } + if (null !== $journal->$field && $journal->$field instanceof Carbon) { + // make field NULL + $carbon = clone $journal->$field; + $journal->$field = null; + $journal->save(); + + // create meta entry + $journal->setMeta($field, $carbon); + + // return that one instead. + return $carbon->format('Y-m-d'); + } + $metaField = $journal->getMeta($field); + if (null !== $metaField) { + $carbon = new Carbon($metaField); + + return $carbon->format('Y-m-d'); + } + + return ''; + } + + /** + * Return a list of all destination accounts related to journal. + * + * @param TransactionJournal $journal + * + * @return Collection + */ + public function getJournalDestinationAccounts(TransactionJournal $journal): Collection + { + $cache = new CacheProperties; + $cache->addProperty($journal->id); + $cache->addProperty('destination-account-list'); + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + $transactions = $journal->transactions()->where('amount', '>', 0)->orderBy('transactions.account_id')->with('account')->get(); + $list = new Collection; + /** @var Transaction $t */ + foreach ($transactions as $t) { + $list->push($t->account); + } + $list = $list->unique('id'); + $cache->store($list); + + return $list; + } + + /** + * Return a list of all source accounts related to journal. + * + * @param TransactionJournal $journal + * + * @return Collection + */ + public function getJournalSourceAccounts(TransactionJournal $journal): Collection + { + $cache = new CacheProperties; + $cache->addProperty($journal->id); + $cache->addProperty('source-account-list'); + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + $transactions = $journal->transactions()->where('amount', '<', 0)->orderBy('transactions.account_id')->with('account')->get(); + $list = new Collection; + /** @var Transaction $t */ + foreach ($transactions as $t) { + $list->push($t->account); + } + $list = $list->unique('id'); + $cache->store($list); + + return $list; + } + + /** + * Return total amount of journal. Is always positive. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getJournalTotal(TransactionJournal $journal): string + { + $cache = new CacheProperties; + $cache->addProperty($journal->id); + $cache->addProperty('amount-positive'); + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + + // saves on queries: + $amount = $journal->transactions()->where('amount', '>', 0)->get()->sum('amount'); + $amount = strval($amount); + $cache->store($amount); + + return $amount; + } + + /** + * Return value of a meta field (or NULL) as a string. + * + * @param TransactionJournal $journal + * @param string $field + * + * @return null|string + */ + public function getMetaField(TransactionJournal $journal, string $field): ?string + { + $value = null; + $cache = new CacheProperties; + $cache->addProperty('journal-meta'); + $cache->addProperty($journal->id); + $cache->addProperty($field); + + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + + Log::debug(sprintf('Looking for journal #%d meta field "%s".', $journal->id, $field)); + $entry = $journal->transactionJournalMeta()->where('name', $field)->first(); + if (is_null($entry)) { + return null; + } + $value = $entry->data; + $cache->store($value); + + return $value; + } + /** * @param TransactionJournal $journal * @@ -203,6 +407,47 @@ class JournalRepository implements JournalRepositoryInterface return $journal->notes()->first(); } + /** + * Return text of a note attached to journal, or ''. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getNoteText(TransactionJournal $journal): string + { + $note = $this->getNote($journal); + if (is_null($note)) { + return ''; + } + + return $note->text; + } + + /** + * Return all tags as strings in an array. + * + * @param TransactionJournal $journal + * + * @return array + */ + public function getTags(TransactionJournal $journal): array + { + return $journal->tags()->get()->pluck('tag')->toArray(); + } + + /** + * Return the transaction type of the journal. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getTransactionType(TransactionJournal $journal): string + { + return $journal->transactionType->type; + } + /** * @return Collection */ @@ -229,13 +474,21 @@ class JournalRepository implements JournalRepositoryInterface } /** + * Will tell you if journal is reconciled or not. + * * @param TransactionJournal $journal * * @return bool */ - public function isTransfer(TransactionJournal $journal): bool + public function isJournalReconciled(TransactionJournal $journal): bool { - return TransactionType::TRANSFER === $journal->transactionType->type; + foreach ($journal->transactions as $transaction) { + if ($transaction->reconciled) { + return true; + } + } + + return false; } /** @@ -263,6 +516,22 @@ class JournalRepository implements JournalRepositoryInterface return true; } + /** + * @param int $transactionId + * + * @return bool + */ + public function reconcileById(int $transactionId): bool + { + /** @var Transaction $transaction */ + $transaction = $this->user->transactions()->find($transactionId); + if (!is_null($transaction)) { + return $this->reconcile($transaction); + } + + return false; + } + /** * @param TransactionJournal $journal * @param int $order @@ -295,81 +564,11 @@ class JournalRepository implements JournalRepositoryInterface */ public function store(array $data): TransactionJournal { - // find transaction type. - /** @var TransactionType $transactionType */ - $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); - $accounts = $this->storeAccounts($this->user, $transactionType, $data); - $data = $this->verifyNativeAmount($data, $accounts); - $amount = strval($data['amount']); - $journal = new TransactionJournal( - [ - 'user_id' => $this->user->id, - 'transaction_type_id' => $transactionType->id, - 'transaction_currency_id' => $data['currency_id'], // no longer used. - 'description' => $data['description'], - 'completed' => 0, - 'date' => $data['date'], - ] - ); - $journal->save(); + /** @var TransactionJournalFactory $factory */ + $factory = app(TransactionJournalFactory::class); + $factory->setUser($this->user); - // store stuff: - $this->storeCategoryWithJournal($journal, strval($data['category'])); - $this->storeBudgetWithJournal($journal, $data['budget_id']); - - // store two transactions: - - $one = [ - 'journal' => $journal, - 'account' => $accounts['source'], - 'amount' => bcmul($amount, '-1'), - 'transaction_currency_id' => $data['currency_id'], - 'foreign_amount' => null === $data['foreign_amount'] ? null : bcmul(strval($data['foreign_amount']), '-1'), - 'foreign_currency_id' => $data['foreign_currency_id'], - 'description' => null, - 'category' => null, - 'budget' => null, - 'identifier' => 0, - ]; - $this->storeTransaction($one); - - $two = [ - 'journal' => $journal, - 'account' => $accounts['destination'], - 'amount' => $amount, - 'transaction_currency_id' => $data['currency_id'], - 'foreign_amount' => $data['foreign_amount'], - 'foreign_currency_id' => $data['foreign_currency_id'], - 'description' => null, - 'category' => null, - 'budget' => null, - 'identifier' => 0, - ]; - - $this->storeTransaction($two); - - // store tags - if (isset($data['tags']) && is_array($data['tags'])) { - $this->saveTags($journal, $data['tags']); - } - - // update note: - if (isset($data['notes'])) { - $this->updateNote($journal, $data['notes']); - } - - foreach ($data as $key => $value) { - if (in_array($key, $this->validMetaFields)) { - $journal->setMeta($key, $value); - continue; - } - Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); - } - - $journal->completed = 1; - $journal->save(); - - return $journal; + return $factory->create($data); } /** @@ -379,63 +578,19 @@ class JournalRepository implements JournalRepositoryInterface * @return TransactionJournal * * @throws \FireflyIII\Exceptions\FireflyException - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \FireflyIII\Exceptions\FireflyException */ public function update(TransactionJournal $journal, array $data): TransactionJournal { - // update actual journal: - $journal->description = $data['description']; - $journal->date = $data['date']; - $accounts = $this->storeAccounts($this->user, $journal->transactionType, $data); - $data = $this->verifyNativeAmount($data, $accounts); - $data['amount'] = strval($data['amount']); - $data['foreign_amount'] = null === $data['foreign_amount'] ? null : strval($data['foreign_amount']); - - // unlink all categories, recreate them: - $journal->categories()->detach(); - $journal->budgets()->detach(); - - $this->storeCategoryWithJournal($journal, strval($data['category'])); - $this->storeBudgetWithJournal($journal, $data['budget_id']); - - // negative because source loses money. - $this->updateSourceTransaction($journal, $accounts['source'], $data); - - // positive because destination gets money. - $this->updateDestinationTransaction($journal, $accounts['destination'], $data); - - $journal->save(); - - // update tags: - if (isset($data['tags']) && is_array($data['tags'])) { - $this->updateTags($journal, $data['tags']); - } - - // update note: - if (isset($data['notes']) && null !== $data['notes']) { - $this->updateNote($journal, strval($data['notes'])); - } - - // update meta fields: - $result = $journal->save(); - if ($result) { - foreach ($data as $key => $value) { - if (in_array($key, $this->validMetaFields)) { - $journal->setMeta($key, $value); - continue; - } - Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); - } - - return $journal; - } + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); + $journal = $service->update($journal, $data); return $journal; } /** + * Update budget for a journal. + * * @param TransactionJournal $journal * @param int $budgetId * @@ -443,18 +598,15 @@ class JournalRepository implements JournalRepositoryInterface */ public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal { - if ($budgetId === 0) { - $journal->budgets()->detach(); - $journal->save(); + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); - return $journal; - } - $this->storeBudgetWithJournal($journal, $budgetId); - - return $journal; + return $service->updateBudget($journal, $budgetId); } /** + * Update category for a journal. + * * @param TransactionJournal $journal * @param string $category * @@ -462,118 +614,27 @@ class JournalRepository implements JournalRepositoryInterface */ 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); + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); - return $journal; + return $service->updateCategory($journal, $category); } /** - * Same as above but for transaction journal with multiple transactions. + * Update tag(s) for a journal. * * @param TransactionJournal $journal - * @param array $data + * @param array $tags * * @return TransactionJournal */ - public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal + public function updateTags(TransactionJournal $journal, array $tags): TransactionJournal { - // update actual journal: - $journal->description = $data['journal_description']; - $journal->date = $data['date']; - $journal->save(); - Log::debug(sprintf('Updated split journal #%d', $journal->id)); - - // unlink all categories: - $journal->categories()->detach(); - $journal->budgets()->detach(); - - // update note: - if (isset($data['notes']) && null !== $data['notes']) { - $this->updateNote($journal, strval($data['notes'])); - } - - // update meta fields: - $result = $journal->save(); - if ($result) { - foreach ($data as $key => $value) { - if (in_array($key, $this->validMetaFields)) { - $journal->setMeta($key, $value); - continue; - } - Log::debug(sprintf('Could not store meta field "%s" with value "%s" for journal #%d', json_encode($key), json_encode($value), $journal->id)); - } - } - - // update tags: - if (isset($data['tags']) && is_array($data['tags'])) { - $this->updateTags($journal, $data['tags']); - } - - // delete original transactions, and recreate them. - $journal->transactions()->delete(); - - // store each transaction. - $identifier = 0; - Log::debug(sprintf('Count %d transactions in updateSplitJournal()', count($data['transactions']))); - - foreach ($data['transactions'] as $transaction) { - Log::debug(sprintf('Split journal update split transaction %d', $identifier)); - $transaction = $this->appendTransactionData($transaction, $data); - $this->storeSplitTransaction($journal, $transaction, $identifier); - ++$identifier; - } - - $journal->save(); + /** @var JournalUpdateService $service */ + $service = app(JournalUpdateService::class); + $service->connectTags($journal, $tags); 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 5a99125173..3d71181414 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -60,7 +60,7 @@ interface JournalRepositoryInterface * * @return bool */ - public function delete(TransactionJournal $journal): bool; + public function destroy(TransactionJournal $journal): bool; /** * Find a specific journal. @@ -99,6 +99,81 @@ interface JournalRepositoryInterface */ public function getAssetTransaction(TransactionJournal $journal): ?Transaction; + /** + * Returns the first positive transaction for the journal. Useful when editing journals. + * + * @param TransactionJournal $journal + * + * @return Transaction + */ + public function getFirstPosTransaction(TransactionJournal $journal): Transaction; + + /** + * Return the ID of the budget linked to the journal (if any) or the transactions (if any). + * + * @param TransactionJournal $journal + * + * @return int + */ + public function getJournalBudgetId(TransactionJournal $journal): int; + + /** + * Return the name of the category linked to the journal (if any) or to the transactions (if any). + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getJournalCategoryName(TransactionJournal $journal): string; + + /** + * Return requested date as string. When it's a NULL return the date of journal, + * otherwise look for meta field and return that one. + * + * @param TransactionJournal $journal + * @param null|string $field + * + * @return string + */ + public function getJournalDate(TransactionJournal $journal, ?string $field): string; + + /** + * Return a list of all destination accounts related to journal. + * + * @param TransactionJournal $journal + * + * @return Collection + */ + public function getJournalDestinationAccounts(TransactionJournal $journal): Collection; + + /** + * Return a list of all source accounts related to journal. + * + * @param TransactionJournal $journal + * + * @return Collection + */ + public function getJournalSourceAccounts(TransactionJournal $journal): Collection; + + /** + * Return total amount of journal. Is always positive. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getJournalTotal(TransactionJournal $journal): string; + + /** + * Return value of a meta field (or NULL). + * + * @param TransactionJournal $journal + * @param string $field + * + * @return null|string + */ + public function getMetaField(TransactionJournal $journal, string $field): ?string; + /** * @param TransactionJournal $journal * @@ -106,6 +181,33 @@ interface JournalRepositoryInterface */ public function getNote(TransactionJournal $journal): ?Note; + /** + * Return text of a note attached to journal, or ''. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getNoteText(TransactionJournal $journal): string; + + /** + * Return all tags as strings in an array. + * + * @param TransactionJournal $journal + * + * @return array + */ + public function getTags(TransactionJournal $journal): array; + + /** + * Return the transaction type of the journal. + * + * @param TransactionJournal $journal + * + * @return string + */ + public function getTransactionType(TransactionJournal $journal): string; + /** * @return Collection */ @@ -119,11 +221,13 @@ interface JournalRepositoryInterface public function getTransactionsById(array $transactionIds): Collection; /** + * Will tell you if journal is reconciled or not. + * * @param TransactionJournal $journal * * @return bool */ - public function isTransfer(TransactionJournal $journal): bool; + public function isJournalReconciled(TransactionJournal $journal): bool; /** * @param Transaction $transaction @@ -132,6 +236,13 @@ interface JournalRepositoryInterface */ public function reconcile(Transaction $transaction): bool; + /** + * @param int $transactionId + * + * @return bool + */ + public function reconcileById(int $transactionId): bool; + /** * @param TransactionJournal $journal * @param int $order @@ -161,6 +272,8 @@ interface JournalRepositoryInterface public function update(TransactionJournal $journal, array $data): TransactionJournal; /** + * Update budget for a journal. + * * @param TransactionJournal $journal * @param int $budgetId * @@ -169,6 +282,8 @@ interface JournalRepositoryInterface public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal; /** + * Update category for a journal. + * * @param TransactionJournal $journal * @param string $category * @@ -177,18 +292,12 @@ interface JournalRepositoryInterface public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal; /** - * @param TransactionJournal $journal - * @param array $data + * Update tag(s) for a journal. * - * @return TransactionJournal - */ - public function updateSplitJournal(TransactionJournal $journal, array $data): TransactionJournal; - - /** * @param TransactionJournal $journal * @param array $tags * - * @return bool + * @return TransactionJournal */ - public function updateTags(TransactionJournal $journal, array $tags): bool; + public function updateTags(TransactionJournal $journal, array $tags): TransactionJournal; } diff --git a/app/Repositories/Journal/JournalTasker.php b/app/Repositories/Journal/JournalTasker.php index b51181fdf4..d360490e0f 100644 --- a/app/Repositories/Journal/JournalTasker.php +++ b/app/Repositories/Journal/JournalTasker.php @@ -42,6 +42,8 @@ class JournalTasker implements JournalTaskerInterface private $user; /** + * @deprecated + * * @param TransactionJournal $journal * * @return Collection @@ -65,6 +67,8 @@ class JournalTasker implements JournalTaskerInterface * * @param TransactionJournal $journal * + * @deprecated + * * @return array */ public function getTransactionsOverview(TransactionJournal $journal): array @@ -187,6 +191,8 @@ class JournalTasker implements JournalTaskerInterface * * @param int $transactionId * + * @deprecated + * @deprecated * @return string */ private function getBalance(int $transactionId): string diff --git a/app/Repositories/Journal/SupportJournalsTrait.php b/app/Repositories/Journal/SupportJournalsTrait.php deleted file mode 100644 index 5815cc8a4f..0000000000 --- a/app/Repositories/Journal/SupportJournalsTrait.php +++ /dev/null @@ -1,287 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Repositories\Journal; - -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; -use FireflyIII\Models\Budget; -use FireflyIII\Models\Category; -use FireflyIII\Models\TransactionJournal; -use FireflyIII\Models\TransactionType; -use FireflyIII\User; -use Log; - -/** - * Trait SupportJournalsTrait. - */ -trait SupportJournalsTrait -{ - /** - * @param User $user - * @param TransactionType $type - * @param array $data - * - * @return array - * - * @throws FireflyException - */ - protected function storeAccounts(User $user, TransactionType $type, array $data): array - { - $accounts = [ - 'source' => null, - 'destination' => null, - ]; - - Log::debug(sprintf('Going to store accounts for type %s', $type->type)); - switch ($type->type) { - case TransactionType::WITHDRAWAL: - $accounts = $this->storeWithdrawalAccounts($user, $data); - break; - - case TransactionType::DEPOSIT: - $accounts = $this->storeDepositAccounts($user, $data); - - break; - case TransactionType::TRANSFER: - $accounts['source'] = Account::where('user_id', $user->id)->where('id', $data['source_account_id'])->first(); - $accounts['destination'] = Account::where('user_id', $user->id)->where('id', $data['destination_account_id'])->first(); - break; - case TransactionType::RECONCILIATION: - $accounts['source'] = $data['source']; - $accounts['destination'] = $data['destination']; - unset($data['source'], $data['destination']); - break; - default: - throw new FireflyException(sprintf('Did not recognise transaction type "%s".', $type->type)); - } - - if (null === $accounts['source']) { - Log::error('"source"-account is null, so we cannot continue!', ['data' => $data]); - throw new FireflyException('"source"-account is null, so we cannot continue!'); - } - - if (null === $accounts['destination']) { - Log::error('"destination"-account is null, so we cannot continue!', ['data' => $data]); - throw new FireflyException('"destination"-account is null, so we cannot continue!'); - } - - return $accounts; - } - - /** - * @param TransactionJournal $journal - * @param int $budgetId - */ - protected function storeBudgetWithJournal(TransactionJournal $journal, int $budgetId) - { - if (intval($budgetId) > 0 && TransactionType::WITHDRAWAL === $journal->transactionType->type) { - /** @var \FireflyIII\Models\Budget $budget */ - $budget = Budget::find($budgetId); - $journal->budgets()->save($budget); - } - $journal->touch(); - } - - /** - * @param TransactionJournal $journal - * @param string $category - */ - protected function storeCategoryWithJournal(TransactionJournal $journal, string $category) - { - if (strlen($category) > 0) { - $category = Category::firstOrCreateEncrypted(['name' => $category, 'user_id' => $journal->user_id]); - $journal->categories()->save($category); - } - $journal->touch(); - } - - /** - * @param User $user - * @param array $data - * - * @return array - * - * @throws FireflyException - * @throws FireflyException - */ - protected function storeDepositAccounts(User $user, array $data): array - { - Log::debug('Now in storeDepositAccounts().'); - $destinationAccount = Account::where('user_id', $user->id)->where('id', $data['destination_account_id'])->first(['accounts.*']); - - Log::debug(sprintf('Destination account is #%d ("%s")', $destinationAccount->id, $destinationAccount->name)); - - if (strlen($data['source_account_name']) > 0) { - $sourceType = AccountType::where('type', 'Revenue account')->first(); - $sourceAccount = Account::firstOrCreateEncrypted( - ['user_id' => $user->id, 'account_type_id' => $sourceType->id, 'name' => $data['source_account_name']] - ); - // always make account active - $sourceAccount->active = true; - $sourceAccount->save(); - - Log::debug(sprintf('source account name is "%s", account is %d', $data['source_account_name'], $sourceAccount->id)); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - - Log::debug('source_account_name is empty, so default to cash account!'); - - $sourceType = AccountType::where('type', AccountType::CASH)->first(); - $sourceAccount = Account::firstOrCreateEncrypted( - ['user_id' => $user->id, 'account_type_id' => $sourceType->id, 'name' => 'Cash account'] - ); - // always make account active - $sourceAccount->active = true; - $sourceAccount->save(); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - - /** - * @param User $user - * @param array $data - * - * @return array - * - * @throws FireflyException - * @throws FireflyException - */ - protected function storeWithdrawalAccounts(User $user, array $data): array - { - Log::debug('Now in storeWithdrawalAccounts().'); - $sourceAccount = Account::where('user_id', $user->id)->where('id', $data['source_account_id'])->first(['accounts.*']); - - Log::debug(sprintf('Source account is #%d ("%s")', $sourceAccount->id, $sourceAccount->name)); - - if (strlen($data['destination_account_name']) > 0) { - $destinationType = AccountType::where('type', AccountType::EXPENSE)->first(); - $destinationAccount = Account::firstOrCreateEncrypted( - [ - 'user_id' => $user->id, - 'account_type_id' => $destinationType->id, - 'name' => $data['destination_account_name'], - ] - ); - - // always make account active - $destinationAccount->active = true; - $destinationAccount->save(); - - Log::debug(sprintf('destination account name is "%s", account is %d', $data['destination_account_name'], $destinationAccount->id)); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - Log::debug('destination_account_name is empty, so default to cash account!'); - $destinationType = AccountType::where('type', AccountType::CASH)->first(); - $destinationAccount = Account::firstOrCreateEncrypted( - ['user_id' => $user->id, 'account_type_id' => $destinationType->id, 'name' => 'Cash account'] - ); - // always make account active - $destinationAccount->active = true; - $destinationAccount->save(); - - return [ - 'source' => $sourceAccount, - 'destination' => $destinationAccount, - ]; - } - - /** - * This method checks the data array and the given accounts to verify that the native amount, currency - * and possible the foreign currency and amount are properly saved. - * - * @param array $data - * @param array $accounts - * - * @return array - * - * @throws FireflyException - */ - protected function verifyNativeAmount(array $data, array $accounts): array - { - /** @var TransactionType $transactionType */ - $transactionType = TransactionType::where('type', ucfirst($data['what']))->first(); - $submittedCurrencyId = $data['currency_id']; - $data['foreign_amount'] = null; - $data['foreign_currency_id'] = null; - - // which account to check for what the native currency is? - $check = 'source'; - if (TransactionType::DEPOSIT === $transactionType->type) { - $check = 'destination'; - } - switch ($transactionType->type) { - case TransactionType::RECONCILIATION: - // do nothing. - break; - case TransactionType::DEPOSIT: - 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) { - // store amount and submitted currency in "foreign currency" fields: - $data['foreign_amount'] = $data['amount']; - $data['foreign_currency_id'] = $submittedCurrencyId; - - // overrule the amount and currency ID fields to be the original again: - $data['amount'] = strval($data['native_amount']); - $data['currency_id'] = $nativeCurrencyId; - } - break; - case TransactionType::TRANSFER: - $sourceCurrencyId = intval($accounts['source']->getMeta('currency_id')); - $destinationCurrencyId = intval($accounts['destination']->getMeta('currency_id')); - $data['amount'] = strval($data['source_amount']); - $data['currency_id'] = intval($accounts['source']->getMeta('currency_id')); - - if ($sourceCurrencyId !== $destinationCurrencyId) { - // accounts have different id's, save this info: - $data['foreign_amount'] = strval($data['destination_amount']); - $data['foreign_currency_id'] = $destinationCurrencyId; - } - - break; - default: - throw new FireflyException(sprintf('Cannot handle %s in verifyNativeAmount()', $transactionType->type)); - } - - return $data; - } -} diff --git a/app/Repositories/Journal/UpdateJournalsTrait.php b/app/Repositories/Journal/UpdateJournalsTrait.php deleted file mode 100644 index eb16eaeda3..0000000000 --- a/app/Repositories/Journal/UpdateJournalsTrait.php +++ /dev/null @@ -1,126 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Repositories\Journal; - -use DB; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\Tag; -use FireflyIII\Models\Transaction; -use FireflyIII\Models\TransactionJournal; -use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Tag\TagRepositoryInterface; -use Log; - -/** - * Trait UpdateJournalsTrait. - */ -trait UpdateJournalsTrait -{ - - /** - * When the user edits a split journal, each line is missing crucial data:. - * - * - Withdrawal lines are missing the source account ID - * - Deposit lines are missing the destination account ID - * - Transfers are missing both. - * - * We need to append the array. - * - * @param array $transaction - * @param array $data - * - * @return array - */ - protected function appendTransactionData(array $transaction, array $data): array - { - switch ($data['what']) { - case strtolower(TransactionType::TRANSFER): - case strtolower(TransactionType::WITHDRAWAL): - $transaction['source_account_id'] = intval($data['journal_source_account_id']); - break; - } - - switch ($data['what']) { - case strtolower(TransactionType::TRANSFER): - case strtolower(TransactionType::DEPOSIT): - $transaction['destination_account_id'] = intval($data['journal_destination_account_id']); - break; - } - - return $transaction; - } - - /** - * Update destination transaction. - * - * @param TransactionJournal $journal - * @param Account $account - * @param array $data - * - * @throws FireflyException - */ - protected function updateDestinationTransaction(TransactionJournal $journal, Account $account, array $data) - { - $set = $journal->transactions()->where('amount', '>', 0)->get(); - if (1 !== $set->count()) { - throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); - } - /** @var Transaction $transaction */ - $transaction = $set->first(); - $transaction->amount = app('steam')->positive($data['amount']); - $transaction->transaction_currency_id = $data['currency_id']; - $transaction->foreign_amount = null === $data['foreign_amount'] ? null : app('steam')->positive($data['foreign_amount']); - $transaction->foreign_currency_id = $data['foreign_currency_id']; - $transaction->account_id = $account->id; - $transaction->save(); - } - - /** - * Update source transaction. - * - * @param TransactionJournal $journal - * @param Account $account - * @param array $data - * - * @throws FireflyException - */ - protected function updateSourceTransaction(TransactionJournal $journal, Account $account, array $data) - { - // should be one: - $set = $journal->transactions()->where('amount', '<', 0)->get(); - if (1 !== $set->count()) { - throw new FireflyException(sprintf('Journal #%d has %d transactions with an amount more than zero.', $journal->id, $set->count())); - } - /** @var Transaction $transaction */ - $transaction = $set->first(); - $transaction->amount = bcmul(app('steam')->positive($data['amount']), '-1'); - $transaction->transaction_currency_id = $data['currency_id']; - $transaction->foreign_amount = null === $data['foreign_amount'] ? null : bcmul(app('steam')->positive($data['foreign_amount']), '-1'); - $transaction->foreign_currency_id = $data['foreign_currency_id']; - $transaction->account_id = $account->id; - $transaction->save(); - } - - -} diff --git a/app/Repositories/LinkType/LinkTypeRepository.php b/app/Repositories/LinkType/LinkTypeRepository.php index 2d47f0964e..94490e91a7 100644 --- a/app/Repositories/LinkType/LinkTypeRepository.php +++ b/app/Repositories/LinkType/LinkTypeRepository.php @@ -131,8 +131,15 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface { $outward = TransactionJournalLink::whereSourceId($journal->id)->get(); $inward = TransactionJournalLink::whereDestinationId($journal->id)->get(); + $merged = $outward->merge($inward); - return $outward->merge($inward); + $filtered = $merged->filter( + function (TransactionJournalLink $link) { + return (!is_null($link->source) && !is_null($link->destination)); + } + ); + + return $filtered; } /** diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 1953be27e2..23c3b7c0eb 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -28,6 +28,7 @@ use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; use Log; @@ -163,6 +164,44 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return new PiggyBank(); } + /** + * Find by name or return NULL. + * + * @param string $name + * + * @return PiggyBank|null + */ + public function findByName(string $name): ?PiggyBank + { + $set = $this->user->piggyBanks()->get(['piggy_banks.*']); + /** @var PiggyBank $piggy */ + foreach ($set as $piggy) { + if ($piggy->name === $name) { + return $piggy; + } + } + + return null; + } + + /** + * Get current amount saved in piggy bank. + * + * @param PiggyBank $piggyBank + * + * @return string + */ + public function getCurrentAmount(PiggyBank $piggyBank): string + { + /** @var PiggyBankRepetition $rep */ + $rep = $piggyBank->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']); + if (null === $rep) { + return '0'; + } + + return strval($rep->currentamount); + } + /** * @param PiggyBank $piggyBank * @@ -184,8 +223,12 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string { - $amount = $journal->amountPositive(); - $sources = $journal->sourceAccountList()->pluck('id')->toArray(); + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($this->user); + + $amount = $repos->getJournalTotal($journal); + $sources = $repos->getJournalSourceAccounts($journal)->pluck('id')->toArray(); $room = bcsub(strval($piggyBank->targetamount), strval($repetition->currentamount)); $compare = bcmul($repetition->currentamount, '-1'); diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index 93ae5f1e3c..57fe6ce14b 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -102,6 +102,24 @@ interface PiggyBankRepositoryInterface */ public function find(int $piggyBankid): PiggyBank; + /** + * Find by name or return NULL. + * + * @param string $name + * + * @return PiggyBank|null + */ + public function findByName(string $name): ?PiggyBank; + + /** + * Get current amount saved in piggy bank. + * + * @param PiggyBank $piggyBank + * + * @return string + */ + public function getCurrentAmount(PiggyBank $piggyBank): string; + /** * Get all events. * diff --git a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php index c45524d31f..2082a78012 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php +++ b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php @@ -52,6 +52,8 @@ interface RuleGroupRepositoryInterface public function find(int $ruleGroupId): RuleGroup; /** + * Get all rule groups. + * * @return Collection */ public function get(): Collection; diff --git a/app/Repositories/TransactionType/TransactionTypeRepository.php b/app/Repositories/TransactionType/TransactionTypeRepository.php new file mode 100644 index 0000000000..47b5d27354 --- /dev/null +++ b/app/Repositories/TransactionType/TransactionTypeRepository.php @@ -0,0 +1,44 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\TransactionType; + +use FireflyIII\Models\TransactionType; + +/** + * Class TransactionTypeRepository + */ +class TransactionTypeRepository implements TransactionTypeRepositoryInterface +{ + /** + * Find a transaction type or return NULL. + * + * @param string $type + * + * @return TransactionType|null + */ + public function findByType(string $type): ?TransactionType + { + return TransactionType::where('type', ucfirst($type))->first(); + } +} \ No newline at end of file diff --git a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php new file mode 100644 index 0000000000..213c044f2f --- /dev/null +++ b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php @@ -0,0 +1,44 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\TransactionType; + +use FireflyIII\Models\TransactionType; + +/** + * Interface TransactionTypeRepositoryInterface + * + * @package FireflyIII\Repositories\TransactionType + */ +interface TransactionTypeRepositoryInterface +{ + /** + * Find a transaction type or return NULL. + * + * @param string $type + * + * @return TransactionType|null + */ + public function findByType(string $type): ?TransactionType; + +} \ No newline at end of file diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php index b69f13381d..4f664f4570 100644 --- a/app/Repositories/User/UserRepository.php +++ b/app/Repositories/User/UserRepository.php @@ -264,12 +264,12 @@ class UserRepository implements UserRepositoryInterface */ public function store(array $data): User { - $password = bcrypt($data['password'] ?? app('str')->random(16)); - return User::create( [ - 'email' => $data['email'], - 'password' => $password, + 'blocked' => $data['blocked'] ?? false, + 'blocked_code' => $data['blocked_code'] ?? null, + 'email' => $data['email'], + 'password' => str_random(24), ] ); } @@ -286,6 +286,24 @@ class UserRepository implements UserRepositoryInterface return; } + /** + * Update user info. + * + * @param User $user + * @param array $data + * + * @return User + */ + public function update(User $user, array $data): User + { + $this->updateEmail($user, $data['email']); + $user->blocked = $data['blocked'] ?? false; + $user->blocked_code = $data['blocked_code'] ?? null; + $user->save(); + + return $user; + } + /** * This updates the users email address. Same as changeEmail just without most logging. This makes sure that the undo/confirm routine can't catch this one. * The user is NOT blocked. diff --git a/app/Repositories/User/UserRepositoryInterface.php b/app/Repositories/User/UserRepositoryInterface.php index 13568f754b..46d261d006 100644 --- a/app/Repositories/User/UserRepositoryInterface.php +++ b/app/Repositories/User/UserRepositoryInterface.php @@ -31,15 +31,6 @@ use Illuminate\Support\Collection; */ interface UserRepositoryInterface { - - /** - * @param string $name - * @param string $displayName - * @param string $description - * - * @return Role - */ - public function createRole(string $name, string $displayName, string $description): Role; /** * Returns a collection of all users. * @@ -47,13 +38,6 @@ interface UserRepositoryInterface */ public function all(): Collection; - /** - * @param string $role - * - * @return Role|null - */ - public function getRole(string $role): ?Role; - /** * Gives a user a role. * @@ -101,6 +85,15 @@ interface UserRepositoryInterface */ public function count(): int; + /** + * @param string $name + * @param string $displayName + * @param string $description + * + * @return Role + */ + public function createRole(string $name, string $displayName, string $description): Role; + /** * @param User $user * @@ -129,6 +122,13 @@ interface UserRepositoryInterface */ public function first(): ?User; + /** + * @param string $role + * + * @return Role|null + */ + public function getRole(string $role): ?Role; + /** * Return basic user information. * @@ -158,6 +158,16 @@ interface UserRepositoryInterface */ public function unblockUser(User $user): void; + /** + * Update user info. + * + * @param User $user + * @param array $data + * + * @return User + */ + public function update(User $user, array $data): User; + /** * This updates the users email address. Same as changeEmail just without most logging. This makes sure that the undo/confirm routine can't catch this one. * The user is NOT blocked. diff --git a/app/Rules/BelongsUser.php b/app/Rules/BelongsUser.php new file mode 100644 index 0000000000..7967117327 --- /dev/null +++ b/app/Rules/BelongsUser.php @@ -0,0 +1,170 @@ +. + */ + +namespace FireflyIII\Rules; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Account; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; +use FireflyIII\Models\PiggyBank; +use Illuminate\Contracts\Validation\Rule; + +/** + * Class BelongsUser + */ +class BelongsUser implements Rule +{ + /** + * Create a new rule instance. + * + * @return void + */ + public function __construct() + { + // + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return trans('validation.belongs_user'); + } + + /** + * Determine if the validation rule passes. + * TODO use repositories? + * @param string $attribute + * @param mixed $value + * + * @return bool + * @throws FireflyException + */ + public function passes($attribute, $value) + { + $attribute = $this->parseAttribute($attribute); + if (!auth()->check()) { + return true; // @codeCoverageIgnore + } + $attribute = strval($attribute); + switch ($attribute) { + case 'piggy_bank_id': + $count = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') + ->where('piggy_banks.id', '=', intval($value)) + ->where('accounts.user_id', '=', auth()->user()->id)->count(); + + return $count === 1; + break; + case 'piggy_bank_name': + $count = $this->countField(PiggyBank::class, 'name', $value); + + return $count === 1; + break; + case 'bill_id': + $count = Bill::where('id', '=', intval($value))->where('user_id', '=', auth()->user()->id)->count(); + + return $count === 1; + case 'bill_name': + $count = $this->countField(Bill::class, 'name', $value); + + return $count === 1; + break; + case 'budget_id': + $count = Budget::where('id', '=', intval($value))->where('user_id', '=', auth()->user()->id)->count(); + + return $count === 1; + break; + case 'category_id': + $count = Category::where('id', '=', intval($value))->where('user_id', '=', auth()->user()->id)->count(); + + return $count === 1; + break; + case 'budget_name': + $count = $this->countField(Budget::class, 'name', $value); + + return $count === 1; + break; + case 'source_id': + case 'destination_id': + $count = Account::where('id', '=', intval($value))->where('user_id', '=', auth()->user()->id)->count(); + + return $count === 1; + break; + + default: + throw new FireflyException(sprintf('Rule BelongUser cannot handle "%s"', $attribute)); // @codeCoverageIgnore + } + } + + /** + * @param string $class + * @param string $field + * @param string $value + * + * @return int + */ + protected function countField(string $class, string $field, string $value): int + { + // get all objects belonging to user: + switch ($class) { + case PiggyBank::class: + $objects = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') + ->where('accounts.user_id', '=', auth()->user()->id)->get(['piggy_banks.*']); + break; + default: + $objects = $class::where('user_id', '=', auth()->user()->id)->get(); + break; + } + $count = 0; + foreach ($objects as $object) { + if (trim(strval($object->$field)) === trim($value)) { + $count++; + } + } + + return $count; + } + + /** + * @param string $attribute + * + * @return string + */ + private function parseAttribute(string $attribute): string + { + $parts = explode('.', $attribute); + if (count($parts) === 1) { + return $attribute; + } + if (count($parts) === 3) { + return $parts[2]; + } + + return $attribute; // @codeCoverageIgnore + } +} diff --git a/app/Rules/UniqueIban.php b/app/Rules/UniqueIban.php new file mode 100644 index 0000000000..39a760f391 --- /dev/null +++ b/app/Rules/UniqueIban.php @@ -0,0 +1,89 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Rules; + +use FireflyIII\Models\Account; +use Illuminate\Contracts\Validation\Rule; +use Illuminate\Support\Collection; + +/** + * Class UniqueIban + */ +class UniqueIban implements Rule +{ + /** @var Account */ + private $account; + + /** + * Create a new rule instance. + * + * @return void + */ + public function __construct(?Account $account) + { + $this->account = $account; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return trans('validation.unique_iban_for_user'); + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * + * @return bool + */ + public function passes($attribute, $value) + { + if (!auth()->check()) { + return true; // @codeCoverageIgnore + } + + $query = auth()->user()->accounts(); + if (!is_null($this->account)) { + $query->where('accounts.id', '!=', $this->account->id); + } + + /** @var Collection $accounts */ + $accounts = $query->get(); + + /** @var Account $account */ + foreach ($accounts as $account) { + if ($account->iban === $value) { + return false; + } + } + + return true; + } +} \ No newline at end of file diff --git a/app/Rules/ValidTransactions.php b/app/Rules/ValidTransactions.php new file mode 100644 index 0000000000..be57f7dccd --- /dev/null +++ b/app/Rules/ValidTransactions.php @@ -0,0 +1,82 @@ +. + */ + +namespace FireflyIII\Rules; + +use FireflyIII\Models\Transaction; +use Illuminate\Contracts\Validation\Rule; +use Log; + +/** + * Class ValidTransactions + */ +class ValidTransactions implements Rule +{ + /** + * Create a new rule instance. + * + * @return void + */ + public function __construct() + { + // + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return trans('validation.invalid_selection'); + } + + /** + * Determine if the validation rule passes. + * + * @param string $attribute + * @param mixed $value + * + * @return bool + */ + public function passes($attribute, $value) + { + Log::debug('In ValidTransactions::passes'); + if (!is_array($value)) { + return true; + } + $userId = auth()->user()->id; + foreach ($value as $transactionId) { + $count = Transaction::where('transactions.id', $transactionId) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->where('accounts.user_id', $userId)->count(); + if ($count === 0) { + Log::debug(sprintf('Count for transaction #%d and user #%d is zero! Return FALSE', $transactionId, $userId)); + return false; + } + } + Log::debug('Return true!'); + return true; + } +} diff --git a/app/Services/Internal/Destroy/AccountDestroyService.php b/app/Services/Internal/Destroy/AccountDestroyService.php new file mode 100644 index 0000000000..b96284ed9c --- /dev/null +++ b/app/Services/Internal/Destroy/AccountDestroyService.php @@ -0,0 +1,72 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Destroy; + +use DB; +use Exception; +use FireflyIII\Models\Account; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use Log; + +/** + * Class AccountDestroyService + */ +class AccountDestroyService +{ + /** + * @param Account $account + * @param Account|null $moveTo + * + * @return bool + */ + public function destroy(Account $account, ?Account $moveTo): bool + { + if (null !== $moveTo) { + DB::table('transactions')->where('account_id', $account->id)->update(['account_id' => $moveTo->id]); + } + + Log::debug('Now trigger account delete response #' . $account->id); + /** @var Transaction $transaction */ + foreach ($account->transactions()->get() as $transaction) { + Log::debug('Now at transaction #' . $transaction->id); + /** @var TransactionJournal $journal */ + $journal = $transaction->transactionJournal()->first(); + if (null !== $journal) { + Log::debug('Call for deletion of journal #' . $journal->id); + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + $service->destroy($journal); + } + } + try { + $account->delete(); + } catch (Exception $e) { // @codeCoverageIgnore + Log::error(sprintf('Could not delete account: %s',$e->getMessage())); // @codeCoverageIgnore + } + + return true; + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Destroy/BillDestroyService.php b/app/Services/Internal/Destroy/BillDestroyService.php new file mode 100644 index 0000000000..c97fad5894 --- /dev/null +++ b/app/Services/Internal/Destroy/BillDestroyService.php @@ -0,0 +1,47 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Destroy; + +use Exception; +use FireflyIII\Models\Bill; +use Log; +/** + * @codeCoverageIgnore + * Class BillDestroyService + */ +class BillDestroyService +{ + /** + * @param Bill $bill + */ + public function destroy(Bill $bill): void + { + try { + $bill->delete(); + } catch (Exception $e) { // @codeCoverageIgnore + Log::error(sprintf('Could not delete bill: %s',$e->getMessage())); // @codeCoverageIgnore + } + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Destroy/JournalDestroyService.php b/app/Services/Internal/Destroy/JournalDestroyService.php new file mode 100644 index 0000000000..1dc825bf1a --- /dev/null +++ b/app/Services/Internal/Destroy/JournalDestroyService.php @@ -0,0 +1,65 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Destroy; + +use Exception; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionJournalMeta; +use Log; + +/** + * @codeCoverageIgnore + * Class JournalDestroyService + */ +class JournalDestroyService +{ + /** + * @param TransactionJournal $journal + */ + public function destroy(TransactionJournal $journal): void + { + try { + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + Log::debug(sprintf('Will now delete transaction #%d', $transaction->id)); + $transaction->delete(); + } + + // also delete journal_meta entries. + + /** @var TransactionJournalMeta $meta */ + foreach ($journal->transactionJournalMeta()->get() as $meta) { + Log::debug(sprintf('Will now delete meta-entry #%d', $meta->id)); + $meta->delete(); + } + $journal->delete(); + } catch (Exception $e) { + Log::error(sprintf('Could not delete bill: %s',$e->getMessage())); // @codeCoverageIgnore + } + + return; + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php new file mode 100644 index 0000000000..c49ebbcc68 --- /dev/null +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -0,0 +1,397 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Support; + +use Exception; +use FireflyIII\Factory\AccountFactory; +use FireflyIII\Factory\AccountMetaFactory; +use FireflyIII\Factory\TransactionFactory; +use FireflyIII\Factory\TransactionJournalFactory; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Note; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use FireflyIII\Services\Internal\Destroy\JournalDestroyService; +use FireflyIII\User; +use Log; +use Validator; + +/** + * Trait AccountServiceTrait + * + * @package FireflyIII\Services\Internal\Support + */ +trait AccountServiceTrait +{ + /** @var array */ + public $validAssetFields = ['accountRole', 'accountNumber', 'currency_id', 'BIC']; + /** @var array */ + public $validCCFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType', 'accountNumber', 'currency_id', 'BIC']; + /** @var array */ + public $validFields = ['accountNumber', 'currency_id', 'BIC']; + + /** + * @param Account $account + * + * @return bool + */ + public function deleteIB(Account $account): bool + { + Log::debug(sprintf('deleteIB() for account #%d', $account->id)); + $openingBalance = $this->getIBJournal($account); + + // opening balance data? update it! + if (null !== $openingBalance) { + Log::debug('Opening balance journal found, delete journal.'); + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + $service->destroy($openingBalance); + + return true; + } + + return true; + } + + /** + * @param null|string $iban + * + * @return null|string + */ + public function filterIban(?string $iban) + { + if (null === $iban) { + return null; + } + $data = ['iban' => $iban]; + $rules = ['iban' => 'required|iban']; + $validator = Validator::make($data, $rules); + if ($validator->fails()) { + Log::error(sprintf('Detected invalid IBAN ("%s"). Return NULL instead.', $iban)); + + return null; + } + + + return $iban; + } + + /** + * Find existing opening balance. + * + * @param Account $account + * + * @return TransactionJournal|null + */ + public function getIBJournal(Account $account): ?TransactionJournal + { + $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); + if (null === $journal) { + Log::debug('Could not find a opening balance journal, return NULL.'); + + return null; + } + Log::debug(sprintf('Found opening balance: journal #%d.', $journal->id)); + + return $journal; + } + + /** + * @param Account $account + * @param array $data + * + * @return TransactionJournal|null + */ + public function storeIBJournal(Account $account, array $data): ?TransactionJournal + { + $amount = strval($data['openingBalance']); + Log::debug(sprintf('Submitted amount is %s', $amount)); + + if (0 === bccomp($amount, '0')) { + return null; + } + + // store journal, without transactions: + $name = $data['name']; + $currencyId = $data['currency_id']; + $journalData = [ + 'type' => TransactionType::OPENING_BALANCE, + 'user' => $account->user->id, + 'transaction_currency_id' => $currencyId, + 'description' => strval(trans('firefly.initial_balance_description', ['account' => $account->name])), + 'completed' => true, + 'date' => $data['openingBalanceDate'], + 'bill_id' => null, + 'bill_name' => null, + 'piggy_bank_id' => null, + 'piggy_bank_name' => null, + 'tags' => null, + 'notes' => null, + 'transactions' => [], + + ]; + /** @var TransactionJournalFactory $factory */ + $factory = app(TransactionJournalFactory::class); + $factory->setUser($account->user); + $journal = $factory->create($journalData); + $opposing = $this->storeOpposingAccount($account->user, $name); + Log::notice(sprintf('Created new opening balance journal: #%d', $journal->id)); + + $firstAccount = $account; + $secondAccount = $opposing; + $firstAmount = $amount; + $secondAmount = bcmul($amount, '-1'); + Log::notice(sprintf('First amount is %s, second amount is %s', $firstAmount, $secondAmount)); + + if (bccomp($amount, '0') === -1) { + Log::debug(sprintf('%s is a negative number.', $amount)); + $firstAccount = $opposing; + $secondAccount = $account; + $firstAmount = bcmul($amount, '-1'); + $secondAmount = $amount; + Log::notice(sprintf('First amount is %s, second amount is %s', $firstAmount, $secondAmount)); + } + /** @var TransactionFactory $factory */ + $factory = app(TransactionFactory::class); + $factory->setUser($account->user); + $one = $factory->create( + [ + 'account' => $firstAccount, + 'transaction_journal' => $journal, + 'amount' => $firstAmount, + 'currency_id' => $currencyId, + 'description' => null, + 'identifier' => 0, + 'foreign_amount' => null, + 'reconciled' => false, + ] + ); + $two = $factory->create( + [ + 'account' => $secondAccount, + 'transaction_journal' => $journal, + 'amount' => $secondAmount, + 'currency_id' => $currencyId, + 'description' => null, + 'identifier' => 0, + 'foreign_amount' => null, + 'reconciled' => false, + ] + ); + Log::notice(sprintf('Stored two transactions for new account, #%d and #%d', $one->id, $two->id)); + + return $journal; + } + + /** + * TODO make sure this works (user ID, etc.) + * + * @param User $user + * @param string $name + * + * @return Account + */ + public function storeOpposingAccount(User $user, string $name): Account + { + $name = $name . ' initial balance'; + Log::debug('Going to create an opening balance opposing account.'); + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($user); + + return $factory->findOrCreate($name, AccountType::INITIAL_BALANCE); + } + + /** + * @param Account $account + * @param array $data + * + * @return bool + */ + public function updateIB(Account $account, array $data): bool + { + Log::debug(sprintf('updateInitialBalance() for account #%d', $account->id)); + $openingBalance = $this->getIBJournal($account); + + // no opening balance journal? create it: + if (null === $openingBalance) { + Log::debug('No opening balance journal yet, create journal.'); + $this->storeIBJournal($account, $data); + + return true; + } + + // opening balance data? update it! + if (null !== $openingBalance->id) { + Log::debug('Opening balance journal found, update journal.'); + $this->updateIBJournal($account, $openingBalance, $data); + + return true; + } + return true; // @codeCoverageIgnore + } + + /** + * @param Account $account + * @param TransactionJournal $journal + * @param array $data + * + * @return bool + */ + public function updateIBJournal(Account $account, TransactionJournal $journal, array $data): bool + { + $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)); + if (0 === bccomp($amount, '0')) { + Log::notice(sprintf('Amount "%s" is zero, delete opening balance.', $amount)); + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + $service->destroy($journal); + + + return true; + } + + // update date: + $journal->date = $date; + $journal->transaction_currency_id = $currencyId; + $journal->save(); + + // update transactions: + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + 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 (!(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(); + } + } + Log::debug('Updated opening balance journal.'); + + return true; + } + + /** + * Update meta data for account. Depends on type which fields are valid. + * + * @param Account $account + * @param array $data + */ + public function updateMetaData(Account $account, array $data) + { + $fields = $this->validFields; + + if ($account->accountType->type === AccountType::ASSET) { + $fields = $this->validAssetFields; + } + if ($account->accountType->type === AccountType::ASSET && $data['accountRole'] === 'ccAsset') { + $fields = $this->validCCFields; + } + /** @var AccountMetaFactory $factory */ + $factory = app(AccountMetaFactory::class); + foreach ($fields as $field) { + /** @var AccountMeta $entry */ + $entry = $account->accountMeta()->where('name', $field)->first(); + + // if $data has field and $entry is null, create new one: + if (isset($data[$field]) && null === $entry) { + Log::debug(sprintf('Created meta-field "%s":"%s" for account #%d ("%s") ', $field, $data[$field], $account->id, $account->name)); + $factory->create(['account_id' => $account->id, 'name' => $field, 'data' => $data[$field],]); + } + + // if $data has field and $entry is not null, update $entry: + // let's not bother with a service. + if (isset($data[$field]) && null !== $entry) { + $entry->data = $data[$field]; + $entry->save(); + Log::debug(sprintf('Updated meta-field "%s":"%s" for #%d ("%s") ', $field, $data[$field], $account->id, $account->name)); + } + } + } + + /** + * @param Account $account + * @param string $note + * + * @return bool + */ + public 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; + } + + /** + * Verify if array contains valid data to possibly store or update the opening balance. + * + * @param array $data + * + * @return bool + */ + public function validIBData(array $data): bool + { + $data['openingBalance'] = strval($data['openingBalance'] ?? ''); + if (isset($data['openingBalance']) && null !== $data['openingBalance'] && strlen($data['openingBalance']) > 0 + && isset($data['openingBalanceDate'])) { + Log::debug('Array has valid opening balance data.'); + + return true; + } + Log::debug('Array does not have valid opening balance data.'); + + return false; + } +} \ No newline at end of file diff --git a/app/Services/Internal/Support/BillServiceTrait.php b/app/Services/Internal/Support/BillServiceTrait.php new file mode 100644 index 0000000000..e3861fb4b3 --- /dev/null +++ b/app/Services/Internal/Support/BillServiceTrait.php @@ -0,0 +1,64 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Support; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Note; + +/** + * Trait BillServiceTrait + * + * @package FireflyIII\Services\Internal\Support + */ +trait BillServiceTrait +{ + + + /** + * @param Bill $bill + * @param string $note + * + * @return bool + */ + public function updateNote(Bill $bill, string $note): bool + { + if (0 === strlen($note)) { + $dbNote = $bill->notes()->first(); + if (null !== $dbNote) { + $dbNote->delete(); // @codeCoverageIgnore + } + + return true; + } + $dbNote = $bill->notes()->first(); + if (null === $dbNote) { + $dbNote = new Note(); + $dbNote->noteable()->associate($bill); + } + $dbNote->text = trim($note); + $dbNote->save(); + + return true; + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php new file mode 100644 index 0000000000..93186c7804 --- /dev/null +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -0,0 +1,133 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Support; + +use FireflyIII\Factory\BillFactory; +use FireflyIII\Factory\TagFactory; +use FireflyIII\Factory\TransactionJournalMetaFactory; +use FireflyIII\Models\Note; +use FireflyIII\Models\TransactionJournal; + +/** + * Trait JournalServiceTrait + * + * @package FireflyIII\Services\Internal\Support + */ +trait JournalServiceTrait +{ + + /** + * @param TransactionJournal $journal + * @param array $data + */ + public function connectTags(TransactionJournal $journal, array $data): void + { + /** @var TagFactory $factory */ + $factory = app(TagFactory::class); + $factory->setUser($journal->user); + $set = []; + if (!is_array($data['tags'])) { + return; // @codeCoverageIgnore + } + foreach ($data['tags'] as $string) { + if (strlen($string) > 0) { + $tag = $factory->findOrCreate($string); + $set[] = $tag->id; + } + } + $journal->tags()->sync($set); + } + + /** + * Connect bill if present. + * + * @param TransactionJournal $journal + * @param array $data + */ + protected function connectBill(TransactionJournal $journal, array $data): void + { + /** @var BillFactory $factory */ + $factory = app(BillFactory::class); + $factory->setUser($journal->user); + $bill = $factory->find($data['bill_id'], $data['bill_name']); + + if (!is_null($bill)) { + $journal->bill_id = $bill->id; + $journal->save(); + + return; + } + $journal->bill_id = null; + $journal->save(); + + return; + } + + /** + * @param TransactionJournal $journal + * @param array $data + * @param string $field + */ + protected function storeMeta(TransactionJournal $journal, array $data, string $field): void + { + if (!isset($data[$field])) { + return; + } + $set = [ + 'journal' => $journal, + 'name' => $field, + 'data' => $data[$field], + ]; + /** @var TransactionJournalMetaFactory $factory */ + $factory = app(TransactionJournalMetaFactory::class); + $factory->updateOrCreate($set); + } + + /** + * @param TransactionJournal $journal + * @param string $notes + */ + protected function storeNote(TransactionJournal $journal, ?string $notes): void + { + $notes = strval($notes); + if (strlen($notes) > 0) { + $note = $journal->notes()->first(); + if (is_null($note)) { + $note = new Note; + $note->noteable()->associate($journal); + } + $note->text = $notes; + $note->save(); + + return; + } + $note = $journal->notes()->first(); + if (!is_null($note)) { + $note->delete(); + } + + return; + + } +} \ No newline at end of file diff --git a/app/Services/Internal/Support/TransactionServiceTrait.php b/app/Services/Internal/Support/TransactionServiceTrait.php new file mode 100644 index 0000000000..7b029997bb --- /dev/null +++ b/app/Services/Internal/Support/TransactionServiceTrait.php @@ -0,0 +1,270 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Support; + + +use FireflyIII\Factory\AccountFactory; +use FireflyIII\Factory\BudgetFactory; +use FireflyIII\Factory\CategoryFactory; +use FireflyIII\Factory\TransactionCurrencyFactory; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use Log; + +/** + * Trait TransactionServiceTrait + * + * @package FireflyIII\Services\Internal\Support + */ +trait TransactionServiceTrait +{ + + /** + * @param TransactionJournal $journal + * @param string $direction + * + * @return string|null + */ + public function accountType(TransactionJournal $journal, string $direction): ?string + { + $types = []; + $type = $journal->transactionType->type; + switch ($type) { + default: + // @codeCoverageIgnoreStart + Log::error(sprintf('Cannot handle type "%s" in accountType()', $type)); + + return null; + // @codeCoverageIgnoreEnd + case TransactionType::WITHDRAWAL: + $types['source'] = AccountType::ASSET; + $types['destination'] = AccountType::EXPENSE; + break; + case TransactionType::DEPOSIT: + $types['source'] = AccountType::REVENUE; + $types['destination'] = AccountType::ASSET; + break; + case TransactionType::TRANSFER: + $types['source'] = AccountType::ASSET; + $types['destination'] = AccountType::ASSET; + break; + case TransactionType::RECONCILIATION: + // always NULL, since this is handled by the reconciliation. + $types['source'] = null; + $types['destination'] = null; + + // return here: + return $types[$direction]; + } + if (!isset($types[$direction])) { + // @codeCoverageIgnoreStart + Log::error(sprintf('No type set for direction "%s" and type "%s"', $type, $direction)); + + return null; + // @codeCoverageIgnoreEnd + } + + return $types[$direction]; + } + + /** + * @param string|null $expectedType + * @param int|null $accountId + * @param string|null $accountName + * + * @return Account + */ + public function findAccount(?string $expectedType, ?int $accountId, ?string $accountName): Account + { + $accountId = intval($accountId); + $accountName = strval($accountName); + $repository = app(AccountRepositoryInterface::class); + $repository->setUser($this->user); + + if (is_null($expectedType)) { + return $repository->findNull($accountId); + } + + switch ($expectedType) { + case AccountType::ASSET: + if ($accountId > 0) { + // must be able to find it based on ID. Validator should catch invalid ID's. + return $repository->findNull($accountId); + } + + // alternatively, return by name. Validator should catch invalid names. + return $repository->findByName($accountName, [AccountType::ASSET]); + break; + case AccountType::EXPENSE: + if ($accountId > 0) { + // must be able to find it based on ID. Validator should catch invalid ID's. + return $repository->findNull($accountId); + } + if (strlen($accountName) > 0) { + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($this->user); + + return $factory->findOrCreate($accountName, AccountType::EXPENSE); + } + + // return cash account: + return $repository->getCashAccount(); + break; + case AccountType::REVENUE: + if ($accountId > 0) { + // must be able to find it based on ID. Validator should catch invalid ID's. + return $repository->findNull($accountId); + } + if (strlen($accountName) > 0) { + // alternatively, return by name. + /** @var AccountFactory $factory */ + $factory = app(AccountFactory::class); + $factory->setUser($this->user); + + return $factory->findOrCreate($accountName, AccountType::REVENUE); + } + + // return cash account: + return $repository->getCashAccount(); + + default: + // @codeCoverageIgnoreStart + Log::error(sprintf('Cannot find account of type "%s".', $expectedType)); + + return null; + // @codeCoverageIgnoreEnd + + } + } + + /** + * @param int|null $budgetId + * @param null|string $budgetName + * + * @return Budget|null + */ + protected function findBudget(?int $budgetId, ?string $budgetName): ?Budget + { + /** @var BudgetFactory $factory */ + $factory = app(BudgetFactory::class); + $factory->setUser($this->user); + + return $factory->find($budgetId, $budgetName); + } + + /** + * @param int|null $categoryId + * @param null|string $categoryName + * + * @return Category|null + */ + protected function findCategory(?int $categoryId, ?string $categoryName): ?Category + { + /** @var CategoryFactory $factory */ + $factory = app(CategoryFactory::class); + $factory->setUser($this->user); + + return $factory->findOrCreate($categoryId, $categoryName); + } + + /** + * @param int|null $currencyId + * @param null|string $currencyCode + * + * @return TransactionCurrency|null + */ + protected function findCurrency(?int $currencyId, ?string $currencyCode): ?TransactionCurrency + { + $factory = app(TransactionCurrencyFactory::class); + + return $factory->find($currencyId, $currencyCode); + } + + /** + * @param Transaction $transaction + * @param Budget|null $budget + */ + protected function setBudget(Transaction $transaction, ?Budget $budget): void + { + if (is_null($budget)) { + $transaction->budgets()->sync([]); + return; + } + $transaction->budgets()->sync([$budget->id]); + + return; + } + + + /** + * @param Transaction $transaction + * @param Category|null $category + */ + protected function setCategory(Transaction $transaction, ?Category $category): void + { + if (is_null($category)) { + $transaction->categories()->sync([]); + return; + } + $transaction->categories()->sync([$category->id]); + + return; + } + + + /** + * @param Transaction $transaction + * @param string|null $amount + */ + protected function setForeignAmount(Transaction $transaction, ?string $amount): void + { + $transaction->foreign_amount = $amount; + $transaction->save(); + } + + /** + * @param Transaction $transaction + * @param TransactionCurrency|null $currency + */ + protected function setForeignCurrency(Transaction $transaction, ?TransactionCurrency $currency): void + { + if (is_null($currency)) { + return; + } + $transaction->foreign_currency_id = $currency->id; + $transaction->save(); + + return; + } + + +} \ No newline at end of file diff --git a/app/Services/Internal/Update/AccountUpdateService.php b/app/Services/Internal/Update/AccountUpdateService.php new file mode 100644 index 0000000000..1352e7a0d7 --- /dev/null +++ b/app/Services/Internal/Update/AccountUpdateService.php @@ -0,0 +1,82 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Update; + +use Exception; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Factory\AccountMetaFactory; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\AccountType; +use FireflyIII\Services\Internal\Support\AccountServiceTrait; +use Log; + +/** + * Class AccountUpdateService + */ +class AccountUpdateService +{ + use AccountServiceTrait; + + + + /** + * Update account data. + * + * @param Account $account + * @param array $data + * + * @return Account + */ + public function update(Account $account, array $data): Account + { + // update the account itself: + $account->name = $data['name']; + $account->active = $data['active']; + $account->virtual_balance = trim($data['virtualBalance']) === '' ? '0' : $data['virtualBalance']; + $account->iban = $data['iban']; + $account->save(); + + // update all meta data: + $this->updateMetaData($account, $data); + + // has valid initial balance (IB) data? + if ($this->validIBData($data)) { + // then do update! + $this->updateIB($account, $data); + } + + // if not, delete it when exist. + if (!$this->validIBData($data)) { + $this->deleteIB($account); + } + + // update note: + if (isset($data['notes']) && null !== $data['notes']) { + $this->updateNote($account, strval($data['notes'])); + } + + return $account; + } +} \ No newline at end of file diff --git a/app/Services/Internal/Update/BillUpdateService.php b/app/Services/Internal/Update/BillUpdateService.php new file mode 100644 index 0000000000..56daa3405d --- /dev/null +++ b/app/Services/Internal/Update/BillUpdateService.php @@ -0,0 +1,69 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Update; + +use FireflyIII\Models\Bill; +use FireflyIII\Services\Internal\Support\BillServiceTrait; + +/** + * @codeCoverageIgnore + * Class BillUpdateService + */ +class BillUpdateService +{ + use BillServiceTrait; + + /** + * @param Bill $bill + * @param array $data + * + * @return Bill + */ + public function update(Bill $bill, array $data): Bill + { + + $matchArray = explode(',', $data['match']); + $matchArray = array_unique($matchArray); + $match = join(',', $matchArray); + + $bill->name = $data['name']; + $bill->match = $match; + $bill->amount_min = $data['amount_min']; + $bill->amount_max = $data['amount_max']; + $bill->date = $data['date']; + $bill->repeat_freq = $data['repeat_freq']; + $bill->skip = $data['skip']; + $bill->automatch = $data['automatch']; + $bill->active = $data['active']; + $bill->save(); + + // update note: + if (isset($data['notes']) && null !== $data['notes']) { + $this->updateNote($bill, strval($data['notes'])); + } + + return $bill; + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Update/JournalUpdateService.php b/app/Services/Internal/Update/JournalUpdateService.php new file mode 100644 index 0000000000..964ea59a88 --- /dev/null +++ b/app/Services/Internal/Update/JournalUpdateService.php @@ -0,0 +1,169 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Update; + +use FireflyIII\Factory\TransactionFactory; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Services\Internal\Support\JournalServiceTrait; +use Illuminate\Support\Collection; +use Log; + +/** + * Class to centralise code that updates a journal given the input by system. + * + * Class JournalUpdateService + */ +class JournalUpdateService +{ + use JournalServiceTrait; + + /** + * @param TransactionJournal $journal + * @param array $data + * + * @return TransactionJournal + */ + public function update(TransactionJournal $journal, array $data): TransactionJournal + { + // update journal: + $journal->description = $data['description']; + $journal->date = $data['date']; + $journal->save(); + + // update transactions: + /** @var TransactionUpdateService $service */ + $service = app(TransactionUpdateService::class); + $service->setUser($journal->user); + + // create transactions + /** @var TransactionFactory $factory */ + $factory = app(TransactionFactory::class); + $factory->setUser($journal->user); + + Log::debug(sprintf('Found %d rows in array (should result in %d transactions', count($data['transactions']), count($data['transactions']) * 2)); + + /** + * @var int $identifier + * @var array $trData + */ + foreach ($data['transactions'] as $identifier => $trData) { + // exists transaction(s) with this identifier? update! + /** @var Collection $existing */ + $existing = $journal->transactions()->where('identifier', $identifier)->get(); + Log::debug(sprintf('Found %d transactions with identifier %d', $existing->count(), $identifier)); + if ($existing->count() > 0) { + $existing->each( + function (Transaction $transaction) use ($service, $trData) { + Log::debug(sprintf('Update transaction #%d (identifier %d)', $transaction->id, $trData['identifier'])); + $service->update($transaction, $trData); + } + ); + continue; + } + Log::debug('Found none, so create a pair.'); + // otherwise, create! + $factory->createPair($journal, $trData); + } + // could be that journal has more transactions than submitted (remove split) + $transactions = $journal->transactions()->where('amount', '>', 0)->get(); + Log::debug(sprintf('Journal #%d has %d transactions', $journal->id, $transactions->count())); + /** @var Transaction $transaction */ + foreach ($transactions as $transaction) { + Log::debug(sprintf('Now at transaction %d with identifier %d', $transaction->id, $transaction->identifier)); + if (!isset($data['transactions'][$transaction->identifier])) { + Log::debug('No such entry in array, delete this set of transactions.'); + $journal->transactions()->where('identifier', $transaction->identifier)->delete(); + } + } + Log::debug(sprintf('New count is %d, transactions array held %d items', $journal->transactions()->count(), count($data['transactions']))); + + // connect bill: + $this->connectBill($journal, $data); + + // connect tags: + $this->connectTags($journal, $data); + + // update or create custom fields: + // store date meta fields (if present): + $this->storeMeta($journal, $data, 'interest_date'); + $this->storeMeta($journal, $data, 'book_date'); + $this->storeMeta($journal, $data, 'process_date'); + $this->storeMeta($journal, $data, 'due_date'); + $this->storeMeta($journal, $data, 'payment_date'); + $this->storeMeta($journal, $data, 'invoice_date'); + $this->storeMeta($journal, $data, 'internal_reference'); + + // store note: + $this->storeNote($journal, $data['notes']); + + + return $journal; + } + + /** + * Update budget for a journal. + * + * @param TransactionJournal $journal + * @param int $budgetId + * + * @return TransactionJournal + */ + public function updateBudget(TransactionJournal $journal, int $budgetId): TransactionJournal + { + /** @var TransactionUpdateService $service */ + $service = app(TransactionUpdateService::class); + $service->setUser($journal->user); + + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + $service->updateBudget($transaction, $budgetId); + } + + return $journal; + } + + /** + * Update category for a journal. + * + * @param TransactionJournal $journal + * @param string $category + * + * @return TransactionJournal + */ + public function updateCategory(TransactionJournal $journal, string $category): TransactionJournal + { + /** @var TransactionUpdateService $service */ + $service = app(TransactionUpdateService::class); + $service->setUser($journal->user); + + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + $service->updateCategory($transaction, $category); + } + + return $journal; + } + +} \ No newline at end of file diff --git a/app/Services/Internal/Update/TransactionUpdateService.php b/app/Services/Internal/Update/TransactionUpdateService.php new file mode 100644 index 0000000000..fa5ac3da05 --- /dev/null +++ b/app/Services/Internal/Update/TransactionUpdateService.php @@ -0,0 +1,162 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Services\Internal\Update; + +use FireflyIII\Models\Transaction; +use FireflyIII\Services\Internal\Support\TransactionServiceTrait; +use FireflyIII\User; + +/** + * Class TransactionUpdateService + */ +class TransactionUpdateService +{ + use TransactionServiceTrait; + + /** @var User */ + private $user; + + /** + * @param int $transactionId + * + * @return Transaction|null + */ + public function reconcile(int $transactionId): ?Transaction + { + $transaction = Transaction::find($transactionId); + if (!is_null($transaction)) { + $transaction->reconciled = true; + $transaction->save(); + + return $transaction; + } + + return null; + + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param Transaction $transaction + * @param array $data + * + * @return Transaction + */ + public function update(Transaction $transaction, array $data): Transaction + { + $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); + $journal = $transaction->transactionJournal; + $description = $journal->description === $data['description'] ? null : $data['description']; + + // update description: + $transaction->description = $description; + $foreignAmount = null; + if (floatval($transaction->amount) < 0) { + // this is the source transaction. + $type = $this->accountType($journal, 'source'); + $account = $this->findAccount($type, $data['source_id'], $data['source_name']); + $amount = app('steam')->negative(strval($data['amount'])); + $foreignAmount = app('steam')->negative(strval($data['foreign_amount'])); + } + + if (floatval($transaction->amount) > 0) { + // this is the destination transaction. + $type = $this->accountType($journal, 'destination'); + $account = $this->findAccount($type, $data['destination_id'], $data['destination_name']); + $amount = app('steam')->positive(strval($data['amount'])); + $foreignAmount = app('steam')->positive(strval($data['foreign_amount'])); + } + + // update the actual transaction: + $transaction->description = $description; + $transaction->amount = $amount; + $transaction->foreign_amount = null; + $transaction->transaction_currency_id = $currency->id; + $transaction->account_id = $account->id; + $transaction->reconciled = $data['reconciled']; + $transaction->save(); + + // set foreign currency + $foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']); + // set foreign amount: + if (!is_null($data['foreign_amount'])) { + $this->setForeignCurrency($transaction, $foreign); + $this->setForeignAmount($transaction, $foreignAmount); + } + if (is_null($data['foreign_amount'])) { + $this->setForeignCurrency($transaction, null); + $this->setForeignAmount($transaction, null); + } + + // set budget: + $budget = $this->findBudget($data['budget_id'], $data['budget_name']); + $this->setBudget($transaction, $budget); + + // set category + $category = $this->findCategory($data['category_id'], $data['category_name']); + $this->setCategory($transaction, $category); + + return $transaction; + } + + /** + * Update budget for a journal. + * + * @param Transaction $transaction + * @param int $budgetId + * + * @return Transaction + */ + public function updateBudget(Transaction $transaction, int $budgetId): Transaction + { + $budget = $this->findBudget($budgetId, null); + $this->setBudget($transaction, $budget); + + return $transaction; + + } + + /** + * Update category for a journal. + * + * @param Transaction $transaction + * @param string $category + * + * @return Transaction + */ + public function updateCategory(Transaction $transaction, string $category): Transaction + { + $category = $this->findCategory(0, $category); + $this->setCategory($transaction, $category); + + return $transaction; + } +} \ No newline at end of file diff --git a/app/Services/Spectre/Object/Transaction.php b/app/Services/Spectre/Object/Transaction.php index 5aa7cd5052..edf5768b64 100644 --- a/app/Services/Spectre/Object/Transaction.php +++ b/app/Services/Spectre/Object/Transaction.php @@ -57,14 +57,6 @@ class Transaction extends SpectreObject /** @var Carbon */ private $updatedAt; - /** - * @return int - */ - public function getId(): int - { - return $this->id; - } - /** * Transaction constructor. * @@ -87,39 +79,6 @@ class Transaction extends SpectreObject $this->updatedAt = new Carbon($data['updated_at']); } - /** - * @return string - */ - public function getMode(): string - { - return $this->mode; - } - - /** - * @return string - */ - public function getStatus(): string - { - return $this->status; - } - - /** - * @return bool - */ - public function isDuplicated(): bool - { - return $this->duplicated; - } - - /** - * @return TransactionExtra - */ - public function getExtra(): TransactionExtra - { - return $this->extra; - } - - /** * @return string */ @@ -152,6 +111,14 @@ class Transaction extends SpectreObject return $this->description; } + /** + * @return TransactionExtra + */ + public function getExtra(): TransactionExtra + { + return $this->extra; + } + /** * @return string */ @@ -177,6 +144,14 @@ class Transaction extends SpectreObject return $hashed; } + /** + * @return int + */ + public function getId(): int + { + return $this->id; + } + /** * @return Carbon */ @@ -185,5 +160,29 @@ class Transaction extends SpectreObject return $this->madeOn; } + /** + * @return string + */ + public function getMode(): string + { + return $this->mode; + } + + /** + * @return string + */ + public function getStatus(): string + { + return $this->status; + } + + /** + * @return bool + */ + public function isDuplicated(): bool + { + return $this->duplicated; + } + } \ No newline at end of file diff --git a/app/Services/Spectre/Request/ListLoginsRequest.php b/app/Services/Spectre/Request/ListLoginsRequest.php index c6444ec514..a7ebd89afe 100644 --- a/app/Services/Spectre/Request/ListLoginsRequest.php +++ b/app/Services/Spectre/Request/ListLoginsRequest.php @@ -26,6 +26,7 @@ namespace FireflyIII\Services\Spectre\Request; use FireflyIII\Services\Spectre\Object\Customer; use FireflyIII\Services\Spectre\Object\Login; use Log; + /** * Class ListLoginsRequest */ @@ -37,14 +38,6 @@ class ListLoginsRequest extends SpectreRequest /** @var array */ private $logins = []; - /** - * @return array - */ - public function getLogins(): array - { - return $this->logins; - } - /** * */ @@ -79,6 +72,14 @@ class ListLoginsRequest extends SpectreRequest } } + /** + * @return array + */ + public function getLogins(): array + { + return $this->logins; + } + /** * @param Customer $customer */ diff --git a/app/Services/Spectre/Request/SpectreRequest.php b/app/Services/Spectre/Request/SpectreRequest.php index b7e129ca0f..5f00a09200 100644 --- a/app/Services/Spectre/Request/SpectreRequest.php +++ b/app/Services/Spectre/Request/SpectreRequest.php @@ -23,7 +23,6 @@ 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; diff --git a/app/Support/Binder/AccountList.php b/app/Support/Binder/AccountList.php index 78be7c6e38..e667ac9a9e 100644 --- a/app/Support/Binder/AccountList.php +++ b/app/Support/Binder/AccountList.php @@ -25,6 +25,7 @@ namespace FireflyIII\Support\Binder; use FireflyIII\Models\Account; use Illuminate\Routing\Route; use Illuminate\Support\Collection; +use Log; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -49,6 +50,7 @@ class AccountList implements BinderInterface } $list = array_unique($list); if (count($list) === 0) { + Log::error('Account list is empty.'); throw new NotFoundHttpException; // @codeCoverageIgnore } @@ -67,6 +69,7 @@ class AccountList implements BinderInterface return $collection; } } + Log::error('User is not logged in.'); throw new NotFoundHttpException; } } diff --git a/app/Support/Binder/CurrencyCode.php b/app/Support/Binder/CurrencyCode.php index e142ee83a6..988a296aac 100644 --- a/app/Support/Binder/CurrencyCode.php +++ b/app/Support/Binder/CurrencyCode.php @@ -37,7 +37,7 @@ class CurrencyCode implements BinderInterface * * @return TransactionCurrency */ - public static function routeBinder(string $value, Route $route): TransactionCurrency + public static function routeBinder(string $value, Route $route): TransactionCurrency { if (auth()->check()) { $currency = TransactionCurrency::where('code', trim($value))->first(); diff --git a/app/Support/Binder/Date.php b/app/Support/Binder/Date.php index 5b04cfbd54..9d9cedfe03 100644 --- a/app/Support/Binder/Date.php +++ b/app/Support/Binder/Date.php @@ -40,7 +40,7 @@ class Date implements BinderInterface * * @return Carbon */ - public static function routeBinder(string $value, Route $route): Carbon + public static function routeBinder(string $value, Route $route): Carbon { /** @var FiscalHelperInterface $fiscalHelper */ $fiscalHelper = app(FiscalHelperInterface::class); diff --git a/app/Support/Binder/JournalList.php b/app/Support/Binder/JournalList.php index ee556f9907..a0f89dfe79 100644 --- a/app/Support/Binder/JournalList.php +++ b/app/Support/Binder/JournalList.php @@ -37,7 +37,7 @@ class JournalList implements BinderInterface * * @return mixed */ - public static function routeBinder(string $value, Route $route): Collection + public static function routeBinder(string $value, Route $route): Collection { if (auth()->check()) { $list = []; diff --git a/app/Support/Binder/TagList.php b/app/Support/Binder/TagList.php index 8cf851c9dc..60eb79420e 100644 --- a/app/Support/Binder/TagList.php +++ b/app/Support/Binder/TagList.php @@ -26,6 +26,7 @@ use FireflyIII\Models\Tag; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use Illuminate\Routing\Route; use Illuminate\Support\Collection; +use Log; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -39,7 +40,7 @@ class TagList implements BinderInterface * * @return Collection */ - public static function routeBinder(string $value, Route $route): Collection + public static function routeBinder(string $value, Route $route): Collection { if (auth()->check()) { $list = []; @@ -49,11 +50,13 @@ class TagList implements BinderInterface } $list = array_unique($list); if (count($list) === 0) { + Log::error('Tag list is empty.'); throw new NotFoundHttpException; // @codeCoverageIgnore } /** @var TagRepositoryInterface $repository */ $repository = app(TagRepositoryInterface::class); - $allTags = $repository->get(); + $repository->setUser(auth()->user()); + $allTags = $repository->get(); $collection = $allTags->filter( function (Tag $tag) use ($list) { @@ -65,6 +68,7 @@ class TagList implements BinderInterface return $collection; } } + Log::error('TagList: user is not logged in.'); throw new NotFoundHttpException; } } diff --git a/app/Support/Binder/UnfinishedJournal.php b/app/Support/Binder/UnfinishedJournal.php index 92d03ac75f..abcc002eb7 100644 --- a/app/Support/Binder/UnfinishedJournal.php +++ b/app/Support/Binder/UnfinishedJournal.php @@ -37,7 +37,7 @@ class UnfinishedJournal implements BinderInterface * * @return TransactionJournal */ - public static function routeBinder(string $value, Route $route): TransactionJournal + public static function routeBinder(string $value, Route $route): TransactionJournal { if (auth()->check()) { $journal = auth()->user()->transactionJournals()->where('transaction_journals.id', $value) diff --git a/app/Support/ExpandedForm.php b/app/Support/ExpandedForm.php index 04ce257ebb..b04e92b11d 100644 --- a/app/Support/ExpandedForm.php +++ b/app/Support/ExpandedForm.php @@ -25,7 +25,6 @@ namespace FireflyIII\Support; use Amount as Amt; use Carbon\Carbon; use Eloquent; -use FireflyIII\Exceptions\FireflyException; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; use RuntimeException; @@ -288,7 +287,6 @@ class ExpandedForm * @return string * * @throws \Throwable - * @throws Facades\FireflyException */ public function nonSelectableAmount(string $name, $value = null, array $options = []): string { @@ -319,7 +317,6 @@ class ExpandedForm * @return string * * @throws \Throwable - * @throws Facades\FireflyException */ public function nonSelectableBalance(string $name, $value = null, array $options = []): string { diff --git a/app/Support/Import/Configuration/File/Initial.php b/app/Support/Import/Configuration/File/Initial.php index c07b56c4a2..615a72e9f0 100644 --- a/app/Support/Import/Configuration/File/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -113,6 +113,7 @@ class Initial implements ConfigurationInterface // process config, if present: if (isset($data['configuration_file'])) { + Log::debug('Will also upload configuration.'); $this->repository->processConfiguration($this->job, $data['configuration_file']); } diff --git a/app/Support/Import/Configuration/File/Roles.php b/app/Support/Import/Configuration/File/Roles.php index e779582df2..68910c0937 100644 --- a/app/Support/Import/Configuration/File/Roles.php +++ b/app/Support/Import/Configuration/File/Roles.php @@ -59,20 +59,19 @@ class Roles implements ConfigurationInterface $content = $this->repository->uploadFileContents($this->job); $config = $this->getConfig(); $headers = []; - $offset = 0; + // create CSV reader. $reader = Reader::createFromString($content); $reader->setDelimiter($config['delimiter']); if ($config['has-headers']) { - $offset = 1; // get headers: - $stmt = (new Statement)->limit(1)->offset(0); - $records = $stmt->process($reader); - $headers = $records->fetchOne(); + $reader->setHeaderOffset(0); + $headers = $reader->getHeader(); } + // example rows: - $stmt = (new Statement)->limit(intval(config('csv.example_rows', 5)))->offset($offset); + $stmt = (new Statement)->limit(intval(config('csv.example_rows', 5)))->offset(0); // set data: $roles = $this->getRoles(); asort($roles); @@ -85,6 +84,7 @@ class Roles implements ConfigurationInterface $records = $stmt->process($reader); foreach ($records as $row) { + $row = array_values($row); $row = $this->processSpecifics($row); $count = count($row); $this->data['total'] = $count > $this->data['total'] ? $count : $this->data['total']; diff --git a/app/Support/Import/Configuration/File/UploadConfig.php b/app/Support/Import/Configuration/File/UploadConfig.php index 5eeda520d8..9dd8309554 100644 --- a/app/Support/Import/Configuration/File/UploadConfig.php +++ b/app/Support/Import/Configuration/File/UploadConfig.php @@ -121,7 +121,7 @@ class UploadConfig implements ConfigurationInterface // 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['delimiter'] = 'tab' === $delimiter ? "\t" : $delimiter; $config['apply-rules'] = intval($data['apply_rules'] ?? 0) === 1; $config['match-bills'] = intval($data['match_bills'] ?? 0) === 1; @@ -136,7 +136,6 @@ class UploadConfig implements ConfigurationInterface 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); diff --git a/app/Support/Models/TransactionJournalTrait.php b/app/Support/Models/TransactionJournalTrait.php index 103bb83c36..006288e478 100644 --- a/app/Support/Models/TransactionJournalTrait.php +++ b/app/Support/Models/TransactionJournalTrait.php @@ -63,66 +63,6 @@ trait TransactionJournalTrait return false; } - /** - * @return string - */ - public function amount(): string - { - $cache = new CacheProperties; - $cache->addProperty($this->id); - $cache->addProperty('transaction-journal'); - $cache->addProperty('amount'); - if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore - } - - // saves on queries: - $amount = $this->transactions()->where('amount', '>', 0)->get()->sum('amount'); - - if ($this->isWithdrawal()) { - $amount = $amount * -1; - } - $amount = strval($amount); - $cache->store($amount); - - return $amount; - } - - /** - * @return string - */ - public function amountPositive(): string - { - $cache = new CacheProperties; - $cache->addProperty($this->id); - $cache->addProperty('transaction-journal'); - $cache->addProperty('amount-positive'); - if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore - } - - // saves on queries: - $amount = $this->transactions()->where('amount', '>', 0)->get()->sum('amount'); - - $amount = strval($amount); - $cache->store($amount); - - return $amount; - } - - /** - * @return int - */ - public function budgetId(): int - { - $budget = $this->budgets()->first(); - if (null !== $budget) { - return $budget->id; - } - - return 0; - } - /** * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany */ @@ -134,51 +74,7 @@ trait TransactionJournalTrait abstract public function categories(): BelongsToMany; /** - * @return string - */ - public function categoryAsString(): string - { - $category = $this->categories()->first(); - if (null !== $category) { - return $category->name; - } - - return ''; - } - - /** - * @param string $dateField - * - * @return string - */ - public function dateAsString(string $dateField = ''): string - { - if ('' === $dateField) { - return $this->date->format('Y-m-d'); - } - if (null !== $this->$dateField && $this->$dateField instanceof Carbon) { - // make field NULL - $carbon = clone $this->$dateField; - $this->$dateField = null; - $this->save(); - - // create meta entry - $this->setMeta($dateField, $carbon); - - // return that one instead. - return $carbon->format('Y-m-d'); - } - $metaField = $this->getMeta($dateField); - if (null !== $metaField) { - $carbon = new Carbon($metaField); - - return $carbon->format('Y-m-d'); - } - - return ''; - } - - /** + * @deprecated * @return Collection */ public function destinationAccountList(): Collection @@ -203,6 +99,7 @@ trait TransactionJournalTrait } /** + * @deprecated * @return Collection */ public function destinationTransactionList(): Collection @@ -221,6 +118,7 @@ trait TransactionJournalTrait } /** + * * @param string $name * * @return string @@ -253,6 +151,7 @@ trait TransactionJournalTrait abstract public function piggyBankEvents(): HasMany; /** + * @deprecated * @return int */ public function piggyBankId(): int @@ -265,6 +164,7 @@ trait TransactionJournalTrait } /** + * @deprecated * @return Transaction */ public function positiveTransaction(): Transaction @@ -290,6 +190,7 @@ trait TransactionJournalTrait abstract public function setMeta(string $name, $value): TransactionJournalMeta; /** + * @deprecated * @return Collection */ public function sourceAccountList(): Collection @@ -314,6 +215,7 @@ trait TransactionJournalTrait } /** + * @deprecated * @return Collection */ public function sourceTransactionList(): Collection @@ -332,6 +234,7 @@ trait TransactionJournalTrait } /** + * @deprecated * @return string */ public function transactionTypeStr(): string diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index 29c569d26f..f543a706f7 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -38,7 +38,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function addPeriod(Carbon $theDate, string $repeatFreq, int $skip): Carbon { @@ -86,12 +86,17 @@ class Navigation * @param string $range * * @return array - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function blockPeriods(\Carbon\Carbon $start, \Carbon\Carbon $end, string $range): array { + if ($end < $start) { + list($start, $end) = [$end, $start]; + } $periods = []; - // Start by looping per period: + /* + * Start looping per months for 1 year + the rest of the year: + */ $perMonthEnd = clone $end; $perMonthStart = clone $end; $perMonthStart->startOfyear()->subYear(); @@ -148,7 +153,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function endOfPeriod(\Carbon\Carbon $end, string $repeatFreq): Carbon { @@ -211,7 +216,7 @@ class Navigation * @param string $repeatFreq * @param \Carbon\Carbon|null $maxDate * - * @return Carbon + * @return \Carbon\Carbon */ public function endOfX(Carbon $theCurrentEnd, string $repeatFreq, ?Carbon $maxDate): Carbon { @@ -285,11 +290,11 @@ class Navigation /** * @param \Carbon\Carbon $theDate - * @param $repeatFrequency + * @param string $repeatFrequency * * @return string * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function periodShow(Carbon $theDate, string $repeatFrequency): string { @@ -444,7 +449,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function startOfPeriod(Carbon $theDate, string $repeatFreq): Carbon { @@ -496,7 +501,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function subtractPeriod(Carbon $theDate, string $repeatFreq, int $subtract = 1): Carbon { @@ -565,7 +570,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function updateEndDate(string $range, Carbon $start): Carbon { @@ -604,7 +609,7 @@ class Navigation * * @return \Carbon\Carbon * - * @throws FireflyException + * @throws \FireflyIII\Exceptions\FireflyException */ public function updateStartDate(string $range, Carbon $start): Carbon { diff --git a/app/Support/Steam.php b/app/Support/Steam.php index c0f5f291f0..e3453c7f2b 100644 --- a/app/Support/Steam.php +++ b/app/Support/Steam.php @@ -54,14 +54,14 @@ class Steam $currencyId = intval($account->getMeta('currency_id')); // use system default currency: if (0 === $currencyId) { - $currency = app('amount')->getDefaultCurrency(); + $currency = app('amount')->getDefaultCurrencyByUser($account->user); $currencyId = $currency->id; } // first part: get all balances in own currency: $nativeBalance = strval( $account->transactions() ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->where('transaction_journals.date', '<=', $date->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->where('transactions.transaction_currency_id', $currencyId) ->sum('transactions.amount') ); @@ -150,9 +150,10 @@ class Steam $start->subDay(); $end->addDay(); - $balances = []; - $formatted = $start->format('Y-m-d'); - $startBalance = $this->balance($account, $start); + $balances = []; + $formatted = $start->format('Y-m-d'); + $startBalance = $this->balance($account, $start); + $balances[$formatted] = $startBalance; $currencyId = intval($account->getMeta('currency_id')); $start->addDay(); @@ -160,8 +161,8 @@ class Steam // query! $set = $account->transactions() ->leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) - ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d 23:59:59')) ->groupBy('transaction_journals.date') ->groupBy('transactions.transaction_currency_id') ->groupBy('transactions.foreign_currency_id') diff --git a/app/Support/Twig/Extension/Transaction.php b/app/Support/Twig/Extension/Transaction.php index bd87af5b36..8d4ca0e84d 100644 --- a/app/Support/Twig/Extension/Transaction.php +++ b/app/Support/Twig/Extension/Transaction.php @@ -88,6 +88,7 @@ class Transaction extends Twig_Extension $currency->decimal_places = $transaction->foreign_currency_dp; $str .= ' (' . sprintf($format, app('amount')->formatAnything($currency, $amount, $coloured)) . ')'; } + return $str; } @@ -115,6 +116,7 @@ class Transaction extends Twig_Extension $fakeCurrency->symbol = $transaction['foreign_currency_symbol']; $string .= ' (' . app('amount')->formatAnything($fakeCurrency, $amount, true) . ')'; } + return $string; } @@ -201,6 +203,7 @@ class Transaction extends Twig_Extension } $txt = ''; + return $txt; } @@ -350,10 +353,12 @@ class Transaction extends Twig_Extension $count = TransactionModel::where('transaction_journal_id', $journalId)->whereNull('deleted_at')->count(); if ($count > 2) { $res = ''; + return $res; } $res = ''; + return $res; } @@ -403,6 +408,7 @@ class Transaction extends Twig_Extension } $txt = sprintf('%1$s', e($name), route('accounts.show', [$transactionId])); + return $txt; } } diff --git a/app/Support/Twig/Extension/TransactionJournal.php b/app/Support/Twig/Extension/TransactionJournal.php index dba951d952..925b1613f0 100644 --- a/app/Support/Twig/Extension/TransactionJournal.php +++ b/app/Support/Twig/Extension/TransactionJournal.php @@ -64,7 +64,9 @@ class TransactionJournal extends Twig_Extension 'currency' => $foreign, ]; } - $totals[$foreignId]['amount'] = bcadd($transaction->foreign_amount, $totals[$foreignId]['amount']); + $totals[$foreignId]['amount'] = bcadd( + $transaction->foreign_amount, + $totals[$foreignId]['amount']); } } $array = []; diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index d3387e31fd..07a5ffe8e1 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -60,11 +60,12 @@ class General extends Twig_Extension $this->getCurrencySymbol(), $this->phpdate(), $this->env(), - $this->getAmountFromJournal(), + //$this->getAmountFromJournal(), $this->activeRouteStrict(), - $this->steamPositive(), + //$this->steamPositive(), $this->activeRoutePartial(), $this->activeRoutePartialWhat(), + $this->formatDate(), ]; } @@ -179,6 +180,21 @@ class General extends Twig_Extension ); } + /** + * @return Twig_SimpleFunction + */ + protected function formatDate() + { + return new Twig_SimpleFunction( + 'formatDate', + function (string $date, string $format): string { + $carbon = new Carbon($date); + + return $carbon->formatLocalized($format); + } + ); + } + /** * @return Twig_SimpleFilter */ @@ -333,29 +349,4 @@ class General extends Twig_Extension ); } - /** - * @return Twig_SimpleFunction - */ - protected function steamPositive() - { - return new Twig_SimpleFunction( - 'steam_positive', - function (string $str): string { - return Steam::positive($str); - } - ); - } - - /** - * @return Twig_SimpleFunction - */ - private function getAmountFromJournal() - { - return new Twig_SimpleFunction( - 'getAmount', - function (TransactionJournal $journal): string { - return $journal->amount(); - } - ); - } } diff --git a/app/TransactionRules/Actions/SetDestinationAccount.php b/app/TransactionRules/Actions/SetDestinationAccount.php index e522903edf..2ba82a4c7e 100644 --- a/app/TransactionRules/Actions/SetDestinationAccount.php +++ b/app/TransactionRules/Actions/SetDestinationAccount.php @@ -117,7 +117,7 @@ class SetDestinationAccount implements ActionInterface { $account = $this->repository->findByName($this->action->action_value, [AccountType::DEFAULT, AccountType::ASSET]); - if (null === $account->id) { + if (null === $account) { Log::debug(sprintf('There is NO asset account called "%s".', $this->action->action_value)); return false; @@ -134,14 +134,14 @@ class SetDestinationAccount implements ActionInterface private function findExpenseAccount() { $account = $this->repository->findByName($this->action->action_value, [AccountType::EXPENSE]); - if (null === $account->id) { - // create new revenue account with this name: + if (null === $account) { $data = [ - 'name' => $this->action->action_value, - 'accountType' => 'expense', - 'virtualBalance' => 0, - 'active' => true, - 'iban' => null, + 'name' => $this->action->action_value, + 'accountType' => 'expense', + 'account_type_id' => null, + 'virtualBalance' => 0, + 'active' => true, + 'iban' => null, ]; $account = $this->repository->store($data); } diff --git a/app/TransactionRules/Actions/SetSourceAccount.php b/app/TransactionRules/Actions/SetSourceAccount.php index 5244211892..570d697bbd 100644 --- a/app/TransactionRules/Actions/SetSourceAccount.php +++ b/app/TransactionRules/Actions/SetSourceAccount.php @@ -116,7 +116,7 @@ class SetSourceAccount implements ActionInterface { $account = $this->repository->findByName($this->action->action_value, [AccountType::DEFAULT, AccountType::ASSET]); - if (null === $account->id) { + if (null === $account) { Log::debug(sprintf('There is NO asset account called "%s".', $this->action->action_value)); return false; @@ -133,14 +133,15 @@ class SetSourceAccount implements ActionInterface private function findRevenueAccount() { $account = $this->repository->findByName($this->action->action_value, [AccountType::REVENUE]); - if (null === $account->id) { + if (null === $account) { // create new revenue account with this name: $data = [ - 'name' => $this->action->action_value, - 'accountType' => 'revenue', - 'virtualBalance' => 0, - 'active' => true, - 'iban' => null, + 'name' => $this->action->action_value, + 'accountType' => 'revenue', + 'account_type_id' => null, + 'virtualBalance' => 0, + 'active' => true, + 'iban' => null, ]; $account = $this->repository->store($data); } diff --git a/app/TransactionRules/Triggers/AmountExactly.php b/app/TransactionRules/Triggers/AmountExactly.php index f0bdfd5d29..cabe53c3df 100644 --- a/app/TransactionRules/Triggers/AmountExactly.php +++ b/app/TransactionRules/Triggers/AmountExactly.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Log; /** @@ -65,7 +66,12 @@ final class AmountExactly extends AbstractTrigger implements TriggerInterface */ public function triggered(TransactionJournal $journal): bool { - $amount = $journal->destination_amount ?? $journal->amountPositive(); + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($journal->user); + + + $amount = $journal->destination_amount ?? $repos->getJournalTotal($journal); $compare = $this->triggerValue; $result = bccomp($amount, $compare); if (0 === $result) { diff --git a/app/TransactionRules/Triggers/AmountLess.php b/app/TransactionRules/Triggers/AmountLess.php index f27fbc0740..d39579ab17 100644 --- a/app/TransactionRules/Triggers/AmountLess.php +++ b/app/TransactionRules/Triggers/AmountLess.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Log; /** @@ -65,7 +66,11 @@ final class AmountLess extends AbstractTrigger implements TriggerInterface */ public function triggered(TransactionJournal $journal): bool { - $amount = $journal->destination_amount ?? $journal->amountPositive(); + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($journal->user); + + $amount = $journal->destination_amount ?? $repos->getJournalTotal($journal); $compare = $this->triggerValue; $result = bccomp($amount, $compare); if ($result === -1) { diff --git a/app/TransactionRules/Triggers/AmountMore.php b/app/TransactionRules/Triggers/AmountMore.php index 894068a032..a56d9cede5 100644 --- a/app/TransactionRules/Triggers/AmountMore.php +++ b/app/TransactionRules/Triggers/AmountMore.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Log; /** @@ -71,7 +72,11 @@ final class AmountMore extends AbstractTrigger implements TriggerInterface */ public function triggered(TransactionJournal $journal): bool { - $amount = $journal->destination_amount ?? $journal->amountPositive(); + /** @var JournalRepositoryInterface $repos */ + $repos = app(JournalRepositoryInterface::class); + $repos->setUser($journal->user); + + $amount = $journal->destination_amount ?? $repos->getJournalTotal($journal); $compare = $this->triggerValue; $result = bccomp($amount, $compare); if (1 === $result) { diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php new file mode 100644 index 0000000000..b36a05f25c --- /dev/null +++ b/app/Transformers/AccountTransformer.php @@ -0,0 +1,243 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use Carbon\Carbon; +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Note; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class AccountTransformer + */ +class AccountTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include. + * + * @var array + */ + protected $availableIncludes = ['transactions', 'piggy_banks', 'user']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + /** @var ParameterBag */ + protected $parameters; + + /** + * + * AccountTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include piggy banks into end result. + * + * @codeCoverageIgnore + * + * @param Account $account + * + * @return FractalCollection + */ + public function includePiggyBanks(Account $account): FractalCollection + { + $piggies = $account->piggyBanks()->get(); + + return $this->collection($piggies, new PiggyBankTransformer($this->parameters), 'piggy_banks'); + } + + /** + * Include transactions into end result. + * + * @codeCoverageIgnore + * + * @param Account $account + * + * @return FractalCollection + */ + public function includeTransactions(Account $account): FractalCollection + { + $pageSize = intval(app('preferences')->getForUser($account->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($account->user); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + if ($account->accountType->type === AccountType::ASSET) { + $collector->setAccounts(new Collection([$account])); + } else { + $collector->setOpposingAccounts(new Collection([$account])); + } + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Include user data in end result. + * + * @codeCoverageIgnore + * + * @param Account $account + * + * @return Item + */ + public function includeUser(Account $account): Item + { + return $this->item($account->user, new UserTransformer($this->parameters), 'user'); + } + + /** + * Transform the account. + * + * @param Account $account + * + * @return array + */ + public function transform(Account $account): array + { + $type = $account->accountType->type; + $role = $account->getMeta('accountRole'); + if (strlen($role) === 0 || $type !== AccountType::ASSET) { + $role = null; + } + $currencyId = (int)$account->getMeta('currency_id'); + $currencyCode = null; + $decimalPlaces = 2; + if ($currencyId > 0) { + $currency = TransactionCurrency::find($currencyId); + $currencyCode = $currency->code; + $decimalPlaces = $currency->decimal_places; + } + + $date = new Carbon; + if (!is_null($this->parameters->get('date'))) { + $date = $this->parameters->get('date'); + } + + if ($currencyId === 0) { + $currencyId = null; + } + + $monthlyPaymentDate = null; + $creditCardType = null; + if ($role === 'ccAsset' && $type === AccountType::ASSET) { + $creditCardType = $this->getMeta($account, 'ccType'); + $monthlyPaymentDate = $this->getMeta($account, 'ccMonthlyPaymentDate'); + } + + $openingBalance = null; + $openingBalanceDate = null; + if ($type === AccountType::ASSET) { + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setuser($account->user); + $amount = $repository->getOpeningBalanceAmount($account); + $openingBalance = is_null($amount) ? null : round($amount, $decimalPlaces); + $openingBalanceDate = $repository->getOpeningBalanceDate($account); + } + + $data = [ + 'id' => (int)$account->id, + 'updated_at' => $account->updated_at->toAtomString(), + 'created_at' => $account->created_at->toAtomString(), + 'name' => $account->name, + 'active' => intval($account->active) === 1, + 'type' => $type, + 'currency_id' => $currencyId, + 'currency_code' => $currencyCode, + 'current_balance' => round(app('steam')->balance($account, $date), $decimalPlaces), + 'current_balance_date' => $date->format('Y-m-d'), + 'notes' => null, + 'monthly_payment_date' => $monthlyPaymentDate, + 'credit_card_type' => $creditCardType, + 'account_number' => $this->getMeta($account, 'accountNumber'), + 'iban' => $account->iban, + 'bic' => $this->getMeta($account, 'BIC'), + 'virtual_balance' => round($account->virtual_balance, $decimalPlaces), + 'opening_balance' => $openingBalance, + 'opening_balance_date' => $openingBalanceDate, + 'role' => $role, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/accounts/' . $account->id, + ], + ], + ]; + + /** @var Note $note */ + $note = $account->notes()->first(); + if (!is_null($note)) { + $data['notes'] = $note->text; // @codeCoverageIgnore + } + + return $data; + } + + /** + * Get meta data field for account. + * + * @codeCoverageIgnore + * + * @param Account $account + * @param string $field + * + * @return null|string + */ + private function getMeta(Account $account, string $field): ?string + { + $result = $account->getMeta($field); + if (strlen($result) === 0) { + return null; + } + + return $result; + } + +} \ No newline at end of file diff --git a/app/Transformers/AttachmentTransformer.php b/app/Transformers/AttachmentTransformer.php new file mode 100644 index 0000000000..18e990cc67 --- /dev/null +++ b/app/Transformers/AttachmentTransformer.php @@ -0,0 +1,109 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Models\Attachment; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class AttachmentTransformer + */ +class AttachmentTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['user']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = ['user']; + + /** @var ParameterBag */ + protected $parameters; + + /** + * BillTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Attach the user. + * + * @codeCoverageIgnore + * + * @param Attachment $attachment + * + * @return Item + */ + public function includeUser(Attachment $attachment): Item + { + return $this->item($attachment->user, new UserTransformer($this->parameters), 'user'); + } + + /** + * Transform attachment. + * + * @param Attachment $attachment + * + * @return array + */ + public function transform(Attachment $attachment): array + { + return [ + 'id' => (int)$attachment->id, + 'updated_at' => $attachment->updated_at->toAtomString(), + 'created_at' => $attachment->created_at->toAtomString(), + 'attachable_type' => $attachment->attachable_type, + 'md5' => $attachment->md5, + 'filename' => $attachment->filename, + 'title' => $attachment->title, + 'description' => $attachment->description, + 'notes' => $attachment->notes, + 'mime' => $attachment->mime, + 'size' => $attachment->size, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/attachment/' . $attachment->id, + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/app/Transformers/BillTransformer.php b/app/Transformers/BillTransformer.php new file mode 100644 index 0000000000..878e88b5b3 --- /dev/null +++ b/app/Transformers/BillTransformer.php @@ -0,0 +1,295 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + +use Carbon\Carbon; +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Note; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Log; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class BillTransformer + */ +class BillTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['attachments', 'transactions', 'user']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * BillTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include any attachments. + * + * @param Bill $bill + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeAttachments(Bill $bill): FractalCollection + { + $attachments = $bill->attachments()->get(); + + return $this->collection($attachments, new AttachmentTransformer($this->parameters), 'attachments'); + } + + /** + * Include any transactions. + * + * @param Bill $bill + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeTransactions(Bill $bill): FractalCollection + { + $pageSize = intval(app('preferences')->getForUser($bill->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($bill->user); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + $collector->setAllAssetAccounts(); + $collector->setBills(new Collection([$bill])); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Include the user. + * + * @param Bill $bill + * + * @codeCoverageIgnore + * @return \League\Fractal\Resource\Item + */ + public function includeUser(Bill $bill): Item + { + return $this->item($bill->user, new UserTransformer($this->parameters), 'users'); + } + + /** + * Transform the bill. + * + * @param Bill $bill + * + * @return array + */ + public function transform(Bill $bill): array + { + $paidData = $this->paidData($bill); + $payDates = $this->payDates($bill); + $data = [ + 'id' => (int)$bill->id, + 'updated_at' => $bill->updated_at->toAtomString(), + 'created_at' => $bill->created_at->toAtomString(), + 'name' => $bill->name, + 'match' => explode(',', $bill->match), + 'amount_min' => round($bill->amount_min, 2), + 'amount_max' => round($bill->amount_max, 2), + 'date' => $bill->date->format('Y-m-d'), + 'repeat_freq' => $bill->repeat_freq, + 'skip' => (int)$bill->skip, + 'automatch' => intval($bill->automatch) === 1, + 'active' => intval($bill->active) === 1, + 'attachments_count' => $bill->attachments()->count(), + 'pay_dates' => $payDates, + 'paid_dates' => $paidData['paid_dates'], + 'next_expected_match' => $paidData['next_expected_match'], + 'notes' => null, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/bills/' . $bill->id, + ], + ], + ]; + /** @var Note $note */ + $note = $bill->notes()->first(); + if (!is_null($note)) { + $data['notes'] = $note->text; + } + + return $data; + + } + + /** + * Returns the latest date in the set, or start when set is empty. + * + * @param Collection $dates + * @param Carbon $default + * + * @return Carbon + */ + protected function lastPaidDate(Collection $dates, Carbon $default): Carbon + { + if (0 === $dates->count()) { + return $default; // @codeCoverageIgnore + } + $latest = $dates->first(); + /** @var Carbon $date */ + foreach ($dates as $date) { + if ($date->gte($latest)) { + $latest = $date; + } + } + + return $latest; + } + + /** + * Given a bill and a date, this method will tell you at which moment this bill expects its next + * transaction. Whether or not it is there already, is not relevant. + * + * @param Bill $bill + * @param Carbon $date + * + * @return \Carbon\Carbon + */ + protected function nextDateMatch(Bill $bill, Carbon $date): Carbon + { + $start = clone $bill->date; + while ($start < $date) { + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + } + + return $start; + } + + /** + * Get the data the bill was paid and predict the next expected match. + * + * @param Bill $bill + * + * @return array + */ + protected function paidData(Bill $bill): array + { + Log::debug(sprintf('Now in paidData for bill #%d', $bill->id)); + if (is_null($this->parameters->get('start')) || is_null($this->parameters->get('end'))) { + Log::debug('parameters are NULL, return empty array'); + + return [ + 'paid_dates' => [], + 'next_expected_match' => null, + ]; + } + + /** @var BillRepositoryInterface $repository */ + $repository = app(BillRepositoryInterface::class); + $repository->setUser($bill->user); + $set = $repository->getPaidDatesInRange($bill, $this->parameters->get('start'), $this->parameters->get('end')); + Log::debug(sprintf('Count %d entries in getPaidDatesInRange()', $set->count())); + $simple = $set->map( + function (Carbon $date) { + return $date->format('Y-m-d'); + } + ); + + // calculate next expected match: + $lastPaidDate = $this->lastPaidDate($set, $this->parameters->get('start')); + $nextMatch = clone $bill->date; + while ($nextMatch < $lastPaidDate) { + $nextMatch = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip); + } + $end = app('navigation')->addPeriod($nextMatch, $bill->repeat_freq, $bill->skip); + $journalCount = $repository->getPaidDatesInRange($bill, $nextMatch, $end)->count(); + if ($journalCount > 0) { + $nextMatch = clone $end; + } + + return [ + 'paid_dates' => $simple->toArray(), + 'next_expected_match' => $nextMatch->format('Y-m-d'), + ]; + } + + /** + * @param Bill $bill + * + * @return array + */ + protected function payDates(Bill $bill): array + { + if (is_null($this->parameters->get('start')) || is_null($this->parameters->get('end'))) { + return []; + } + $set = new Collection; + $currentStart = clone $this->parameters->get('start'); + while ($currentStart <= $this->parameters->get('end')) { + $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); + // If nextExpectedMatch is after end, we continue: + if ($nextExpectedMatch > $this->parameters->get('end')) { + break; + } + // add to set + $set->push(clone $nextExpectedMatch); + $nextExpectedMatch->addDay(); + $currentStart = clone $nextExpectedMatch; + } + $simple = $set->map( + function (Carbon $date) { + return $date->format('Y-m-d'); + } + ); + + return $simple->toArray(); + } +} \ No newline at end of file diff --git a/app/Transformers/BudgetTransformer.php b/app/Transformers/BudgetTransformer.php new file mode 100644 index 0000000000..6423aa70c1 --- /dev/null +++ b/app/Transformers/BudgetTransformer.php @@ -0,0 +1,135 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Budget; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class BudgetTransformer + */ +class BudgetTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['user', 'transactions']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * BudgetTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include any transactions. + * + * @param Budget $budget + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeTransactions(Budget $budget): FractalCollection + { + $pageSize = intval(app('preferences')->getForUser($budget->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($budget->user); + $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); + $collector->setAllAssetAccounts(); + $collector->setBudgets(new Collection([$budget])); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Include the user. + * + * @param Budget $budget + * + * @codeCoverageIgnore + * @return Item + */ + public function includeUser(Budget $budget): Item + { + return $this->item($budget->user, new UserTransformer($this->parameters), 'users'); + } + + /** + * Transform a budget. + * + * @param Budget $budget + * + * @return array + */ + public function transform(Budget $budget): array + { + $data = [ + 'id' => (int)$budget->id, + 'updated_at' => $budget->updated_at->toAtomString(), + 'created_at' => $budget->created_at->toAtomString(), + 'active' => intval($budget->active) === 1, + 'name' => $budget->name, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/budgets/' . $budget->id, + ], + ], + ]; + + return $data; + } + +} \ No newline at end of file diff --git a/app/Transformers/CategoryTransformer.php b/app/Transformers/CategoryTransformer.php new file mode 100644 index 0000000000..c25222d43a --- /dev/null +++ b/app/Transformers/CategoryTransformer.php @@ -0,0 +1,134 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Category; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class CategoryTransformer + */ +class CategoryTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['user', 'transactions']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * CategoryTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include any transactions. + * + * @param Category $category + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeTransactions(Category $category): FractalCollection + { + $pageSize = intval(app('preferences')->getForUser($category->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($category->user); + $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); + $collector->setAllAssetAccounts(); + $collector->setCategories(new Collection([$category])); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Include the user. + * + * @param Category $category + * + * @codeCoverageIgnore + * @return Item + */ + public function includeUser(Category $category): Item + { + return $this->item($category->user, new UserTransformer($this->parameters), 'users'); + } + + /** + * Convert category. + * + * @param Category $category + * + * @return array + */ + public function transform(Category $category): array + { + $data = [ + 'id' => (int)$category->id, + 'updated_at' => $category->updated_at->toAtomString(), + 'created_at' => $category->created_at->toAtomString(), + 'name' => $category->name, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/categories/' . $category->id, + ], + ], + ]; + + return $data; + } + +} \ No newline at end of file diff --git a/app/Transformers/JournalMetaTransformer.php b/app/Transformers/JournalMetaTransformer.php new file mode 100644 index 0000000000..23d9359397 --- /dev/null +++ b/app/Transformers/JournalMetaTransformer.php @@ -0,0 +1,123 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\TransactionJournalMeta; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class JournalMetaTransformer + */ +class JournalMetaTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['transactions']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * JournalMetaTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include any transactions. + * + * @param TransactionJournalMeta $meta + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeTransactions(TransactionJournalMeta $meta): FractalCollection + { + $journal = $meta->transactionJournal; + $pageSize = intval(app('preferences')->getForUser($journal->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($journal->user); + $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); + $collector->setAllAssetAccounts(); + $collector->setJournals(new Collection([$journal])); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Convert meta object. + * + * @param TransactionJournalMeta $meta + * + * @return array + */ + public function transform(TransactionJournalMeta $meta): array + { + $data = [ + 'id' => (int)$meta->id, + 'updated_at' => $meta->updated_at->toAtomString(), + 'created_at' => $meta->created_at->toAtomString(), + 'name' => $meta->name, + 'data' => $meta->data, + 'hash' => $meta->hash, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/journal_meta/' . $meta->id, + ], + ], + ]; + + return $data; + } + +} \ No newline at end of file diff --git a/app/Transformers/PiggyBankEventTransformer.php b/app/Transformers/PiggyBankEventTransformer.php new file mode 100644 index 0000000000..5a3daf2719 --- /dev/null +++ b/app/Transformers/PiggyBankEventTransformer.php @@ -0,0 +1,148 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\PiggyBankEvent; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class PiggyBankEventTransformer + */ +class PiggyBankEventTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['piggy_bank', 'transaction']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * PiggyBankEventTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include piggy bank into end result. + * + * @codeCoverageIgnore + * + * @param PiggyBankEvent $event + * + * @return Item + */ + public function includePiggyBank(PiggyBankEvent $event): Item + { + return $this->item($event->piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks'); + } + + /** + * Include transaction into end result. + * + * @codeCoverageIgnore + * + * @param PiggyBankEvent $event + * + * @return Item + */ + public function includeTransaction(PiggyBankEvent $event): Item + { + $journal = $event->transactionJournal; + $pageSize = intval(app('preferences')->getForUser($journal->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($journal->user); + $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); + $collector->setAllAssetAccounts(); + $collector->setJournals(new Collection([$journal])); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->item($journals->first(), new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Convert piggy bank event. + * + * @param PiggyBankEvent $event + * + * @return array + */ + public function transform(PiggyBankEvent $event): array + { + $account = $event->piggyBank->account; + $currencyId = intval($account->getMeta('currency_id')); + $decimalPlaces = 2; + if ($currencyId > 0) { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + $repository->setUser($account->user); + $currency = $repository->findNull($currencyId); + $decimalPlaces = $currency->decimal_places; + } + + $data = [ + 'id' => (int)$event->id, + 'updated_at' => $event->updated_at->toAtomString(), + 'created_at' => $event->created_at->toAtomString(), + 'amount' => round($event->amount, $decimalPlaces), + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/piggy_bank_events/' . $event->id, + ], + ], + ]; + + return $data; + } + +} \ No newline at end of file diff --git a/app/Transformers/PiggyBankTransformer.php b/app/Transformers/PiggyBankTransformer.php new file mode 100644 index 0000000000..55ba083cf6 --- /dev/null +++ b/app/Transformers/PiggyBankTransformer.php @@ -0,0 +1,166 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Models\Note; +use FireflyIII\Models\PiggyBank; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class PiggyBankTransformer + */ +class PiggyBankTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['account', 'user', 'piggy_bank_events']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * PiggyBankTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include account. + * + * @codeCoverageIgnore + * + * @param PiggyBank $piggyBank + * + * @return Item + */ + public function includeAccount(PiggyBank $piggyBank): Item + { + return $this->item($piggyBank->account, new AccountTransformer($this->parameters), 'accounts'); + } + + /** + * Include events. + * + * @codeCoverageIgnore + * + * @param PiggyBank $piggyBank + * + * @return FractalCollection + */ + public function includePiggyBankEvents(PiggyBank $piggyBank): FractalCollection + { + return $this->collection($piggyBank->piggyBankEvents, new PiggyBankEventTransformer($this->parameters), 'piggy_bank_events'); + } + + /** + * Include the user. + * + * @param PiggyBank $piggyBank + * + * @codeCoverageIgnore + * @return Item + */ + public function includeUser(PiggyBank $piggyBank): Item + { + return $this->item($piggyBank->account->user, new UserTransformer($this->parameters), 'users'); + } + + /** + * Transform the piggy bank. + * + * @param PiggyBank $piggyBank + * + * @return array + */ + public function transform(PiggyBank $piggyBank): array + { + $account = $piggyBank->account; + $currencyId = intval($account->getMeta('currency_id')); + $decimalPlaces = 2; + if ($currencyId > 0) { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + $repository->setUser($account->user); + $currency = $repository->findNull($currencyId); + $decimalPlaces = $currency->decimal_places; + } + + // get currently saved amount: + /** @var PiggyBankRepositoryInterface $piggyRepos */ + $piggyRepos = app(PiggyBankRepositoryInterface::class); + $piggyRepos->setUser($account->user); + $currentAmount = round($piggyRepos->getCurrentAmount($piggyBank), $decimalPlaces); + + $startDate = is_null($piggyBank->startdate) ? null : $piggyBank->startdate->format('Y-m-d'); + $targetDate = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate->format('Y-m-d'); + $targetAmount = round($piggyBank->targetamount, $decimalPlaces); + $data = [ + 'id' => (int)$piggyBank->id, + 'updated_at' => $piggyBank->updated_at->toAtomString(), + 'created_at' => $piggyBank->created_at->toAtomString(), + 'name' => $piggyBank->name, + 'target_amount' => $targetAmount, + 'current_amount' => $currentAmount, + 'startdate' => $startDate, + 'targetdate' => $targetDate, + 'order' => (int)$piggyBank->order, + 'active' => intval($piggyBank->active) === 1, + 'notes' => null, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/piggy_banks/' . $piggyBank->id, + ], + ], + ]; + /** @var Note $note */ + $note = $piggyBank->notes()->first(); + if (!is_null($note)) { + $data['notes'] = $note->text; + } + + return $data; + } +} \ No newline at end of file diff --git a/app/Transformers/TagTransformer.php b/app/Transformers/TagTransformer.php new file mode 100644 index 0000000000..20c9ee2023 --- /dev/null +++ b/app/Transformers/TagTransformer.php @@ -0,0 +1,140 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Helpers\Collector\JournalCollector; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Models\Tag; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class TagTransformer + */ +class TagTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['user', 'transactions']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * TagTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include any transactions. + * + * @param Tag $tag + * + * @codeCoverageIgnore + * @return FractalCollection + */ + public function includeTransactions(Tag $tag): FractalCollection + { + $pageSize = intval(app('preferences')->getForUser($tag->user, 'listPageSize', 50)->data); + + // journals always use collector and limited using URL parameters. + $collector = app(JournalCollectorInterface::class); + $collector->setUser($tag->user); + $collector->withOpposingAccount()->withCategoryInformation()->withCategoryInformation(); + $collector->setAllAssetAccounts(); + $collector->setTag($tag); + if (!is_null($this->parameters->get('start')) && !is_null($this->parameters->get('end'))) { + $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + } + $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); + $journals = $collector->getJournals(); + + return $this->collection($journals, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Include the user. + * + * @param Tag $tag + * + * @codeCoverageIgnore + * @return Item + */ + public function includeUser(Tag $tag): Item + { + return $this->item($tag->user, new UserTransformer($this->parameters), 'users'); + } + + /** + * Transform a tag. + * + * @param Tag $tag + * + * @return array + */ + public function transform(Tag $tag): array + { + $date = is_null($tag->date) ? null : $tag->date->format('Y-m-d'); + $data = [ + 'id' => (int)$tag->id, + 'updated_at' => $tag->updated_at->toAtomString(), + 'created_at' => $tag->created_at->toAtomString(), + 'tag' => $tag->tag, + 'tag_mode' => $tag->tagMode, + 'date' => $date, + 'description' => $tag->description === '' ? null : $tag->description, + 'latitude' => (float)$tag->latitude, + 'longitude' => (float)$tag->longitude, + 'zoom_level' => (int)$tag->zoomLevel, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/tags/' . $tag->id, + ], + ], + ]; + + return $data; + } + +} \ No newline at end of file diff --git a/app/Transformers/TransactionTransformer.php b/app/Transformers/TransactionTransformer.php new file mode 100644 index 0000000000..ac4386ac7e --- /dev/null +++ b/app/Transformers/TransactionTransformer.php @@ -0,0 +1,258 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Note; +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionType; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class TransactionTransformer + */ +class TransactionTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include + * + * @var array + */ + protected $availableIncludes = ['attachments', 'user', 'tags', 'journal_meta', 'piggy_bank_events']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * TransactionTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include attachments. + * + * @codeCoverageIgnore + * + * @param Transaction $transaction + * + * @return FractalCollection + */ + public function includeAttachments(Transaction $transaction): FractalCollection + { + return $this->collection($transaction->transactionJournal->attachments, new AttachmentTransformer($this->parameters), 'attachments'); + } + + /** + * Include meta data + * + * @codeCoverageIgnore + * + * @param Transaction $transaction + * + * @return FractalCollection + */ + public function includeJournalMeta(Transaction $transaction): FractalCollection + { + $meta = $transaction->transactionJournal->transactionJournalMeta()->get(); + + return $this->collection($meta, new JournalMetaTransformer($this->parameters), 'journal_meta'); + } + + /** + * Include piggy bank events + * + * @codeCoverageIgnore + * + * @param Transaction $transaction + * + * @return FractalCollection + */ + public function includePiggyBankEvents(Transaction $transaction): FractalCollection + { + $events = $transaction->transactionJournal->piggyBankEvents()->get(); + + return $this->collection($events, new PiggyBankEventTransformer($this->parameters), 'piggy_bank_events'); + } + + /** + * Include tags + * + * @codeCoverageIgnore + * + * @param Transaction $transaction + * + * @return FractalCollection + */ + public function includeTags(Transaction $transaction): FractalCollection + { + $set = $transaction->transactionJournal->tags; + + return $this->collection($set, new TagTransformer($this->parameters), 'tags'); + } + + /** + * Include the user. + * + * @codeCoverageIgnore + * + * @param Transaction $transaction + * + * @return \League\Fractal\Resource\Item + */ + public function includeUser(Transaction $transaction): Item + { + return $this->item($transaction->transactionJournal->user, new UserTransformer($this->parameters), 'users'); + } + + + /** + * Transform the journal. + * + * @param Transaction $transaction + * + * @return array + * @throws FireflyException + */ + public function transform(Transaction $transaction): array + { + $categoryId = null; + $categoryName = null; + $budgetId = null; + $budgetName = null; + $categoryId = is_null($transaction->transaction_category_id) ? $transaction->transaction_journal_category_id + : $transaction->transaction_category_id; + $categoryName = is_null($transaction->transaction_category_name) ? $transaction->transaction_journal_category_name + : $transaction->transaction_category_name; + + if ($transaction->transaction_type_type === TransactionType::WITHDRAWAL) { + $budgetId = is_null($transaction->transaction_budget_id) ? $transaction->transaction_journal_budget_id + : $transaction->transaction_budget_id; + $budgetName = is_null($transaction->transaction_budget_name) ? $transaction->transaction_journal_budget_name + : $transaction->transaction_budget_name; + } + /** @var Note $dbNote */ + $dbNote = $transaction->transactionJournal->notes()->first(); + $notes = null; + if(!is_null($dbNote)) { + $notes = $dbNote->text; + } + + $data = [ + 'id' => (int)$transaction->id, + 'updated_at' => $transaction->updated_at->toAtomString(), + 'created_at' => $transaction->created_at->toAtomString(), + 'description' => $transaction->description, + 'date' => $transaction->date->format('Y-m-d'), + 'type' => $transaction->transaction_type_type, + 'identifier' => $transaction->identifier, + 'journal_id' => (int)$transaction->journal_id, + 'reconciled' => (bool)$transaction->reconciled, + 'amount' => round($transaction->transaction_amount, intval($transaction->transaction_currency_dp)), + 'currency_id' => $transaction->transaction_currency_id, + 'currency_code' => $transaction->transaction_currency_code, + 'currency_dp' => $transaction->transaction_currency_dp, + 'foreign_amount' => null, + 'foreign_currency_id' => $transaction->foreign_currency_id, + 'foreign_currency_code' => $transaction->foreign_currency_code, + 'foreign_currency_dp' => $transaction->foreign_currency_dp, + 'bill_id' => $transaction->bill_id, + 'bill_name' => $transaction->bill_name, + 'category_id' => $categoryId, + 'category_name' => $categoryName, + 'budget_id' => $budgetId, + 'budget_name' => $budgetName, + 'notes' => $notes, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/transactions/' . $transaction->id, + ], + ], + ]; + + // expand foreign amount: + if (!is_null($transaction->transaction_foreign_amount)) { + $data['foreign_amount'] = round($transaction->transaction_foreign_amount, intval($transaction->foreign_currency_dp)); + } + + // switch on type for consistency + switch ($transaction->transaction_type_type) { + case TransactionType::WITHDRAWAL: + $data['source_id'] = $transaction->account_id; + $data['source_name'] = $transaction->account_name; + $data['source_iban'] = $transaction->account_iban; + $data['source_type'] = $transaction->account_type; + $data['destination_id'] = $transaction->opposing_account_id; + $data['destination_name'] = $transaction->opposing_account_name; + $data['destination_iban'] = $transaction->opposing_account_iban; + $data['destination_type'] = $transaction->opposing_account_type; + break; + case TransactionType::DEPOSIT: + case TransactionType::TRANSFER: + case TransactionType::OPENING_BALANCE: + case TransactionType::RECONCILIATION: + $data['source_id'] = $transaction->opposing_account_id; + $data['source_name'] = $transaction->opposing_account_name; + $data['source_iban'] = $transaction->opposing_account_iban; + $data['source_type'] = $transaction->opposing_account_type; + $data['destination_id'] = $transaction->account_id; + $data['destination_name'] = $transaction->account_name; + $data['destination_iban'] = $transaction->account_iban; + $data['destination_type'] = $transaction->account_type; + break; + default: + // @codeCoverageIgnoreStart + throw new FireflyException( + sprintf('Transaction transformer cannot handle transactions of type "%s"!', $transaction->transaction_type_type) + ); + // @codeCoverageIgnoreEnd + + } + + // expand description. + if (strlen(strval($transaction->transaction_description)) > 0) { + $data['description'] = $transaction->transaction_description . ' (' . $transaction->description . ')'; + } + + + return $data; + } +} \ No newline at end of file diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php new file mode 100644 index 0000000000..66e5c835e5 --- /dev/null +++ b/app/Transformers/UserTransformer.php @@ -0,0 +1,208 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers; + + +use FireflyIII\Models\Role; +use FireflyIII\User; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class UserTransformer + */ +class UserTransformer extends TransformerAbstract +{ + /** + * List of resources possible to include. + * + * @var array + */ + protected $availableIncludes = ['accounts', 'attachments', 'bills', 'budgets', 'categories', 'piggy_banks', 'tags', 'transactions']; + /** + * List of resources to automatically include + * + * @var array + */ + protected $defaultIncludes = []; + + /** @var ParameterBag */ + protected $parameters; + + /** + * UserTransformer constructor. + * + * @codeCoverageIgnore + * + * @param ParameterBag $parameters + */ + public function __construct(ParameterBag $parameters) + { + $this->parameters = $parameters; + } + + /** + * Include accounts. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeAccounts(User $user): FractalCollection + { + return $this->collection($user->accounts, new AccountTransformer($this->parameters), 'accounts'); + } + + /** + * Include attachments. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeAttachments(User $user): FractalCollection + { + return $this->collection($user->attachments, new AttachmentTransformer($this->parameters), 'attachments'); + } + + /** + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeBills(User $user): FractalCollection + { + return $this->collection($user->bills, new BillTransformer($this->parameters), 'bills'); + } + + /** + * Include budgets. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeBudgets(User $user): FractalCollection + { + return $this->collection($user->budgets, new BudgetTransformer($this->parameters), 'budgets'); + } + + /** + * Include categories. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeCategories(User $user): FractalCollection + { + return $this->collection($user->categories, new CategoryTransformer($this->parameters), 'categories'); + } + + /** + * Include piggy banks. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includePiggyBanks(User $user): FractalCollection + { + return $this->collection($user->piggyBanks, new PiggyBankTransformer($this->parameters), 'piggy_banks'); + } + + /** + * Include tags. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeTags(User $user): FractalCollection + { + return $this->collection($user->tags, new TagTransformer($this->parameters), 'tags'); + } + + /** + * Include transactions. + * + * @codeCoverageIgnore + * + * @param User $user + * + * @return FractalCollection + */ + public function includeTransactions(User $user): FractalCollection + { + return $this->collection($user->transactions, new TransactionTransformer($this->parameters), 'transactions'); + } + + /** + * Transform user. + * + * @param User $user + * + * @return array + */ + public function transform(User $user): array + { + /** @var Role $role */ + $role = $user->roles()->first(); + if (!is_null($role)) { + $role = $role->name; + } + + return [ + 'id' => (int)$user->id, + 'updated_at' => $user->updated_at->toAtomString(), + 'created_at' => $user->created_at->toAtomString(), + 'email' => $user->email, + 'blocked' => intval($user->blocked) === 1, + 'blocked_code' => $user->blocked_code, + 'role' => $role, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/users/' . $user->id, + ], + ], + ]; + } + +} \ No newline at end of file diff --git a/app/User.php b/app/User.php index db03b5189f..d8d76af5e7 100644 --- a/app/User.php +++ b/app/User.php @@ -30,6 +30,7 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\QueryException; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Laravel\Passport\HasApiTokens; use Log; use Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -39,15 +40,25 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class User extends Authenticatable { - use Notifiable; + use Notifiable, HasApiTokens; + /** + * The attributes that should be casted to native types. + * + * @var array + */ + protected $casts + = [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'blocked' => 'boolean', + ]; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['email', 'password', 'blocked', 'blocked_code']; - /** * The attributes excluded from the model's JSON form. * diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index 8427db6780..ff07c8321b 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -65,7 +65,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validate2faCode(/** @scrutinizer ignore-unused */ $attribute, $value): bool + public function validate2faCode($attribute, $value): bool { if (!is_string($value) || null === $value || 6 != strlen($value)) { return false; @@ -85,7 +85,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateBelongsToUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateBelongsToUser($attribute, $value, $parameters): bool { $field = $parameters[1] ?? 'id'; @@ -108,7 +108,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateBic(/** @scrutinizer ignore-unused */ $attribute, $value): bool + public function validateBic($attribute, $value): bool { $regex = '/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i'; $result = preg_match($regex, $value); @@ -130,7 +130,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateIban(/** @scrutinizer ignore-unused */ $attribute, $value): bool + public function validateIban($attribute, $value): bool { if (!is_string($value) || null === $value || strlen($value) < 6) { return false; @@ -210,11 +210,11 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateMore(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateMore($attribute, $value, $parameters): bool { - $compare = $parameters[0] ?? '0'; + $compare = strval($parameters[0] ?? '0'); - return bccomp($value, $compare) > 0; + return bccomp(strval($value), $compare) > 0; } /** @@ -226,7 +226,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateMustExist(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateMustExist($attribute, $value, $parameters): bool { $field = $parameters[1] ?? 'id'; @@ -335,7 +335,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateSecurePassword(/** @scrutinizer ignore-unused */ $attribute, $value): bool + public function validateSecurePassword($attribute, $value): bool { $verify = false; if (isset($this->data['verify_password'])) { @@ -360,7 +360,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateUniqueAccountForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateUniqueAccountForUser($attribute, $value, $parameters): bool { // because a user does not have to be logged in (tests and what-not). if (!auth()->check()) { @@ -368,7 +368,10 @@ class FireflyValidator extends Validator } if (isset($this->data['what'])) { - return $this->validateByAccountTypeString($value, $parameters); + return $this->validateByAccountTypeString($value, $parameters, $this->data['what']); + } + if (isset($this->data['type'])) { + return $this->validateByAccountTypeString($value, $parameters, $this->data['type']); } if (isset($this->data['account_type_id'])) { @@ -390,11 +393,15 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateUniqueAccountNumberForUser(/** @scrutinizer ignore-unused */ $attribute, $value): bool + public function validateUniqueAccountNumberForUser($attribute, $value, $parameters): bool { $accountId = $this->data['id'] ?? 0; + if($accountId === 0) { + $accountId = $parameters[0] ?? 0; + } $query = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') + ->whereNull('accounts.deleted_at') ->where('accounts.user_id', auth()->user()->id) ->where('account_meta.name', 'accountNumber'); @@ -428,7 +435,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateUniqueObjectForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateUniqueObjectForUser($attribute, $value, $parameters): bool { $value = $this->tryDecrypt($value); // exclude? @@ -436,6 +443,16 @@ class FireflyValidator extends Validator $field = $parameters[1]; $exclude = $parameters[2] ?? 0; + /* + * If other data (in $this->getData()) contains + * ID field, set that field to be the $exclude. + */ + $data = $this->getData(); + if (!isset($parameters[2]) && isset($data['id']) && intval($data['id']) > 0) { + $exclude = intval($data['id']); + } + + // get entries from table $set = DB::table($table)->where('user_id', auth()->user()->id)->whereNull('deleted_at') ->where('id', '!=', $exclude)->get([$field]); @@ -460,7 +477,7 @@ class FireflyValidator extends Validator * * @return bool */ - public function validateUniquePiggyBankForUser(/** @scrutinizer ignore-unused */ $attribute, $value, $parameters): bool + public function validateUniquePiggyBankForUser($attribute, $value, $parameters): bool { $exclude = $parameters[0] ?? null; $query = DB::table('piggy_banks')->whereNull('piggy_banks.deleted_at') @@ -590,18 +607,19 @@ class FireflyValidator extends Validator } /** - * @param $value - * @param $parameters + * @param string $value + * @param array $parameters + * @param string $type * * @return bool */ - private function validateByAccountTypeString($value, $parameters): bool + private function validateByAccountTypeString(string $value, array $parameters, string $type): bool { - $search = Config::get('firefly.accountTypeByIdentifier.' . $this->data['what']); - $type = AccountType::whereType($search)->first(); - $ignore = $parameters[0] ?? 0; + $search = Config::get('firefly.accountTypeByIdentifier.' . $type); + $accountType = AccountType::whereType($search)->first(); + $ignore = $parameters[0] ?? 0; - $set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get(); + $set = auth()->user()->accounts()->where('account_type_id', $accountType->id)->where('id', '!=', $ignore)->get(); /** @var Account $entry */ foreach ($set as $entry) { if ($entry->name === $value) { diff --git a/changelog.md b/changelog.md index bedddff2fb..c94884e46a 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,25 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## [4.7.1] - 2018-03-04 +### Added +- A brand new API. Read about it in the [documentation](http://firefly-iii.readthedocs.io/en/latest/). +- Add support for Spanish. [issue 1194](https://github.com/firefly-iii/firefly-iii/issues/1194) +- Some custom preferences are selected by default for a better user experience. +- Some new currencies [issue 1211](https://github.com/firefly-iii/firefly-iii/issues/1211) + +### Fixed +- Fixed [issue 1155](https://github.com/firefly-iii/firefly-iii/issues/1155) (reported by [ndandanov](https://github.com/ndandanov)) +- [Issue 1156](https://github.com/firefly-iii/firefly-iii/issues/1156) [issue 1182](https://github.com/firefly-iii/firefly-iii/issues/1182) and other issues related to SQLite databases. +- Multi-page budget overview was broken (reported by [jinformatique](https://github.com/jinformatique)) +- Importing CSV files with semi-colons in them did not work [issue 1172](https://github.com/firefly-iii/firefly-iii/issues/1172) [issue 1183](https://github.com/firefly-iii/firefly-iii/issues/1183) [issue 1210](https://github.com/firefly-iii/firefly-iii/issues/1210) +- Could not use account number that was in use by a deleted account [issue 1174](https://github.com/firefly-iii/firefly-iii/issues/1174) +- Fixed spelling error that lead to 404's [issue 1175](https://github.com/firefly-iii/firefly-iii/issues/1175) [issue 1190](https://github.com/firefly-iii/firefly-iii/issues/1190) +- Fixed tag autocomplete [issue 1178](https://github.com/firefly-iii/firefly-iii/issues/1178) +- Better links for "new transaction" buttons [issue 1185](https://github.com/firefly-iii/firefly-iii/issues/1185) +- Cache errors in budget charts [issue 1192](https://github.com/firefly-iii/firefly-iii/issues/1192) +- Deleting transactions that are linked to other other transactions would lead to errors [issue 1209](https://github.com/firefly-iii/firefly-iii/issues/1209) + ## [4.7.0] - 2018-01-31 ### Added - Support for Russian and Portuguese (Brazil) diff --git a/composer.json b/composer.json index 607f2251c9..2048e28814 100644 --- a/composer.json +++ b/composer.json @@ -56,9 +56,11 @@ "doctrine/dbal": "2.*", "fideloper/proxy": "3.*", "laravel/framework": "5.5.*", + "laravel/passport": "^4.0", "laravelcollective/html": "5.5.*", "league/commonmark": "0.*", "league/csv": "9.*", + "league/fractal": "^0.17.0", "pragmarx/google2fa": "2.*", "pragmarx/google2fa-laravel": "^0.1.4", "rcrowe/twigbridge": "0.9.*", @@ -73,7 +75,7 @@ "fzaninotto/faker": "1.*", "mockery/mockery": "^1.0", "php-coveralls/php-coveralls": "^2.0", - "phpunit/phpunit": "^6.0" + "phpunit/phpunit": "~6.0" }, "autoload": { "classmap": [ diff --git a/composer.lock b/composer.lock index a1ba0048ab..88e62967f1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "b65015e818e8643480e794b418268e97", + "content-hash": "40e3a639ee41d56a8253f5fe431f53f9", "packages": [ { "name": "bacon/bacon-qr-code", @@ -111,6 +111,69 @@ ], "time": "2017-09-14T08:23:50+00:00" }, + { + "name": "defuse/php-encryption", + "version": "v2.1.0", + "source": { + "type": "git", + "url": "https://github.com/defuse/php-encryption.git", + "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/defuse/php-encryption/zipball/5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", + "reference": "5176f5abb38d3ea8a6e3ac6cd3bbb54d8185a689", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "paragonie/random_compat": "~2.0", + "php": ">=5.4.0" + }, + "require-dev": { + "nikic/php-parser": "^2.0|^3.0", + "phpunit/phpunit": "^4|^5" + }, + "bin": [ + "bin/generate-defuse-key" + ], + "type": "library", + "autoload": { + "psr-4": { + "Defuse\\Crypto\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Hornby", + "email": "taylor@defuse.ca", + "homepage": "https://defuse.ca/" + }, + { + "name": "Scott Arciszewski", + "email": "info@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "Secure PHP Encryption Library", + "keywords": [ + "aes", + "authenticated encryption", + "cipher", + "crypto", + "cryptography", + "encrypt", + "encryption", + "openssl", + "security", + "symmetric key cryptography" + ], + "time": "2017-05-18T21:28:48+00:00" + }, { "name": "doctrine/annotations", "version": "v1.6.0", @@ -646,16 +709,16 @@ }, { "name": "erusev/parsedown", - "version": "1.6.4", + "version": "1.7.0", "source": { "type": "git", "url": "https://github.com/erusev/parsedown.git", - "reference": "fbe3fe878f4fe69048bb8a52783a09802004f548" + "reference": "6678d59be48c4be64eaca6ce70bea48a09488cc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/erusev/parsedown/zipball/fbe3fe878f4fe69048bb8a52783a09802004f548", - "reference": "fbe3fe878f4fe69048bb8a52783a09802004f548", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/6678d59be48c4be64eaca6ce70bea48a09488cc2", + "reference": "6678d59be48c4be64eaca6ce70bea48a09488cc2", "shasum": "" }, "require": { @@ -687,7 +750,7 @@ "markdown", "parser" ], - "time": "2017-11-14T20:44:03+00:00" + "time": "2018-02-28T11:41:37+00:00" }, { "name": "fideloper/proxy", @@ -747,22 +810,249 @@ "time": "2017-06-15T17:19:42+00:00" }, { - "name": "laravel/framework", - "version": "v5.5.33", + "name": "firebase/php-jwt", + "version": "v5.0.0", "source": { "type": "git", - "url": "https://github.com/laravel/framework.git", - "reference": "ef7880e665390f999f4def7c9f78133636f973cf" + "url": "https://github.com/firebase/php-jwt.git", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/ef7880e665390f999f4def7c9f78133636f973cf", - "reference": "ef7880e665390f999f4def7c9f78133636f973cf", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "reference": "9984a4d3a32ae7673d6971ea00bae9d0a1abba0e", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": " 4.8.35" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "time": "2017-06-27T22:17:23+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "6.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "shasum": "" + }, + "require": { + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0 || ^5.0", + "psr/log": "^1.0" + }, + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "6.2-dev" + } + }, + "autoload": { + "files": [ + "src/functions_include.php" + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2017-06-22T18:50:49+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "shasum": "" + }, + "require": { + "php": ">=5.5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "time": "2016-12-20T10:07:11+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.4.2", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "request", + "response", + "stream", + "uri", + "url" + ], + "time": "2017-03-20T17:10:46+00:00" + }, + { + "name": "laravel/framework", + "version": "v5.5.36", + "source": { + "type": "git", + "url": "https://github.com/laravel/framework.git", + "reference": "9283cea4a5727aaf1def60a8fa820e49df2cf874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/framework/zipball/9283cea4a5727aaf1def60a8fa820e49df2cf874", + "reference": "9283cea4a5727aaf1def60a8fa820e49df2cf874", "shasum": "" }, "require": { "doctrine/inflector": "~1.1", - "erusev/parsedown": "~1.6", + "erusev/parsedown": "~1.7", "ext-mbstring": "*", "ext-openssl": "*", "league/flysystem": "~1.0", @@ -814,7 +1104,7 @@ "illuminate/translation": "self.version", "illuminate/validation": "self.version", "illuminate/view": "self.version", - "tightenco/collect": "self.version" + "tightenco/collect": "<5.5.33" }, "require-dev": { "aws/aws-sdk-php": "~3.0", @@ -878,20 +1168,89 @@ "framework", "laravel" ], - "time": "2018-01-30T15:06:13+00:00" + "time": "2018-03-01T13:59:00+00:00" }, { - "name": "laravelcollective/html", - "version": "v5.5.1", + "name": "laravel/passport", + "version": "v4.0.3", "source": { "type": "git", - "url": "https://github.com/LaravelCollective/html.git", - "reference": "2f6dc39ab3655724a615fe8a652d8b7f04fc9ac6" + "url": "https://github.com/laravel/passport.git", + "reference": "0542f1f82edfbf857d0197c34a3d41f549aff30a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LaravelCollective/html/zipball/2f6dc39ab3655724a615fe8a652d8b7f04fc9ac6", - "reference": "2f6dc39ab3655724a615fe8a652d8b7f04fc9ac6", + "url": "https://api.github.com/repos/laravel/passport/zipball/0542f1f82edfbf857d0197c34a3d41f549aff30a", + "reference": "0542f1f82edfbf857d0197c34a3d41f549aff30a", + "shasum": "" + }, + "require": { + "firebase/php-jwt": "~3.0|~4.0|~5.0", + "guzzlehttp/guzzle": "~6.0", + "illuminate/auth": "~5.4", + "illuminate/console": "~5.4", + "illuminate/container": "~5.4", + "illuminate/contracts": "~5.4", + "illuminate/database": "~5.4", + "illuminate/encryption": "~5.4", + "illuminate/http": "~5.4", + "illuminate/support": "~5.4", + "league/oauth2-server": "^6.0", + "php": ">=5.6.4", + "phpseclib/phpseclib": "^2.0", + "symfony/psr-http-message-bridge": "~1.0", + "zendframework/zend-diactoros": "~1.0" + }, + "require-dev": { + "mockery/mockery": "~0.9", + "phpunit/phpunit": "~5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Passport\\PassportServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Passport\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Passport provides OAuth2 server support to Laravel.", + "keywords": [ + "laravel", + "oauth", + "passport" + ], + "time": "2017-09-24T14:21:39+00:00" + }, + { + "name": "laravelcollective/html", + "version": "v5.5.3", + "source": { + "type": "git", + "url": "https://github.com/LaravelCollective/html.git", + "reference": "b79edc7acf574144c9811277286b4cafee8a07cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/LaravelCollective/html/zipball/b79edc7acf574144c9811277286b4cafee8a07cc", + "reference": "b79edc7acf574144c9811277286b4cafee8a07cc", "shasum": "" }, "require": { @@ -909,6 +1268,7 @@ }, "type": "library", "extra": { + "branch-alias": [], "laravel": { "providers": [ "Collective\\Html\\HtmlServiceProvider" @@ -942,8 +1302,66 @@ } ], "description": "HTML and Form Builders for the Laravel Framework", - "homepage": "http://laravelcollective.com", - "time": "2017-08-31T14:46:03+00:00" + "homepage": "https://laravelcollective.com", + "time": "2018-02-12T14:19:55+00:00" + }, + { + "name": "lcobucci/jwt", + "version": "3.2.2", + "source": { + "type": "git", + "url": "https://github.com/lcobucci/jwt.git", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/0b5930be73582369e10c4d4bb7a12bac927a203c", + "reference": "0b5930be73582369e10c4d4bb7a12bac927a203c", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "php": ">=5.5" + }, + "require-dev": { + "mdanter/ecc": "~0.3.1", + "mikey179/vfsstream": "~1.5", + "phpmd/phpmd": "~2.2", + "phpunit/php-invoker": "~1.1", + "phpunit/phpunit": "~4.5", + "squizlabs/php_codesniffer": "~2.3" + }, + "suggest": { + "mdanter/ecc": "Required to use Elliptic Curves based algorithms." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Lcobucci\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Luís Otávio Cobucci Oblonczyk", + "email": "lcobucci@gmail.com", + "role": "Developer" + } + ], + "description": "A simple library to work with JSON Web Token and JSON Web Signature", + "keywords": [ + "JWS", + "jwt" + ], + "time": "2017-09-01T08:23:26+00:00" }, { "name": "league/commonmark", @@ -1016,16 +1434,16 @@ }, { "name": "league/csv", - "version": "9.1.1", + "version": "9.1.2", "source": { "type": "git", "url": "https://github.com/thephpleague/csv.git", - "reference": "66118f5c2a7e4da77e743e69f74773c63b73e8f9" + "reference": "90bedd96fa3e3d2a988be985b9b1ee29cdb38301" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/csv/zipball/66118f5c2a7e4da77e743e69f74773c63b73e8f9", - "reference": "66118f5c2a7e4da77e743e69f74773c63b73e8f9", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/90bedd96fa3e3d2a988be985b9b1ee29cdb38301", + "reference": "90bedd96fa3e3d2a988be985b9b1ee29cdb38301", "shasum": "" }, "require": { @@ -1076,20 +1494,70 @@ "read", "write" ], - "time": "2017-11-28T08:29:49+00:00" + "time": "2018-02-05T14:07:11+00:00" }, { - "name": "league/flysystem", - "version": "1.0.42", + "name": "league/event", + "version": "2.1.2", "source": { "type": "git", - "url": "https://github.com/thephpleague/flysystem.git", - "reference": "09eabc54e199950041aef258a85847676496fe8e" + "url": "https://github.com/thephpleague/event.git", + "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/09eabc54e199950041aef258a85847676496fe8e", - "reference": "09eabc54e199950041aef258a85847676496fe8e", + "url": "https://api.github.com/repos/thephpleague/event/zipball/e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", + "reference": "e4bfc88dbcb60c8d8a2939a71f9813e141bbe4cd", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "~2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Event\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Event package", + "keywords": [ + "emitter", + "event", + "listener" + ], + "time": "2015-05-21T12:24:47+00:00" + }, + { + "name": "league/flysystem", + "version": "1.0.43", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem.git", + "reference": "1ce7cc142d906ba58dc54c82915d355a9191c8a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/1ce7cc142d906ba58dc54c82915d355a9191c8a8", + "reference": "1ce7cc142d906ba58dc54c82915d355a9191c8a8", "shasum": "" }, "require": { @@ -1160,7 +1628,139 @@ "sftp", "storage" ], - "time": "2018-01-27T16:03:56+00:00" + "time": "2018-03-01T10:27:04+00:00" + }, + { + "name": "league/fractal", + "version": "0.17.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/fractal.git", + "reference": "a0b350824f22fc2fdde2500ce9d6851a3f275b0e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/fractal/zipball/a0b350824f22fc2fdde2500ce9d6851a3f275b0e", + "reference": "a0b350824f22fc2fdde2500ce9d6851a3f275b0e", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "doctrine/orm": "^2.5", + "illuminate/contracts": "~5.0", + "mockery/mockery": "~0.9", + "pagerfanta/pagerfanta": "~1.0.0", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~1.5", + "zendframework/zend-paginator": "~2.3" + }, + "suggest": { + "illuminate/pagination": "The Illuminate Pagination component.", + "pagerfanta/pagerfanta": "Pagerfanta Paginator", + "zendframework/zend-paginator": "Zend Framework Paginator" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.13-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Fractal\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Phil Sturgeon", + "email": "me@philsturgeon.uk", + "homepage": "http://philsturgeon.uk/", + "role": "Developer" + } + ], + "description": "Handle the output of complex data structures ready for API output.", + "homepage": "http://fractal.thephpleague.com/", + "keywords": [ + "api", + "json", + "league", + "rest" + ], + "time": "2017-06-12T11:04:56+00:00" + }, + { + "name": "league/oauth2-server", + "version": "6.1.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-server.git", + "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/a0cabb573c7cd5ee01803daec992d6ee3677c4ae", + "reference": "a0cabb573c7cd5ee01803daec992d6ee3677c4ae", + "shasum": "" + }, + "require": { + "defuse/php-encryption": "^2.1", + "ext-openssl": "*", + "lcobucci/jwt": "^3.1", + "league/event": "^2.1", + "paragonie/random_compat": "^2.0", + "php": ">=5.6.0", + "psr/http-message": "^1.0" + }, + "replace": { + "league/oauth2server": "*", + "lncd/oauth2": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.38 || ^5.7.21", + "zendframework/zend-diactoros": "^1.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\OAuth2\\Server\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + } + ], + "description": "A lightweight and powerful OAuth 2.0 authorization and resource server library with support for all the core specification grants. This library will allow you to secure your API with OAuth and allow your applications users to approve apps that want to access their data from your API.", + "homepage": "https://oauth2.thephpleague.com/", + "keywords": [ + "Authentication", + "api", + "auth", + "authorisation", + "authorization", + "oauth", + "oauth 2", + "oauth 2.0", + "oauth2", + "protect", + "resource", + "secure", + "server" + ], + "time": "2017-12-23T23:33:42+00:00" }, { "name": "monolog/monolog", @@ -1286,25 +1886,25 @@ }, { "name": "nesbot/carbon", - "version": "1.22.1", + "version": "1.23.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc" + "reference": "4a874a39b2b00d7e0146cd46fab6f47c41ce9e65" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", - "reference": "7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4a874a39b2b00d7e0146cd46fab6f47c41ce9e65", + "reference": "4a874a39b2b00d7e0146cd46fab6f47c41ce9e65", "shasum": "" }, "require": { "php": ">=5.3.0", - "symfony/translation": "~2.6 || ~3.0" + "symfony/translation": "~2.6 || ~3.0 || ~4.0" }, "require-dev": { "friendsofphp/php-cs-fixer": "~2", - "phpunit/phpunit": "~4.0 || ~5.0" + "phpunit/phpunit": "^4.8.35 || ^5.7" }, "type": "library", "extra": { @@ -1335,7 +1935,7 @@ "datetime", "time" ], - "time": "2017-01-16T07:55:07+00:00" + "time": "2018-02-28T09:22:05+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -1447,6 +2047,98 @@ ], "time": "2017-09-27T21:40:39+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.10", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d305b780829ea4252ed9400b3f5937c2c99b51d4", + "reference": "d305b780829ea4252ed9400b3f5937c2c99b51d4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0", + "sami/sami": "~2.0", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "time": "2018-02-19T04:29:13+00:00" + }, { "name": "pragmarx/google2fa", "version": "v2.0.7", @@ -1628,6 +2320,56 @@ ], "time": "2017-02-14T16:28:37+00:00" }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "time": "2016-08-06T14:39:51+00:00" + }, { "name": "psr/log", "version": "1.0.2", @@ -1805,21 +2547,21 @@ }, { "name": "rcrowe/twigbridge", - "version": "v0.9.5", + "version": "v0.9.6", "source": { "type": "git", "url": "https://github.com/rcrowe/TwigBridge.git", - "reference": "0a0784c6fb4d383bceebd7ee4f8a2dcac15df5cf" + "reference": "c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/0a0784c6fb4d383bceebd7ee4f8a2dcac15df5cf", - "reference": "0a0784c6fb4d383bceebd7ee4f8a2dcac15df5cf", + "url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5", + "reference": "c3579440a3ca47ca45bfb0ed854bc0ff9b086bf5", "shasum": "" }, "require": { - "illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*", - "illuminate/view": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*", + "illuminate/support": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*", + "illuminate/view": "5.0.*|5.1.*|5.2.*|5.3.*|5.4.*|5.5.*|5.6.*", "php": ">=5.4.0", "twig/twig": "~1.30" }, @@ -1838,6 +2580,14 @@ "extra": { "branch-alias": { "dev-master": "0.10-dev" + }, + "laravel": { + "providers": [ + "TwigBridge\\ServiceProvider" + ], + "aliases": { + "Twig": "TwigBridge\\Facade\\Twig" + } } }, "autoload": { @@ -1865,7 +2615,7 @@ "laravel", "twig" ], - "time": "2017-08-28T11:57:12+00:00" + "time": "2018-02-08T15:59:23+00:00" }, { "name": "rmccue/requests", @@ -1973,16 +2723,16 @@ }, { "name": "symfony/console", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "26b6f419edda16c19775211987651cb27baea7f1" + "reference": "067339e9b8ec30d5f19f5950208893ff026b94f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/26b6f419edda16c19775211987651cb27baea7f1", - "reference": "26b6f419edda16c19775211987651cb27baea7f1", + "url": "https://api.github.com/repos/symfony/console/zipball/067339e9b8ec30d5f19f5950208893ff026b94f7", + "reference": "067339e9b8ec30d5f19f5950208893ff026b94f7", "shasum": "" }, "require": { @@ -2038,20 +2788,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-02-26T15:46:28+00:00" }, { "name": "symfony/css-selector", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "f97600434e3141ef3cbb9ea42cf500fba88022b7" + "reference": "c69f1e93aa898fd9fec627ebef467188151c8dc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/f97600434e3141ef3cbb9ea42cf500fba88022b7", - "reference": "f97600434e3141ef3cbb9ea42cf500fba88022b7", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/c69f1e93aa898fd9fec627ebef467188151c8dc2", + "reference": "c69f1e93aa898fd9fec627ebef467188151c8dc2", "shasum": "" }, "require": { @@ -2091,20 +2841,20 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" + "time": "2018-02-03T14:58:37+00:00" }, { "name": "symfony/debug", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937" + "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937", + "url": "https://api.github.com/repos/symfony/debug/zipball/9b1071f86e79e1999b3d3675d2e0e7684268b9bc", + "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc", "shasum": "" }, "require": { @@ -2147,20 +2897,20 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-01-18T22:16:57+00:00" + "time": "2018-02-28T21:49:22+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb" + "reference": "85eaf6a8ec915487abac52e133efc4a268204428" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/74d33aac36208c4d6757807d9f598f0133a3a4eb", - "reference": "74d33aac36208c4d6757807d9f598f0133a3a4eb", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/85eaf6a8ec915487abac52e133efc4a268204428", + "reference": "85eaf6a8ec915487abac52e133efc4a268204428", "shasum": "" }, "require": { @@ -2210,20 +2960,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" + "time": "2018-02-14T14:11:10+00:00" }, { "name": "symfony/finder", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f" + "reference": "6a615613745cef820d807443f32076bb9f5d0a38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/613e26310776f49a1773b6737c6bd554b8bc8c6f", - "reference": "613e26310776f49a1773b6737c6bd554b8bc8c6f", + "url": "https://api.github.com/repos/symfony/finder/zipball/6a615613745cef820d807443f32076bb9f5d0a38", + "reference": "6a615613745cef820d807443f32076bb9f5d0a38", "shasum": "" }, "require": { @@ -2259,20 +3009,20 @@ ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2018-02-11T17:15:12+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30" + "reference": "6f5935723c11b4125fc9927db6ad2feaa196e175" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6f5935723c11b4125fc9927db6ad2feaa196e175", + "reference": "6f5935723c11b4125fc9927db6ad2feaa196e175", "shasum": "" }, "require": { @@ -2313,20 +3063,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-02-22T10:48:49+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907" + "reference": "494f950becf513c174f52f9010cedb9026c12a92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/911d2e5dd4beb63caad9a72e43857de984301907", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/494f950becf513c174f52f9010cedb9026c12a92", + "reference": "494f950becf513c174f52f9010cedb9026c12a92", "shasum": "" }, "require": { @@ -2338,7 +3088,7 @@ }, "conflict": { "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4", + "symfony/dependency-injection": "<3.4.5|<4.0.5,>=4", "symfony/var-dumper": "<3.3", "twig/twig": "<1.34|<2.4,>=2" }, @@ -2352,7 +3102,7 @@ "symfony/config": "~2.8|~3.0|~4.0", "symfony/console": "~2.8|~3.0|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", + "symfony/dependency-injection": "^3.4.5|^4.0.5", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", @@ -2401,20 +3151,20 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-01-29T12:29:46+00:00" + "time": "2018-03-01T19:23:56+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296" + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", - "reference": "2ec8b39c38cb16674bbf3fea2b6ce5bf117e1296", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", "shasum": "" }, "require": { @@ -2426,7 +3176,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -2460,20 +3210,20 @@ "portable", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/polyfill-php56", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "265fc96795492430762c29be291a371494ba3a5b" + "reference": "ebc999ce5f14204c5150b9bd15f8f04e621409d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/265fc96795492430762c29be291a371494ba3a5b", - "reference": "265fc96795492430762c29be291a371494ba3a5b", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/ebc999ce5f14204c5150b9bd15f8f04e621409d8", + "reference": "ebc999ce5f14204c5150b9bd15f8f04e621409d8", "shasum": "" }, "require": { @@ -2483,7 +3233,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -2516,20 +3266,20 @@ "portable", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/polyfill-php70", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff" + "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", - "reference": "0442b9c0596610bd24ae7b5f0a6cdbbc16d9fcff", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f", + "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f", "shasum": "" }, "require": { @@ -2539,7 +3289,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -2575,20 +3325,20 @@ "portable", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-01-30T19:27:44+00:00" }, { "name": "symfony/polyfill-util", - "version": "v1.6.0", + "version": "v1.7.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "6e719200c8e540e0c0effeb31f96bdb344b94176" + "reference": "e17c808ec4228026d4f5a8832afa19be85979563" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/6e719200c8e540e0c0effeb31f96bdb344b94176", - "reference": "6e719200c8e540e0c0effeb31f96bdb344b94176", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/e17c808ec4228026d4f5a8832afa19be85979563", + "reference": "e17c808ec4228026d4f5a8832afa19be85979563", "shasum": "" }, "require": { @@ -2597,7 +3347,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6-dev" + "dev-master": "1.7-dev" } }, "autoload": { @@ -2627,20 +3377,20 @@ "polyfill", "shim" ], - "time": "2017-10-11T12:05:26+00:00" + "time": "2018-01-31T18:08:44+00:00" }, { "name": "symfony/process", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "09a5172057be8fc677840e591b17f385e58c7c0d" + "reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/09a5172057be8fc677840e591b17f385e58c7c0d", - "reference": "09a5172057be8fc677840e591b17f385e58c7c0d", + "url": "https://api.github.com/repos/symfony/process/zipball/cc4aea21f619116aaf1c58016a944e4821c8e8af", + "reference": "cc4aea21f619116aaf1c58016a944e4821c8e8af", "shasum": "" }, "require": { @@ -2676,20 +3426,80 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-02-12T17:55:00+00:00" }, { - "name": "symfony/routing", - "version": "v3.4.4", + "name": "symfony/psr-http-message-bridge", + "version": "v1.0.2", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "235d01730d553a97732990588407eaf6779bb4b2" + "url": "https://github.com/symfony/psr-http-message-bridge.git", + "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/235d01730d553a97732990588407eaf6779bb4b2", - "reference": "235d01730d553a97732990588407eaf6779bb4b2", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/c2b757934f2d9681a287e662efbc27c41fe8ef86", + "reference": "c2b757934f2d9681a287e662efbc27c41fe8ef86", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "psr/http-message": "~1.0", + "symfony/http-foundation": "~2.3|~3.0|~4.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "~3.2|4.0" + }, + "suggest": { + "psr/http-message-implementation": "To use the HttpFoundation factory", + "zendframework/zend-diactoros": "To use the Zend Diactoros factory" + }, + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Bridge\\PsrHttpMessage\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "PSR HTTP message bridge", + "homepage": "http://symfony.com", + "keywords": [ + "http", + "http-message", + "psr-7" + ], + "time": "2017-12-19T00:31:44+00:00" + }, + { + "name": "symfony/routing", + "version": "v3.4.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "8773a9d52715f1a579576ce0e60213de34f5ef3e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/8773a9d52715f1a579576ce0e60213de34f5ef3e", + "reference": "8773a9d52715f1a579576ce0e60213de34f5ef3e", "shasum": "" }, "require": { @@ -2754,37 +3564,37 @@ "uri", "url" ], - "time": "2018-01-16T18:03:57+00:00" + "time": "2018-02-28T21:49:22+00:00" }, { "name": "symfony/translation", - "version": "v3.4.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84" + "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/10b32cf0eae28b9b39fe26c456c42b19854c4b84", - "reference": "10b32cf0eae28b9b39fe26c456c42b19854c4b84", + "url": "https://api.github.com/repos/symfony/translation/zipball/e20a9b7f9f62cb33a11638b345c248e7d510c938", + "reference": "e20a9b7f9f62cb33a11638b345c248e7d510c938", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/config": "<2.8", + "symfony/config": "<3.4", "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", + "symfony/config": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/intl": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { @@ -2795,7 +3605,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } }, "autoload": { @@ -2822,20 +3632,20 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2018-01-18T22:16:57+00:00" + "time": "2018-02-22T10:50:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "472a9849930cf21f73abdb02240f17cf5b5bd1a7" + "reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/472a9849930cf21f73abdb02240f17cf5b5bd1a7", - "reference": "472a9849930cf21f73abdb02240f17cf5b5bd1a7", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/80964679d81da3d5618519e0e4be488c3d7ecd7d", + "reference": "80964679d81da3d5618519e0e4be488c3d7ecd7d", "shasum": "" }, "require": { @@ -2891,7 +3701,7 @@ "debug", "dump" ], - "time": "2018-01-29T09:03:43+00:00" + "time": "2018-02-22T17:29:24+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -2942,16 +3752,16 @@ }, { "name": "twig/twig", - "version": "v1.35.0", + "version": "v1.35.2", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f" + "reference": "9c24f2cd39dc1906b76879e099970b7e53724601" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/daa657073e55b0a78cce8fdd22682fddecc6385f", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/9c24f2cd39dc1906b76879e099970b7e53724601", + "reference": "9c24f2cd39dc1906b76879e099970b7e53724601", "shasum": "" }, "require": { @@ -3003,7 +3813,7 @@ "keywords": [ "templating" ], - "time": "2017-09-27T18:06:46+00:00" + "time": "2018-03-03T16:21:29+00:00" }, { "name": "vlucas/phpdotenv", @@ -3104,31 +3914,83 @@ "validation" ], "time": "2017-11-06T21:35:49+00:00" + }, + { + "name": "zendframework/zend-diactoros", + "version": "1.7.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-diactoros.git", + "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/bf26aff803a11c5cc8eb7c4878a702c403ec67f1", + "reference": "bf26aff803a11c5cc8eb7c4878a702c403ec67f1", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0", + "psr/http-message": "^1.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-dom": "*", + "ext-libxml": "*", + "phpunit/phpunit": "^5.7.16 || ^6.0.8", + "zendframework/zend-coding-standard": "~1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7.x-dev", + "dev-develop": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Diactoros\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "description": "PSR HTTP Message implementations", + "homepage": "https://github.com/zendframework/zend-diactoros", + "keywords": [ + "http", + "psr", + "psr-7" + ], + "time": "2018-02-26T15:44:50+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v3.1.0", + "version": "v3.1.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "01a859752094e00aa8548832312366753272f8af" + "reference": "664fa434e26febf04d60df0368303cf0fe14f63a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/01a859752094e00aa8548832312366753272f8af", - "reference": "01a859752094e00aa8548832312366753272f8af", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/664fa434e26febf04d60df0368303cf0fe14f63a", + "reference": "664fa434e26febf04d60df0368303cf0fe14f63a", "shasum": "" }, "require": { - "illuminate/routing": "5.5.x", - "illuminate/session": "5.5.x", - "illuminate/support": "5.5.x", - "maximebf/debugbar": "~1.14.0", + "illuminate/routing": "5.5.x|5.6.x", + "illuminate/session": "5.5.x|5.6.x", + "illuminate/support": "5.5.x|5.6.x", + "maximebf/debugbar": "~1.15.0", "php": ">=7.0", - "symfony/debug": "^3", - "symfony/finder": "^3" + "symfony/debug": "^3|^4", + "symfony/finder": "^3|^4" }, "require-dev": { "illuminate/framework": "5.5.x" @@ -3136,7 +3998,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "3.2-dev" }, "laravel": { "providers": [ @@ -3173,34 +4035,34 @@ "profiler", "webprofiler" ], - "time": "2017-09-18T13:32:46+00:00" + "time": "2018-02-25T13:31:58+00:00" }, { "name": "barryvdh/laravel-ide-helper", - "version": "v2.4.1", + "version": "v2.4.3", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "2b1273c45e2f8df7a625563e2283a17c14f02ae8" + "reference": "5c304db44fba8e9c4aa0c09739e59f7be7736fdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/2b1273c45e2f8df7a625563e2283a17c14f02ae8", - "reference": "2b1273c45e2f8df7a625563e2283a17c14f02ae8", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/5c304db44fba8e9c4aa0c09739e59f7be7736fdd", + "reference": "5c304db44fba8e9c4aa0c09739e59f7be7736fdd", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.0.4", - "illuminate/console": "^5.0,<5.6", - "illuminate/filesystem": "^5.0,<5.6", - "illuminate/support": "^5.0,<5.6", + "illuminate/console": "^5.0,<5.7", + "illuminate/filesystem": "^5.0,<5.7", + "illuminate/support": "^5.0,<5.7", "php": ">=5.4.0", "symfony/class-loader": "^2.3|^3.0" }, "require-dev": { "doctrine/dbal": "~2.3", - "illuminate/config": "^5.0,<5.6", - "illuminate/view": "^5.0,<5.6", + "illuminate/config": "^5.0,<5.7", + "illuminate/view": "^5.0,<5.7", "phpunit/phpunit": "4.*", "scrutinizer/ocular": "~1.1", "squizlabs/php_codesniffer": "~2.3" @@ -3246,7 +4108,7 @@ "phpstorm", "sublime" ], - "time": "2017-07-16T00:24:12+00:00" + "time": "2018-02-08T07:56:07+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -3462,187 +4324,6 @@ ], "time": "2017-08-15T16:48:10+00:00" }, - { - "name": "guzzlehttp/guzzle", - "version": "6.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "shasum": "" - }, - "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "6.2-dev" - } - }, - "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2017-06-22T18:50:49+00:00" - }, - { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "source": { - "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "shasum": "" - }, - "require": { - "php": ">=5.5.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle promises library", - "keywords": [ - "promise" - ], - "time": "2016-12-20T10:07:11+00:00" - }, - { - "name": "guzzlehttp/psr7", - "version": "1.4.2", - "source": { - "type": "git", - "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "shasum": "" - }, - "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" - }, - "provide": { - "psr/http-message-implementation": "1.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.4-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Tobias Schultze", - "homepage": "https://github.com/Tobion" - } - ], - "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": [ - "http", - "message", - "request", - "response", - "stream", - "uri", - "url" - ], - "time": "2017-03-20T17:10:46+00:00" - }, { "name": "hamcrest/hamcrest-php", "version": "v2.0.0", @@ -3693,22 +4374,22 @@ }, { "name": "maximebf/debugbar", - "version": "v1.14.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "64251a392344e3d22f3d21c3b7c531ba96eb01d2" + "reference": "30e7d60937ee5f1320975ca9bc7bcdd44d500f07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/64251a392344e3d22f3d21c3b7c531ba96eb01d2", - "reference": "64251a392344e3d22f3d21c3b7c531ba96eb01d2", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/30e7d60937ee5f1320975ca9bc7bcdd44d500f07", + "reference": "30e7d60937ee5f1320975ca9bc7bcdd44d500f07", "shasum": "" }, "require": { "php": ">=5.3.0", "psr/log": "^1.0", - "symfony/var-dumper": "^2.6|^3.0" + "symfony/var-dumper": "^2.6|^3.0|^4.0" }, "require-dev": { "phpunit/phpunit": "^4.0|^5.0" @@ -3750,7 +4431,7 @@ "debug", "debugbar" ], - "time": "2017-09-13T12:19:36+00:00" + "time": "2017-12-15T11:13:46+00:00" }, { "name": "mockery/mockery", @@ -4201,16 +4882,16 @@ }, { "name": "phpspec/prophecy", - "version": "1.7.3", + "version": "1.7.5", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf" + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", - "reference": "e4ed002c67da8eceb0eb8ddb8b3847bb53c5c2bf", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/dfd6be44111a7c41c2e884a336cc4f461b3b2401", + "reference": "dfd6be44111a7c41c2e884a336cc4f461b3b2401", "shasum": "" }, "require": { @@ -4222,7 +4903,7 @@ }, "require-dev": { "phpspec/phpspec": "^2.5|^3.2", - "phpunit/phpunit": "^4.8.35 || ^5.7" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5" }, "type": "library", "extra": { @@ -4260,7 +4941,7 @@ "spy", "stub" ], - "time": "2017-11-24T13:59:53+00:00" + "time": "2018-02-19T10:16:54+00:00" }, { "name": "phpunit/php-code-coverage", @@ -4513,16 +5194,16 @@ }, { "name": "phpunit/phpunit", - "version": "6.5.5", + "version": "6.5.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "83d27937a310f2984fd575686138597147bdc7df" + "reference": "6bd77b57707c236833d2b57b968e403df060c9d9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/83d27937a310f2984fd575686138597147bdc7df", - "reference": "83d27937a310f2984fd575686138597147bdc7df", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6bd77b57707c236833d2b57b968e403df060c9d9", + "reference": "6bd77b57707c236833d2b57b968e403df060c9d9", "shasum": "" }, "require": { @@ -4593,7 +5274,7 @@ "testing", "xunit" ], - "time": "2017-12-17T06:31:19+00:00" + "time": "2018-02-26T07:01:09+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -4654,56 +5335,6 @@ ], "time": "2018-01-06T05:45:45+00:00" }, - { - "name": "psr/http-message", - "version": "1.0.1", - "source": { - "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", - "shasum": "" - }, - "require": { - "php": ">=5.3.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" - } - ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", - "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" - ], - "time": "2016-08-06T14:39:51+00:00" - }, { "name": "sebastian/code-unit-reverse-lookup", "version": "1.0.1", @@ -4751,21 +5382,21 @@ }, { "name": "sebastian/comparator", - "version": "2.1.2", + "version": "2.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "11c07feade1d65453e06df3b3b90171d6d982087" + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/11c07feade1d65453e06df3b3b90171d6d982087", - "reference": "11c07feade1d65453e06df3b3b90171d6d982087", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/34369daee48eafb2651bea869b4b15d75ccc35f9", + "reference": "34369daee48eafb2651bea869b4b15d75ccc35f9", "shasum": "" }, "require": { "php": "^7.0", - "sebastian/diff": "^2.0", + "sebastian/diff": "^2.0 || ^3.0", "sebastian/exporter": "^3.1" }, "require-dev": { @@ -4811,7 +5442,7 @@ "compare", "equality" ], - "time": "2018-01-12T06:34:42+00:00" + "time": "2018-02-01T13:46:46+00:00" }, { "name": "sebastian/diff", @@ -5265,7 +5896,7 @@ }, { "name": "symfony/class-loader", - "version": "v3.4.4", + "version": "v3.4.5", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -5321,16 +5952,16 @@ }, { "name": "symfony/config", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "ecd917899167922086ddb3247aa43eb1c418fcb2" + "reference": "289eadd3771f7682ea2540e4925861c18ec5b4d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/ecd917899167922086ddb3247aa43eb1c418fcb2", - "reference": "ecd917899167922086ddb3247aa43eb1c418fcb2", + "url": "https://api.github.com/repos/symfony/config/zipball/289eadd3771f7682ea2540e4925861c18ec5b4d0", + "reference": "289eadd3771f7682ea2540e4925861c18ec5b4d0", "shasum": "" }, "require": { @@ -5341,6 +5972,8 @@ "symfony/finder": "<3.4" }, "require-dev": { + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", "symfony/finder": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, @@ -5377,20 +6010,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", - "time": "2018-01-21T19:06:11+00:00" + "time": "2018-02-04T16:43:51+00:00" }, { "name": "symfony/filesystem", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed" + "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/760e47a4ee64b4c48f4b30017011e09d4c0f05ed", - "reference": "760e47a4ee64b4c48f4b30017011e09d4c0f05ed", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", + "reference": "5d2d655b2c72fc4d9bf7e9bf14f72a447b940f21", "shasum": "" }, "require": { @@ -5426,20 +6059,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" + "time": "2018-02-22T10:50:29+00:00" }, { "name": "symfony/stopwatch", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/stopwatch.git", - "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704" + "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/stopwatch/zipball/d52321f0e2b596bd03b5d1dd6eebe71caa925704", - "reference": "d52321f0e2b596bd03b5d1dd6eebe71caa925704", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6795ffa2f8eebedac77f045aa62c0c10b2763042", + "reference": "6795ffa2f8eebedac77f045aa62c0c10b2763042", "shasum": "" }, "require": { @@ -5475,20 +6108,20 @@ ], "description": "Symfony Stopwatch Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:38:00+00:00" + "time": "2018-02-19T16:50:22+00:00" }, { "name": "symfony/yaml", - "version": "v4.0.4", + "version": "v4.0.5", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "ffc60bda1d4a00ec0b32eeabf39dc017bf480028" + "reference": "de5f125ea39de846b90b313b2cfb031a0152d223" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/ffc60bda1d4a00ec0b32eeabf39dc017bf480028", - "reference": "ffc60bda1d4a00ec0b32eeabf39dc017bf480028", + "url": "https://api.github.com/repos/symfony/yaml/zipball/de5f125ea39de846b90b313b2cfb031a0152d223", + "reference": "de5f125ea39de846b90b313b2cfb031a0152d223", "shasum": "" }, "require": { @@ -5533,7 +6166,7 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2018-01-21T19:06:11+00:00" + "time": "2018-02-19T20:08:53+00:00" }, { "name": "theseer/tokenizer", diff --git a/config/auth.php b/config/auth.php index 134d34926f..fec9f2f764 100644 --- a/config/auth.php +++ b/config/auth.php @@ -64,7 +64,7 @@ return [ ], 'api' => [ - 'driver' => 'token', + 'driver' => 'passport', 'provider' => 'users', ], ], diff --git a/config/breadcrumbs.php b/config/breadcrumbs.php index dcfbba2987..66d8ac024d 100644 --- a/config/breadcrumbs.php +++ b/config/breadcrumbs.php @@ -1,5 +1,26 @@ . + */ + return [ /* diff --git a/config/firefly.php b/config/firefly.php index 98c8543aae..6e406795d3 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -33,7 +33,8 @@ return [ 'is_demo_site' => false, ], 'encryption' => (is_null(env('USE_ENCRYPTION')) || env('USE_ENCRYPTION') === true), - 'version' => '4.7.0', + 'version' => '4.7.1', + 'api_version' => '0.1', 'maxUploadSize' => 15242880, 'allowedMimes' => [ /* plain files */ @@ -175,6 +176,7 @@ return [ 'languages' => [ // completed languages 'en_US' => ['name_locale' => 'English', 'name_english' => 'English'], + 'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'], 'de_DE' => ['name_locale' => 'Deutsch', 'name_english' => 'German'], 'fr_FR' => ['name_locale' => 'Français', 'name_english' => 'French'], 'id_ID' => ['name_locale' => 'Bahasa Indonesia', 'name_english' => 'Indonesian'], @@ -185,9 +187,7 @@ return [ 'tr_TR' => ['name_locale' => 'Türkçe', 'name_english' => 'Turkish'], // incomplete languages: - //'id_ID' => ['name_locale' => 'Indonesian', 'name_english' => 'Indonesian'], - //'es_ES' => ['name_locale' => 'Spanish', 'name_english' => 'Spanish'], - //'sl_SI' => ['name_locale' => 'Slovenščina', 'name_english' => 'Slovenian'], + // 'ca_ES' => ['name_locale' => 'Català', 'name_english' => 'Catalan'], ], 'transactionTypesByWhat' => [ 'expenses' => ['Withdrawal'], @@ -225,6 +225,7 @@ return [ 'ruleGroup' => \FireflyIII\Models\RuleGroup::class, 'exportJob' => \FireflyIII\Models\ExportJob::class, 'importJob' => \FireflyIII\Models\ImportJob::class, + 'transaction' => \FireflyIII\Models\Transaction::class, 'user' => \FireflyIII\User::class, // strings diff --git a/config/google2fa.php b/config/google2fa.php index e04f5e0b76..bf65120b83 100644 --- a/config/google2fa.php +++ b/config/google2fa.php @@ -1,5 +1,26 @@ . + */ + return [ /* diff --git a/config/mail.php b/config/mail.php index 85ed8227d4..642a58be96 100644 --- a/config/mail.php +++ b/config/mail.php @@ -51,7 +51,7 @@ return [ | */ - 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'host' => env('MAIL_HOST', 'smtp.mailtrap.io'), /* |-------------------------------------------------------------------------- @@ -64,7 +64,7 @@ return [ | */ - 'port' => env('MAIL_PORT', 587), + 'port' => env('MAIL_PORT', 2525), /* |-------------------------------------------------------------------------- @@ -76,7 +76,7 @@ return [ | used globally for all e-mails that are sent by your application. | */ - 'from' => ['address' => env('MAIL_FROM', 'noreply@example.com'), 'name' => 'Firefly III Mailer'], + 'from' => ['address' => env('MAIL_FROM', 'changeme@example.com'), 'name' => 'Firefly III Mailer'], /* diff --git a/database/factories/ModelFactory.php b/database/factories/ModelFactory.php index db84ef623b..923658054f 100644 --- a/database/factories/ModelFactory.php +++ b/database/factories/ModelFactory.php @@ -100,7 +100,6 @@ $factory->define( 'user_id' => 1, 'transaction_type_id' => 1, 'bill_id' => null, - // TODO update this transaction currency reference. 'transaction_currency_id' => 1, 'description' => $faker->words(3, true), 'date' => '2017-01-01', @@ -119,7 +118,8 @@ $factory->define( FireflyIII\Models\Bill::class, function (Faker\Generator $faker) { return [ - 'id' => $faker->numberBetween(1, 10), + 'created_at' => new Carbon, + 'updated_at' => new Carbon, 'user_id' => 1, 'name' => $faker->words(3, true), 'match' => $faker->words(3, true), @@ -128,9 +128,7 @@ $factory->define( 'date' => '2017-01-01', 'repeat_freq' => 'monthly', 'skip' => 0, - 'automatch' => 1, - 'name_encrypted' => 0, - 'match_encrypted' => 0, + 'automatch' => 1 ]; } ); @@ -227,6 +225,9 @@ $factory->define( function (Faker\Generator $faker) { return [ 'id' => $faker->unique()->numberBetween(1000, 10000), + 'user_id' => 1, + 'created_at' => new Carbon, + 'updated_at' => new Carbon, 'name' => $faker->words(3, true), 'account_type_id' => 1, 'active' => true, diff --git a/database/migrations/2018_01_01_000001_create_oauth_auth_codes_table.php b/database/migrations/2018_01_01_000001_create_oauth_auth_codes_table.php new file mode 100644 index 0000000000..41dea9acbd --- /dev/null +++ b/database/migrations/2018_01_01_000001_create_oauth_auth_codes_table.php @@ -0,0 +1,59 @@ +. + */ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +/** + * Class CreateOauthAuthCodesTable + */ +class CreateOauthAuthCodesTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('oauth_auth_codes', function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->integer('user_id'); + $table->integer('client_id'); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('oauth_auth_codes'); + } +} diff --git a/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php new file mode 100644 index 0000000000..8fdeaec3d4 --- /dev/null +++ b/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php @@ -0,0 +1,61 @@ +. + */ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +/** + * Class CreateOauthAccessTokensTable + */ +class CreateOauthAccessTokensTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('oauth_access_tokens', function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->integer('user_id')->index()->nullable(); + $table->integer('client_id'); + $table->string('name')->nullable(); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->timestamps(); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('oauth_access_tokens'); + } +} diff --git a/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php new file mode 100644 index 0000000000..bc588d3c30 --- /dev/null +++ b/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php @@ -0,0 +1,57 @@ +. + */ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +/** + * Class CreateOauthRefreshTokensTable + */ +class CreateOauthRefreshTokensTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('oauth_refresh_tokens', function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->string('access_token_id', 100)->index(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('oauth_refresh_tokens'); + } +} diff --git a/database/migrations/2018_01_01_000004_create_oauth_clients_table.php b/database/migrations/2018_01_01_000004_create_oauth_clients_table.php new file mode 100644 index 0000000000..1e440e75b9 --- /dev/null +++ b/database/migrations/2018_01_01_000004_create_oauth_clients_table.php @@ -0,0 +1,62 @@ +. + */ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +/** + * Class CreateOauthClientsTable + */ +class CreateOauthClientsTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('oauth_clients', function (Blueprint $table) { + $table->increments('id'); + $table->integer('user_id')->index()->nullable(); + $table->string('name'); + $table->string('secret', 100); + $table->text('redirect'); + $table->boolean('personal_access_client'); + $table->boolean('password_client'); + $table->boolean('revoked'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('oauth_clients'); + } +} diff --git a/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php new file mode 100644 index 0000000000..fb7a22568a --- /dev/null +++ b/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php @@ -0,0 +1,56 @@ +. + */ + +use Illuminate\Support\Facades\Schema; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Migrations\Migration; + +/** + * Class CreateOauthPersonalAccessClientsTable + */ +class CreateOauthPersonalAccessClientsTable extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('oauth_personal_access_clients', function (Blueprint $table) { + $table->increments('id'); + $table->integer('client_id')->index(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('oauth_personal_access_clients'); + } +} diff --git a/database/seeds/TransactionCurrencySeeder.php b/database/seeds/TransactionCurrencySeeder.php index 49b62b2697..1fc5dce66d 100644 --- a/database/seeds/TransactionCurrencySeeder.php +++ b/database/seeds/TransactionCurrencySeeder.php @@ -35,6 +35,9 @@ class TransactionCurrencySeeder extends Seeder $currencies[] = ['code' => 'EUR', 'name' => 'Euro', 'symbol' => '€', 'decimal_places' => 2]; $currencies[] = ['code' => 'HUF', 'name' => 'Hungarian forint', 'symbol' => 'Ft', 'decimal_places' => 2]; $currencies[] = ['code' => 'GBP', 'name' => 'British Pound', 'symbol' => '£', 'decimal_places' => 2]; + $currencies[] = ['code' => 'UAH', 'name' => 'Ukrainian hryvnia', 'symbol' => '₴', 'decimal_places' => 2]; + $currencies[] = ['code' => 'PLN', 'name' => 'Polish złoty', 'symbol' => 'zł', 'decimal_places' => 2]; + $currencies[] = ['code' => 'TRY', 'name' => 'Turkish lira', 'symbol' => '₺', 'decimal_places' => 2]; // american currencies $currencies[] = ['code' => 'USD', 'name' => 'US Dollar', 'symbol' => '$', 'decimal_places' => 2]; diff --git a/docker-compose.yml b/docker-compose.yml index 47af6350d2..80ead689d7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,36 +1,38 @@ -version: '3.2' -services: - firefly_iii_db: - image: mysql:8 - environment: - - MYSQL_DATABASE=firefly_db - - MYSQL_USER=firefly_db - - MYSQL_PASSWORD=firefly_db_secret - - MYSQL_RANDOM_ROOT_PASSWORD=yes - volumes: - - firefly_iii_db:/var/lib/mysql - firefly_iii_app: - image: jc5x/firefly-iii - environment: +--- +services: + firefly_iii_app: + environment: - FF_DB_HOST=firefly_iii_db - FF_DB_NAME=firefly_db - FF_DB_USER=firefly_db - FF_DB_PASSWORD=firefly_db_secret - FF_APP_KEY=S0m3R@nd0mStr1ngOf32Ch@rsEx@ctly - FF_APP_ENV=local - ports: + image: jc5x/firefly-iii + links: + - firefly_iii_db + ports: - "80:80" - volumes: - - type: volume + volumes: + - source: firefly_iii_export target: /var/www/firefly-iii/storage/export - - type: volume + type: volume + - source: firefly_iii_upload target: /var/www/firefly-iii/storage/upload - links: - - firefly_iii_db - -volumes: - firefly_iii_db: - firefly_iii_export: - firefly_iii_upload: + type: volume + firefly_iii_db: + environment: + - MYSQL_DATABASE=firefly_db + - MYSQL_USER=firefly_db + - MYSQL_PASSWORD=firefly_db_secret + - MYSQL_RANDOM_ROOT_PASSWORD=yes + image: "mysql:latest" + volumes: + - "firefly_iii_db:/var/lib/mysql" +version: "3.2" +volumes: + firefly_iii_db: ~ + firefly_iii_export: ~ + firefly_iii_upload: ~ diff --git a/package-lock.json b/package-lock.json new file mode 100755 index 0000000000..0bb7e2d589 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13644 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", + "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "dev": true, + "requires": { + "mime-types": "2.1.17", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.3.0.tgz", + "integrity": "sha512-Yej+zOJ1Dm/IMZzzj78OntP/r3zHEaKcyNoU2lAaxPtrseM6rF0xwqoz5Q5ysAiED9hTjI2hgtvLXitlCN1/Ug==", + "dev": true + }, + "acorn-dynamic-import": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", + "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", + "dev": true, + "requires": { + "acorn": "4.0.13" + }, + "dependencies": { + "acorn": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", + "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", + "dev": true + } + } + }, + "adjust-sourcemap-loader": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-1.1.0.tgz", + "integrity": "sha1-QS2SQE62HkETY1ASy6U6M9AI4OI=", + "dev": true, + "requires": { + "assert": "1.4.1", + "camelcase": "1.2.1", + "loader-utils": "1.1.0", + "lodash.assign": "4.2.0", + "lodash.defaults": "3.1.2", + "object-path": "0.9.2", + "regex-parser": "2.2.8" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "lodash.defaults": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", + "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", + "dev": true, + "requires": { + "lodash.assign": "3.2.0", + "lodash.restparam": "3.6.1" + }, + "dependencies": { + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._createassigner": "3.1.1", + "lodash.keys": "3.1.2" + } + } + } + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "archive-type": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", + "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", + "dev": true, + "requires": { + "file-type": "3.9.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + } + } + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-flatten": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.1.tgz", + "integrity": "sha1-Qmu52oQJDBg42BLIFQryCoMx4pY=", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "1.1.2", + "es-abstract": "1.10.0" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "asn1.js": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.9.2.tgz", + "integrity": "sha512-b/OsSjvWEo8Pi8H0zsDd2P6Uqo2TK2pH8gNLSJtNLM2Db0v2QaAZ0pBQJXVjAn4gBuugeVDr7s63ZogpUIwWDg==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "assert": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", + "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", + "dev": true, + "requires": { + "util": "0.10.3" + } + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "ast-types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz", + "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk=", + "dev": true + }, + "async": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", + "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true + }, + "async-each-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", + "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", + "dev": true + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "autoprefixer": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.2.5.tgz", + "integrity": "sha512-XqHfo8Ht0VU+T5P+eWEVoXza456KJ4l62BPewu3vpNf3LP9s2+zYXkXBznzYby4XeECXgG3N4i+hGvOhXErZmA==", + "dev": true, + "requires": { + "browserslist": "2.11.3", + "caniuse-lite": "1.0.30000792", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "6.0.16", + "postcss-value-parser": "3.3.0" + } + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "dev": true, + "requires": { + "follow-redirects": "1.4.1", + "is-buffer": "1.1.6" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.1", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-loader": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-7.1.2.tgz", + "integrity": "sha512-jRwlFbINAeyDStqK6Dd5YuY0k5YuzQUvlz2ZamuXrXmxav3pNqe9vfJ402+2G+OmlJSXxCOpB6Uz0INM7RQe2A==", + "dev": true, + "requires": { + "find-cache-dir": "1.0.0", + "loader-utils": "1.1.0", + "mkdirp": "0.5.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-object-rest-spread": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", + "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-object-rest-spread": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", + "integrity": "sha1-DzZpLVD+9rfi1LOsFHgTepY7ewY=", + "dev": true, + "requires": { + "babel-plugin-syntax-object-rest-spread": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-runtime": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz", + "integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-preset-env": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz", + "integrity": "sha512-W6VIyA6Ch9ePMI7VptNn2wBM6dbG0eSz25HEiL40nQXCsXGTGZSTZu1Iap+cj3Q0S5a7T9+529l/5Bkvd+afNA==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.11.3", + "invariant": "2.2.2", + "semver": "5.5.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.3", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.3", + "regenerator-runtime": "0.11.1" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.0", + "pascalcase": "0.1.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "base64-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "bin-build": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", + "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", + "dev": true, + "requires": { + "archive-type": "3.2.0", + "decompress": "3.0.0", + "download": "4.4.3", + "exec-series": "1.0.3", + "rimraf": "2.6.2", + "tempfile": "1.1.1", + "url-regex": "3.2.0" + }, + "dependencies": { + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2", + "uuid": "2.0.3" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "bin-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", + "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", + "dev": true, + "requires": { + "executable": "1.1.0" + } + }, + "bin-version": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "dev": true, + "requires": { + "find-versions": "1.2.1" + } + }, + "bin-version-check": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "dev": true, + "requires": { + "bin-version": "1.0.4", + "minimist": "1.2.0", + "semver": "4.3.6", + "semver-truncate": "1.1.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + } + } + }, + "bin-wrapper": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", + "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", + "dev": true, + "requires": { + "bin-check": "2.0.0", + "bin-version-check": "2.1.0", + "download": "4.4.3", + "each-async": "1.1.1", + "lazy-req": "1.1.0", + "os-filter-obj": "1.0.3" + } + }, + "binary-extensions": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", + "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", + "dev": true + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, + "bn.js": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "dev": true + }, + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-type": "1.0.4", + "debug": "2.6.9", + "depd": "1.1.2", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "1.6.15" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "2.1.1", + "deep-equal": "1.0.1", + "dns-equal": "1.0.0", + "dns-txt": "2.0.2", + "multicast-dns": "6.2.3", + "multicast-dns-service-types": "1.1.0" + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "bootstrap-sass": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/bootstrap-sass/-/bootstrap-sass-3.3.7.tgz", + "integrity": "sha1-ZZbHq0D2Y3OTMjqwvIDQZPxjBJg=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", + "dev": true, + "requires": { + "buffer-xor": "1.0.3", + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "browserify-cipher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.0.tgz", + "integrity": "sha1-mYgkSHS/XtTijalWZtzWasj8Njo=", + "dev": true, + "requires": { + "browserify-aes": "1.1.1", + "browserify-des": "1.0.0", + "evp_bytestokey": "1.0.3" + } + }, + "browserify-des": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.0.tgz", + "integrity": "sha1-2qJ3cXRwki7S/hhZQRihdUOXId0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "des.js": "1.0.0", + "inherits": "2.0.3" + } + }, + "browserify-rsa": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "randombytes": "2.0.6" + } + }, + "browserify-sign": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", + "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "elliptic": "6.4.0", + "inherits": "2.0.3", + "parse-asn1": "5.1.0" + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "1.0.6" + } + }, + "browserslist": { + "version": "2.11.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.11.3.tgz", + "integrity": "sha512-yWu5cXT7Av6mVwzWc8lMsJMHWn4xyjSuGYi4IozbVTLUOEYPSagUB8kiMDUHA1fS3zjr8nkxkn9jdvug4BBRmA==", + "dev": true, + "requires": { + "caniuse-lite": "1.0.30000792", + "electron-to-chromium": "1.3.31" + } + }, + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "1.2.1", + "ieee754": "1.1.8", + "isarray": "1.0.0" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-to-vinyl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", + "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", + "dev": true, + "requires": { + "file-type": "3.9.0", + "readable-stream": "2.3.3", + "uuid": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + } + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cacache": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-10.0.2.tgz", + "integrity": "sha512-dljb7dk1jqO5ogE+dRpoR9tpHYv5xz9vPSNunh1+0wRuNdYxmzp9WmsyokgW/DUF1FDRVA/TMsmxt027R8djbQ==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "chownr": "1.0.1", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "lru-cache": "4.1.1", + "mississippi": "1.3.1", + "mkdirp": "0.5.1", + "move-concurrently": "1.0.1", + "promise-inflight": "1.0.1", + "rimraf": "2.6.2", + "ssri": "5.1.0", + "unique-filename": "1.1.0", + "y18n": "3.2.1" + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "2.3.2", + "upper-case": "1.1.3" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caniuse-api": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", + "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000800", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" + }, + "dependencies": { + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000800", + "electron-to-chromium": "1.3.31" + } + } + } + }, + "caniuse-db": { + "version": "1.0.30000800", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000800.tgz", + "integrity": "sha1-qG5rwjvZpwfV30LzPmTQSVz9ohg=", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30000792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000792.tgz", + "integrity": "sha1-0M6pgfgRjzlhRxr7tDyaHlu/AzI=", + "dev": true + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "caw": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", + "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", + "dev": true, + "requires": { + "get-proxy": "1.1.0", + "is-obj": "1.0.1", + "object-assign": "3.0.0", + "tunnel-agent": "0.4.3" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + }, + "dependencies": { + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + } + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + }, + "dependencies": { + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", + "dev": true + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.3", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "dev": true, + "requires": { + "chalk": "1.1.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "clean-css": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz", + "integrity": "sha1-Nc7ornaHpJuYA09w3gDE7dOCYwE=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-deep": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.3.0.tgz", + "integrity": "sha1-NIxhrpzb4O3+BT2R/0zFIdeQ7eg=", + "dev": true, + "requires": { + "for-own": "1.0.0", + "is-plain-object": "2.0.4", + "kind-of": "3.2.2", + "shallow-clone": "0.1.2" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + } + } + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "1.5.1" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "1.0.0", + "object-visit": "1.0.1" + } + }, + "color": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/color/-/color-0.11.4.tgz", + "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", + "dev": true, + "requires": { + "clone": "1.0.3", + "color-convert": "1.9.1", + "color-string": "0.3.0" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, + "colormin": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", + "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", + "dev": true, + "requires": { + "color": "0.11.4", + "css-color-names": "0.0.4", + "has": "1.0.1" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-BFnaq5ZOGcDN7FlrtBT4xxkgIToalIIxwjxLWVJ8bGTpe1LroqMiqQXdA7ygc7CRvaYS+9zfPGFnJqFSayx+AA==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true + }, + "compressible": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.12.tgz", + "integrity": "sha1-xZpcmdt2dn6YdlAOJx72OzSTvWY=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "compression": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.1.tgz", + "integrity": "sha1-7/JgPvwuIs+G810uuTWJ+YdTc9s=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "bytes": "3.0.0", + "compressible": "2.0.12", + "debug": "2.6.9", + "on-headers": "1.0.1", + "safe-buffer": "5.1.1", + "vary": "1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "concatenate": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/concatenate/-/concatenate-0.0.2.tgz", + "integrity": "sha1-C0nW6MQQR9dyjNyNYqCGYjOXtJ8=", + "dev": true, + "requires": { + "globs": "0.1.3" + } + }, + "connect-history-api-fallback": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz", + "integrity": "sha1-sGhzk0vF40T+9hGhlqb6rgruAVo=", + "dev": true + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "console-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", + "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", + "dev": true + }, + "consolidate": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", + "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", + "dev": true, + "requires": { + "bluebird": "3.5.1" + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz", + "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=", + "dev": true + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "1.2.0", + "fs-write-stream-atomic": "1.0.10", + "iferr": "0.1.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "core-js": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.3.tgz", + "integrity": "sha1-isw4NFgk8W2DZbfJtCWRaOjtYD4=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-2.2.2.tgz", + "integrity": "sha512-GiNXLwAFPYHy25XmTPpafYvn3CLAkJ8FLsscq78MQd1Kh0OU6Yzhn4eV2MVF4G9WEQZoWEGltatdR+ntGPMl5A==", + "dev": true, + "requires": { + "is-directory": "0.3.1", + "js-yaml": "3.7.0", + "minimist": "1.2.0", + "object-assign": "4.1.1", + "os-homedir": "1.0.2", + "parse-json": "2.2.0", + "require-from-string": "1.2.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "create-ecdh": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.0.tgz", + "integrity": "sha1-iIxyNZbN92EvZJgjPuvXo1MBc30=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "elliptic": "6.4.0" + } + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "create-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.1.3.tgz", + "integrity": "sha1-YGBCrIuSYnUPSDyt2rD1gZFy2P0=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "sha.js": "2.4.10" + } + }, + "create-hmac": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.6.tgz", + "integrity": "sha1-rLniIaThe9sHbpBlfEK5PjcmzwY=", + "dev": true, + "requires": { + "cipher-base": "1.0.4", + "create-hash": "1.1.3", + "inherits": "2.0.3", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "cross-env": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.1.3.tgz", + "integrity": "sha512-UOokgwvDzCT0mqRSLEkJzUhYXB1vK3E5UgDrD41QiXsm9UetcW2rCGHYz/O3p873lMJ1VZbFCF9Izkwh7nYR5A==", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "is-windows": "1.0.1" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "1.0.0", + "browserify-sign": "4.0.4", + "create-ecdh": "4.0.0", + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "diffie-hellman": "5.0.2", + "inherits": "2.0.3", + "pbkdf2": "3.0.14", + "public-encrypt": "4.0.0", + "randombytes": "2.0.6", + "randomfill": "1.0.3" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-loader": { + "version": "0.28.9", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.9.tgz", + "integrity": "sha512-r3dgelMm/mkPz5Y7m9SeiGE46i2VsEU/OYbez+1llfxtv8b2y5/b5StaeEvPK3S5tlNQI+tDW/xDIhKJoZgDtw==", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "css-selector-tokenizer": "0.7.0", + "cssnano": "3.10.0", + "icss-utils": "2.1.0", + "loader-utils": "1.1.0", + "lodash.camelcase": "4.3.0", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-modules-extract-imports": "1.2.0", + "postcss-modules-local-by-default": "1.2.0", + "postcss-modules-scope": "1.1.0", + "postcss-modules-values": "1.3.0", + "postcss-value-parser": "3.3.0", + "source-list-map": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "css-selector-tokenizer": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", + "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", + "dev": true, + "requires": { + "cssesc": "0.1.0", + "fastparse": "1.1.1", + "regexpu-core": "1.0.0" + }, + "dependencies": { + "regexpu-core": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", + "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + } + } + }, + "cssesc": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", + "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=", + "dev": true + }, + "cssnano": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", + "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.1", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.2", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "autoprefixer": { + "version": "6.7.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-6.7.7.tgz", + "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000800", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000800", + "electron-to-chromium": "1.3.31" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "csso": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-2.3.2.tgz", + "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", + "dev": true, + "requires": { + "clap": "1.2.3", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "cyclist": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz", + "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "0.10.38" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", + "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", + "dev": true, + "requires": { + "buffer-to-vinyl": "1.1.0", + "concat-stream": "1.6.0", + "decompress-tar": "3.1.0", + "decompress-tarbz2": "3.1.0", + "decompress-targz": "3.1.0", + "decompress-unzip": "3.4.0", + "stream-combiner2": "1.1.1", + "vinyl-assign": "1.2.1", + "vinyl-fs": "2.4.4" + } + }, + "decompress-tar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", + "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", + "dev": true, + "requires": { + "is-tar": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.5", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-tarbz2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", + "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", + "dev": true, + "requires": { + "is-bzip2": "1.0.0", + "object-assign": "2.1.1", + "seek-bzip": "1.0.5", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.5", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-targz": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", + "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", + "dev": true, + "requires": { + "is-gzip": "1.0.0", + "object-assign": "2.1.1", + "strip-dirs": "1.1.1", + "tar-stream": "1.5.5", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "decompress-unzip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", + "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", + "dev": true, + "requires": { + "is-zip": "1.0.0", + "read-all-stream": "3.1.0", + "stat-mode": "0.2.2", + "strip-dirs": "1.1.1", + "through2": "2.0.3", + "vinyl": "1.2.0", + "yauzl": "2.9.1" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "2.0.5", + "object-keys": "1.0.11" + } + }, + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "defined": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", + "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=", + "dev": true + }, + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "dev": true, + "requires": { + "globby": "6.1.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "p-map": "1.2.0", + "pify": "3.0.0", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", + "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-node": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.3.tgz", + "integrity": "sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.2.tgz", + "integrity": "sha1-tYNXOScM/ias9jIJn97SoH8gnl4=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "miller-rabin": "4.0.1", + "randombytes": "2.0.6" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz", + "integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==", + "dev": true, + "requires": { + "ip": "1.1.5", + "safe-buffer": "5.1.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "1.1.1" + } + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", + "dev": true + }, + "dotenv-expand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.0.1.tgz", + "integrity": "sha1-aP3cFWGBTgoQlkERBX/xOM7X16g=", + "dev": true + }, + "download": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", + "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", + "dev": true, + "requires": { + "caw": "1.2.0", + "concat-stream": "1.6.0", + "each-async": "1.1.1", + "filenamify": "1.2.1", + "got": "5.7.1", + "gulp-decompress": "1.2.0", + "gulp-rename": "1.2.2", + "is-url": "1.2.2", + "object-assign": "4.1.1", + "read-all-stream": "3.1.0", + "readable-stream": "2.3.3", + "stream-combiner2": "1.1.1", + "vinyl": "1.2.0", + "vinyl-fs": "2.4.4", + "ware": "1.3.0" + } + }, + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "duplexify": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.3.tgz", + "integrity": "sha512-g8ID9OroF9hKt2POf8YLayy+9594PzmM3scI00/uBXocX3TWNgoB67hjzkFe9ITAbQOne/lLdBxHXvYUM4ZgGA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "1.1.0", + "set-immediate-shim": "1.0.1" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.31.tgz", + "integrity": "sha512-XE4CLbswkZgZFn34cKFy1xaX+F5LHxeDLjY1+rsK9asDzknhbrd9g/n/01/acbU25KTsUSiLKwvlLyA+6XLUOA==", + "dev": true + }, + "elliptic": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.0.tgz", + "integrity": "sha1-ysmvh2LIWDYYcAPI3+GT5eLq5d8=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0", + "hash.js": "1.1.3", + "hmac-drbg": "1.0.1", + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "enhanced-resolve": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-3.4.1.tgz", + "integrity": "sha1-BCHjOf1xQZs9oT0Smzl5BAIwR24=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "memory-fs": "0.4.1", + "object-assign": "4.1.1", + "tapable": "0.2.8" + } + }, + "errno": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", + "dev": true, + "requires": { + "prr": "1.0.1" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "error-stack-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.1.tgz", + "integrity": "sha1-oyArj7AxFKqbQKDjZp5IsrZaAQo=", + "dev": true, + "requires": { + "stackframe": "1.0.4" + } + }, + "es-abstract": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.10.0.tgz", + "integrity": "sha512-/uh/DhdqIOSkAWifU+8nG78vlQxdLckUdI/sPgy0VhuXi2qJ7T8czBmqIYtLQVpCIFYafChnsRsB5pyb1JdmCQ==", + "dev": true, + "requires": { + "es-to-primitive": "1.1.1", + "function-bind": "1.1.1", + "has": "1.0.1", + "is-callable": "1.1.3", + "is-regex": "1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "1.1.3", + "is-date-object": "1.0.1", + "is-symbol": "1.0.1" + } + }, + "es5-ext": { + "version": "0.10.38", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.38.tgz", + "integrity": "sha512-jCMyePo7AXbUESwbl8Qi01VSH2piY9s/a3rSU/5w/MlTIx8HPL1xn2InGN8ejt/xulcJgnTO7vqNtOAxzYd2Kg==", + "dev": true, + "requires": { + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-symbol": "3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-set": "0.1.5", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1", + "event-emitter": "0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "es6-templates": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/es6-templates/-/es6-templates-0.2.3.tgz", + "integrity": "sha1-XLmsn7He1usSOTQrgdeSu7QHjuQ=", + "dev": true, + "requires": { + "recast": "0.11.23", + "through": "2.3.8" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38", + "es6-iterator": "2.0.3", + "es6-symbol": "3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "0.1.5", + "es6-weak-map": "2.0.2", + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + } + }, + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1.0.0", + "es5-ext": "0.10.38" + } + }, + "eventemitter3": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-1.2.0.tgz", + "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-0.1.6.tgz", + "integrity": "sha1-Cs7ehJ7X3RzMMsgRuxG5RNTykjI=", + "dev": true, + "requires": { + "original": "1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "1.3.4", + "safe-buffer": "5.1.1" + } + }, + "exec-buffer": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "p-finally": "1.0.0", + "pify": "3.0.0", + "rimraf": "2.6.2", + "tempfile": "2.0.0" + } + }, + "exec-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", + "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", + "dev": true, + "requires": { + "async-each-series": "1.1.0", + "object-assign": "4.1.1" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "executable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", + "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", + "dev": true, + "requires": { + "meow": "3.7.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "express": { + "version": "4.16.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", + "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "1.1.2", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "finalhandler": "1.1.0", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "1.1.2", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "2.0.2", + "qs": "6.5.1", + "range-parser": "1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.1", + "serve-static": "1.13.1", + "setprototypeof": "1.1.0", + "statuses": "1.3.1", + "type-is": "1.6.15", + "utils-merge": "1.0.1", + "vary": "1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-text-webpack-plugin": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extract-text-webpack-plugin/-/extract-text-webpack-plugin-3.0.2.tgz", + "integrity": "sha512-bt/LZ4m5Rqt/Crl2HiKuAl/oqg0psx1tsTLkvWbJen1CtD+fftkZhMaQ9HOtY2gWsl2Wq+sABmMVi9z3DhKWQQ==", + "dev": true, + "requires": { + "async": "2.6.0", + "loader-utils": "1.1.0", + "schema-utils": "0.3.0", + "webpack-sources": "1.1.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", + "dev": true, + "requires": { + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" + } + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fastparse": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", + "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=", + "dev": true + }, + "faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" + } + }, + "file-loader": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-0.11.2.tgz", + "integrity": "sha512-N+uhF3mswIFeziHQjGScJ/yHXYt3DiLBeC+9vWW+WjUBiClMSOlV1YrXQi+7KM2aA3Rn4Bybgv+uXFQbfkzpvg==", + "dev": true, + "requires": { + "loader-utils": "1.1.0" + } + }, + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", + "dev": true + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "dev": true, + "requires": { + "filename-reserved-regex": "1.0.0", + "strip-outer": "1.0.0", + "trim-repeated": "1.0.0" + } + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "finalhandler": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", + "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "find-cache-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-1.0.0.tgz", + "integrity": "sha1-kojj6ePMN0hxfTnq3hfPcfww7m8=", + "dev": true, + "requires": { + "commondir": "1.0.1", + "make-dir": "1.1.0", + "pkg-dir": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "find-versions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "dev": true, + "requires": { + "array-uniq": "1.0.3", + "get-stdin": "4.0.1", + "meow": "3.7.0", + "semver-regex": "1.0.0" + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flatten": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", + "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", + "dev": true + }, + "flush-write-stream": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.2.tgz", + "integrity": "sha1-yBuQ2HRnZvGmCaRoCZRsRd2K5Bc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "follow-redirects": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.4.1.tgz", + "integrity": "sha512-uxYePVPogtya1ktGnAAXOacnbIuRMB4dkvqeNz2qTtTQsuzSfbDolV+wMMKxAmCx0bLgAKLbBOkjItMbbkR1vg==", + "dev": true, + "requires": { + "debug": "3.1.0" + } + }, + "font-awesome": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/font-awesome/-/font-awesome-4.7.0.tgz", + "integrity": "sha1-j6jPBBGhoxr9B7BtKQK7n8gVoTM=" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "friendly-errors-webpack-plugin": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.6.1.tgz", + "integrity": "sha1-4yeBxHIvVGoGqbXXp8+ihSA3XXA=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "error-stack-parser": "2.0.1", + "string-length": "1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.1", + "universalify": "0.1.1" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "iferr": "0.1.5", + "imurmurhash": "0.1.4", + "readable-stream": "2.3.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.8.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "dev": true, + "requires": { + "globule": "1.2.0" + } + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-proxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", + "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", + "dev": true, + "requires": { + "rc": "1.2.5" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "gifsicle": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", + "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "3.0.1", + "glob": "5.0.15", + "glob-parent": "3.1.0", + "micromatch": "2.3.11", + "ordered-read-streams": "0.3.0", + "through2": "0.6.5", + "to-absolute-glob": "0.1.1", + "unique-stream": "2.2.1" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "globs": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/globs/-/globs-0.1.3.tgz", + "integrity": "sha1-ZwA3ElKHy2VJqtlqRM+mhP18VQI=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + } + }, + "glogg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.1.tgz", + "integrity": "sha512-ynYqXLoluBKf9XGR1gA59yEJisIL7YHEH4xr3ZziHB5/yl4qWfaK8Js9jGe6gBGCSCKVqiyO30WnRZADvemUNw==", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer2": "0.1.4", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "node-status-codes": "1.0.0", + "object-assign": "4.1.1", + "parse-json": "2.2.0", + "pinkie-promise": "2.0.1", + "read-all-stream": "3.1.0", + "readable-stream": "2.3.3", + "timed-out": "3.1.3", + "unzip-response": "1.0.2", + "url-parse-lax": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growly": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", + "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=", + "dev": true + }, + "gulp-decompress": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", + "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", + "dev": true, + "requires": { + "archive-type": "3.2.0", + "decompress": "3.0.0", + "gulp-util": "3.0.8", + "readable-stream": "2.3.3" + } + }, + "gulp-rename": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.2.2.tgz", + "integrity": "sha1-OtRCh2PwXidk3sHGfYaNsnVoeBc=", + "dev": true + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "1.5.1", + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "through2": "2.0.3", + "vinyl": "1.2.0" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.1" + } + }, + "handle-thing": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", + "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "commander": "2.12.2", + "is-my-json-valid": "2.17.1", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", + "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", + "dev": true, + "requires": { + "function-bind": "1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "hash-base": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-2.0.2.tgz", + "integrity": "sha1-ZuodhW206KVHDK32/OI65SRO8uE=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true + }, + "hash.js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "minimalistic-assert": "1.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.0", + "minimalistic-crypto-utils": "1.0.1" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "wbuf": "1.7.2" + } + }, + "html-comment-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.1.tgz", + "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", + "dev": true + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "dev": true + }, + "html-loader": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/html-loader/-/html-loader-0.4.5.tgz", + "integrity": "sha1-X7zYfNY6XEmn/OL+VvQl4Fcpxow=", + "dev": true, + "requires": { + "es6-templates": "0.2.3", + "fastparse": "1.1.1", + "html-minifier": "3.5.8", + "loader-utils": "1.1.0", + "object-assign": "4.1.1" + } + }, + "html-minifier": { + "version": "3.5.8", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.8.tgz", + "integrity": "sha512-WX7D6PB9PFq05fZ1/CyxPUuyqXed6vh2fGOM80+zJT5wAO93D/cUjLs0CcbBFjQmlwmCgRvl97RurtArIpOnkw==", + "dev": true, + "requires": { + "camel-case": "3.0.0", + "clean-css": "4.1.9", + "commander": "2.12.2", + "he": "1.1.1", + "ncname": "1.0.0", + "param-case": "2.1.1", + "relateurl": "0.2.7", + "uglify-js": "3.3.9" + }, + "dependencies": { + "uglify-js": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.9.tgz", + "integrity": "sha512-J2t8B5tj9JdPTW4+sNZXmiIWHzTvcoITkaqzTiilu/biZF/9crqf/Fi7k5hqbOmVRh9/hVNxAxBYIMF7N6SqMQ==", + "dev": true, + "requires": { + "commander": "2.13.0", + "source-map": "0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + } + } + } + } + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "dev": true, + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.3.1" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", + "dev": true + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.9.tgz", + "integrity": "sha1-6hoE+2St/wJC6ZdPKX3Uw8rSceE=", + "dev": true + }, + "http-proxy": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.16.2.tgz", + "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", + "dev": true, + "requires": { + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", + "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", + "dev": true, + "requires": { + "http-proxy": "1.16.2", + "is-glob": "3.1.0", + "lodash": "4.17.4", + "micromatch": "2.3.11" + }, + "dependencies": { + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", + "dev": true + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "6.0.16" + } + }, + "ieee754": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.8.tgz", + "integrity": "sha1-vjPUCsEO8ZJnAfbwii2G+/0a0+Q=", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "imagemin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", + "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", + "dev": true, + "requires": { + "file-type": "4.4.0", + "globby": "6.1.0", + "make-dir": "1.1.0", + "p-pipe": "1.2.0", + "pify": "2.3.0", + "replace-ext": "1.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "imagemin-gifsicle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", + "integrity": "sha512-K01m5QuPK+0en8oVhiOOAicF7KjrHlCZxS++mfLI2mV/Ksfq/Y9nCXCWDz6jRv13wwlqe5T7hXT+ji2DnLc2yQ==", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "gifsicle": "3.0.4", + "is-gif": "1.0.0" + } + }, + "imagemin-mozjpeg": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-6.0.0.tgz", + "integrity": "sha1-caMqRXqhsmEXpo7u8tmxkMLlCR4=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-jpg": "1.0.0", + "mozjpeg": "4.1.1" + } + }, + "imagemin-optipng": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", + "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "optipng-bin": "3.1.4" + } + }, + "imagemin-pngquant": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/imagemin-pngquant/-/imagemin-pngquant-5.0.1.tgz", + "integrity": "sha1-2KMp2lU6+iJrEc5i3r4Lfje0OeY=", + "dev": true, + "requires": { + "exec-buffer": "3.2.0", + "is-png": "1.1.0", + "pngquant-bin": "3.1.1" + } + }, + "imagemin-svgo": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-5.2.4.tgz", + "integrity": "sha512-1bNZdlWVKdfxzu0xDD1pWjwK/G8FLcztUh/GWaI7xLgCFrn0j35o+uBbY7VcdY2AmKgiLYTXhrzrbkQk6xj8aA==", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "svgo": "0.7.2" + } + }, + "img-loader": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/img-loader/-/img-loader-2.0.0.tgz", + "integrity": "sha1-WDdAs+KjiuulQ1x91TC+nOdFT9k=", + "dev": true, + "requires": { + "imagemin": "5.3.1", + "imagemin-gifsicle": "5.2.0", + "imagemin-mozjpeg": "6.0.0", + "imagemin-optipng": "5.2.1", + "imagemin-pngquant": "5.0.1", + "imagemin-svgo": "5.2.4", + "loader-utils": "1.1.0" + } + }, + "import-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-1.0.0.tgz", + "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", + "dev": true, + "requires": { + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "internal-ip": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-1.2.0.tgz", + "integrity": "sha1-rp+/k7mEh4eF1QqN4bNWlWBYz1w=", + "dev": true, + "requires": { + "meow": "3.7.0" + } + }, + "interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true, + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true + }, + "ipaddr.js": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", + "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=", + "dev": true + }, + "is-absolute": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", + "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", + "dev": true, + "requires": { + "is-relative": "0.1.3" + } + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "1.11.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-bzip2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", + "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", + "dev": true + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" + }, + "dependencies": { + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-gif": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", + "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, + "is-jpg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.0.tgz", + "integrity": "sha1-KVnBfnNDDbOCZNp1uQ3VTy2G2hw=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", + "integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-natural-number": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", + "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-odd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", + "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", + "dev": true, + "requires": { + "is-number": "3.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.1" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-png": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", + "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", + "dev": true + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "1.0.1" + } + }, + "is-relative": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", + "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-svg": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", + "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", + "dev": true, + "requires": { + "html-comment-regex": "1.1.1" + } + }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-tar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", + "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-url": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.2.tgz", + "integrity": "sha1-SYkFpZO/R8wtnn9zg3K792lsfyY=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, + "is-windows": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.1.tgz", + "integrity": "sha1-MQ23D3QtJZoWo2kgK1GvhCMzENk=", + "dev": true + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "is-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", + "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "jquery": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz", + "integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==", + "dev": true + }, + "js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", + "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "2.7.3" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-loader": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "killable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.0.tgz", + "integrity": "sha1-2ouEvUfeU5WHj5XWTQLyRJ/gXms=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "laravel-mix": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-1.7.2.tgz", + "integrity": "sha512-La1eAsCkEdySc9J9MJ/g8Dj1EfGo7aXW92GZKoSbrSg4uQWNNoV824e6+o4f4Eo/YWYrYwZTkdnWJJ1uVqP+dw==", + "dev": true, + "requires": { + "autoprefixer": "7.2.5", + "babel-core": "6.26.0", + "babel-loader": "7.1.2", + "babel-plugin-transform-object-rest-spread": "6.26.0", + "babel-plugin-transform-runtime": "6.23.0", + "babel-preset-env": "1.6.1", + "chokidar": "1.7.0", + "clean-css": "4.1.9", + "concatenate": "0.0.2", + "css-loader": "0.28.9", + "dotenv": "4.0.0", + "dotenv-expand": "4.0.1", + "extract-text-webpack-plugin": "3.0.2", + "file-loader": "0.11.2", + "friendly-errors-webpack-plugin": "1.6.1", + "fs-extra": "3.0.1", + "glob": "7.1.2", + "html-loader": "0.4.5", + "img-loader": "2.0.0", + "lodash": "4.17.4", + "md5": "2.2.1", + "node-sass": "4.7.2", + "postcss-loader": "2.0.10", + "resolve-url-loader": "2.2.1", + "sass-loader": "6.0.6", + "style-loader": "0.18.2", + "uglify-js": "2.8.29", + "uglifyjs-webpack-plugin": "1.1.8", + "vue-loader": "13.7.1", + "vue-template-compiler": "2.5.13", + "webpack": "3.10.0", + "webpack-chunk-hash": "0.4.0", + "webpack-dev-server": "2.11.1", + "webpack-merge": "4.1.1", + "webpack-notifier": "1.5.1", + "yargs": "8.0.2" + } + }, + "lazy-cache": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", + "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=", + "dev": true + }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", + "dev": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "loader-runner": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.3.0.tgz", + "integrity": "sha1-9IKuqC1UPgeSFwDVpG7yb9rGuKI=", + "dev": true + }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "dev": true, + "requires": { + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=", + "dev": true + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", + "dev": true + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.mergewith": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz", + "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.tail": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.tail/-/lodash.tail-4.1.1.tgz", + "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "logalot": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", + "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", + "dev": true, + "requires": { + "figures": "1.7.0", + "squeak": "1.3.0" + } + }, + "loglevel": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz", + "integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=", + "dev": true + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true, + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "lpad-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", + "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "indent-string": "2.1.0", + "longest": "1.0.1", + "meow": "3.7.0" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "macaddress": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", + "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", + "dev": true + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "1.0.1" + } + }, + "math-expression-evaluator": { + "version": "1.2.17", + "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", + "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", + "dev": true + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "dev": true, + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.6" + } + }, + "md5.js": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.4.tgz", + "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", + "dev": true, + "requires": { + "hash-base": "3.0.4", + "inherits": "2.0.3" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "0.1.6", + "readable-stream": "2.3.3" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "brorand": "1.1.0" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimalistic-assert": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.0.tgz", + "integrity": "sha1-cCvi3aazf0g2vLP121ZkG2Sh09M=", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mississippi": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-1.3.1.tgz", + "integrity": "sha512-/6rB8YXFbAtsUVRphIRQqB0+9c7VaPHCjVtvto+JqwVxgz8Zz+I+f68/JgQ+Pb4VlZb2svA9OtdXnHHsZz7ltg==", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "duplexify": "3.5.3", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.2", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "1.0.3", + "pumpify": "1.4.0", + "stream-each": "1.2.2", + "through2": "2.0.3" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "mixin-deep": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.0.tgz", + "integrity": "sha512-dgaCvoh6i1nosAUBKb0l0pfJ78K8+S9fluyIR2YvAeUD/QuMahnFnF3xYty5eYXMjhGSsB0DsW6A0uAZyetoAg==", + "dev": true, + "requires": { + "for-in": "1.0.2", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "0.1.8", + "is-extendable": "0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" + } + }, + "mozjpeg": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-4.1.1.tgz", + "integrity": "sha1-hZAwsk9omlPbm0DwFg2JGVuI/VA=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "1.3.1", + "thunky": "1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "dev": true + }, + "nanomatch": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", + "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "is-odd": "1.0.0", + "kind-of": "5.1.0", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "ncname": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ncname/-/ncname-1.0.0.tgz", + "integrity": "sha1-W1etGLHKCShk72Kwse2BlPODtxw=", + "dev": true, + "requires": { + "xml-char-classes": "1.0.0" + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "1.1.4" + } + }, + "node-forge": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz", + "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA=", + "dev": true + }, + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "dev": true, + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.4", + "request": "2.79.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "node-libs-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.1.0.tgz", + "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", + "dev": true, + "requires": { + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", + "path-browserify": "0.0.0", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.3", + "stream-browserify": "2.0.1", + "stream-http": "2.8.0", + "string_decoder": "1.0.3", + "timers-browserify": "2.0.6", + "tty-browserify": "0.0.0", + "url": "0.11.0", + "util": "0.10.3", + "vm-browserify": "0.0.4" + } + }, + "node-notifier": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", + "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", + "dev": true, + "requires": { + "growly": "1.3.0", + "semver": "5.5.0", + "shellwords": "0.1.1", + "which": "1.3.0" + } + }, + "node-sass": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.7.2.tgz", + "integrity": "sha512-CaV+wLqZ7//Jdom5aUFCpGNoECd7BbNhjuwdsX/LkXBrHl8eb1Wjw4HvWqcFvhr5KuNgAk8i/myf/MQ1YYeroA==", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.2", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.0", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.8.0", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.79.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.0", + "true-case-path": "1.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1.1.1" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + } + } + }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, + "object-path": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz", + "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU=", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "obuf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.1.tgz", + "integrity": "sha1-EEEktsYCxnlogaBCVB0220OlJk4=", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "opn": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.2.0.tgz", + "integrity": "sha512-Jd/GpzPyHF4P2/aNOVmS3lfMSWV9J7cOhCG1s08XCEAsPkB7lp6ddiU0J7XzyQRDUh8BqJ7PchfINjR8jyofRQ==", + "dev": true, + "requires": { + "is-wsl": "1.1.0" + } + }, + "optipng-bin": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", + "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "1.1.0", + "readable-stream": "2.3.3" + } + }, + "original": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.0.tgz", + "integrity": "sha1-kUf5P6FpbQS+YeAb1QuurKZWvTs=", + "dev": true, + "requires": { + "url-parse": "1.0.5" + }, + "dependencies": { + "url-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.0.5.tgz", + "integrity": "sha1-CFSGBCKv3P7+tsllxmLUgAFpkns=", + "dev": true, + "requires": { + "querystringify": "0.0.4", + "requires-port": "1.0.0" + } + } + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-filter-obj": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", + "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", + "dev": true + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "pako": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", + "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==", + "dev": true + }, + "parallel-transform": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.1.0.tgz", + "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "dev": true, + "requires": { + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "2.3.2" + } + }, + "parse-asn1": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.0.tgz", + "integrity": "sha1-N8T5t+06tlx0gXtfJICTf7+XxxI=", + "dev": true, + "requires": { + "asn1.js": "4.9.2", + "browserify-aes": "1.1.1", + "create-hash": "1.1.3", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.14" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.0.tgz", + "integrity": "sha1-oLhwcpquIUAFt9UDLsLLuw+0RRo=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pbkdf2": { + "version": "3.0.14", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", + "dev": true, + "requires": { + "create-hash": "1.1.3", + "create-hmac": "1.1.6", + "ripemd160": "2.0.1", + "safe-buffer": "5.1.1", + "sha.js": "2.4.10" + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "2.1.0" + } + }, + "pngquant-bin": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pngquant-bin/-/pngquant-bin-3.1.1.tgz", + "integrity": "sha1-0STZinWpSH9AwWQLTb/Lsr1aH9E=", + "dev": true, + "requires": { + "bin-build": "2.2.0", + "bin-wrapper": "3.0.2", + "logalot": "2.1.0" + } + }, + "portfinder": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.13.tgz", + "integrity": "sha1-uzLs2HwnEErm7kS1o8y/Drsa7ek=", + "dev": true, + "requires": { + "async": "1.5.2", + "debug": "2.6.9", + "mkdirp": "0.5.1" + }, + "dependencies": { + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.16.tgz", + "integrity": "sha512-m758RWPmSjFH/2MyyG3UOW1fgYbR9rtdzz5UNJnlm7OLtu4B2h9C6gi+bE4qFKghsBRFfZT8NzoQBs6JhLotoA==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "source-map": "0.6.1", + "supports-color": "5.1.0" + } + }, + "postcss-calc": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-5.3.1.tgz", + "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-colormin": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-2.2.2.tgz", + "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", + "dev": true, + "requires": { + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-convert-values": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-2.6.1.tgz", + "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-comments": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-2.0.4.tgz", + "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-duplicates": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-2.1.0.tgz", + "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-empty": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-2.1.0.tgz", + "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-overridden": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-0.1.1.tgz", + "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-discard-unused": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-2.2.3.tgz", + "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-filter-plugins": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-filter-plugins/-/postcss-filter-plugins-2.0.2.tgz", + "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "uniqid": "4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-load-config": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", + "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" + } + }, + "postcss-load-options": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-load-options/-/postcss-load-options-1.2.0.tgz", + "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" + } + }, + "postcss-load-plugins": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/postcss-load-plugins/-/postcss-load-plugins-2.3.0.tgz", + "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", + "dev": true, + "requires": { + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" + } + }, + "postcss-loader": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-2.0.10.tgz", + "integrity": "sha512-xQaDcEgJ/2JqFY18zpFkik8vyYs7oS5ZRbrjvDqkP97k2wYWfPT4+qA0m4o3pTSCsz0u26PNqs8ZO9FRUWAqrA==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "postcss": "6.0.16", + "postcss-load-config": "1.2.0", + "schema-utils": "0.3.0" + } + }, + "postcss-merge-idents": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-2.1.7.tgz", + "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-merge-longhand": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-2.0.2.tgz", + "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-merge-rules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-2.1.2.tgz", + "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000800", + "electron-to-chromium": "1.3.31" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-message-helpers": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz", + "integrity": "sha1-pPL0+rbk/gAvCu0ABHjN9S+bpg4=", + "dev": true + }, + "postcss-minify-font-values": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-1.0.5.tgz", + "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-params": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-1.2.2.tgz", + "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-minify-selectors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-2.1.1.tgz", + "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", + "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", + "dev": true, + "requires": { + "postcss": "6.0.16" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.16" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.16" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.16" + } + }, + "postcss-normalize-charset": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-1.1.1.tgz", + "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-normalize-url": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-3.0.8.tgz", + "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", + "dev": true, + "requires": { + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-ordered-values": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-2.2.3.tgz", + "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-reduce-idents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz", + "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", + "dev": true, + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-reduce-initial": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-1.0.1.tgz", + "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", + "dev": true, + "requires": { + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-reduce-transforms": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-1.0.4.tgz", + "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-2.2.3.tgz", + "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", + "dev": true, + "requires": { + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" + } + }, + "postcss-svgo": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", + "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", + "dev": true, + "requires": { + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-unique-selectors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-2.0.2.tgz", + "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", + "dev": true, + "requires": { + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=", + "dev": true + }, + "postcss-zindex": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-2.2.0.tgz", + "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", + "dev": true, + "requires": { + "has": "1.0.1", + "postcss": "5.2.18", + "uniqs": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "dev": true, + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "dev": true, + "requires": { + "has-flag": "1.0.0" + } + } + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "prettier": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.10.2.tgz", + "integrity": "sha512-TcdNoQIWFoHblurqqU6d1ysopjq7UX0oRcT/hJ8qvBAELiYWn+Ugf0AXdnzISEJ7vuhNnQ98N8jR8Sh53x4IZg==", + "dev": true + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", + "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "dev": true, + "requires": { + "forwarded": "0.1.2", + "ipaddr.js": "1.5.2" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "public-encrypt": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.0.tgz", + "integrity": "sha1-OfaZ86RlYN1eusvKaTyvfGXBjMY=", + "dev": true, + "requires": { + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.1.3", + "parse-asn1": "5.1.0", + "randombytes": "2.0.6" + } + }, + "pump": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", + "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + }, + "pumpify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.4.0.tgz", + "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "inherits": "2.0.3", + "pump": "2.0.1" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "once": "1.4.0" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.3.2.tgz", + "integrity": "sha1-51vV9uJoEioqDgvaYwslUMFmUCw=", + "dev": true + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-0.0.4.tgz", + "integrity": "sha1-DPf4T5Rj/wrlHExLFC2VvjdyTZw=", + "dev": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "randombytes": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.0.6.tgz", + "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "randomfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.3.tgz", + "integrity": "sha512-YL6GrhrWoic0Eq8rXVbMptH7dAxCs0J+mh5Y0euNekPPYaxEmdVGim6GdoxoRzKW2yJoU8tueifS7mYxvcFDEQ==", + "dev": true, + "requires": { + "randombytes": "2.0.6", + "safe-buffer": "5.1.1" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "dev": true, + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.5.tgz", + "integrity": "sha1-J1zWh/bjs2zHVrqibf7oCnkDAf0=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.5", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1", + "readable-stream": "2.3.3" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + }, + "dependencies": { + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "recast": { + "version": "0.11.23", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", + "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=", + "dev": true, + "requires": { + "ast-types": "0.9.6", + "esprima": "3.1.3", + "private": "0.1.8", + "source-map": "0.5.7" + }, + "dependencies": { + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "reduce-css-calc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", + "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "reduce-function-call": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce-function-call/-/reduce-function-call-1.0.2.tgz", + "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", + "dev": true, + "requires": { + "balanced-match": "0.4.2" + }, + "dependencies": { + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + } + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regex-not": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.0.tgz", + "integrity": "sha1-Qvg+OXcWIt+CawKvF2Ul1qXxV/k=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "regex-parser": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.8.tgz", + "integrity": "sha1-2kwM2lqChVkJQWiTD0VfUytv+6w=", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "request": { + "version": "2.79.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.79.0.tgz", + "integrity": "sha1-Tf5b9r6LjNw3/Pk+BLZVd3InEN4=", + "dev": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.11.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "2.0.6", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "qs": "6.3.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.4.3", + "uuid": "3.2.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz", + "integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "resolve-url-loader": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-2.2.1.tgz", + "integrity": "sha512-ywToZt/yttp4qG/SiiGMLAgaGuSaWSujAaf3WCadXehvQLxIgKFmMOSegaoH9Laa70Ayl4kti0zCAqLR48H/Mw==", + "dev": true, + "requires": { + "adjust-sourcemap-loader": "1.1.0", + "camelcase": "4.1.0", + "convert-source-map": "1.5.1", + "loader-utils": "1.1.0", + "lodash.defaults": "4.2.0", + "rework": "1.0.1", + "rework-visit": "1.0.0", + "source-map": "0.5.7", + "urix": "0.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "0.3.5", + "css": "2.2.1" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + } + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "ripemd160": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.1.tgz", + "integrity": "sha1-D0WEKVxTo2KK9+bXmsohzlfRxuc=", + "dev": true, + "requires": { + "hash-base": "2.0.2", + "inherits": "2.0.3" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "1.2.0" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "dev": true, + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "scss-tokenizer": "0.2.3", + "yargs": "7.1.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + } + } + } + }, + "sass-loader": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-6.0.6.tgz", + "integrity": "sha512-c3/Zc+iW+qqDip6kXPYLEgsAu2lf4xz0EZDplB7EmSUMda12U1sGJPetH55B/j9eu0bTtKzKlNPWWyYC7wFNyQ==", + "dev": true, + "requires": { + "async": "2.6.0", + "clone-deep": "0.3.0", + "loader-utils": "1.1.0", + "lodash.tail": "4.1.1", + "pify": "3.0.0" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", + "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", + "dev": true, + "requires": { + "ajv": "5.5.2" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "dev": true, + "requires": { + "js-base64": "2.4.3", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + } + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.2.tgz", + "integrity": "sha1-tESVgNmZKbZbEKSDiTAaZZIIh1g=", + "dev": true, + "requires": { + "node-forge": "0.7.1" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", + "dev": true + }, + "semver-truncate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", + "dev": true, + "requires": { + "semver": "5.5.0" + } + }, + "send": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", + "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "1.1.2", + "destroy": "1.0.4", + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "etag": "1.8.1", + "fresh": "0.5.2", + "http-errors": "1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "2.3.0", + "range-parser": "1.2.0", + "statuses": "1.3.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "serialize-javascript": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.4.0.tgz", + "integrity": "sha1-fJWFFNtqwkQ6irwGLcn3iGp/YAU=", + "dev": true + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "1.0.3", + "http-errors": "1.6.2", + "mime-types": "2.1.17", + "parseurl": "1.3.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "serve-static": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", + "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "dev": true, + "requires": { + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "parseurl": "1.3.2", + "send": "0.16.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-getter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/set-getter/-/set-getter-0.1.0.tgz", + "integrity": "sha1-12nBgsnVpR9AkUXy+6guXoboA3Y=", + "dev": true, + "requires": { + "to-object-path": "0.3.0" + } + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true + }, + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "sha.js": { + "version": "2.4.10", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.10.tgz", + "integrity": "sha512-vnwmrFDlOExK4Nm16J2KMWHLrp14lBrjxMxBJpu++EnsuBmpiYaM/MEs46Vxxm/4FvdP5yTwuCTO9it5FSjrqA==", + "dev": true, + "requires": { + "inherits": "2.0.3", + "safe-buffer": "5.1.1" + } + }, + "shallow-clone": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz", + "integrity": "sha1-WQnodLp3EG1zrEFM/sH/yofZcGA=", + "dev": true, + "requires": { + "is-extendable": "0.1.1", + "kind-of": "2.0.1", + "lazy-cache": "0.2.7", + "mixin-object": "2.0.1" + }, + "dependencies": { + "kind-of": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz", + "integrity": "sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "snapdragon": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.1.tgz", + "integrity": "sha1-4StUh/re0+PeoKyR6UAL91tAE3A=", + "dev": true, + "requires": { + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "2.0.2" + }, + "dependencies": { + "atob": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", + "integrity": "sha1-GcenYEc3dEaPILLS0DNyrX1Mv10=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", + "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", + "dev": true, + "requires": { + "atob": "2.0.3", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sockjs": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", + "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "dev": true, + "requires": { + "faye-websocket": "0.10.0", + "uuid": "3.2.1" + } + }, + "sockjs-client": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.1.4.tgz", + "integrity": "sha1-W6vjhrd15M8U51IJEUUmVAFsixI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "eventsource": "0.1.6", + "faye-websocket": "0.11.1", + "inherits": "2.0.3", + "json3": "3.3.2", + "url-parse": "1.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "faye-websocket": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.1.tgz", + "integrity": "sha1-8O/hjE9W5PQK/H4Gxxn9XuYYjzg=", + "dev": true, + "requires": { + "websocket-driver": "0.7.0" + } + } + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "dev": true, + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "source-list-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", + "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "spdy": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", + "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", + "dev": true, + "requires": { + "debug": "2.6.9", + "handle-thing": "1.2.5", + "http-deceiver": "1.2.7", + "safe-buffer": "5.1.1", + "select-hose": "2.0.0", + "spdy-transport": "2.0.20" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "spdy-transport": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.0.20.tgz", + "integrity": "sha1-c15yBUxIayNU/onnAiVgBKOazk0=", + "dev": true, + "requires": { + "debug": "2.6.9", + "detect-node": "2.0.3", + "hpack.js": "2.1.6", + "obuf": "1.1.1", + "readable-stream": "2.3.3", + "safe-buffer": "5.1.1", + "wbuf": "1.7.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "squeak": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", + "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "console-stream": "0.1.1", + "lpad-align": "1.1.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "ssri": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-5.1.0.tgz", + "integrity": "sha512-TevC8fgxQKTfQ1nWtM9GNzr3q5rrHNntG9CDMH1k3QhSZI6Kb+NbjLRs8oPFZa2Hgo7zoekL+UTvoEk7tsbjQg==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stackframe": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.0.4.tgz", + "integrity": "sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw==", + "dev": true + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "object-copy": "0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=", + "dev": true + }, + "stdout-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", + "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "stream-browserify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz", + "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "0.1.4", + "readable-stream": "2.3.3" + } + }, + "stream-each": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.2.tgz", + "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "dev": true, + "requires": { + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" + } + }, + "stream-http": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.0.tgz", + "integrity": "sha512-sZOFxI/5xw058XIRHl4dU3dZ+TTOIGJR78Dvo0oEAejIt4ou27k+3ne1zYmCV+v7UucbxIFQuOgnkTVHh8YPnw==", + "dev": true, + "requires": { + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" + } + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz", + "integrity": "sha1-VpcPscOFWOnnC3KL894mmsRa36w=", + "dev": true, + "requires": { + "strip-ansi": "3.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + } + }, + "strip-dirs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", + "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "get-stdin": "4.0.1", + "is-absolute": "0.1.7", + "is-natural-number": "2.1.1", + "minimist": "1.2.0", + "sum-up": "1.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.0.tgz", + "integrity": "sha1-qsC6YNLpDF1PJ1/Yhp/ZotMQ/7g=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "style-loader": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.18.2.tgz", + "integrity": "sha512-WPpJPZGUxWYHWIUMNNOYqql7zh85zGmr84FdTVWq52WTIkqlW9xSxD3QYWi/T31cqn9UNSsietVEgGn2aaSCzw==", + "dev": true, + "requires": { + "loader-utils": "1.1.0", + "schema-utils": "0.3.0" + } + }, + "sum-up": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", + "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", + "dev": true, + "requires": { + "chalk": "1.1.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "supports-color": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.1.0.tgz", + "integrity": "sha512-Ry0AwkoKjDpVKK4sV4h6o3UJmNRbjYm2uXhwfj3J56lMVdvnUNqzQVRztOOMGQ++w1K/TjNDFvpJk0F/LoeBCQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "svgo": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", + "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", + "dev": true, + "requires": { + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" + } + }, + "tapable": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.8.tgz", + "integrity": "sha1-mTcqXJmb8t8WCvwNdL7U9HlIzSI=", + "dev": true + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "dev": true, + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.1", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", + "dev": true, + "requires": { + "temp-dir": "1.0.0", + "uuid": "3.2.1" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "2.0.3", + "xtend": "4.0.1" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "thunky": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.2.tgz", + "integrity": "sha1-qGLgGOP7HqLsP85dVWBc9X8kc3E=", + "dev": true + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", + "dev": true + }, + "timers-browserify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.6.tgz", + "integrity": "sha512-HQ3nbYRAowdVd0ckGFvmJPPCOH/CHleFN/Y0YQCX1DVaB7t+KFvisuyN09fuP8Jtp1CpfSh8O8bMkHbdbPe6Pw==", + "dev": true, + "requires": { + "setimmediate": "1.0.5" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "to-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.1.tgz", + "integrity": "sha1-FTWL7kosg712N3uh3ASdDxiDeq4=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "regex-not": "1.0.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "repeat-string": "1.6.1" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + } + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "true-case-path": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.2.tgz", + "integrity": "sha1-fskRMJJHZsf1c74wIMNPj9/QDWI=", + "dev": true, + "requires": { + "glob": "6.0.4" + }, + "dependencies": { + "glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } + } + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "type-is": { + "version": "1.6.15", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", + "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "2.1.17" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "uglifyjs-webpack-plugin": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-1.1.8.tgz", + "integrity": "sha512-XG8/QmR1pyPeE1kj2aigo5kos8umefB31zW+PMvAAytHSB0T/vQvN6sqt8+Sh+y0b0A7zlmxNi2dzRnj0wcqGA==", + "dev": true, + "requires": { + "cacache": "10.0.2", + "find-cache-dir": "1.0.0", + "schema-utils": "0.4.3", + "serialize-javascript": "1.4.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.5.2" + }, + "dependencies": { + "commander": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz", + "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==", + "dev": true + }, + "schema-utils": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.4.3.tgz", + "integrity": "sha512-sgv/iF/T4/SewJkaVpldKC4WjSkz0JsOh2eKtxCPpCO1oR05+7MOF+H476HVRbLArkgA7j5TRJJ4p2jdFkUGQQ==", + "dev": true, + "requires": { + "ajv": "5.5.2", + "ajv-keywords": "2.1.1" + } + }, + "uglify-es": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz", + "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", + "dev": true, + "requires": { + "commander": "2.13.0", + "source-map": "0.6.1" + } + } + } + }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" + }, + "dependencies": { + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" + } + } + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqid": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-4.1.1.tgz", + "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", + "dev": true, + "requires": { + "macaddress": "0.2.8" + } + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.0.tgz", + "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", + "dev": true, + "requires": { + "unique-slug": "2.0.0" + } + }, + "unique-slug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.0.tgz", + "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "dev": true, + "requires": { + "imurmurhash": "0.1.4" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "1.0.1", + "through2-filter": "2.0.0" + } + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "0.3.1", + "isobject": "3.0.1" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-parse": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.2.0.tgz", + "integrity": "sha512-DT1XbYAfmQP65M/mE6OALxmXzZ/z1+e5zk2TcSKe/KiYbNGZxgtttzC0mR/sjopbpOXcbniq7eIKmocJnUWlEw==", + "dev": true, + "requires": { + "querystringify": "1.0.0", + "requires-port": "1.0.0" + }, + "dependencies": { + "querystringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", + "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=", + "dev": true + } + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "requires": { + "ip-regex": "1.0.3" + } + }, + "use": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/use/-/use-2.0.2.tgz", + "integrity": "sha1-riig1y+TvyJCKhii43mZMRLeyOg=", + "dev": true, + "requires": { + "define-property": "0.2.5", + "isobject": "3.0.1", + "lazy-cache": "2.0.2" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + }, + "lazy-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-2.0.2.tgz", + "integrity": "sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=", + "dev": true, + "requires": { + "set-getter": "0.1.0" + } + } + } + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.1.tgz", + "integrity": "sha1-N61zyO5Bf7PVgOeFMSMH0nSEfyI=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + }, + "dependencies": { + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + } + } + }, + "vinyl-assign": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", + "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", + "dev": true, + "requires": { + "object-assign": "4.1.1", + "readable-stream": "2.3.3" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "3.5.3", + "glob-stream": "5.3.5", + "graceful-fs": "4.1.11", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "0.3.0", + "lazystream": "1.0.0", + "lodash.isequal": "4.5.0", + "merge-stream": "1.0.1", + "mkdirp": "0.5.1", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "through2": "2.0.3", + "through2-filter": "2.0.0", + "vali-date": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + } + } + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "vue": { + "version": "2.5.13", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.13.tgz", + "integrity": "sha512-3D+lY7HTkKbtswDM4BBHgqyq+qo8IAEE8lz8va1dz3LLmttjgo0FxairO4r1iN2OBqk8o1FyL4hvzzTFEdQSEw==", + "dev": true + }, + "vue-hot-reload-api": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.2.4.tgz", + "integrity": "sha512-e+ThJMYmZg4D9UnrLcr6LQxGu6YlcxkrmZGPCyIN4malcNhdeGGKxmFuM5y6ICMJJxQywLfT8MM1rYZr4LpeLw==", + "dev": true + }, + "vue-loader": { + "version": "13.7.1", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-13.7.1.tgz", + "integrity": "sha512-v6PbKMGl/hWHGPxB2uGHsA66vusrXF66J/h1QiFXtU6z5zVSK8jq5xl95M1p3QNXmuEJKNP3nxoXfbgQNs7hJg==", + "dev": true, + "requires": { + "consolidate": "0.14.5", + "hash-sum": "1.0.2", + "loader-utils": "1.1.0", + "lru-cache": "4.1.1", + "postcss": "6.0.16", + "postcss-load-config": "1.2.0", + "postcss-selector-parser": "2.2.3", + "prettier": "1.10.2", + "resolve": "1.5.0", + "source-map": "0.6.1", + "vue-hot-reload-api": "2.2.4", + "vue-style-loader": "3.1.2", + "vue-template-es2015-compiler": "1.6.0" + } + }, + "vue-style-loader": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-3.1.2.tgz", + "integrity": "sha512-ICtVdK/p+qXWpdSs2alWtsXt9YnDoYjQe0w5616j9+/EhjoxZkbun34uWgsMFnC1MhrMMwaWiImz3K2jK1Yp2Q==", + "dev": true, + "requires": { + "hash-sum": "1.0.2", + "loader-utils": "1.1.0" + } + }, + "vue-template-compiler": { + "version": "2.5.13", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.5.13.tgz", + "integrity": "sha512-15HWSgIxrGUcV0v7QRen2Y3fQsbgxXwMvjT/5XKMO0ANmaCcNh7y2OeIDTAuSGeosjb9+E1Pn2PHZ61VQWEgBQ==", + "dev": true, + "requires": { + "de-indent": "1.0.2", + "he": "1.1.1" + } + }, + "vue-template-es2015-compiler": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz", + "integrity": "sha512-x3LV3wdmmERhVCYy3quqA57NJW7F3i6faas++pJQWtknWT+n7k30F4TVdHvCLn48peTJFRvCpxs3UuFPqgeELg==", + "dev": true + }, + "ware": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", + "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", + "dev": true, + "requires": { + "wrap-fn": "0.1.5" + } + }, + "watchpack": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.4.0.tgz", + "integrity": "sha1-ShRyvLuVK9Cpu0A2gB+VTfs5+qw=", + "dev": true, + "requires": { + "async": "2.6.0", + "chokidar": "1.7.0", + "graceful-fs": "4.1.11" + } + }, + "wbuf": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.2.tgz", + "integrity": "sha1-1pe5nx9ZUS3ydRvkJ2nBWAtYAf4=", + "dev": true, + "requires": { + "minimalistic-assert": "1.0.0" + } + }, + "webpack": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.10.0.tgz", + "integrity": "sha512-fxxKXoicjdXNUMY7LIdY89tkJJJ0m1Oo8PQutZ5rLgWbV5QVKI15Cn7+/IHnRTd3vfKfiwBx6SBqlorAuNA8LA==", + "dev": true, + "requires": { + "acorn": "5.3.0", + "acorn-dynamic-import": "2.0.2", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "async": "2.6.0", + "enhanced-resolve": "3.4.1", + "escope": "3.6.0", + "interpret": "1.1.0", + "json-loader": "0.5.7", + "json5": "0.5.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "mkdirp": "0.5.1", + "node-libs-browser": "2.1.0", + "source-map": "0.5.7", + "supports-color": "4.5.0", + "tapable": "0.2.8", + "uglifyjs-webpack-plugin": "0.4.6", + "watchpack": "1.4.0", + "webpack-sources": "1.1.0", + "yargs": "8.0.2" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "uglifyjs-webpack-plugin": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/uglifyjs-webpack-plugin/-/uglifyjs-webpack-plugin-0.4.6.tgz", + "integrity": "sha1-uVH0q7a9YX5m9j64kUmOORdj4wk=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-js": "2.8.29", + "webpack-sources": "1.1.0" + } + } + } + }, + "webpack-chunk-hash": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/webpack-chunk-hash/-/webpack-chunk-hash-0.4.0.tgz", + "integrity": "sha1-a0DDBw+8n/DP4P54HHF0r2x8FqQ=", + "dev": true + }, + "webpack-dev-middleware": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-1.12.2.tgz", + "integrity": "sha512-FCrqPy1yy/sN6U/SaEZcHKRXGlqU0DUaEBL45jkUYoB8foVb6wCnbIJ1HKIx+qUFTW+3JpVcCJCxZ8VATL4e+A==", + "dev": true, + "requires": { + "memory-fs": "0.4.1", + "mime": "1.6.0", + "path-is-absolute": "1.0.1", + "range-parser": "1.2.0", + "time-stamp": "2.0.0" + }, + "dependencies": { + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "time-stamp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-2.0.0.tgz", + "integrity": "sha1-lcakRTDhW6jW9KPsuMOj+sRto1c=", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-2.11.1.tgz", + "integrity": "sha512-ombhu5KsO/85sVshIDTyQ5HF3xjZR3N0sf5Ao6h3vFwpNyzInEzA1GV3QPVjTMLTNckp8PjfG1PFGznzBwS5lg==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "array-includes": "3.0.3", + "bonjour": "3.5.0", + "chokidar": "2.0.0", + "compression": "1.7.1", + "connect-history-api-fallback": "1.5.0", + "debug": "3.1.0", + "del": "3.0.0", + "express": "4.16.2", + "html-entities": "1.2.1", + "http-proxy-middleware": "0.17.4", + "import-local": "1.0.0", + "internal-ip": "1.2.0", + "ip": "1.1.5", + "killable": "1.0.0", + "loglevel": "1.6.1", + "opn": "5.2.0", + "portfinder": "1.0.13", + "selfsigned": "1.10.2", + "serve-index": "1.9.1", + "sockjs": "0.3.19", + "sockjs-client": "1.1.4", + "spdy": "3.4.7", + "strip-ansi": "3.0.1", + "supports-color": "5.1.0", + "webpack-dev-middleware": "1.12.2", + "yargs": "6.6.0" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "3.1.5", + "normalize-path": "2.1.1" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", + "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", + "dev": true, + "requires": { + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "repeat-element": "1.1.2", + "snapdragon": "0.8.1", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.1" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + }, + "chokidar": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.0.tgz", + "integrity": "sha512-OgXCNv2U6TnG04D3tth0gsvdbV4zdbxFG3sYUqcoQMoEFVd1j1pZR6TZ8iknC45o9IJ6PeQI/J6wT/+cHcniAw==", + "dev": true, + "requires": { + "anymatch": "2.0.0", + "async-each": "1.0.1", + "braces": "2.3.0", + "fsevents": "1.1.3", + "glob-parent": "3.1.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "4.0.0", + "normalize-path": "2.1.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "0.1.6" + } + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "3.1.0", + "path-dirname": "1.0.2" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", + "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", + "dev": true, + "requires": { + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.0", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.7", + "object.pick": "1.3.0", + "regex-not": "1.0.0", + "snapdragon": "0.8.1", + "to-regex": "3.0.1" + } + }, + "yargs": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-6.6.0.tgz", + "integrity": "sha1-eC7CHvQDNF+DCoCMo9UTr1YGUgg=", + "dev": true, + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "4.2.1" + } + }, + "yargs-parser": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-4.2.1.tgz", + "integrity": "sha1-KczqwNxPA8bIe0qfIX3RjJ90hxw=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + } + } + } + }, + "webpack-merge": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.1.1.tgz", + "integrity": "sha512-geQsZ86YkXOVOjvPC5yv3JSNnL6/X3Kzh935AQ/gJNEYXEfJDQFu/sdFuktS9OW2JcH/SJec8TGfRdrpHshH7A==", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "webpack-notifier": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/webpack-notifier/-/webpack-notifier-1.5.1.tgz", + "integrity": "sha1-z19rmhcR+Alpu8T3vRXUDqexh2E=", + "dev": true, + "requires": { + "node-notifier": "5.2.1", + "object-assign": "4.1.1", + "strip-ansi": "3.0.1" + } + }, + "webpack-sources": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.1.0.tgz", + "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", + "dev": true, + "requires": { + "source-list-map": "2.0.0", + "source-map": "0.6.1" + } + }, + "websocket-driver": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", + "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", + "dev": true, + "requires": { + "http-parser-js": "0.4.9", + "websocket-extensions": "0.1.3" + } + }, + "websocket-extensions": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", + "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "dev": true + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", + "dev": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + }, + "worker-farm": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.5.2.tgz", + "integrity": "sha512-XxiQ9kZN5n6mmnW+mFJ+wXjNNI/Nx4DIdaAKLX1Bn6LYBWlN/zaBhu34DQYPZ1AJobQuu67S2OfDdNSVULvXkQ==", + "dev": true, + "requires": { + "errno": "0.1.6", + "xtend": "4.0.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrap-fn": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", + "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", + "dev": true, + "requires": { + "co": "3.1.0" + }, + "dependencies": { + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xml-char-classes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/xml-char-classes/-/xml-char-classes-1.0.0.tgz", + "integrity": "sha1-ZGV4SKIP/F31g6Qq2KJ3tFErvE0=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "dev": true, + "requires": { + "camelcase": "4.1.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "read-pkg-up": "2.0.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "dev": true, + "requires": { + "camelcase": "3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.9.1.tgz", + "integrity": "sha1-qBmB6nCleUYTOIPwKcWCGok1mn8=", + "dev": true, + "requires": { + "buffer-crc32": "0.2.13", + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/package.json b/package.json old mode 100644 new mode 100755 index dedcbef712..bd9df38cf5 --- a/package.json +++ b/package.json @@ -7,15 +7,18 @@ "watch-poll": "npm run watch -- --watch-poll", "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", "prod": "npm run production", - "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" + "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { - "axios": "^0.16.2", + "axios": "^0.17", "bootstrap-sass": "^3.3.7", - "cross-env": "^5.0.1", + "cross-env": "^5.1", "jquery": "^3.1.1", "laravel-mix": "^1.0", "lodash": "^4.17.4", - "vue": "^2.1.10" + "vue": "^2.5.7" + }, + "dependencies": { + "font-awesome": "^4.7.0" } } diff --git a/phpunit.coverage.specific.xml b/phpunit.coverage.specific.xml index 7bcd1ffa62..9a25379977 100644 --- a/phpunit.coverage.specific.xml +++ b/phpunit.coverage.specific.xml @@ -16,6 +16,9 @@ ./tests/Unit + + ./tests/Api + diff --git a/phpunit.coverage.xml b/phpunit.coverage.xml index 1f52d8a767..874f28e793 100644 --- a/phpunit.coverage.xml +++ b/phpunit.coverage.xml @@ -16,6 +16,9 @@ ./tests/Unit + + ./tests/Api + diff --git a/phpunit.xml b/phpunit.xml index 8ce1608fc8..1b5e9f6f27 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -16,6 +16,9 @@ ./tests/Unit + + ./tests/Api + diff --git a/public/css/app.css b/public/css/app.css new file mode 100644 index 0000000000..4f01b92a4b --- /dev/null +++ b/public/css/app.css @@ -0,0 +1,14 @@ +/*! + * Bootstrap v3.3.7 (http://getbootstrap.com) + * Copyright 2011-2016 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} + +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{background:transparent!important;color:#000!important;-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}@font-face{font-family:Glyphicons Halflings;src:url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot?f4769f9bdb7466be65088239c12046d1);src:url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot?f4769f9bdb7466be65088239c12046d1?#iefix) format("embedded-opentype"),url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2?448c34a56d699c29117adc64c43affeb) format("woff2"),url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff?fa2772327f55d8198301fdb8bcfc8158) format("woff"),url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf?e18bbf611f2a2e43afc071aa2f4e1512) format("truetype"),url(/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.svg?89889688147bd7575d6327160d64e760#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:Glyphicons Halflings;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"*"}.glyphicon-plus:before{content:"+"}.glyphicon-eur:before,.glyphicon-euro:before{content:"\20AC"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270F"}.glyphicon-glass:before{content:"\E001"}.glyphicon-music:before{content:"\E002"}.glyphicon-search:before{content:"\E003"}.glyphicon-heart:before{content:"\E005"}.glyphicon-star:before{content:"\E006"}.glyphicon-star-empty:before{content:"\E007"}.glyphicon-user:before{content:"\E008"}.glyphicon-film:before{content:"\E009"}.glyphicon-th-large:before{content:"\E010"}.glyphicon-th:before{content:"\E011"}.glyphicon-th-list:before{content:"\E012"}.glyphicon-ok:before{content:"\E013"}.glyphicon-remove:before{content:"\E014"}.glyphicon-zoom-in:before{content:"\E015"}.glyphicon-zoom-out:before{content:"\E016"}.glyphicon-off:before{content:"\E017"}.glyphicon-signal:before{content:"\E018"}.glyphicon-cog:before{content:"\E019"}.glyphicon-trash:before{content:"\E020"}.glyphicon-home:before{content:"\E021"}.glyphicon-file:before{content:"\E022"}.glyphicon-time:before{content:"\E023"}.glyphicon-road:before{content:"\E024"}.glyphicon-download-alt:before{content:"\E025"}.glyphicon-download:before{content:"\E026"}.glyphicon-upload:before{content:"\E027"}.glyphicon-inbox:before{content:"\E028"}.glyphicon-play-circle:before{content:"\E029"}.glyphicon-repeat:before{content:"\E030"}.glyphicon-refresh:before{content:"\E031"}.glyphicon-list-alt:before{content:"\E032"}.glyphicon-lock:before{content:"\E033"}.glyphicon-flag:before{content:"\E034"}.glyphicon-headphones:before{content:"\E035"}.glyphicon-volume-off:before{content:"\E036"}.glyphicon-volume-down:before{content:"\E037"}.glyphicon-volume-up:before{content:"\E038"}.glyphicon-qrcode:before{content:"\E039"}.glyphicon-barcode:before{content:"\E040"}.glyphicon-tag:before{content:"\E041"}.glyphicon-tags:before{content:"\E042"}.glyphicon-book:before{content:"\E043"}.glyphicon-bookmark:before{content:"\E044"}.glyphicon-print:before{content:"\E045"}.glyphicon-camera:before{content:"\E046"}.glyphicon-font:before{content:"\E047"}.glyphicon-bold:before{content:"\E048"}.glyphicon-italic:before{content:"\E049"}.glyphicon-text-height:before{content:"\E050"}.glyphicon-text-width:before{content:"\E051"}.glyphicon-align-left:before{content:"\E052"}.glyphicon-align-center:before{content:"\E053"}.glyphicon-align-right:before{content:"\E054"}.glyphicon-align-justify:before{content:"\E055"}.glyphicon-list:before{content:"\E056"}.glyphicon-indent-left:before{content:"\E057"}.glyphicon-indent-right:before{content:"\E058"}.glyphicon-facetime-video:before{content:"\E059"}.glyphicon-picture:before{content:"\E060"}.glyphicon-map-marker:before{content:"\E062"}.glyphicon-adjust:before{content:"\E063"}.glyphicon-tint:before{content:"\E064"}.glyphicon-edit:before{content:"\E065"}.glyphicon-share:before{content:"\E066"}.glyphicon-check:before{content:"\E067"}.glyphicon-move:before{content:"\E068"}.glyphicon-step-backward:before{content:"\E069"}.glyphicon-fast-backward:before{content:"\E070"}.glyphicon-backward:before{content:"\E071"}.glyphicon-play:before{content:"\E072"}.glyphicon-pause:before{content:"\E073"}.glyphicon-stop:before{content:"\E074"}.glyphicon-forward:before{content:"\E075"}.glyphicon-fast-forward:before{content:"\E076"}.glyphicon-step-forward:before{content:"\E077"}.glyphicon-eject:before{content:"\E078"}.glyphicon-chevron-left:before{content:"\E079"}.glyphicon-chevron-right:before{content:"\E080"}.glyphicon-plus-sign:before{content:"\E081"}.glyphicon-minus-sign:before{content:"\E082"}.glyphicon-remove-sign:before{content:"\E083"}.glyphicon-ok-sign:before{content:"\E084"}.glyphicon-question-sign:before{content:"\E085"}.glyphicon-info-sign:before{content:"\E086"}.glyphicon-screenshot:before{content:"\E087"}.glyphicon-remove-circle:before{content:"\E088"}.glyphicon-ok-circle:before{content:"\E089"}.glyphicon-ban-circle:before{content:"\E090"}.glyphicon-arrow-left:before{content:"\E091"}.glyphicon-arrow-right:before{content:"\E092"}.glyphicon-arrow-up:before{content:"\E093"}.glyphicon-arrow-down:before{content:"\E094"}.glyphicon-share-alt:before{content:"\E095"}.glyphicon-resize-full:before{content:"\E096"}.glyphicon-resize-small:before{content:"\E097"}.glyphicon-exclamation-sign:before{content:"\E101"}.glyphicon-gift:before{content:"\E102"}.glyphicon-leaf:before{content:"\E103"}.glyphicon-fire:before{content:"\E104"}.glyphicon-eye-open:before{content:"\E105"}.glyphicon-eye-close:before{content:"\E106"}.glyphicon-warning-sign:before{content:"\E107"}.glyphicon-plane:before{content:"\E108"}.glyphicon-calendar:before{content:"\E109"}.glyphicon-random:before{content:"\E110"}.glyphicon-comment:before{content:"\E111"}.glyphicon-magnet:before{content:"\E112"}.glyphicon-chevron-up:before{content:"\E113"}.glyphicon-chevron-down:before{content:"\E114"}.glyphicon-retweet:before{content:"\E115"}.glyphicon-shopping-cart:before{content:"\E116"}.glyphicon-folder-close:before{content:"\E117"}.glyphicon-folder-open:before{content:"\E118"}.glyphicon-resize-vertical:before{content:"\E119"}.glyphicon-resize-horizontal:before{content:"\E120"}.glyphicon-hdd:before{content:"\E121"}.glyphicon-bullhorn:before{content:"\E122"}.glyphicon-bell:before{content:"\E123"}.glyphicon-certificate:before{content:"\E124"}.glyphicon-thumbs-up:before{content:"\E125"}.glyphicon-thumbs-down:before{content:"\E126"}.glyphicon-hand-right:before{content:"\E127"}.glyphicon-hand-left:before{content:"\E128"}.glyphicon-hand-up:before{content:"\E129"}.glyphicon-hand-down:before{content:"\E130"}.glyphicon-circle-arrow-right:before{content:"\E131"}.glyphicon-circle-arrow-left:before{content:"\E132"}.glyphicon-circle-arrow-up:before{content:"\E133"}.glyphicon-circle-arrow-down:before{content:"\E134"}.glyphicon-globe:before{content:"\E135"}.glyphicon-wrench:before{content:"\E136"}.glyphicon-tasks:before{content:"\E137"}.glyphicon-filter:before{content:"\E138"}.glyphicon-briefcase:before{content:"\E139"}.glyphicon-fullscreen:before{content:"\E140"}.glyphicon-dashboard:before{content:"\E141"}.glyphicon-paperclip:before{content:"\E142"}.glyphicon-heart-empty:before{content:"\E143"}.glyphicon-link:before{content:"\E144"}.glyphicon-phone:before{content:"\E145"}.glyphicon-pushpin:before{content:"\E146"}.glyphicon-usd:before{content:"\E148"}.glyphicon-gbp:before{content:"\E149"}.glyphicon-sort:before{content:"\E150"}.glyphicon-sort-by-alphabet:before{content:"\E151"}.glyphicon-sort-by-alphabet-alt:before{content:"\E152"}.glyphicon-sort-by-order:before{content:"\E153"}.glyphicon-sort-by-order-alt:before{content:"\E154"}.glyphicon-sort-by-attributes:before{content:"\E155"}.glyphicon-sort-by-attributes-alt:before{content:"\E156"}.glyphicon-unchecked:before{content:"\E157"}.glyphicon-expand:before{content:"\E158"}.glyphicon-collapse-down:before{content:"\E159"}.glyphicon-collapse-up:before{content:"\E160"}.glyphicon-log-in:before{content:"\E161"}.glyphicon-flash:before{content:"\E162"}.glyphicon-log-out:before{content:"\E163"}.glyphicon-new-window:before{content:"\E164"}.glyphicon-record:before{content:"\E165"}.glyphicon-save:before{content:"\E166"}.glyphicon-open:before{content:"\E167"}.glyphicon-saved:before{content:"\E168"}.glyphicon-import:before{content:"\E169"}.glyphicon-export:before{content:"\E170"}.glyphicon-send:before{content:"\E171"}.glyphicon-floppy-disk:before{content:"\E172"}.glyphicon-floppy-saved:before{content:"\E173"}.glyphicon-floppy-remove:before{content:"\E174"}.glyphicon-floppy-save:before{content:"\E175"}.glyphicon-floppy-open:before{content:"\E176"}.glyphicon-credit-card:before{content:"\E177"}.glyphicon-transfer:before{content:"\E178"}.glyphicon-cutlery:before{content:"\E179"}.glyphicon-header:before{content:"\E180"}.glyphicon-compressed:before{content:"\E181"}.glyphicon-earphone:before{content:"\E182"}.glyphicon-phone-alt:before{content:"\E183"}.glyphicon-tower:before{content:"\E184"}.glyphicon-stats:before{content:"\E185"}.glyphicon-sd-video:before{content:"\E186"}.glyphicon-hd-video:before{content:"\E187"}.glyphicon-subtitles:before{content:"\E188"}.glyphicon-sound-stereo:before{content:"\E189"}.glyphicon-sound-dolby:before{content:"\E190"}.glyphicon-sound-5-1:before{content:"\E191"}.glyphicon-sound-6-1:before{content:"\E192"}.glyphicon-sound-7-1:before{content:"\E193"}.glyphicon-copyright-mark:before{content:"\E194"}.glyphicon-registration-mark:before{content:"\E195"}.glyphicon-cloud-download:before{content:"\E197"}.glyphicon-cloud-upload:before{content:"\E198"}.glyphicon-tree-conifer:before{content:"\E199"}.glyphicon-tree-deciduous:before{content:"\E200"}.glyphicon-cd:before{content:"\E201"}.glyphicon-save-file:before{content:"\E202"}.glyphicon-open-file:before{content:"\E203"}.glyphicon-level-up:before{content:"\E204"}.glyphicon-copy:before{content:"\E205"}.glyphicon-paste:before{content:"\E206"}.glyphicon-alert:before{content:"\E209"}.glyphicon-equalizer:before{content:"\E210"}.glyphicon-king:before{content:"\E211"}.glyphicon-queen:before{content:"\E212"}.glyphicon-pawn:before{content:"\E213"}.glyphicon-bishop:before{content:"\E214"}.glyphicon-knight:before{content:"\E215"}.glyphicon-baby-formula:before{content:"\E216"}.glyphicon-tent:before{content:"\26FA"}.glyphicon-blackboard:before{content:"\E218"}.glyphicon-bed:before{content:"\E219"}.glyphicon-apple:before{content:"\F8FF"}.glyphicon-erase:before{content:"\E221"}.glyphicon-hourglass:before{content:"\231B"}.glyphicon-lamp:before{content:"\E223"}.glyphicon-duplicate:before{content:"\E224"}.glyphicon-piggy-bank:before{content:"\E225"}.glyphicon-scissors:before{content:"\E226"}.glyphicon-bitcoin:before,.glyphicon-btc:before,.glyphicon-xbt:before{content:"\E227"}.glyphicon-jpy:before,.glyphicon-yen:before{content:"\A5"}.glyphicon-rub:before,.glyphicon-ruble:before{content:"\20BD"}.glyphicon-scale:before{content:"\E230"}.glyphicon-ice-lolly:before{content:"\E231"}.glyphicon-ice-lolly-tasted:before{content:"\E232"}.glyphicon-education:before{content:"\E233"}.glyphicon-option-horizontal:before{content:"\E234"}.glyphicon-option-vertical:before{content:"\E235"}.glyphicon-menu-hamburger:before{content:"\E236"}.glyphicon-modal-window:before{content:"\E237"}.glyphicon-oil:before{content:"\E238"}.glyphicon-grain:before{content:"\E239"}.glyphicon-sunglasses:before{content:"\E240"}.glyphicon-text-size:before{content:"\E241"}.glyphicon-text-color:before{content:"\E242"}.glyphicon-text-background:before{content:"\E243"}.glyphicon-object-align-top:before{content:"\E244"}.glyphicon-object-align-bottom:before{content:"\E245"}.glyphicon-object-align-horizontal:before{content:"\E246"}.glyphicon-object-align-left:before{content:"\E247"}.glyphicon-object-align-vertical:before{content:"\E248"}.glyphicon-object-align-right:before{content:"\E249"}.glyphicon-triangle-right:before{content:"\E250"}.glyphicon-triangle-left:before{content:"\E251"}.glyphicon-triangle-bottom:before{content:"\E252"}.glyphicon-triangle-top:before{content:"\E253"}.glyphicon-console:before{content:"\E254"}.glyphicon-superscript:before{content:"\E255"}.glyphicon-subscript:before{content:"\E256"}.glyphicon-menu-left:before{content:"\E257"}.glyphicon-menu-right:before{content:"\E258"}.glyphicon-menu-down:before{content:"\E259"}.glyphicon-menu-up:before{content:"\E260"}*,:after,:before{-webkit-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:Raleway,sans-serif;font-size:14px;line-height:1.6;color:#636b6f;background-color:#f5f8fa}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#3097d1;text-decoration:none}a:focus,a:hover{color:#216a94;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.6;background-color:#f5f8fa;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:22px;margin-bottom:22px;border:0;border-top:1px solid #eee}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:22px;margin-bottom:11px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:11px;margin-bottom:11px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 11px}.lead{margin-bottom:22px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.initialism,.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#3097d1}a.text-primary:focus,a.text-primary:hover{color:#2579a9}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#3097d1}a.bg-primary:focus,a.bg-primary:hover{background-color:#2579a9}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:10px;margin:44px 0 22px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:11px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline{margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:22px}dd,dt{line-height:1.6}dt{font-weight:700}dd{margin-left:0}.dl-horizontal dd:after,.dl-horizontal dd:before{content:" ";display:table}.dl-horizontal dd:after{clear:both}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-bottom:1px dotted #777}.initialism{font-size:90%}blockquote{padding:11px 22px;margin:0 0 22px;font-size:17.5px;border-left:5px solid #eee}blockquote ol:last-child,blockquote p:last-child,blockquote ul:last-child{margin-bottom:0}blockquote .small,blockquote footer,blockquote small{display:block;font-size:80%;line-height:1.6;color:#777}blockquote .small:before,blockquote footer:before,blockquote small:before{content:"\2014 \A0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse .small:before,.blockquote-reverse footer:before,.blockquote-reverse small:before,blockquote.pull-right .small:before,blockquote.pull-right footer:before,blockquote.pull-right small:before{content:""}.blockquote-reverse .small:after,.blockquote-reverse footer:after,.blockquote-reverse small:after,blockquote.pull-right .small:after,blockquote.pull-right footer:after,blockquote.pull-right small:after{content:"\A0 \2014"}address{margin-bottom:22px;font-style:normal;line-height:1.6}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Courier New,monospace}code{color:#c7254e;background-color:#f9f2f4;border-radius:4px}code,kbd{padding:2px 4px;font-size:90%}kbd{color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:10.5px;margin:0 0 11px;font-size:13px;line-height:1.6;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.container:after,.container:before{content:" ";display:table}.container:after{clear:both}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.container-fluid:after,.container-fluid:before{content:" ";display:table}.container-fluid:after{clear:both}.row{margin-left:-15px;margin-right:-15px}.row:after,.row:before{content:" ";display:table}.row:after{clear:both}.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-1{width:8.33333333%}.col-xs-2{width:16.66666667%}.col-xs-3{width:25%}.col-xs-4{width:33.33333333%}.col-xs-5{width:41.66666667%}.col-xs-6{width:50%}.col-xs-7{width:58.33333333%}.col-xs-8{width:66.66666667%}.col-xs-9{width:75%}.col-xs-10{width:83.33333333%}.col-xs-11{width:91.66666667%}.col-xs-12{width:100%}.col-xs-pull-0{right:auto}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-3{right:25%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-6{right:50%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-9{right:75%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-12{right:100%}.col-xs-push-0{left:auto}.col-xs-push-1{left:8.33333333%}.col-xs-push-2{left:16.66666667%}.col-xs-push-3{left:25%}.col-xs-push-4{left:33.33333333%}.col-xs-push-5{left:41.66666667%}.col-xs-push-6{left:50%}.col-xs-push-7{left:58.33333333%}.col-xs-push-8{left:66.66666667%}.col-xs-push-9{left:75%}.col-xs-push-10{left:83.33333333%}.col-xs-push-11{left:91.66666667%}.col-xs-push-12{left:100%}.col-xs-offset-0{margin-left:0}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-12{margin-left:100%}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-1{width:8.33333333%}.col-sm-2{width:16.66666667%}.col-sm-3{width:25%}.col-sm-4{width:33.33333333%}.col-sm-5{width:41.66666667%}.col-sm-6{width:50%}.col-sm-7{width:58.33333333%}.col-sm-8{width:66.66666667%}.col-sm-9{width:75%}.col-sm-10{width:83.33333333%}.col-sm-11{width:91.66666667%}.col-sm-12{width:100%}.col-sm-pull-0{right:auto}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-3{right:25%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-6{right:50%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-9{right:75%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-12{right:100%}.col-sm-push-0{left:auto}.col-sm-push-1{left:8.33333333%}.col-sm-push-2{left:16.66666667%}.col-sm-push-3{left:25%}.col-sm-push-4{left:33.33333333%}.col-sm-push-5{left:41.66666667%}.col-sm-push-6{left:50%}.col-sm-push-7{left:58.33333333%}.col-sm-push-8{left:66.66666667%}.col-sm-push-9{left:75%}.col-sm-push-10{left:83.33333333%}.col-sm-push-11{left:91.66666667%}.col-sm-push-12{left:100%}.col-sm-offset-0{margin-left:0}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-12{margin-left:100%}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-1{width:8.33333333%}.col-md-2{width:16.66666667%}.col-md-3{width:25%}.col-md-4{width:33.33333333%}.col-md-5{width:41.66666667%}.col-md-6{width:50%}.col-md-7{width:58.33333333%}.col-md-8{width:66.66666667%}.col-md-9{width:75%}.col-md-10{width:83.33333333%}.col-md-11{width:91.66666667%}.col-md-12{width:100%}.col-md-pull-0{right:auto}.col-md-pull-1{right:8.33333333%}.col-md-pull-2{right:16.66666667%}.col-md-pull-3{right:25%}.col-md-pull-4{right:33.33333333%}.col-md-pull-5{right:41.66666667%}.col-md-pull-6{right:50%}.col-md-pull-7{right:58.33333333%}.col-md-pull-8{right:66.66666667%}.col-md-pull-9{right:75%}.col-md-pull-10{right:83.33333333%}.col-md-pull-11{right:91.66666667%}.col-md-pull-12{right:100%}.col-md-push-0{left:auto}.col-md-push-1{left:8.33333333%}.col-md-push-2{left:16.66666667%}.col-md-push-3{left:25%}.col-md-push-4{left:33.33333333%}.col-md-push-5{left:41.66666667%}.col-md-push-6{left:50%}.col-md-push-7{left:58.33333333%}.col-md-push-8{left:66.66666667%}.col-md-push-9{left:75%}.col-md-push-10{left:83.33333333%}.col-md-push-11{left:91.66666667%}.col-md-push-12{left:100%}.col-md-offset-0{margin-left:0}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-3{margin-left:25%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-6{margin-left:50%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-9{margin-left:75%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-12{margin-left:100%}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-1{width:8.33333333%}.col-lg-2{width:16.66666667%}.col-lg-3{width:25%}.col-lg-4{width:33.33333333%}.col-lg-5{width:41.66666667%}.col-lg-6{width:50%}.col-lg-7{width:58.33333333%}.col-lg-8{width:66.66666667%}.col-lg-9{width:75%}.col-lg-10{width:83.33333333%}.col-lg-11{width:91.66666667%}.col-lg-12{width:100%}.col-lg-pull-0{right:auto}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-3{right:25%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-6{right:50%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-9{right:75%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-12{right:100%}.col-lg-push-0{left:auto}.col-lg-push-1{left:8.33333333%}.col-lg-push-2{left:16.66666667%}.col-lg-push-3{left:25%}.col-lg-push-4{left:33.33333333%}.col-lg-push-5{left:41.66666667%}.col-lg-push-6{left:50%}.col-lg-push-7{left:58.33333333%}.col-lg-push-8{left:66.66666667%}.col-lg-push-9{left:75%}.col-lg-push-10{left:83.33333333%}.col-lg-push-11{left:91.66666667%}.col-lg-push-12{left:100%}.col-lg-offset-0{margin-left:0}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-12{margin-left:100%}}table{background-color:transparent}caption{padding-top:8px;padding-bottom:8px;color:#777}caption,th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:22px}.table>tbody>tr>td,.table>tbody>tr>th,.table>tfoot>tr>td,.table>tfoot>tr>th,.table>thead>tr>td,.table>thead>tr>th{padding:8px;line-height:1.6;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>td,.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>td,.table>thead:first-child>tr:first-child>th{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#f5f8fa}.table-condensed>tbody>tr>td,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>td,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>thead>tr>th{padding:5px}.table-bordered,.table-bordered>tbody>tr>td,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>td,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border:1px solid #ddd}.table-bordered>thead>tr>td,.table-bordered>thead>tr>th{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}table col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>tbody>tr.active>td,.table>tbody>tr.active>th,.table>tbody>tr>td.active,.table>tbody>tr>th.active,.table>tfoot>tr.active>td,.table>tfoot>tr.active>th,.table>tfoot>tr>td.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>thead>tr.active>th,.table>thead>tr>td.active,.table>thead>tr>th.active{background-color:#f5f5f5}.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover{background-color:#e8e8e8}.table>tbody>tr.success>td,.table>tbody>tr.success>th,.table>tbody>tr>td.success,.table>tbody>tr>th.success,.table>tfoot>tr.success>td,.table>tfoot>tr.success>th,.table>tfoot>tr>td.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>thead>tr.success>th,.table>thead>tr>td.success,.table>thead>tr>th.success{background-color:#dff0d8}.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover{background-color:#d0e9c6}.table>tbody>tr.info>td,.table>tbody>tr.info>th,.table>tbody>tr>td.info,.table>tbody>tr>th.info,.table>tfoot>tr.info>td,.table>tfoot>tr.info>th,.table>tfoot>tr>td.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>thead>tr.info>th,.table>thead>tr>td.info,.table>thead>tr>th.info{background-color:#d9edf7}.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover{background-color:#c4e3f3}.table>tbody>tr.warning>td,.table>tbody>tr.warning>th,.table>tbody>tr>td.warning,.table>tbody>tr>th.warning,.table>tfoot>tr.warning>td,.table>tfoot>tr.warning>th,.table>tfoot>tr>td.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>thead>tr.warning>th,.table>thead>tr>td.warning,.table>thead>tr>th.warning{background-color:#fcf8e3}.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover{background-color:#faf2cc}.table>tbody>tr.danger>td,.table>tbody>tr.danger>th,.table>tbody>tr>td.danger,.table>tbody>tr>th.danger,.table>tfoot>tr.danger>td,.table>tfoot>tr.danger>th,.table>tfoot>tr>td.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>thead>tr.danger>th,.table>thead>tr>td.danger,.table>thead>tr>th.danger{background-color:#f2dede}.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover{background-color:#ebcccc}.table-responsive{overflow-x:auto;min-height:.01%}@media screen and (max-width:767px){.table-responsive{width:100%;margin-bottom:16.5px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>td,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>thead>tr>th{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}}fieldset{margin:0;min-width:0}fieldset,legend{padding:0;border:0}legend{display:block;width:100%;margin-bottom:22px;font-size:21px;line-height:inherit;color:#333;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;margin-top:1px\9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=checkbox]:focus,input[type=file]:focus,input[type=radio]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{padding-top:7px}.form-control,output{display:block;font-size:14px;line-height:1.6;color:#555}.form-control{width:100%;height:36px;padding:6px 12px;background-color:#fff;background-image:none;border:1px solid #ccd0d2;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;-webkit-transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,-webkit-box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out,-webkit-box-shadow .15s ease-in-out}.form-control:focus{border-color:#98cbe8;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(152,203,232,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(152,203,232,.6)}.form-control::-moz-placeholder{color:#b1b7ba;opacity:1}.form-control:-ms-input-placeholder{color:#b1b7ba}.form-control::-webkit-input-placeholder{color:#b1b7ba}.form-control::-ms-expand{border:0;background-color:transparent}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}input[type=search]{-webkit-appearance:none}@media screen and (-webkit-min-device-pixel-ratio:0){input[type=date].form-control,input[type=datetime-local].form-control,input[type=month].form-control,input[type=time].form-control{line-height:36px}.input-group-sm>.input-group-btn>input[type=date].btn,.input-group-sm>.input-group-btn>input[type=datetime-local].btn,.input-group-sm>.input-group-btn>input[type=month].btn,.input-group-sm>.input-group-btn>input[type=time].btn,.input-group-sm>input[type=date].form-control,.input-group-sm>input[type=date].input-group-addon,.input-group-sm>input[type=datetime-local].form-control,.input-group-sm>input[type=datetime-local].input-group-addon,.input-group-sm>input[type=month].form-control,.input-group-sm>input[type=month].input-group-addon,.input-group-sm>input[type=time].form-control,.input-group-sm>input[type=time].input-group-addon,.input-group-sm input[type=date],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month],.input-group-sm input[type=time],input[type=date].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,input[type=time].input-sm{line-height:30px}.input-group-lg>.input-group-btn>input[type=date].btn,.input-group-lg>.input-group-btn>input[type=datetime-local].btn,.input-group-lg>.input-group-btn>input[type=month].btn,.input-group-lg>.input-group-btn>input[type=time].btn,.input-group-lg>input[type=date].form-control,.input-group-lg>input[type=date].input-group-addon,.input-group-lg>input[type=datetime-local].form-control,.input-group-lg>input[type=datetime-local].input-group-addon,.input-group-lg>input[type=month].form-control,.input-group-lg>input[type=month].input-group-addon,.input-group-lg>input[type=time].form-control,.input-group-lg>input[type=time].input-group-addon,.input-group-lg input[type=date],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month],.input-group-lg input[type=time],input[type=date].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,input[type=time].input-lg{line-height:46px}}.form-group{margin-bottom:15px}.checkbox,.radio{position:relative;display:block;margin-top:10px;margin-bottom:10px}.checkbox label,.radio label{min-height:22px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.checkbox-inline input[type=checkbox],.checkbox input[type=checkbox],.radio-inline input[type=radio],.radio input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px\9}.checkbox+.checkbox,.radio+.radio{margin-top:-5px}.checkbox-inline,.radio-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.checkbox-inline+.checkbox-inline,.radio-inline+.radio-inline{margin-top:0;margin-left:10px}.checkbox-inline.disabled,.checkbox.disabled label,.radio-inline.disabled,.radio.disabled label,fieldset[disabled] .checkbox-inline,fieldset[disabled] .checkbox label,fieldset[disabled] .radio-inline,fieldset[disabled] .radio label,fieldset[disabled] input[type=checkbox],fieldset[disabled] input[type=radio],input[type=checkbox].disabled,input[type=checkbox][disabled],input[type=radio].disabled,input[type=radio][disabled]{cursor:not-allowed}.form-control-static{padding-top:7px;padding-bottom:7px;margin-bottom:0;min-height:36px}.form-control-static.input-lg,.form-control-static.input-sm,.input-group-lg>.form-control-static.form-control,.input-group-lg>.form-control-static.input-group-addon,.input-group-lg>.input-group-btn>.form-control-static.btn,.input-group-sm>.form-control-static.form-control,.input-group-sm>.form-control-static.input-group-addon,.input-group-sm>.input-group-btn>.form-control-static.btn{padding-left:0;padding-right:0}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn,.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.input-group-sm>.input-group-btn>select.btn,.input-group-sm>select.form-control,.input-group-sm>select.input-group-addon,select.input-sm{height:30px;line-height:30px}.input-group-sm>.input-group-btn>select[multiple].btn,.input-group-sm>.input-group-btn>textarea.btn,.input-group-sm>select[multiple].form-control,.input-group-sm>select[multiple].input-group-addon,.input-group-sm>textarea.form-control,.input-group-sm>textarea.input-group-addon,select[multiple].input-sm,textarea.input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm select[multiple].form-control,.form-group-sm textarea.form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:34px;padding:6px 10px;font-size:12px;line-height:1.5}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn,.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.input-group-lg>.input-group-btn>select.btn,.input-group-lg>select.form-control,.input-group-lg>select.input-group-addon,select.input-lg{height:46px;line-height:46px}.input-group-lg>.input-group-btn>select[multiple].btn,.input-group-lg>.input-group-btn>textarea.btn,.input-group-lg>select[multiple].form-control,.input-group-lg>select[multiple].input-group-addon,.input-group-lg>textarea.form-control,.input-group-lg>textarea.input-group-addon,select[multiple].input-lg,textarea.input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg select[multiple].form-control,.form-group-lg textarea.form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:40px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:45px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:36px;height:36px;line-height:36px;text-align:center;pointer-events:none}.form-group-lg .form-control+.form-control-feedback,.input-group-lg+.form-control-feedback,.input-group-lg>.form-control+.form-control-feedback,.input-group-lg>.input-group-addon+.form-control-feedback,.input-group-lg>.input-group-btn>.btn+.form-control-feedback,.input-lg+.form-control-feedback{width:46px;height:46px;line-height:46px}.form-group-sm .form-control+.form-control-feedback,.input-group-sm+.form-control-feedback,.input-group-sm>.form-control+.form-control-feedback,.input-group-sm>.input-group-addon+.form-control-feedback,.input-group-sm>.input-group-btn>.btn+.form-control-feedback,.input-sm+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .checkbox,.has-success .checkbox-inline,.has-success.checkbox-inline label,.has-success.checkbox label,.has-success .control-label,.has-success .help-block,.has-success .radio,.has-success .radio-inline,.has-success.radio-inline label,.has-success.radio label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .checkbox,.has-warning .checkbox-inline,.has-warning.checkbox-inline label,.has-warning.checkbox label,.has-warning .control-label,.has-warning .help-block,.has-warning .radio,.has-warning .radio-inline,.has-warning.radio-inline label,.has-warning.radio label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .checkbox,.has-error .checkbox-inline,.has-error.checkbox-inline label,.has-error.checkbox label,.has-error .control-label,.has-error .help-block,.has-error .radio,.has-error .radio-inline,.has-error.radio-inline label,.has-error.radio label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:27px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#a4aaae}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .form-control,.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .checkbox,.form-inline .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .checkbox label,.form-inline .radio label{padding-left:0}.form-inline .checkbox input[type=checkbox],.form-inline .radio input[type=radio]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .checkbox,.form-horizontal .checkbox-inline,.form-horizontal .radio,.form-horizontal .radio-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .checkbox,.form-horizontal .radio{min-height:29px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-group:after,.form-horizontal .form-group:before{content:" ";display:table}.form-horizontal .form-group:after{clear:both}@media (min-width:768px){.form-horizontal .control-label{text-align:right;margin-bottom:0;padding-top:7px}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width:768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width:768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.6;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn.active.focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn:active:focus,.btn:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.focus,.btn:focus,.btn:hover{color:#636b6f;text-decoration:none}.btn.active,.btn:active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#636b6f;background-color:#fff;border-color:#ccc}.btn-default.focus,.btn-default:focus{color:#636b6f;background-color:#e6e5e5;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.btn-default:hover,.open>.btn-default.dropdown-toggle{color:#636b6f;background-color:#e6e5e5;border-color:#adadad}.btn-default.active.focus,.btn-default.active:focus,.btn-default.active:hover,.btn-default:active.focus,.btn-default:active:focus,.btn-default:active:hover,.open>.btn-default.dropdown-toggle.focus,.open>.btn-default.dropdown-toggle:focus,.open>.btn-default.dropdown-toggle:hover{color:#636b6f;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.active,.btn-default:active,.open>.btn-default.dropdown-toggle{background-image:none}.btn-default.disabled.focus,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled].focus,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#636b6f}.btn-primary{color:#fff;background-color:#3097d1;border-color:#2a88bd}.btn-primary.focus,.btn-primary:focus{color:#fff;background-color:#2579a9;border-color:#133d55}.btn-primary.active,.btn-primary:active,.btn-primary:hover,.open>.btn-primary.dropdown-toggle{color:#fff;background-color:#2579a9;border-color:#1f648b}.btn-primary.active.focus,.btn-primary.active:focus,.btn-primary.active:hover,.btn-primary:active.focus,.btn-primary:active:focus,.btn-primary:active:hover,.open>.btn-primary.dropdown-toggle.focus,.open>.btn-primary.dropdown-toggle:focus,.open>.btn-primary.dropdown-toggle:hover{color:#fff;background-color:#1f648b;border-color:#133d55}.btn-primary.active,.btn-primary:active,.open>.btn-primary.dropdown-toggle{background-image:none}.btn-primary.disabled.focus,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled].focus,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#3097d1;border-color:#2a88bd}.btn-primary .badge{color:#3097d1;background-color:#fff}.btn-success{color:#fff;background-color:#2ab27b;border-color:#259d6d}.btn-success.focus,.btn-success:focus{color:#fff;background-color:#20895e;border-color:#0d3625}.btn-success.active,.btn-success:active,.btn-success:hover,.open>.btn-success.dropdown-toggle{color:#fff;background-color:#20895e;border-color:#196c4b}.btn-success.active.focus,.btn-success.active:focus,.btn-success.active:hover,.btn-success:active.focus,.btn-success:active:focus,.btn-success:active:hover,.open>.btn-success.dropdown-toggle.focus,.open>.btn-success.dropdown-toggle:focus,.open>.btn-success.dropdown-toggle:hover{color:#fff;background-color:#196c4b;border-color:#0d3625}.btn-success.active,.btn-success:active,.open>.btn-success.dropdown-toggle{background-image:none}.btn-success.disabled.focus,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled].focus,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#2ab27b;border-color:#259d6d}.btn-success .badge{color:#2ab27b;background-color:#fff}.btn-info{color:#fff;background-color:#8eb4cb;border-color:#7da8c3}.btn-info.focus,.btn-info:focus{color:#fff;background-color:#6b9dbb;border-color:#3d6983}.btn-info.active,.btn-info:active,.btn-info:hover,.open>.btn-info.dropdown-toggle{color:#fff;background-color:#6b9dbb;border-color:#538db0}.btn-info.active.focus,.btn-info.active:focus,.btn-info.active:hover,.btn-info:active.focus,.btn-info:active:focus,.btn-info:active:hover,.open>.btn-info.dropdown-toggle.focus,.open>.btn-info.dropdown-toggle:focus,.open>.btn-info.dropdown-toggle:hover{color:#fff;background-color:#538db0;border-color:#3d6983}.btn-info.active,.btn-info:active,.open>.btn-info.dropdown-toggle{background-image:none}.btn-info.disabled.focus,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled].focus,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#8eb4cb;border-color:#7da8c3}.btn-info .badge{color:#8eb4cb;background-color:#fff}.btn-warning{color:#fff;background-color:#cbb956;border-color:#c5b143}.btn-warning.focus,.btn-warning:focus{color:#fff;background-color:#b6a338;border-color:#685d20}.btn-warning.active,.btn-warning:active,.btn-warning:hover,.open>.btn-warning.dropdown-toggle{color:#fff;background-color:#b6a338;border-color:#9b8a30}.btn-warning.active.focus,.btn-warning.active:focus,.btn-warning.active:hover,.btn-warning:active.focus,.btn-warning:active:focus,.btn-warning:active:hover,.open>.btn-warning.dropdown-toggle.focus,.open>.btn-warning.dropdown-toggle:focus,.open>.btn-warning.dropdown-toggle:hover{color:#fff;background-color:#9b8a30;border-color:#685d20}.btn-warning.active,.btn-warning:active,.open>.btn-warning.dropdown-toggle{background-image:none}.btn-warning.disabled.focus,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled].focus,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#cbb956;border-color:#c5b143}.btn-warning .badge{color:#cbb956;background-color:#fff}.btn-danger{color:#fff;background-color:#bf5329;border-color:#aa4a24}.btn-danger.focus,.btn-danger:focus{color:#fff;background-color:#954120;border-color:#411c0e}.btn-danger.active,.btn-danger:active,.btn-danger:hover,.open>.btn-danger.dropdown-toggle{color:#fff;background-color:#954120;border-color:#78341a}.btn-danger.active.focus,.btn-danger.active:focus,.btn-danger.active:hover,.btn-danger:active.focus,.btn-danger:active:focus,.btn-danger:active:hover,.open>.btn-danger.dropdown-toggle.focus,.open>.btn-danger.dropdown-toggle:focus,.open>.btn-danger.dropdown-toggle:hover{color:#fff;background-color:#78341a;border-color:#411c0e}.btn-danger.active,.btn-danger:active,.open>.btn-danger.dropdown-toggle{background-image:none}.btn-danger.disabled.focus,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled].focus,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#bf5329;border-color:#aa4a24}.btn-danger .badge{color:#bf5329;background-color:#fff}.btn-link{color:#3097d1;font-weight:400;border-radius:0}.btn-link,.btn-link.active,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:active,.btn-link:focus,.btn-link:hover{border-color:transparent}.btn-link:focus,.btn-link:hover{color:#216a94;text-decoration:underline;background-color:transparent}.btn-link[disabled]:focus,.btn-link[disabled]:hover,fieldset[disabled] .btn-link:focus,fieldset[disabled] .btn-link:hover{color:#777;text-decoration:none}.btn-group-lg>.btn,.btn-lg{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-group-sm>.btn,.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-xs>.btn,.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=button].btn-block,input[type=reset].btn-block,input[type=submit].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid\9;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown,.dropup{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;font-size:14px;text-align:left;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.6;color:#333;white-space:nowrap}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{color:#fff;text-decoration:none;outline:0;background-color:#3097d1}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{color:#777}.dropdown-menu>.disabled>a:focus,.dropdown-menu>.disabled>a:hover{text-decoration:none;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.6;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px dashed;border-bottom:4px solid\9;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width:768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group-vertical>.btn,.btn-group>.btn{position:relative;float:left}.btn-group-vertical>.btn.active,.btn-group-vertical>.btn:active,.btn-group-vertical>.btn:focus,.btn-group-vertical>.btn:hover,.btn-group>.btn.active,.btn-group>.btn:active,.btn-group>.btn:focus,.btn-group>.btn:hover{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar:after,.btn-toolbar:before{content:" ";display:table}.btn-toolbar:after{clear:both}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group-lg.btn-group>.btn+.dropdown-toggle,.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-group-lg>.btn .caret,.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-group-lg>.btn .caret,.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group:after,.btn-group-vertical>.btn-group:before{content:" ";display:table}.btn-group-vertical>.btn-group:after{clear:both}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-top-right-radius:0;border-top-left-radius:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn-group>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=radio],[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn input[type=radio]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccd0d2;border-radius:4px}.input-group-addon.input-sm,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.input-group-addon.btn{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.input-group-addon.btn{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=checkbox],.input-group-addon input[type=radio]{margin-top:0}.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn-group:not(:last-child)>.btn,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group .form-control:first-child{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group-addon:last-child,.input-group-btn:first-child>.btn-group:not(:first-child)>.btn,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group .form-control:last-child{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{font-size:0;white-space:nowrap}.input-group-btn,.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:active,.input-group-btn>.btn:focus,.input-group-btn>.btn:hover{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav:after,.nav:before{content:" ";display:table}.nav:after{clear:both}.nav>li,.nav>li>a{position:relative;display:block}.nav>li>a{padding:10px 15px}.nav>li>a:focus,.nav>li>a:hover{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:focus,.nav>li.disabled>a:hover{color:#777;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:focus,.nav .open>a:hover{background-color:#eee;border-color:#3097d1}.nav .nav-divider{height:1px;margin:10px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.6;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:focus,.nav-tabs>li.active>a:hover{color:#555;background-color:#f5f8fa;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:focus,.nav-pills>li.active>a:hover{color:#fff;background-color:#3097d1}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified,.nav-tabs.nav-justified{width:100%}.nav-justified>li,.nav-tabs.nav-justified>li{float:none}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li,.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a,.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified,.nav-tabs.nav-justified{border-bottom:0}.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a,.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:focus,.nav-tabs-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:focus,.nav-tabs.nav-justified>.active>a:hover{border-bottom-color:#f5f8fa}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:22px;border:1px solid transparent}.navbar:after,.navbar:before{content:" ";display:table}.navbar:after{clear:both}@media (min-width:768px){.navbar{border-radius:4px}}.navbar-header:after,.navbar-header:before{content:" ";display:table}.navbar-header:after{clear:both}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1);-webkit-overflow-scrolling:touch}.navbar-collapse:after,.navbar-collapse:before{content:" ";display:table}.navbar-collapse:after{clear:both}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse{padding-left:0;padding-right:0}}.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:340px}@media (max-device-width:480px) and (orientation:landscape){.navbar-fixed-bottom .navbar-collapse,.navbar-fixed-top .navbar-collapse{max-height:200px}}.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container-fluid>.navbar-collapse,.container-fluid>.navbar-header,.container>.navbar-collapse,.container>.navbar-header{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-bottom,.navbar-fixed-top{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-bottom,.navbar-fixed-top{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:14px 15px;font-size:18px;line-height:22px;height:50px}.navbar-brand:focus,.navbar-brand:hover{text-decoration:none}.navbar-brand>img{display:block}@media (min-width:768px){.navbar>.container-fluid .navbar-brand,.navbar>.container .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:22px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu .dropdown-header,.navbar-nav .open .dropdown-menu>li>a{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:22px}.navbar-nav .open .dropdown-menu>li>a:focus,.navbar-nav .open .dropdown-menu>li>a:hover{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:14px;padding-bottom:14px}}.navbar-form{margin:7px -15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1),0 1px 0 hsla(0,0%,100%,.1);box-shadow:inset 0 1px 0 hsla(0,0%,100%,.1),0 1px 0 hsla(0,0%,100%,.1)}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .form-control,.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .checkbox,.navbar-form .radio{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .checkbox label,.navbar-form .radio label{padding-left:0}.navbar-form .checkbox input[type=checkbox],.navbar-form .radio input[type=radio]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-top-right-radius:4px;border-top-left-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:7px;margin-bottom:7px}.btn-group-sm>.navbar-btn.btn,.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.btn-group-xs>.navbar-btn.btn,.navbar-btn.btn-xs,.navbar-text{margin-top:14px;margin-bottom:14px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#fff;border-color:#d3e0e9}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:focus,.navbar-default .navbar-brand:hover{color:#5e5d5d;background-color:transparent}.navbar-default .navbar-nav>li>a,.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a:focus,.navbar-default .navbar-nav>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:focus,.navbar-default .navbar-nav>.active>a:hover{color:#555;background-color:#eee}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:focus,.navbar-default .navbar-nav>.disabled>a:hover{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:focus,.navbar-default .navbar-toggle:hover{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#d3e0e9}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:focus,.navbar-default .navbar-nav>.open>a:hover{background-color:#eee;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover{color:#555;background-color:#eee}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:focus,.navbar-default .btn-link:hover{color:#333}.navbar-default .btn-link[disabled]:focus,.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:focus,fieldset[disabled] .navbar-default .btn-link:hover{color:#ccc}.navbar-inverse{background-color:#222;border-color:#090909}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:focus,.navbar-inverse .navbar-brand:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>li>a,.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:focus,.navbar-inverse .navbar-nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:focus,.navbar-inverse .navbar-nav>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:focus,.navbar-inverse .navbar-nav>.disabled>a:hover{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:focus,.navbar-inverse .navbar-toggle:hover{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:focus,.navbar-inverse .navbar-nav>.open>a:hover{background-color:#090909;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-color:#090909}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:focus,.navbar-inverse .btn-link:hover{color:#fff}.navbar-inverse .btn-link[disabled]:focus,.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:focus,fieldset[disabled] .navbar-inverse .btn-link:hover{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:22px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\A0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:22px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.6;text-decoration:none;color:#3097d1;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:focus,.pagination>li>a:hover,.pagination>li>span:focus,.pagination>li>span:hover{z-index:2;color:#216a94;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>a:focus,.pagination>.active>a:hover,.pagination>.active>span,.pagination>.active>span:focus,.pagination>.active>span:hover{z-index:3;color:#fff;background-color:#3097d1;border-color:#3097d1;cursor:default}.pagination>.disabled>a,.pagination>.disabled>a:focus,.pagination>.disabled>a:hover,.pagination>.disabled>span,.pagination>.disabled>span:focus,.pagination>.disabled>span:hover{color:#777;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:22px 0;list-style:none;text-align:center}.pager:after,.pager:before{content:" ";display:table}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:focus,.pager li>a:hover{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:focus,.pager .disabled>a:hover,.pager .disabled>span{color:#777;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label:empty{display:none}.btn .label{position:relative;top:-1px}a.label:focus,a.label:hover{color:#fff;text-decoration:none;cursor:pointer}.label-default{background-color:#777}.label-default[href]:focus,.label-default[href]:hover{background-color:#5e5e5e}.label-primary{background-color:#3097d1}.label-primary[href]:focus,.label-primary[href]:hover{background-color:#2579a9}.label-success{background-color:#2ab27b}.label-success[href]:focus,.label-success[href]:hover{background-color:#20895e}.label-info{background-color:#8eb4cb}.label-info[href]:focus,.label-info[href]:hover{background-color:#6b9dbb}.label-warning{background-color:#cbb956}.label-warning[href]:focus,.label-warning[href]:hover{background-color:#b6a338}.label-danger{background-color:#bf5329}.label-danger[href]:focus,.label-danger[href]:hover{background-color:#954120}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-group-xs>.btn .badge,.btn-xs .badge{top:0;padding:1px 5px}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#3097d1;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}a.badge:focus,a.badge:hover{color:#fff;text-decoration:none;cursor:pointer}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;background-color:#eee}.jumbotron,.jumbotron .h1,.jumbotron h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container-fluid .jumbotron,.container .jumbotron{border-radius:6px;padding-left:15px;padding-right:15px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container-fluid .jumbotron,.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron .h1,.jumbotron h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:22px;line-height:1.6;background-color:#f5f8fa;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}.thumbnail .caption{padding:9px;color:#636b6f}a.thumbnail.active,a.thumbnail:focus,a.thumbnail:hover{border-color:#3097d1}.alert{padding:15px;margin-bottom:22px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:22px;margin-bottom:22px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:22px;color:#fff;text-align:center;background-color:#3097d1;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-bar-striped,.progress-striped .progress-bar{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent);background-size:40px 40px}.progress-bar.active,.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#2ab27b}.progress-striped .progress-bar-success{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-info{background-color:#8eb4cb}.progress-striped .progress-bar-info{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-warning{background-color:#cbb956}.progress-striped .progress-bar-warning{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.progress-bar-danger{background-color:#bf5329}.progress-striped .progress-bar-danger{background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{zoom:1;overflow:hidden}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-body,.media-left,.media-right{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #d3e0e9}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{text-decoration:none;color:#555;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item.disabled,.list-group-item.disabled:focus,.list-group-item.disabled:hover{background-color:#eee;color:#777;cursor:not-allowed}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{z-index:2;color:#fff;background-color:#3097d1;border-color:#3097d1}.list-group-item.active .list-group-item-heading,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#d7ebf6}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:focus,a.list-group-item-success:hover,button.list-group-item-success:focus,button.list-group-item-success:hover{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-group-item-success.active:hover,button.list-group-item-success.active,button.list-group-item-success.active:focus,button.list-group-item-success.active:hover{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:focus,a.list-group-item-warning:hover,button.list-group-item-warning:focus,button.list-group-item-warning:hover{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:focus,a.list-group-item-warning.active:hover,button.list-group-item-warning.active,button.list-group-item-warning.active:focus,button.list-group-item-warning.active:hover{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:focus,a.list-group-item-danger:hover,button.list-group-item-danger:focus,button.list-group-item-danger:hover{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:focus,a.list-group-item-danger.active:hover,button.list-group-item-danger.active,button.list-group-item-danger.active:focus,button.list-group-item-danger.active:hover{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:22px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel-body:after,.panel-body:before{content:" ";display:table}.panel-body:after{clear:both}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle,.panel-title{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px}.panel-title>.small,.panel-title>.small>a,.panel-title>a,.panel-title>small,.panel-title>small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #d3e0e9;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-right-radius:0;border-top-left-radius:0}.list-group+.panel-footer,.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.panel-collapse>.table,.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.panel-collapse>.table caption,.panel>.table-responsive>.table caption,.panel>.table caption{padding-left:15px;padding-right:15px}.panel>.table-responsive:first-child>.table:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table:first-child>thead:first-child>tr:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table-responsive:last-child>.table:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child td,.panel>.table>tbody:first-child>tr:first-child th{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child{border-left:0}.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child{border-right:0}.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-group{margin-bottom:22px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.list-group,.panel-group .panel-heading+.panel-collapse>.panel-body{border-top:1px solid #d3e0e9}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #d3e0e9}.panel-default{border-color:#d3e0e9}.panel-default>.panel-heading{color:#333;background-color:#fff;border-color:#d3e0e9}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d3e0e9}.panel-default>.panel-heading .badge{color:#fff;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d3e0e9}.panel-primary{border-color:#3097d1}.panel-primary>.panel-heading{color:#fff;background-color:#3097d1;border-color:#3097d1}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#3097d1}.panel-primary>.panel-heading .badge{color:#3097d1;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#3097d1}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive embed,.embed-responsive iframe,.embed-responsive object,.embed-responsive video{position:absolute;top:0;left:0;bottom:0;height:100%;width:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.modal,.modal-open{overflow:hidden}.modal{display:none;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translateY(-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header:after,.modal-header:before{content:" ";display:table}.modal-header:after{clear:both}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.6}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer:after,.modal-footer:before{content:" ";display:table}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}}@media (min-width:992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:Raleway,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.6;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:12px;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px}.tooltip.top-left .tooltip-arrow,.tooltip.top-right .tooltip-arrow{bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{left:5px}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:Raleway,sans-serif;font-style:normal;font-weight:400;letter-spacing:normal;line-break:auto;line-height:1.6;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;white-space:normal;word-break:normal;word-spacing:normal;word-wrap:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow{border-width:11px}.popover>.arrow:after{border-width:10px;content:""}.popover.top>.arrow{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top>.arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right>.arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom>.arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom>.arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left>.arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel,.carousel-inner{position:relative}.carousel-inner{overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:left .6s ease-in-out;transition:left .6s ease-in-out}.carousel-inner>.item>a>img,.carousel-inner>.item>img{display:block;max-width:100%;height:auto;line-height:1}@media (-webkit-transform-3d),(transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.active.right,.carousel-inner>.item.next{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.active.left,.carousel-inner>.item.prev{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.active,.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right{-webkit-transform:translateZ(0);transform:translateZ(0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:transparent}.carousel-control.left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(90deg,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80000000",endColorstr="#00000000",GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(90deg,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5));background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#00000000",endColorstr="#80000000",GradientType=1)}.carousel-control:focus,.carousel-control:hover{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{position:absolute;top:50%;margin-top:-10px;z-index:5;display:inline-block}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{left:50%;margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{right:50%;margin-right:-10px}.carousel-control .icon-next,.carousel-control .icon-prev{width:20px;height:20px;line-height:1;font-family:serif}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203A"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000\9;background-color:transparent}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next,.carousel-control .icon-prev{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:after,.clearfix:before{content:" ";display:table}.clearfix:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-lg,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block,.visible-md,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-sm,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-xs,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}td.visible-xs,th.visible-xs{display:table-cell!important}}@media (max-width:767px){.visible-xs-block{display:block!important}}@media (max-width:767px){.visible-xs-inline{display:inline!important}}@media (max-width:767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}td.visible-sm,th.visible-sm{display:table-cell!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-block{display:block!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline{display:inline!important}}@media (min-width:768px) and (max-width:991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}td.visible-md,th.visible-md{display:table-cell!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-block{display:block!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline{display:inline!important}}@media (min-width:992px) and (max-width:1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}td.visible-lg,th.visible-lg{display:table-cell!important}}@media (min-width:1200px){.visible-lg-block{display:block!important}}@media (min-width:1200px){.visible-lg-inline{display:inline!important}}@media (min-width:1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width:767px){.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}td.visible-print,th.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}} + +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:FontAwesome;src:url(/fonts/vendor/font-awesome/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713);src:url(/fonts/vendor/font-awesome/fontawesome-webfont.eot?674f50d287a8c48dc19ba404d20fe713) format("embedded-opentype"),url(/fonts/vendor/font-awesome/fontawesome-webfont.woff2?af7ae505a9eed503f8b8e6982036873e) format("woff2"),url(/fonts/vendor/font-awesome/fontawesome-webfont.woff?fee66e712a8a08eef5805a46892932ad) format("woff"),url(/fonts/vendor/font-awesome/fontawesome-webfont.ttf?b06871f281fee6b241d60582ae9369b9) format("truetype"),url(/fonts/vendor/font-awesome/fontawesome-webfont.svg?912ec66d7572ff821749319396470bde) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{-webkit-filter:none;filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\F000"}.fa-music:before{content:"\F001"}.fa-search:before{content:"\F002"}.fa-envelope-o:before{content:"\F003"}.fa-heart:before{content:"\F004"}.fa-star:before{content:"\F005"}.fa-star-o:before{content:"\F006"}.fa-user:before{content:"\F007"}.fa-film:before{content:"\F008"}.fa-th-large:before{content:"\F009"}.fa-th:before{content:"\F00A"}.fa-th-list:before{content:"\F00B"}.fa-check:before{content:"\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\F00D"}.fa-search-plus:before{content:"\F00E"}.fa-search-minus:before{content:"\F010"}.fa-power-off:before{content:"\F011"}.fa-signal:before{content:"\F012"}.fa-cog:before,.fa-gear:before{content:"\F013"}.fa-trash-o:before{content:"\F014"}.fa-home:before{content:"\F015"}.fa-file-o:before{content:"\F016"}.fa-clock-o:before{content:"\F017"}.fa-road:before{content:"\F018"}.fa-download:before{content:"\F019"}.fa-arrow-circle-o-down:before{content:"\F01A"}.fa-arrow-circle-o-up:before{content:"\F01B"}.fa-inbox:before{content:"\F01C"}.fa-play-circle-o:before{content:"\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\F01E"}.fa-refresh:before{content:"\F021"}.fa-list-alt:before{content:"\F022"}.fa-lock:before{content:"\F023"}.fa-flag:before{content:"\F024"}.fa-headphones:before{content:"\F025"}.fa-volume-off:before{content:"\F026"}.fa-volume-down:before{content:"\F027"}.fa-volume-up:before{content:"\F028"}.fa-qrcode:before{content:"\F029"}.fa-barcode:before{content:"\F02A"}.fa-tag:before{content:"\F02B"}.fa-tags:before{content:"\F02C"}.fa-book:before{content:"\F02D"}.fa-bookmark:before{content:"\F02E"}.fa-print:before{content:"\F02F"}.fa-camera:before{content:"\F030"}.fa-font:before{content:"\F031"}.fa-bold:before{content:"\F032"}.fa-italic:before{content:"\F033"}.fa-text-height:before{content:"\F034"}.fa-text-width:before{content:"\F035"}.fa-align-left:before{content:"\F036"}.fa-align-center:before{content:"\F037"}.fa-align-right:before{content:"\F038"}.fa-align-justify:before{content:"\F039"}.fa-list:before{content:"\F03A"}.fa-dedent:before,.fa-outdent:before{content:"\F03B"}.fa-indent:before{content:"\F03C"}.fa-video-camera:before{content:"\F03D"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\F03E"}.fa-pencil:before{content:"\F040"}.fa-map-marker:before{content:"\F041"}.fa-adjust:before{content:"\F042"}.fa-tint:before{content:"\F043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\F044"}.fa-share-square-o:before{content:"\F045"}.fa-check-square-o:before{content:"\F046"}.fa-arrows:before{content:"\F047"}.fa-step-backward:before{content:"\F048"}.fa-fast-backward:before{content:"\F049"}.fa-backward:before{content:"\F04A"}.fa-play:before{content:"\F04B"}.fa-pause:before{content:"\F04C"}.fa-stop:before{content:"\F04D"}.fa-forward:before{content:"\F04E"}.fa-fast-forward:before{content:"\F050"}.fa-step-forward:before{content:"\F051"}.fa-eject:before{content:"\F052"}.fa-chevron-left:before{content:"\F053"}.fa-chevron-right:before{content:"\F054"}.fa-plus-circle:before{content:"\F055"}.fa-minus-circle:before{content:"\F056"}.fa-times-circle:before{content:"\F057"}.fa-check-circle:before{content:"\F058"}.fa-question-circle:before{content:"\F059"}.fa-info-circle:before{content:"\F05A"}.fa-crosshairs:before{content:"\F05B"}.fa-times-circle-o:before{content:"\F05C"}.fa-check-circle-o:before{content:"\F05D"}.fa-ban:before{content:"\F05E"}.fa-arrow-left:before{content:"\F060"}.fa-arrow-right:before{content:"\F061"}.fa-arrow-up:before{content:"\F062"}.fa-arrow-down:before{content:"\F063"}.fa-mail-forward:before,.fa-share:before{content:"\F064"}.fa-expand:before{content:"\F065"}.fa-compress:before{content:"\F066"}.fa-plus:before{content:"\F067"}.fa-minus:before{content:"\F068"}.fa-asterisk:before{content:"\F069"}.fa-exclamation-circle:before{content:"\F06A"}.fa-gift:before{content:"\F06B"}.fa-leaf:before{content:"\F06C"}.fa-fire:before{content:"\F06D"}.fa-eye:before{content:"\F06E"}.fa-eye-slash:before{content:"\F070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\F071"}.fa-plane:before{content:"\F072"}.fa-calendar:before{content:"\F073"}.fa-random:before{content:"\F074"}.fa-comment:before{content:"\F075"}.fa-magnet:before{content:"\F076"}.fa-chevron-up:before{content:"\F077"}.fa-chevron-down:before{content:"\F078"}.fa-retweet:before{content:"\F079"}.fa-shopping-cart:before{content:"\F07A"}.fa-folder:before{content:"\F07B"}.fa-folder-open:before{content:"\F07C"}.fa-arrows-v:before{content:"\F07D"}.fa-arrows-h:before{content:"\F07E"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\F080"}.fa-twitter-square:before{content:"\F081"}.fa-facebook-square:before{content:"\F082"}.fa-camera-retro:before{content:"\F083"}.fa-key:before{content:"\F084"}.fa-cogs:before,.fa-gears:before{content:"\F085"}.fa-comments:before{content:"\F086"}.fa-thumbs-o-up:before{content:"\F087"}.fa-thumbs-o-down:before{content:"\F088"}.fa-star-half:before{content:"\F089"}.fa-heart-o:before{content:"\F08A"}.fa-sign-out:before{content:"\F08B"}.fa-linkedin-square:before{content:"\F08C"}.fa-thumb-tack:before{content:"\F08D"}.fa-external-link:before{content:"\F08E"}.fa-sign-in:before{content:"\F090"}.fa-trophy:before{content:"\F091"}.fa-github-square:before{content:"\F092"}.fa-upload:before{content:"\F093"}.fa-lemon-o:before{content:"\F094"}.fa-phone:before{content:"\F095"}.fa-square-o:before{content:"\F096"}.fa-bookmark-o:before{content:"\F097"}.fa-phone-square:before{content:"\F098"}.fa-twitter:before{content:"\F099"}.fa-facebook-f:before,.fa-facebook:before{content:"\F09A"}.fa-github:before{content:"\F09B"}.fa-unlock:before{content:"\F09C"}.fa-credit-card:before{content:"\F09D"}.fa-feed:before,.fa-rss:before{content:"\F09E"}.fa-hdd-o:before{content:"\F0A0"}.fa-bullhorn:before{content:"\F0A1"}.fa-bell:before{content:"\F0F3"}.fa-certificate:before{content:"\F0A3"}.fa-hand-o-right:before{content:"\F0A4"}.fa-hand-o-left:before{content:"\F0A5"}.fa-hand-o-up:before{content:"\F0A6"}.fa-hand-o-down:before{content:"\F0A7"}.fa-arrow-circle-left:before{content:"\F0A8"}.fa-arrow-circle-right:before{content:"\F0A9"}.fa-arrow-circle-up:before{content:"\F0AA"}.fa-arrow-circle-down:before{content:"\F0AB"}.fa-globe:before{content:"\F0AC"}.fa-wrench:before{content:"\F0AD"}.fa-tasks:before{content:"\F0AE"}.fa-filter:before{content:"\F0B0"}.fa-briefcase:before{content:"\F0B1"}.fa-arrows-alt:before{content:"\F0B2"}.fa-group:before,.fa-users:before{content:"\F0C0"}.fa-chain:before,.fa-link:before{content:"\F0C1"}.fa-cloud:before{content:"\F0C2"}.fa-flask:before{content:"\F0C3"}.fa-cut:before,.fa-scissors:before{content:"\F0C4"}.fa-copy:before,.fa-files-o:before{content:"\F0C5"}.fa-paperclip:before{content:"\F0C6"}.fa-floppy-o:before,.fa-save:before{content:"\F0C7"}.fa-square:before{content:"\F0C8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\F0C9"}.fa-list-ul:before{content:"\F0CA"}.fa-list-ol:before{content:"\F0CB"}.fa-strikethrough:before{content:"\F0CC"}.fa-underline:before{content:"\F0CD"}.fa-table:before{content:"\F0CE"}.fa-magic:before{content:"\F0D0"}.fa-truck:before{content:"\F0D1"}.fa-pinterest:before{content:"\F0D2"}.fa-pinterest-square:before{content:"\F0D3"}.fa-google-plus-square:before{content:"\F0D4"}.fa-google-plus:before{content:"\F0D5"}.fa-money:before{content:"\F0D6"}.fa-caret-down:before{content:"\F0D7"}.fa-caret-up:before{content:"\F0D8"}.fa-caret-left:before{content:"\F0D9"}.fa-caret-right:before{content:"\F0DA"}.fa-columns:before{content:"\F0DB"}.fa-sort:before,.fa-unsorted:before{content:"\F0DC"}.fa-sort-desc:before,.fa-sort-down:before{content:"\F0DD"}.fa-sort-asc:before,.fa-sort-up:before{content:"\F0DE"}.fa-envelope:before{content:"\F0E0"}.fa-linkedin:before{content:"\F0E1"}.fa-rotate-left:before,.fa-undo:before{content:"\F0E2"}.fa-gavel:before,.fa-legal:before{content:"\F0E3"}.fa-dashboard:before,.fa-tachometer:before{content:"\F0E4"}.fa-comment-o:before{content:"\F0E5"}.fa-comments-o:before{content:"\F0E6"}.fa-bolt:before,.fa-flash:before{content:"\F0E7"}.fa-sitemap:before{content:"\F0E8"}.fa-umbrella:before{content:"\F0E9"}.fa-clipboard:before,.fa-paste:before{content:"\F0EA"}.fa-lightbulb-o:before{content:"\F0EB"}.fa-exchange:before{content:"\F0EC"}.fa-cloud-download:before{content:"\F0ED"}.fa-cloud-upload:before{content:"\F0EE"}.fa-user-md:before{content:"\F0F0"}.fa-stethoscope:before{content:"\F0F1"}.fa-suitcase:before{content:"\F0F2"}.fa-bell-o:before{content:"\F0A2"}.fa-coffee:before{content:"\F0F4"}.fa-cutlery:before{content:"\F0F5"}.fa-file-text-o:before{content:"\F0F6"}.fa-building-o:before{content:"\F0F7"}.fa-hospital-o:before{content:"\F0F8"}.fa-ambulance:before{content:"\F0F9"}.fa-medkit:before{content:"\F0FA"}.fa-fighter-jet:before{content:"\F0FB"}.fa-beer:before{content:"\F0FC"}.fa-h-square:before{content:"\F0FD"}.fa-plus-square:before{content:"\F0FE"}.fa-angle-double-left:before{content:"\F100"}.fa-angle-double-right:before{content:"\F101"}.fa-angle-double-up:before{content:"\F102"}.fa-angle-double-down:before{content:"\F103"}.fa-angle-left:before{content:"\F104"}.fa-angle-right:before{content:"\F105"}.fa-angle-up:before{content:"\F106"}.fa-angle-down:before{content:"\F107"}.fa-desktop:before{content:"\F108"}.fa-laptop:before{content:"\F109"}.fa-tablet:before{content:"\F10A"}.fa-mobile-phone:before,.fa-mobile:before{content:"\F10B"}.fa-circle-o:before{content:"\F10C"}.fa-quote-left:before{content:"\F10D"}.fa-quote-right:before{content:"\F10E"}.fa-spinner:before{content:"\F110"}.fa-circle:before{content:"\F111"}.fa-mail-reply:before,.fa-reply:before{content:"\F112"}.fa-github-alt:before{content:"\F113"}.fa-folder-o:before{content:"\F114"}.fa-folder-open-o:before{content:"\F115"}.fa-smile-o:before{content:"\F118"}.fa-frown-o:before{content:"\F119"}.fa-meh-o:before{content:"\F11A"}.fa-gamepad:before{content:"\F11B"}.fa-keyboard-o:before{content:"\F11C"}.fa-flag-o:before{content:"\F11D"}.fa-flag-checkered:before{content:"\F11E"}.fa-terminal:before{content:"\F120"}.fa-code:before{content:"\F121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\F122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\F123"}.fa-location-arrow:before{content:"\F124"}.fa-crop:before{content:"\F125"}.fa-code-fork:before{content:"\F126"}.fa-chain-broken:before,.fa-unlink:before{content:"\F127"}.fa-question:before{content:"\F128"}.fa-info:before{content:"\F129"}.fa-exclamation:before{content:"\F12A"}.fa-superscript:before{content:"\F12B"}.fa-subscript:before{content:"\F12C"}.fa-eraser:before{content:"\F12D"}.fa-puzzle-piece:before{content:"\F12E"}.fa-microphone:before{content:"\F130"}.fa-microphone-slash:before{content:"\F131"}.fa-shield:before{content:"\F132"}.fa-calendar-o:before{content:"\F133"}.fa-fire-extinguisher:before{content:"\F134"}.fa-rocket:before{content:"\F135"}.fa-maxcdn:before{content:"\F136"}.fa-chevron-circle-left:before{content:"\F137"}.fa-chevron-circle-right:before{content:"\F138"}.fa-chevron-circle-up:before{content:"\F139"}.fa-chevron-circle-down:before{content:"\F13A"}.fa-html5:before{content:"\F13B"}.fa-css3:before{content:"\F13C"}.fa-anchor:before{content:"\F13D"}.fa-unlock-alt:before{content:"\F13E"}.fa-bullseye:before{content:"\F140"}.fa-ellipsis-h:before{content:"\F141"}.fa-ellipsis-v:before{content:"\F142"}.fa-rss-square:before{content:"\F143"}.fa-play-circle:before{content:"\F144"}.fa-ticket:before{content:"\F145"}.fa-minus-square:before{content:"\F146"}.fa-minus-square-o:before{content:"\F147"}.fa-level-up:before{content:"\F148"}.fa-level-down:before{content:"\F149"}.fa-check-square:before{content:"\F14A"}.fa-pencil-square:before{content:"\F14B"}.fa-external-link-square:before{content:"\F14C"}.fa-share-square:before{content:"\F14D"}.fa-compass:before{content:"\F14E"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\F150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\F151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\F152"}.fa-eur:before,.fa-euro:before{content:"\F153"}.fa-gbp:before{content:"\F154"}.fa-dollar:before,.fa-usd:before{content:"\F155"}.fa-inr:before,.fa-rupee:before{content:"\F156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\F157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\F158"}.fa-krw:before,.fa-won:before{content:"\F159"}.fa-bitcoin:before,.fa-btc:before{content:"\F15A"}.fa-file:before{content:"\F15B"}.fa-file-text:before{content:"\F15C"}.fa-sort-alpha-asc:before{content:"\F15D"}.fa-sort-alpha-desc:before{content:"\F15E"}.fa-sort-amount-asc:before{content:"\F160"}.fa-sort-amount-desc:before{content:"\F161"}.fa-sort-numeric-asc:before{content:"\F162"}.fa-sort-numeric-desc:before{content:"\F163"}.fa-thumbs-up:before{content:"\F164"}.fa-thumbs-down:before{content:"\F165"}.fa-youtube-square:before{content:"\F166"}.fa-youtube:before{content:"\F167"}.fa-xing:before{content:"\F168"}.fa-xing-square:before{content:"\F169"}.fa-youtube-play:before{content:"\F16A"}.fa-dropbox:before{content:"\F16B"}.fa-stack-overflow:before{content:"\F16C"}.fa-instagram:before{content:"\F16D"}.fa-flickr:before{content:"\F16E"}.fa-adn:before{content:"\F170"}.fa-bitbucket:before{content:"\F171"}.fa-bitbucket-square:before{content:"\F172"}.fa-tumblr:before{content:"\F173"}.fa-tumblr-square:before{content:"\F174"}.fa-long-arrow-down:before{content:"\F175"}.fa-long-arrow-up:before{content:"\F176"}.fa-long-arrow-left:before{content:"\F177"}.fa-long-arrow-right:before{content:"\F178"}.fa-apple:before{content:"\F179"}.fa-windows:before{content:"\F17A"}.fa-android:before{content:"\F17B"}.fa-linux:before{content:"\F17C"}.fa-dribbble:before{content:"\F17D"}.fa-skype:before{content:"\F17E"}.fa-foursquare:before{content:"\F180"}.fa-trello:before{content:"\F181"}.fa-female:before{content:"\F182"}.fa-male:before{content:"\F183"}.fa-gittip:before,.fa-gratipay:before{content:"\F184"}.fa-sun-o:before{content:"\F185"}.fa-moon-o:before{content:"\F186"}.fa-archive:before{content:"\F187"}.fa-bug:before{content:"\F188"}.fa-vk:before{content:"\F189"}.fa-weibo:before{content:"\F18A"}.fa-renren:before{content:"\F18B"}.fa-pagelines:before{content:"\F18C"}.fa-stack-exchange:before{content:"\F18D"}.fa-arrow-circle-o-right:before{content:"\F18E"}.fa-arrow-circle-o-left:before{content:"\F190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\F191"}.fa-dot-circle-o:before{content:"\F192"}.fa-wheelchair:before{content:"\F193"}.fa-vimeo-square:before{content:"\F194"}.fa-try:before,.fa-turkish-lira:before{content:"\F195"}.fa-plus-square-o:before{content:"\F196"}.fa-space-shuttle:before{content:"\F197"}.fa-slack:before{content:"\F198"}.fa-envelope-square:before{content:"\F199"}.fa-wordpress:before{content:"\F19A"}.fa-openid:before{content:"\F19B"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\F19C"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\F19D"}.fa-yahoo:before{content:"\F19E"}.fa-google:before{content:"\F1A0"}.fa-reddit:before{content:"\F1A1"}.fa-reddit-square:before{content:"\F1A2"}.fa-stumbleupon-circle:before{content:"\F1A3"}.fa-stumbleupon:before{content:"\F1A4"}.fa-delicious:before{content:"\F1A5"}.fa-digg:before{content:"\F1A6"}.fa-pied-piper-pp:before{content:"\F1A7"}.fa-pied-piper-alt:before{content:"\F1A8"}.fa-drupal:before{content:"\F1A9"}.fa-joomla:before{content:"\F1AA"}.fa-language:before{content:"\F1AB"}.fa-fax:before{content:"\F1AC"}.fa-building:before{content:"\F1AD"}.fa-child:before{content:"\F1AE"}.fa-paw:before{content:"\F1B0"}.fa-spoon:before{content:"\F1B1"}.fa-cube:before{content:"\F1B2"}.fa-cubes:before{content:"\F1B3"}.fa-behance:before{content:"\F1B4"}.fa-behance-square:before{content:"\F1B5"}.fa-steam:before{content:"\F1B6"}.fa-steam-square:before{content:"\F1B7"}.fa-recycle:before{content:"\F1B8"}.fa-automobile:before,.fa-car:before{content:"\F1B9"}.fa-cab:before,.fa-taxi:before{content:"\F1BA"}.fa-tree:before{content:"\F1BB"}.fa-spotify:before{content:"\F1BC"}.fa-deviantart:before{content:"\F1BD"}.fa-soundcloud:before{content:"\F1BE"}.fa-database:before{content:"\F1C0"}.fa-file-pdf-o:before{content:"\F1C1"}.fa-file-word-o:before{content:"\F1C2"}.fa-file-excel-o:before{content:"\F1C3"}.fa-file-powerpoint-o:before{content:"\F1C4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\F1C5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\F1C6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\F1C7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\F1C8"}.fa-file-code-o:before{content:"\F1C9"}.fa-vine:before{content:"\F1CA"}.fa-codepen:before{content:"\F1CB"}.fa-jsfiddle:before{content:"\F1CC"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\F1CD"}.fa-circle-o-notch:before{content:"\F1CE"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\F1D0"}.fa-empire:before,.fa-ge:before{content:"\F1D1"}.fa-git-square:before{content:"\F1D2"}.fa-git:before{content:"\F1D3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\F1D4"}.fa-tencent-weibo:before{content:"\F1D5"}.fa-qq:before{content:"\F1D6"}.fa-wechat:before,.fa-weixin:before{content:"\F1D7"}.fa-paper-plane:before,.fa-send:before{content:"\F1D8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\F1D9"}.fa-history:before{content:"\F1DA"}.fa-circle-thin:before{content:"\F1DB"}.fa-header:before{content:"\F1DC"}.fa-paragraph:before{content:"\F1DD"}.fa-sliders:before{content:"\F1DE"}.fa-share-alt:before{content:"\F1E0"}.fa-share-alt-square:before{content:"\F1E1"}.fa-bomb:before{content:"\F1E2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\F1E3"}.fa-tty:before{content:"\F1E4"}.fa-binoculars:before{content:"\F1E5"}.fa-plug:before{content:"\F1E6"}.fa-slideshare:before{content:"\F1E7"}.fa-twitch:before{content:"\F1E8"}.fa-yelp:before{content:"\F1E9"}.fa-newspaper-o:before{content:"\F1EA"}.fa-wifi:before{content:"\F1EB"}.fa-calculator:before{content:"\F1EC"}.fa-paypal:before{content:"\F1ED"}.fa-google-wallet:before{content:"\F1EE"}.fa-cc-visa:before{content:"\F1F0"}.fa-cc-mastercard:before{content:"\F1F1"}.fa-cc-discover:before{content:"\F1F2"}.fa-cc-amex:before{content:"\F1F3"}.fa-cc-paypal:before{content:"\F1F4"}.fa-cc-stripe:before{content:"\F1F5"}.fa-bell-slash:before{content:"\F1F6"}.fa-bell-slash-o:before{content:"\F1F7"}.fa-trash:before{content:"\F1F8"}.fa-copyright:before{content:"\F1F9"}.fa-at:before{content:"\F1FA"}.fa-eyedropper:before{content:"\F1FB"}.fa-paint-brush:before{content:"\F1FC"}.fa-birthday-cake:before{content:"\F1FD"}.fa-area-chart:before{content:"\F1FE"}.fa-pie-chart:before{content:"\F200"}.fa-line-chart:before{content:"\F201"}.fa-lastfm:before{content:"\F202"}.fa-lastfm-square:before{content:"\F203"}.fa-toggle-off:before{content:"\F204"}.fa-toggle-on:before{content:"\F205"}.fa-bicycle:before{content:"\F206"}.fa-bus:before{content:"\F207"}.fa-ioxhost:before{content:"\F208"}.fa-angellist:before{content:"\F209"}.fa-cc:before{content:"\F20A"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\F20B"}.fa-meanpath:before{content:"\F20C"}.fa-buysellads:before{content:"\F20D"}.fa-connectdevelop:before{content:"\F20E"}.fa-dashcube:before{content:"\F210"}.fa-forumbee:before{content:"\F211"}.fa-leanpub:before{content:"\F212"}.fa-sellsy:before{content:"\F213"}.fa-shirtsinbulk:before{content:"\F214"}.fa-simplybuilt:before{content:"\F215"}.fa-skyatlas:before{content:"\F216"}.fa-cart-plus:before{content:"\F217"}.fa-cart-arrow-down:before{content:"\F218"}.fa-diamond:before{content:"\F219"}.fa-ship:before{content:"\F21A"}.fa-user-secret:before{content:"\F21B"}.fa-motorcycle:before{content:"\F21C"}.fa-street-view:before{content:"\F21D"}.fa-heartbeat:before{content:"\F21E"}.fa-venus:before{content:"\F221"}.fa-mars:before{content:"\F222"}.fa-mercury:before{content:"\F223"}.fa-intersex:before,.fa-transgender:before{content:"\F224"}.fa-transgender-alt:before{content:"\F225"}.fa-venus-double:before{content:"\F226"}.fa-mars-double:before{content:"\F227"}.fa-venus-mars:before{content:"\F228"}.fa-mars-stroke:before{content:"\F229"}.fa-mars-stroke-v:before{content:"\F22A"}.fa-mars-stroke-h:before{content:"\F22B"}.fa-neuter:before{content:"\F22C"}.fa-genderless:before{content:"\F22D"}.fa-facebook-official:before{content:"\F230"}.fa-pinterest-p:before{content:"\F231"}.fa-whatsapp:before{content:"\F232"}.fa-server:before{content:"\F233"}.fa-user-plus:before{content:"\F234"}.fa-user-times:before{content:"\F235"}.fa-bed:before,.fa-hotel:before{content:"\F236"}.fa-viacoin:before{content:"\F237"}.fa-train:before{content:"\F238"}.fa-subway:before{content:"\F239"}.fa-medium:before{content:"\F23A"}.fa-y-combinator:before,.fa-yc:before{content:"\F23B"}.fa-optin-monster:before{content:"\F23C"}.fa-opencart:before{content:"\F23D"}.fa-expeditedssl:before{content:"\F23E"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\F240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\F241"}.fa-battery-2:before,.fa-battery-half:before{content:"\F242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\F243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\F244"}.fa-mouse-pointer:before{content:"\F245"}.fa-i-cursor:before{content:"\F246"}.fa-object-group:before{content:"\F247"}.fa-object-ungroup:before{content:"\F248"}.fa-sticky-note:before{content:"\F249"}.fa-sticky-note-o:before{content:"\F24A"}.fa-cc-jcb:before{content:"\F24B"}.fa-cc-diners-club:before{content:"\F24C"}.fa-clone:before{content:"\F24D"}.fa-balance-scale:before{content:"\F24E"}.fa-hourglass-o:before{content:"\F250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\F251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\F252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\F253"}.fa-hourglass:before{content:"\F254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\F255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\F256"}.fa-hand-scissors-o:before{content:"\F257"}.fa-hand-lizard-o:before{content:"\F258"}.fa-hand-spock-o:before{content:"\F259"}.fa-hand-pointer-o:before{content:"\F25A"}.fa-hand-peace-o:before{content:"\F25B"}.fa-trademark:before{content:"\F25C"}.fa-registered:before{content:"\F25D"}.fa-creative-commons:before{content:"\F25E"}.fa-gg:before{content:"\F260"}.fa-gg-circle:before{content:"\F261"}.fa-tripadvisor:before{content:"\F262"}.fa-odnoklassniki:before{content:"\F263"}.fa-odnoklassniki-square:before{content:"\F264"}.fa-get-pocket:before{content:"\F265"}.fa-wikipedia-w:before{content:"\F266"}.fa-safari:before{content:"\F267"}.fa-chrome:before{content:"\F268"}.fa-firefox:before{content:"\F269"}.fa-opera:before{content:"\F26A"}.fa-internet-explorer:before{content:"\F26B"}.fa-television:before,.fa-tv:before{content:"\F26C"}.fa-contao:before{content:"\F26D"}.fa-500px:before{content:"\F26E"}.fa-amazon:before{content:"\F270"}.fa-calendar-plus-o:before{content:"\F271"}.fa-calendar-minus-o:before{content:"\F272"}.fa-calendar-times-o:before{content:"\F273"}.fa-calendar-check-o:before{content:"\F274"}.fa-industry:before{content:"\F275"}.fa-map-pin:before{content:"\F276"}.fa-map-signs:before{content:"\F277"}.fa-map-o:before{content:"\F278"}.fa-map:before{content:"\F279"}.fa-commenting:before{content:"\F27A"}.fa-commenting-o:before{content:"\F27B"}.fa-houzz:before{content:"\F27C"}.fa-vimeo:before{content:"\F27D"}.fa-black-tie:before{content:"\F27E"}.fa-fonticons:before{content:"\F280"}.fa-reddit-alien:before{content:"\F281"}.fa-edge:before{content:"\F282"}.fa-credit-card-alt:before{content:"\F283"}.fa-codiepie:before{content:"\F284"}.fa-modx:before{content:"\F285"}.fa-fort-awesome:before{content:"\F286"}.fa-usb:before{content:"\F287"}.fa-product-hunt:before{content:"\F288"}.fa-mixcloud:before{content:"\F289"}.fa-scribd:before{content:"\F28A"}.fa-pause-circle:before{content:"\F28B"}.fa-pause-circle-o:before{content:"\F28C"}.fa-stop-circle:before{content:"\F28D"}.fa-stop-circle-o:before{content:"\F28E"}.fa-shopping-bag:before{content:"\F290"}.fa-shopping-basket:before{content:"\F291"}.fa-hashtag:before{content:"\F292"}.fa-bluetooth:before{content:"\F293"}.fa-bluetooth-b:before{content:"\F294"}.fa-percent:before{content:"\F295"}.fa-gitlab:before{content:"\F296"}.fa-wpbeginner:before{content:"\F297"}.fa-wpforms:before{content:"\F298"}.fa-envira:before{content:"\F299"}.fa-universal-access:before{content:"\F29A"}.fa-wheelchair-alt:before{content:"\F29B"}.fa-question-circle-o:before{content:"\F29C"}.fa-blind:before{content:"\F29D"}.fa-audio-description:before{content:"\F29E"}.fa-volume-control-phone:before{content:"\F2A0"}.fa-braille:before{content:"\F2A1"}.fa-assistive-listening-systems:before{content:"\F2A2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\F2A3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\F2A4"}.fa-glide:before{content:"\F2A5"}.fa-glide-g:before{content:"\F2A6"}.fa-sign-language:before,.fa-signing:before{content:"\F2A7"}.fa-low-vision:before{content:"\F2A8"}.fa-viadeo:before{content:"\F2A9"}.fa-viadeo-square:before{content:"\F2AA"}.fa-snapchat:before{content:"\F2AB"}.fa-snapchat-ghost:before{content:"\F2AC"}.fa-snapchat-square:before{content:"\F2AD"}.fa-pied-piper:before{content:"\F2AE"}.fa-first-order:before{content:"\F2B0"}.fa-yoast:before{content:"\F2B1"}.fa-themeisle:before{content:"\F2B2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\F2B3"}.fa-fa:before,.fa-font-awesome:before{content:"\F2B4"}.fa-handshake-o:before{content:"\F2B5"}.fa-envelope-open:before{content:"\F2B6"}.fa-envelope-open-o:before{content:"\F2B7"}.fa-linode:before{content:"\F2B8"}.fa-address-book:before{content:"\F2B9"}.fa-address-book-o:before{content:"\F2BA"}.fa-address-card:before,.fa-vcard:before{content:"\F2BB"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\F2BC"}.fa-user-circle:before{content:"\F2BD"}.fa-user-circle-o:before{content:"\F2BE"}.fa-user-o:before{content:"\F2C0"}.fa-id-badge:before{content:"\F2C1"}.fa-drivers-license:before,.fa-id-card:before{content:"\F2C2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\F2C3"}.fa-quora:before{content:"\F2C4"}.fa-free-code-camp:before{content:"\F2C5"}.fa-telegram:before{content:"\F2C6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\F2C7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\F2C8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\F2C9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\F2CA"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\F2CB"}.fa-shower:before{content:"\F2CC"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\F2CD"}.fa-podcast:before{content:"\F2CE"}.fa-window-maximize:before{content:"\F2D0"}.fa-window-minimize:before{content:"\F2D1"}.fa-window-restore:before{content:"\F2D2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\F2D3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\F2D4"}.fa-bandcamp:before{content:"\F2D5"}.fa-grav:before{content:"\F2D6"}.fa-etsy:before{content:"\F2D7"}.fa-imdb:before{content:"\F2D8"}.fa-ravelry:before{content:"\F2D9"}.fa-eercast:before{content:"\F2DA"}.fa-microchip:before{content:"\F2DB"}.fa-snowflake-o:before{content:"\F2DC"}.fa-superpowers:before{content:"\F2DD"}.fa-wpexplorer:before{content:"\F2DE"}.fa-meetup:before{content:"\F2E0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} \ No newline at end of file diff --git a/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot similarity index 100% rename from public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot rename to public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.eot diff --git a/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.svg similarity index 100% rename from public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg rename to public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.svg diff --git a/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf similarity index 100% rename from public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf rename to public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.ttf diff --git a/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff similarity index 100% rename from public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff rename to public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff diff --git a/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2 similarity index 100% rename from public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 rename to public/fonts/vendor/bootstrap-sass/bootstrap/glyphicons-halflings-regular.woff2 diff --git a/public/lib/font-awesome/fonts/fontawesome-webfont.eot b/public/fonts/vendor/font-awesome/fontawesome-webfont.eot similarity index 100% rename from public/lib/font-awesome/fonts/fontawesome-webfont.eot rename to public/fonts/vendor/font-awesome/fontawesome-webfont.eot diff --git a/public/lib/font-awesome/fonts/fontawesome-webfont.svg b/public/fonts/vendor/font-awesome/fontawesome-webfont.svg similarity index 100% rename from public/lib/font-awesome/fonts/fontawesome-webfont.svg rename to public/fonts/vendor/font-awesome/fontawesome-webfont.svg diff --git a/public/lib/font-awesome/fonts/fontawesome-webfont.ttf b/public/fonts/vendor/font-awesome/fontawesome-webfont.ttf similarity index 100% rename from public/lib/font-awesome/fonts/fontawesome-webfont.ttf rename to public/fonts/vendor/font-awesome/fontawesome-webfont.ttf diff --git a/public/lib/font-awesome/fonts/fontawesome-webfont.woff b/public/fonts/vendor/font-awesome/fontawesome-webfont.woff similarity index 100% rename from public/lib/font-awesome/fonts/fontawesome-webfont.woff rename to public/fonts/vendor/font-awesome/fontawesome-webfont.woff diff --git a/public/lib/font-awesome/fonts/fontawesome-webfont.woff2 b/public/fonts/vendor/font-awesome/fontawesome-webfont.woff2 similarity index 100% rename from public/lib/font-awesome/fonts/fontawesome-webfont.woff2 rename to public/fonts/vendor/font-awesome/fontawesome-webfont.woff2 diff --git a/public/js/app.js b/public/js/app.js new file mode 100644 index 0000000000..8e29fa9b26 --- /dev/null +++ b/public/js/app.js @@ -0,0 +1 @@ +!function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=12)}([function(t,e,n){"use strict";var r=n(6),i=n(21),o=Object.prototype.toString;function a(t){return"[object Array]"===o.call(t)}function s(t){return null!==t&&"object"==typeof t}function u(t){return"[object Function]"===o.call(t)}function c(t,e){if(null!==t&&void 0!==t)if("object"!=typeof t&&(t=[t]),a(t))for(var n=0,r=t.length;n=200&&t<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},r.forEach(["delete","get","head"],function(t){u.headers[t]={}}),r.forEach(["post","put","patch"],function(t){u.headers[t]=r.merge(o)}),t.exports=u}).call(e,n(7))},function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var n=function(t,e){var n=t[1]||"",r=t[3];if(!r)return n;if(e&&"function"==typeof btoa){var i=(a=r,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(a))))+" */"),o=r.sources.map(function(t){return"/*# sourceURL="+r.sourceRoot+t+" */"});return[n].concat(o).concat([i]).join("\n")}var a;return[n].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+n+"}":n}).join("")},e.i=function(t,n){"string"==typeof t&&(t=[[null,t,""]]);for(var r={},i=0;in.parts.length&&(r.parts.length=n.parts.length)}else{var a=[];for(i=0;i1)for(var n=1;n>>1,q=[["ary",T],["bind",g],["bindKey",y],["curry",_],["curryRight",w],["flip",$],["partial",x],["partialRight",C],["rearg",k]],B="[object Arguments]",H="[object Array]",U="[object AsyncFunction]",W="[object Boolean]",z="[object Date]",V="[object DOMException]",X="[object Error]",K="[object Function]",J="[object GeneratorFunction]",G="[object Map]",Q="[object Number]",Y="[object Null]",Z="[object Object]",tt="[object Proxy]",et="[object RegExp]",nt="[object Set]",rt="[object String]",it="[object Symbol]",ot="[object Undefined]",at="[object WeakMap]",st="[object WeakSet]",ut="[object ArrayBuffer]",ct="[object DataView]",lt="[object Float32Array]",ft="[object Float64Array]",pt="[object Int8Array]",dt="[object Int16Array]",ht="[object Int32Array]",vt="[object Uint8Array]",mt="[object Uint8ClampedArray]",gt="[object Uint16Array]",yt="[object Uint32Array]",bt=/\b__p \+= '';/g,_t=/\b(__p \+=) '' \+/g,wt=/(__e\(.*?\)|\b__t\)) \+\n'';/g,xt=/&(?:amp|lt|gt|quot|#39);/g,Ct=/[&<>"']/g,Tt=RegExp(xt.source),kt=RegExp(Ct.source),$t=/<%-([\s\S]+?)%>/g,At=/<%([\s\S]+?)%>/g,St=/<%=([\s\S]+?)%>/g,Et=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Ot=/^\w*$/,jt=/^\./,Nt=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Dt=/[\\^$.*+?()[\]{}|]/g,It=RegExp(Dt.source),Lt=/^\s+|\s+$/g,Rt=/^\s+/,Pt=/\s+$/,Ft=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Mt=/\{\n\/\* \[wrapped with (.+)\] \*/,qt=/,? & /,Bt=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Ht=/\\(\\)?/g,Ut=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Wt=/\w*$/,zt=/^[-+]0x[0-9a-f]+$/i,Vt=/^0b[01]+$/i,Xt=/^\[object .+?Constructor\]$/,Kt=/^0o[0-7]+$/i,Jt=/^(?:0|[1-9]\d*)$/,Gt=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Qt=/($^)/,Yt=/['\n\r\u2028\u2029\\]/g,Zt="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",te="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",ee="[\\ud800-\\udfff]",ne="["+te+"]",re="["+Zt+"]",ie="\\d+",oe="[\\u2700-\\u27bf]",ae="[a-z\\xdf-\\xf6\\xf8-\\xff]",se="[^\\ud800-\\udfff"+te+ie+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",ue="\\ud83c[\\udffb-\\udfff]",ce="[^\\ud800-\\udfff]",le="(?:\\ud83c[\\udde6-\\uddff]){2}",fe="[\\ud800-\\udbff][\\udc00-\\udfff]",pe="[A-Z\\xc0-\\xd6\\xd8-\\xde]",de="(?:"+ae+"|"+se+")",he="(?:"+pe+"|"+se+")",ve="(?:"+re+"|"+ue+")"+"?",me="[\\ufe0e\\ufe0f]?"+ve+("(?:\\u200d(?:"+[ce,le,fe].join("|")+")[\\ufe0e\\ufe0f]?"+ve+")*"),ge="(?:"+[oe,le,fe].join("|")+")"+me,ye="(?:"+[ce+re+"?",re,le,fe,ee].join("|")+")",be=RegExp("['’]","g"),_e=RegExp(re,"g"),we=RegExp(ue+"(?="+ue+")|"+ye+me,"g"),xe=RegExp([pe+"?"+ae+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[ne,pe,"$"].join("|")+")",he+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[ne,pe+de,"$"].join("|")+")",pe+"?"+de+"+(?:['’](?:d|ll|m|re|s|t|ve))?",pe+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)","\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)",ie,ge].join("|"),"g"),Ce=RegExp("[\\u200d\\ud800-\\udfff"+Zt+"\\ufe0e\\ufe0f]"),Te=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,ke=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],$e=-1,Ae={};Ae[lt]=Ae[ft]=Ae[pt]=Ae[dt]=Ae[ht]=Ae[vt]=Ae[mt]=Ae[gt]=Ae[yt]=!0,Ae[B]=Ae[H]=Ae[ut]=Ae[W]=Ae[ct]=Ae[z]=Ae[X]=Ae[K]=Ae[G]=Ae[Q]=Ae[Z]=Ae[et]=Ae[nt]=Ae[rt]=Ae[at]=!1;var Se={};Se[B]=Se[H]=Se[ut]=Se[ct]=Se[W]=Se[z]=Se[lt]=Se[ft]=Se[pt]=Se[dt]=Se[ht]=Se[G]=Se[Q]=Se[Z]=Se[et]=Se[nt]=Se[rt]=Se[it]=Se[vt]=Se[mt]=Se[gt]=Se[yt]=!0,Se[X]=Se[K]=Se[at]=!1;var Ee={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Oe=parseFloat,je=parseInt,Ne="object"==typeof t&&t&&t.Object===Object&&t,De="object"==typeof self&&self&&self.Object===Object&&self,Ie=Ne||De||Function("return this")(),Le="object"==typeof e&&e&&!e.nodeType&&e,Re=Le&&"object"==typeof r&&r&&!r.nodeType&&r,Pe=Re&&Re.exports===Le,Fe=Pe&&Ne.process,Me=function(){try{return Fe&&Fe.binding&&Fe.binding("util")}catch(t){}}(),qe=Me&&Me.isArrayBuffer,Be=Me&&Me.isDate,He=Me&&Me.isMap,Ue=Me&&Me.isRegExp,We=Me&&Me.isSet,ze=Me&&Me.isTypedArray;function Ve(t,e){return t.set(e[0],e[1]),t}function Xe(t,e){return t.add(e),t}function Ke(t,e,n){switch(n.length){case 0:return t.call(e);case 1:return t.call(e,n[0]);case 2:return t.call(e,n[0],n[1]);case 3:return t.call(e,n[0],n[1],n[2])}return t.apply(e,n)}function Je(t,e,n,r){for(var i=-1,o=null==t?0:t.length;++i-1}function en(t,e,n){for(var r=-1,i=null==t?0:t.length;++r-1;);return n}function Tn(t,e){for(var n=t.length;n--&&fn(e,t[n],0)>-1;);return n}var kn=mn({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),$n=mn({"&":"&","<":"<",">":">",'"':""","'":"'"});function An(t){return"\\"+Ee[t]}function Sn(t){return Ce.test(t)}function En(t){var e=-1,n=Array(t.size);return t.forEach(function(t,r){n[++e]=[r,t]}),n}function On(t,e){return function(n){return t(e(n))}}function jn(t,e){for(var n=-1,r=t.length,i=0,o=[];++n",""":'"',"'":"'"});var Pn=function t(e){var n,r=(e=null==e?Ie:Pn.defaults(Ie.Object(),e,Pn.pick(Ie,ke))).Array,i=e.Date,Zt=e.Error,te=e.Function,ee=e.Math,ne=e.Object,re=e.RegExp,ie=e.String,oe=e.TypeError,ae=r.prototype,se=te.prototype,ue=ne.prototype,ce=e["__core-js_shared__"],le=se.toString,fe=ue.hasOwnProperty,pe=0,de=(n=/[^.]+$/.exec(ce&&ce.keys&&ce.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",he=ue.toString,ve=le.call(ne),me=Ie._,ge=re("^"+le.call(fe).replace(Dt,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),ye=Pe?e.Buffer:o,we=e.Symbol,Ce=e.Uint8Array,Ee=ye?ye.allocUnsafe:o,Ne=On(ne.getPrototypeOf,ne),De=ne.create,Le=ue.propertyIsEnumerable,Re=ae.splice,Fe=we?we.isConcatSpreadable:o,Me=we?we.iterator:o,un=we?we.toStringTag:o,mn=function(){try{var t=Ho(ne,"defineProperty");return t({},"",{}),t}catch(t){}}(),Fn=e.clearTimeout!==Ie.clearTimeout&&e.clearTimeout,Mn=i&&i.now!==Ie.Date.now&&i.now,qn=e.setTimeout!==Ie.setTimeout&&e.setTimeout,Bn=ee.ceil,Hn=ee.floor,Un=ne.getOwnPropertySymbols,Wn=ye?ye.isBuffer:o,zn=e.isFinite,Vn=ae.join,Xn=On(ne.keys,ne),Kn=ee.max,Jn=ee.min,Gn=i.now,Qn=e.parseInt,Yn=ee.random,Zn=ae.reverse,tr=Ho(e,"DataView"),er=Ho(e,"Map"),nr=Ho(e,"Promise"),rr=Ho(e,"Set"),ir=Ho(e,"WeakMap"),or=Ho(ne,"create"),ar=ir&&new ir,sr={},ur=da(tr),cr=da(er),lr=da(nr),fr=da(rr),pr=da(ir),dr=we?we.prototype:o,hr=dr?dr.valueOf:o,vr=dr?dr.toString:o;function mr(t){if(Os(t)&&!bs(t)&&!(t instanceof _r)){if(t instanceof br)return t;if(fe.call(t,"__wrapped__"))return ha(t)}return new br(t)}var gr=function(){function t(){}return function(e){if(!Es(e))return{};if(De)return De(e);t.prototype=e;var n=new t;return t.prototype=o,n}}();function yr(){}function br(t,e){this.__wrapped__=t,this.__actions__=[],this.__chain__=!!e,this.__index__=0,this.__values__=o}function _r(t){this.__wrapped__=t,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=P,this.__views__=[]}function wr(t){var e=-1,n=null==t?0:t.length;for(this.clear();++e=e?t:e)),t}function Fr(t,e,n,r,i,a){var s,u=e&p,c=e&d,l=e&h;if(n&&(s=i?n(t,r,i,a):n(t)),s!==o)return s;if(!Es(t))return t;var f=bs(t);if(f){if(s=function(t){var e=t.length,n=t.constructor(e);return e&&"string"==typeof t[0]&&fe.call(t,"index")&&(n.index=t.index,n.input=t.input),n}(t),!u)return oo(t,s)}else{var v=zo(t),m=v==K||v==J;if(Cs(t))return Zi(t,u);if(v==Z||v==B||m&&!i){if(s=c||m?{}:Xo(t),!u)return c?function(t,e){return ao(t,Wo(t),e)}(t,function(t,e){return t&&ao(e,su(e),t)}(s,t)):function(t,e){return ao(t,Uo(t),e)}(t,Ir(s,t))}else{if(!Se[v])return i?t:{};s=function(t,e,n,r){var i,o,a,s=t.constructor;switch(e){case ut:return to(t);case W:case z:return new s(+t);case ct:return function(t,e){var n=e?to(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.byteLength)}(t,r);case lt:case ft:case pt:case dt:case ht:case vt:case mt:case gt:case yt:return eo(t,r);case G:return function(t,e,n){return on(e?n(En(t),p):En(t),Ve,new t.constructor)}(t,r,n);case Q:case rt:return new s(t);case et:return(a=new(o=t).constructor(o.source,Wt.exec(o))).lastIndex=o.lastIndex,a;case nt:return function(t,e,n){return on(e?n(Nn(t),p):Nn(t),Xe,new t.constructor)}(t,r,n);case it:return i=t,hr?ne(hr.call(i)):{}}}(t,v,Fr,u)}}a||(a=new kr);var g=a.get(t);if(g)return g;a.set(t,s);var y=f?o:(l?c?Lo:Io:c?su:au)(t);return Ge(y||t,function(r,i){y&&(r=t[i=r]),jr(s,i,Fr(r,e,n,i,t,a))}),s}function Mr(t,e,n){var r=n.length;if(null==t)return!r;for(t=ne(t);r--;){var i=n[r],a=e[i],s=t[i];if(s===o&&!(i in t)||!a(s))return!1}return!0}function qr(t,e,n){if("function"!=typeof t)throw new oe(u);return aa(function(){t.apply(o,n)},e)}function Br(t,e,n,r){var i=-1,o=tn,s=!0,u=t.length,c=[],l=e.length;if(!u)return c;n&&(e=nn(e,_n(n))),r?(o=en,s=!1):e.length>=a&&(o=xn,s=!1,e=new Tr(e));t:for(;++i-1},xr.prototype.set=function(t,e){var n=this.__data__,r=Nr(n,t);return r<0?(++this.size,n.push([t,e])):n[r][1]=e,this},Cr.prototype.clear=function(){this.size=0,this.__data__={hash:new wr,map:new(er||xr),string:new wr}},Cr.prototype.delete=function(t){var e=qo(this,t).delete(t);return this.size-=e?1:0,e},Cr.prototype.get=function(t){return qo(this,t).get(t)},Cr.prototype.has=function(t){return qo(this,t).has(t)},Cr.prototype.set=function(t,e){var n=qo(this,t),r=n.size;return n.set(t,e),this.size+=n.size==r?0:1,this},Tr.prototype.add=Tr.prototype.push=function(t){return this.__data__.set(t,c),this},Tr.prototype.has=function(t){return this.__data__.has(t)},kr.prototype.clear=function(){this.__data__=new xr,this.size=0},kr.prototype.delete=function(t){var e=this.__data__,n=e.delete(t);return this.size=e.size,n},kr.prototype.get=function(t){return this.__data__.get(t)},kr.prototype.has=function(t){return this.__data__.has(t)},kr.prototype.set=function(t,e){var n=this.__data__;if(n instanceof xr){var r=n.__data__;if(!er||r.length0&&n(s)?e>1?Xr(s,e-1,n,r,i):rn(i,s):r||(i[i.length]=s)}return i}var Kr=lo(),Jr=lo(!0);function Gr(t,e){return t&&Kr(t,e,au)}function Qr(t,e){return t&&Jr(t,e,au)}function Yr(t,e){return Ze(e,function(e){return $s(t[e])})}function Zr(t,e){for(var n=0,r=(e=Ji(e,t)).length;null!=t&&ne}function ri(t,e){return null!=t&&fe.call(t,e)}function ii(t,e){return null!=t&&e in ne(t)}function oi(t,e,n){for(var i=n?en:tn,a=t[0].length,s=t.length,u=s,c=r(s),l=1/0,f=[];u--;){var p=t[u];u&&e&&(p=nn(p,_n(e))),l=Jn(p.length,l),c[u]=!n&&(e||a>=120&&p.length>=120)?new Tr(u&&p):o}p=t[0];var d=-1,h=c[0];t:for(;++d=s)return u;var c=n[r];return u*("desc"==c?-1:1)}}return t.index-e.index}(t,e,n)})}function wi(t,e,n){for(var r=-1,i=e.length,o={};++r-1;)s!==t&&Re.call(s,u,1),Re.call(t,u,1);return t}function Ci(t,e){for(var n=t?e.length:0,r=n-1;n--;){var i=e[n];if(n==r||i!==o){var o=i;Jo(i)?Re.call(t,i,1):Bi(t,i)}}return t}function Ti(t,e){return t+Hn(Yn()*(e-t+1))}function ki(t,e){var n="";if(!t||e<1||e>I)return n;do{e%2&&(n+=t),(e=Hn(e/2))&&(t+=t)}while(e);return n}function $i(t,e){return sa(ra(t,e,Nu),t+"")}function Ai(t){return Ar(vu(t))}function Si(t,e){var n=vu(t);return la(n,Pr(e,0,n.length))}function Ei(t,e,n,r){if(!Es(t))return t;for(var i=-1,a=(e=Ji(e,t)).length,s=a-1,u=t;null!=u&&++io?0:o+e),(n=n>o?o:n)<0&&(n+=o),o=e>n?0:n-e>>>0,e>>>=0;for(var a=r(o);++i>>1,a=t[o];null!==a&&!Ps(a)&&(n?a<=e:a=a){var l=e?null:$o(t);if(l)return Nn(l);s=!1,i=xn,c=new Tr}else c=e?[]:u;t:for(;++r=r?t:Di(t,e,n)}var Yi=Fn||function(t){return Ie.clearTimeout(t)};function Zi(t,e){if(e)return t.slice();var n=t.length,r=Ee?Ee(n):new t.constructor(n);return t.copy(r),r}function to(t){var e=new t.constructor(t.byteLength);return new Ce(e).set(new Ce(t)),e}function eo(t,e){var n=e?to(t.buffer):t.buffer;return new t.constructor(n,t.byteOffset,t.length)}function no(t,e){if(t!==e){var n=t!==o,r=null===t,i=t==t,a=Ps(t),s=e!==o,u=null===e,c=e==e,l=Ps(e);if(!u&&!l&&!a&&t>e||a&&s&&c&&!u&&!l||r&&s&&c||!n&&c||!i)return 1;if(!r&&!a&&!l&&t1?n[i-1]:o,s=i>2?n[2]:o;for(a=t.length>3&&"function"==typeof a?(i--,a):o,s&&Go(n[0],n[1],s)&&(a=i<3?o:a,i=1),e=ne(e);++r-1?i[a?e[s]:s]:o}}function mo(t){return Do(function(e){var n=e.length,r=n,i=br.prototype.thru;for(t&&e.reverse();r--;){var a=e[r];if("function"!=typeof a)throw new oe(u);if(i&&!s&&"wrapper"==Po(a))var s=new br([],!0)}for(r=s?r:n;++r1&&_.reverse(),p&&lu))return!1;var l=a.get(t);if(l&&a.get(e))return l==e;var f=-1,p=!0,d=n&m?new Tr:o;for(a.set(t,e),a.set(e,t);++f-1&&t%1==0&&t1?"& ":"")+e[r],e=e.join(n>2?", ":" "),t.replace(Ft,"{\n/* [wrapped with "+e+"] */\n")}(r,function(t,e){return Ge(q,function(n){var r="_."+n[0];e&n[1]&&!tn(t,r)&&t.push(r)}),t.sort()}(function(t){var e=t.match(Mt);return e?e[1].split(qt):[]}(r),n)))}function ca(t){var e=0,n=0;return function(){var r=Gn(),i=O-(r-n);if(n=r,i>0){if(++e>=E)return arguments[0]}else e=0;return t.apply(o,arguments)}}function la(t,e){var n=-1,r=t.length,i=r-1;for(e=e===o?r:e;++n1?t[e-1]:o;return Ia(t,n="function"==typeof n?(t.pop(),n):o)});function Ba(t){var e=mr(t);return e.__chain__=!0,e}function Ha(t,e){return e(t)}var Ua=Do(function(t){var e=t.length,n=e?t[0]:0,r=this.__wrapped__,i=function(e){return Rr(e,t)};return!(e>1||this.__actions__.length)&&r instanceof _r&&Jo(n)?((r=r.slice(n,+n+(e?1:0))).__actions__.push({func:Ha,args:[i],thisArg:o}),new br(r,this.__chain__).thru(function(t){return e&&!t.length&&t.push(o),t})):this.thru(i)});var Wa=so(function(t,e,n){fe.call(t,n)?++t[n]:Lr(t,n,1)});var za=vo(ya),Va=vo(ba);function Xa(t,e){return(bs(t)?Ge:Hr)(t,Mo(e,3))}function Ka(t,e){return(bs(t)?Qe:Ur)(t,Mo(e,3))}var Ja=so(function(t,e,n){fe.call(t,n)?t[n].push(e):Lr(t,n,[e])});var Ga=$i(function(t,e,n){var i=-1,o="function"==typeof e,a=ws(t)?r(t.length):[];return Hr(t,function(t){a[++i]=o?Ke(e,t,n):ai(t,e,n)}),a}),Qa=so(function(t,e,n){Lr(t,n,e)});function Ya(t,e){return(bs(t)?nn:vi)(t,Mo(e,3))}var Za=so(function(t,e,n){t[n?0:1].push(e)},function(){return[[],[]]});var ts=$i(function(t,e){if(null==t)return[];var n=e.length;return n>1&&Go(t,e[0],e[1])?e=[]:n>2&&Go(e[0],e[1],e[2])&&(e=[e[0]]),_i(t,Xr(e,1),[])}),es=Mn||function(){return Ie.Date.now()};function ns(t,e,n){return e=n?o:e,e=t&&null==e?t.length:e,So(t,T,o,o,o,o,e)}function rs(t,e){var n;if("function"!=typeof e)throw new oe(u);return t=Us(t),function(){return--t>0&&(n=e.apply(this,arguments)),t<=1&&(e=o),n}}var is=$i(function(t,e,n){var r=g;if(n.length){var i=jn(n,Fo(is));r|=x}return So(t,r,e,n,i)}),os=$i(function(t,e,n){var r=g|y;if(n.length){var i=jn(n,Fo(os));r|=x}return So(e,r,t,n,i)});function as(t,e,n){var r,i,a,s,c,l,f=0,p=!1,d=!1,h=!0;if("function"!=typeof t)throw new oe(u);function v(e){var n=r,a=i;return r=i=o,f=e,s=t.apply(a,n)}function m(t){var n=t-l;return l===o||n>=e||n<0||d&&t-f>=a}function g(){var t=es();if(m(t))return y(t);c=aa(g,function(t){var n=e-(t-l);return d?Jn(n,a-(t-f)):n}(t))}function y(t){return c=o,h&&r?v(t):(r=i=o,s)}function b(){var t=es(),n=m(t);if(r=arguments,i=this,l=t,n){if(c===o)return function(t){return f=t,c=aa(g,e),p?v(t):s}(l);if(d)return c=aa(g,e),v(l)}return c===o&&(c=aa(g,e)),s}return e=zs(e)||0,Es(n)&&(p=!!n.leading,a=(d="maxWait"in n)?Kn(zs(n.maxWait)||0,e):a,h="trailing"in n?!!n.trailing:h),b.cancel=function(){c!==o&&Yi(c),f=0,r=l=i=c=o},b.flush=function(){return c===o?s:y(es())},b}var ss=$i(function(t,e){return qr(t,1,e)}),us=$i(function(t,e,n){return qr(t,zs(e)||0,n)});function cs(t,e){if("function"!=typeof t||null!=e&&"function"!=typeof e)throw new oe(u);var n=function(){var r=arguments,i=e?e.apply(this,r):r[0],o=n.cache;if(o.has(i))return o.get(i);var a=t.apply(this,r);return n.cache=o.set(i,a)||o,a};return n.cache=new(cs.Cache||Cr),n}function ls(t){if("function"!=typeof t)throw new oe(u);return function(){var e=arguments;switch(e.length){case 0:return!t.call(this);case 1:return!t.call(this,e[0]);case 2:return!t.call(this,e[0],e[1]);case 3:return!t.call(this,e[0],e[1],e[2])}return!t.apply(this,e)}}cs.Cache=Cr;var fs=Gi(function(t,e){var n=(e=1==e.length&&bs(e[0])?nn(e[0],_n(Mo())):nn(Xr(e,1),_n(Mo()))).length;return $i(function(r){for(var i=-1,o=Jn(r.length,n);++i=e}),ys=si(function(){return arguments}())?si:function(t){return Os(t)&&fe.call(t,"callee")&&!Le.call(t,"callee")},bs=r.isArray,_s=qe?_n(qe):function(t){return Os(t)&&ei(t)==ut};function ws(t){return null!=t&&Ss(t.length)&&!$s(t)}function xs(t){return Os(t)&&ws(t)}var Cs=Wn||zu,Ts=Be?_n(Be):function(t){return Os(t)&&ei(t)==z};function ks(t){if(!Os(t))return!1;var e=ei(t);return e==X||e==V||"string"==typeof t.message&&"string"==typeof t.name&&!Ds(t)}function $s(t){if(!Es(t))return!1;var e=ei(t);return e==K||e==J||e==U||e==tt}function As(t){return"number"==typeof t&&t==Us(t)}function Ss(t){return"number"==typeof t&&t>-1&&t%1==0&&t<=I}function Es(t){var e=typeof t;return null!=t&&("object"==e||"function"==e)}function Os(t){return null!=t&&"object"==typeof t}var js=He?_n(He):function(t){return Os(t)&&zo(t)==G};function Ns(t){return"number"==typeof t||Os(t)&&ei(t)==Q}function Ds(t){if(!Os(t)||ei(t)!=Z)return!1;var e=Ne(t);if(null===e)return!0;var n=fe.call(e,"constructor")&&e.constructor;return"function"==typeof n&&n instanceof n&&le.call(n)==ve}var Is=Ue?_n(Ue):function(t){return Os(t)&&ei(t)==et};var Ls=We?_n(We):function(t){return Os(t)&&zo(t)==nt};function Rs(t){return"string"==typeof t||!bs(t)&&Os(t)&&ei(t)==rt}function Ps(t){return"symbol"==typeof t||Os(t)&&ei(t)==it}var Fs=ze?_n(ze):function(t){return Os(t)&&Ss(t.length)&&!!Ae[ei(t)]};var Ms=Co(hi),qs=Co(function(t,e){return t<=e});function Bs(t){if(!t)return[];if(ws(t))return Rs(t)?Ln(t):oo(t);if(Me&&t[Me])return function(t){for(var e,n=[];!(e=t.next()).done;)n.push(e.value);return n}(t[Me]());var e=zo(t);return(e==G?En:e==nt?Nn:vu)(t)}function Hs(t){return t?(t=zs(t))===D||t===-D?(t<0?-1:1)*L:t==t?t:0:0===t?t:0}function Us(t){var e=Hs(t),n=e%1;return e==e?n?e-n:e:0}function Ws(t){return t?Pr(Us(t),0,P):0}function zs(t){if("number"==typeof t)return t;if(Ps(t))return R;if(Es(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=Es(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(Lt,"");var n=Vt.test(t);return n||Kt.test(t)?je(t.slice(2),n?2:8):zt.test(t)?R:+t}function Vs(t){return ao(t,su(t))}function Xs(t){return null==t?"":Mi(t)}var Ks=uo(function(t,e){if(ta(e)||ws(e))ao(e,au(e),t);else for(var n in e)fe.call(e,n)&&jr(t,n,e[n])}),Js=uo(function(t,e){ao(e,su(e),t)}),Gs=uo(function(t,e,n,r){ao(e,su(e),t,r)}),Qs=uo(function(t,e,n,r){ao(e,au(e),t,r)}),Ys=Do(Rr);var Zs=$i(function(t){return t.push(o,Eo),Ke(Gs,o,t)}),tu=$i(function(t){return t.push(o,Oo),Ke(cu,o,t)});function eu(t,e,n){var r=null==t?o:Zr(t,e);return r===o?n:r}function nu(t,e){return null!=t&&Vo(t,e,ii)}var ru=yo(function(t,e,n){t[e]=n},Eu(Nu)),iu=yo(function(t,e,n){fe.call(t,e)?t[e].push(n):t[e]=[n]},Mo),ou=$i(ai);function au(t){return ws(t)?$r(t):pi(t)}function su(t){return ws(t)?$r(t,!0):di(t)}var uu=uo(function(t,e,n){yi(t,e,n)}),cu=uo(function(t,e,n,r){yi(t,e,n,r)}),lu=Do(function(t,e){var n={};if(null==t)return n;var r=!1;e=nn(e,function(e){return e=Ji(e,t),r||(r=e.length>1),e}),ao(t,Lo(t),n),r&&(n=Fr(n,p|d|h,jo));for(var i=e.length;i--;)Bi(n,e[i]);return n});var fu=Do(function(t,e){return null==t?{}:function(t,e){return wi(t,e,function(e,n){return nu(t,n)})}(t,e)});function pu(t,e){if(null==t)return{};var n=nn(Lo(t),function(t){return[t]});return e=Mo(e),wi(t,n,function(t,n){return e(t,n[0])})}var du=Ao(au),hu=Ao(su);function vu(t){return null==t?[]:wn(t,au(t))}var mu=po(function(t,e,n){return e=e.toLowerCase(),t+(n?gu(e):e)});function gu(t){return ku(Xs(t).toLowerCase())}function yu(t){return(t=Xs(t))&&t.replace(Gt,kn).replace(_e,"")}var bu=po(function(t,e,n){return t+(n?"-":"")+e.toLowerCase()}),_u=po(function(t,e,n){return t+(n?" ":"")+e.toLowerCase()}),wu=fo("toLowerCase");var xu=po(function(t,e,n){return t+(n?"_":"")+e.toLowerCase()});var Cu=po(function(t,e,n){return t+(n?" ":"")+ku(e)});var Tu=po(function(t,e,n){return t+(n?" ":"")+e.toUpperCase()}),ku=fo("toUpperCase");function $u(t,e,n){return t=Xs(t),(e=n?o:e)===o?function(t){return Te.test(t)}(t)?function(t){return t.match(xe)||[]}(t):function(t){return t.match(Bt)||[]}(t):t.match(e)||[]}var Au=$i(function(t,e){try{return Ke(t,o,e)}catch(t){return ks(t)?t:new Zt(t)}}),Su=Do(function(t,e){return Ge(e,function(e){e=pa(e),Lr(t,e,is(t[e],t))}),t});function Eu(t){return function(){return t}}var Ou=mo(),ju=mo(!0);function Nu(t){return t}function Du(t){return fi("function"==typeof t?t:Fr(t,p))}var Iu=$i(function(t,e){return function(n){return ai(n,t,e)}}),Lu=$i(function(t,e){return function(n){return ai(t,n,e)}});function Ru(t,e,n){var r=au(e),i=Yr(e,r);null!=n||Es(e)&&(i.length||!r.length)||(n=e,e=t,t=this,i=Yr(e,au(e)));var o=!(Es(n)&&"chain"in n&&!n.chain),a=$s(t);return Ge(i,function(n){var r=e[n];t[n]=r,a&&(t.prototype[n]=function(){var e=this.__chain__;if(o||e){var n=t(this.__wrapped__);return(n.__actions__=oo(this.__actions__)).push({func:r,args:arguments,thisArg:t}),n.__chain__=e,n}return r.apply(t,rn([this.value()],arguments))})}),t}function Pu(){}var Fu=_o(nn),Mu=_o(Ye),qu=_o(sn);function Bu(t){return Qo(t)?vn(pa(t)):function(t){return function(e){return Zr(e,t)}}(t)}var Hu=xo(),Uu=xo(!0);function Wu(){return[]}function zu(){return!1}var Vu=bo(function(t,e){return t+e},0),Xu=ko("ceil"),Ku=bo(function(t,e){return t/e},1),Ju=ko("floor");var Gu,Qu=bo(function(t,e){return t*e},1),Yu=ko("round"),Zu=bo(function(t,e){return t-e},0);return mr.after=function(t,e){if("function"!=typeof e)throw new oe(u);return t=Us(t),function(){if(--t<1)return e.apply(this,arguments)}},mr.ary=ns,mr.assign=Ks,mr.assignIn=Js,mr.assignInWith=Gs,mr.assignWith=Qs,mr.at=Ys,mr.before=rs,mr.bind=is,mr.bindAll=Su,mr.bindKey=os,mr.castArray=function(){if(!arguments.length)return[];var t=arguments[0];return bs(t)?t:[t]},mr.chain=Ba,mr.chunk=function(t,e,n){e=(n?Go(t,e,n):e===o)?1:Kn(Us(e),0);var i=null==t?0:t.length;if(!i||e<1)return[];for(var a=0,s=0,u=r(Bn(i/e));ai?0:i+n),(r=r===o||r>i?i:Us(r))<0&&(r+=i),r=n>r?0:Ws(r);n>>0)?(t=Xs(t))&&("string"==typeof e||null!=e&&!Is(e))&&!(e=Mi(e))&&Sn(t)?Qi(Ln(t),0,n):t.split(e,n):[]},mr.spread=function(t,e){if("function"!=typeof t)throw new oe(u);return e=null==e?0:Kn(Us(e),0),$i(function(n){var r=n[e],i=Qi(n,0,e);return r&&rn(i,r),Ke(t,this,i)})},mr.tail=function(t){var e=null==t?0:t.length;return e?Di(t,1,e):[]},mr.take=function(t,e,n){return t&&t.length?Di(t,0,(e=n||e===o?1:Us(e))<0?0:e):[]},mr.takeRight=function(t,e,n){var r=null==t?0:t.length;return r?Di(t,(e=r-(e=n||e===o?1:Us(e)))<0?0:e,r):[]},mr.takeRightWhile=function(t,e){return t&&t.length?Ui(t,Mo(e,3),!1,!0):[]},mr.takeWhile=function(t,e){return t&&t.length?Ui(t,Mo(e,3)):[]},mr.tap=function(t,e){return e(t),t},mr.throttle=function(t,e,n){var r=!0,i=!0;if("function"!=typeof t)throw new oe(u);return Es(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),as(t,e,{leading:r,maxWait:e,trailing:i})},mr.thru=Ha,mr.toArray=Bs,mr.toPairs=du,mr.toPairsIn=hu,mr.toPath=function(t){return bs(t)?nn(t,pa):Ps(t)?[t]:oo(fa(Xs(t)))},mr.toPlainObject=Vs,mr.transform=function(t,e,n){var r=bs(t),i=r||Cs(t)||Fs(t);if(e=Mo(e,4),null==n){var o=t&&t.constructor;n=i?r?new o:[]:Es(t)&&$s(o)?gr(Ne(t)):{}}return(i?Ge:Gr)(t,function(t,r,i){return e(n,t,r,i)}),n},mr.unary=function(t){return ns(t,1)},mr.union=Oa,mr.unionBy=ja,mr.unionWith=Na,mr.uniq=function(t){return t&&t.length?qi(t):[]},mr.uniqBy=function(t,e){return t&&t.length?qi(t,Mo(e,2)):[]},mr.uniqWith=function(t,e){return e="function"==typeof e?e:o,t&&t.length?qi(t,o,e):[]},mr.unset=function(t,e){return null==t||Bi(t,e)},mr.unzip=Da,mr.unzipWith=Ia,mr.update=function(t,e,n){return null==t?t:Hi(t,e,Ki(n))},mr.updateWith=function(t,e,n,r){return r="function"==typeof r?r:o,null==t?t:Hi(t,e,Ki(n),r)},mr.values=vu,mr.valuesIn=function(t){return null==t?[]:wn(t,su(t))},mr.without=La,mr.words=$u,mr.wrap=function(t,e){return ps(Ki(e),t)},mr.xor=Ra,mr.xorBy=Pa,mr.xorWith=Fa,mr.zip=Ma,mr.zipObject=function(t,e){return Vi(t||[],e||[],jr)},mr.zipObjectDeep=function(t,e){return Vi(t||[],e||[],Ei)},mr.zipWith=qa,mr.entries=du,mr.entriesIn=hu,mr.extend=Js,mr.extendWith=Gs,Ru(mr,mr),mr.add=Vu,mr.attempt=Au,mr.camelCase=mu,mr.capitalize=gu,mr.ceil=Xu,mr.clamp=function(t,e,n){return n===o&&(n=e,e=o),n!==o&&(n=(n=zs(n))==n?n:0),e!==o&&(e=(e=zs(e))==e?e:0),Pr(zs(t),e,n)},mr.clone=function(t){return Fr(t,h)},mr.cloneDeep=function(t){return Fr(t,p|h)},mr.cloneDeepWith=function(t,e){return Fr(t,p|h,e="function"==typeof e?e:o)},mr.cloneWith=function(t,e){return Fr(t,h,e="function"==typeof e?e:o)},mr.conformsTo=function(t,e){return null==e||Mr(t,e,au(e))},mr.deburr=yu,mr.defaultTo=function(t,e){return null==t||t!=t?e:t},mr.divide=Ku,mr.endsWith=function(t,e,n){t=Xs(t),e=Mi(e);var r=t.length,i=n=n===o?r:Pr(Us(n),0,r);return(n-=e.length)>=0&&t.slice(n,i)==e},mr.eq=vs,mr.escape=function(t){return(t=Xs(t))&&kt.test(t)?t.replace(Ct,$n):t},mr.escapeRegExp=function(t){return(t=Xs(t))&&It.test(t)?t.replace(Dt,"\\$&"):t},mr.every=function(t,e,n){var r=bs(t)?Ye:Wr;return n&&Go(t,e,n)&&(e=o),r(t,Mo(e,3))},mr.find=za,mr.findIndex=ya,mr.findKey=function(t,e){return cn(t,Mo(e,3),Gr)},mr.findLast=Va,mr.findLastIndex=ba,mr.findLastKey=function(t,e){return cn(t,Mo(e,3),Qr)},mr.floor=Ju,mr.forEach=Xa,mr.forEachRight=Ka,mr.forIn=function(t,e){return null==t?t:Kr(t,Mo(e,3),su)},mr.forInRight=function(t,e){return null==t?t:Jr(t,Mo(e,3),su)},mr.forOwn=function(t,e){return t&&Gr(t,Mo(e,3))},mr.forOwnRight=function(t,e){return t&&Qr(t,Mo(e,3))},mr.get=eu,mr.gt=ms,mr.gte=gs,mr.has=function(t,e){return null!=t&&Vo(t,e,ri)},mr.hasIn=nu,mr.head=wa,mr.identity=Nu,mr.includes=function(t,e,n,r){t=ws(t)?t:vu(t),n=n&&!r?Us(n):0;var i=t.length;return n<0&&(n=Kn(i+n,0)),Rs(t)?n<=i&&t.indexOf(e,n)>-1:!!i&&fn(t,e,n)>-1},mr.indexOf=function(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=null==n?0:Us(n);return i<0&&(i=Kn(r+i,0)),fn(t,e,i)},mr.inRange=function(t,e,n){return e=Hs(e),n===o?(n=e,e=0):n=Hs(n),function(t,e,n){return t>=Jn(e,n)&&t=-I&&t<=I},mr.isSet=Ls,mr.isString=Rs,mr.isSymbol=Ps,mr.isTypedArray=Fs,mr.isUndefined=function(t){return t===o},mr.isWeakMap=function(t){return Os(t)&&zo(t)==at},mr.isWeakSet=function(t){return Os(t)&&ei(t)==st},mr.join=function(t,e){return null==t?"":Vn.call(t,e)},mr.kebabCase=bu,mr.last=ka,mr.lastIndexOf=function(t,e,n){var r=null==t?0:t.length;if(!r)return-1;var i=r;return n!==o&&(i=(i=Us(n))<0?Kn(r+i,0):Jn(i,r-1)),e==e?function(t,e,n){for(var r=n+1;r--;)if(t[r]===e)return r;return r}(t,e,i):ln(t,dn,i,!0)},mr.lowerCase=_u,mr.lowerFirst=wu,mr.lt=Ms,mr.lte=qs,mr.max=function(t){return t&&t.length?zr(t,Nu,ni):o},mr.maxBy=function(t,e){return t&&t.length?zr(t,Mo(e,2),ni):o},mr.mean=function(t){return hn(t,Nu)},mr.meanBy=function(t,e){return hn(t,Mo(e,2))},mr.min=function(t){return t&&t.length?zr(t,Nu,hi):o},mr.minBy=function(t,e){return t&&t.length?zr(t,Mo(e,2),hi):o},mr.stubArray=Wu,mr.stubFalse=zu,mr.stubObject=function(){return{}},mr.stubString=function(){return""},mr.stubTrue=function(){return!0},mr.multiply=Qu,mr.nth=function(t,e){return t&&t.length?bi(t,Us(e)):o},mr.noConflict=function(){return Ie._===this&&(Ie._=me),this},mr.noop=Pu,mr.now=es,mr.pad=function(t,e,n){t=Xs(t);var r=(e=Us(e))?In(t):0;if(!e||r>=e)return t;var i=(e-r)/2;return wo(Hn(i),n)+t+wo(Bn(i),n)},mr.padEnd=function(t,e,n){t=Xs(t);var r=(e=Us(e))?In(t):0;return e&&re){var r=t;t=e,e=r}if(n||t%1||e%1){var i=Yn();return Jn(t+i*(e-t+Oe("1e-"+((i+"").length-1))),e)}return Ti(t,e)},mr.reduce=function(t,e,n){var r=bs(t)?on:gn,i=arguments.length<3;return r(t,Mo(e,4),n,i,Hr)},mr.reduceRight=function(t,e,n){var r=bs(t)?an:gn,i=arguments.length<3;return r(t,Mo(e,4),n,i,Ur)},mr.repeat=function(t,e,n){return e=(n?Go(t,e,n):e===o)?1:Us(e),ki(Xs(t),e)},mr.replace=function(){var t=arguments,e=Xs(t[0]);return t.length<3?e:e.replace(t[1],t[2])},mr.result=function(t,e,n){var r=-1,i=(e=Ji(e,t)).length;for(i||(i=1,t=o);++rI)return[];var n=P,r=Jn(t,P);e=Mo(e),t-=P;for(var i=bn(r,e);++n=a)return t;var u=n-In(r);if(u<1)return r;var c=s?Qi(s,0,u).join(""):t.slice(0,u);if(i===o)return c+r;if(s&&(u+=c.length-u),Is(i)){if(t.slice(u).search(i)){var l,f=c;for(i.global||(i=re(i.source,Xs(Wt.exec(i))+"g")),i.lastIndex=0;l=i.exec(f);)var p=l.index;c=c.slice(0,p===o?u:p)}}else if(t.indexOf(Mi(i),u)!=u){var d=c.lastIndexOf(i);d>-1&&(c=c.slice(0,d))}return c+r},mr.unescape=function(t){return(t=Xs(t))&&Tt.test(t)?t.replace(xt,Rn):t},mr.uniqueId=function(t){var e=++pe;return Xs(t)+e},mr.upperCase=Tu,mr.upperFirst=ku,mr.each=Xa,mr.eachRight=Ka,mr.first=wa,Ru(mr,(Gu={},Gr(mr,function(t,e){fe.call(mr.prototype,e)||(Gu[e]=t)}),Gu),{chain:!1}),mr.VERSION="4.17.4",Ge(["bind","bindKey","curry","curryRight","partial","partialRight"],function(t){mr[t].placeholder=mr}),Ge(["drop","take"],function(t,e){_r.prototype[t]=function(n){n=n===o?1:Kn(Us(n),0);var r=this.__filtered__&&!e?new _r(this):this.clone();return r.__filtered__?r.__takeCount__=Jn(n,r.__takeCount__):r.__views__.push({size:Jn(n,P),type:t+(r.__dir__<0?"Right":"")}),r},_r.prototype[t+"Right"]=function(e){return this.reverse()[t](e).reverse()}}),Ge(["filter","map","takeWhile"],function(t,e){var n=e+1,r=n==j||3==n;_r.prototype[t]=function(t){var e=this.clone();return e.__iteratees__.push({iteratee:Mo(t,3),type:n}),e.__filtered__=e.__filtered__||r,e}}),Ge(["head","last"],function(t,e){var n="take"+(e?"Right":"");_r.prototype[t]=function(){return this[n](1).value()[0]}}),Ge(["initial","tail"],function(t,e){var n="drop"+(e?"":"Right");_r.prototype[t]=function(){return this.__filtered__?new _r(this):this[n](1)}}),_r.prototype.compact=function(){return this.filter(Nu)},_r.prototype.find=function(t){return this.filter(t).head()},_r.prototype.findLast=function(t){return this.reverse().find(t)},_r.prototype.invokeMap=$i(function(t,e){return"function"==typeof t?new _r(this):this.map(function(n){return ai(n,t,e)})}),_r.prototype.reject=function(t){return this.filter(ls(Mo(t)))},_r.prototype.slice=function(t,e){t=Us(t);var n=this;return n.__filtered__&&(t>0||e<0)?new _r(n):(t<0?n=n.takeRight(-t):t&&(n=n.drop(t)),e!==o&&(n=(e=Us(e))<0?n.dropRight(-e):n.take(e-t)),n)},_r.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},_r.prototype.toArray=function(){return this.take(P)},Gr(_r.prototype,function(t,e){var n=/^(?:filter|find|map|reject)|While$/.test(e),r=/^(?:head|last)$/.test(e),i=mr[r?"take"+("last"==e?"Right":""):e],a=r||/^find/.test(e);i&&(mr.prototype[e]=function(){var e=this.__wrapped__,s=r?[1]:arguments,u=e instanceof _r,c=s[0],l=u||bs(e),f=function(t){var e=i.apply(mr,rn([t],s));return r&&p?e[0]:e};l&&n&&"function"==typeof c&&1!=c.length&&(u=l=!1);var p=this.__chain__,d=!!this.__actions__.length,h=a&&!p,v=u&&!d;if(!a&&l){e=v?e:new _r(this);var m=t.apply(e,s);return m.__actions__.push({func:Ha,args:[f],thisArg:o}),new br(m,p)}return h&&v?t.apply(this,s):(m=this.thru(f),h?r?m.value()[0]:m.value():m)})}),Ge(["pop","push","shift","sort","splice","unshift"],function(t){var e=ae[t],n=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",r=/^(?:pop|shift)$/.test(t);mr.prototype[t]=function(){var t=arguments;if(r&&!this.__chain__){var i=this.value();return e.apply(bs(i)?i:[],t)}return this[n](function(n){return e.apply(bs(n)?n:[],t)})}}),Gr(_r.prototype,function(t,e){var n=mr[e];if(n){var r=n.name+"";(sr[r]||(sr[r]=[])).push({name:e,func:n})}}),sr[go(o,y).name]=[{name:"wrapper",func:o}],_r.prototype.clone=function(){var t=new _r(this.__wrapped__);return t.__actions__=oo(this.__actions__),t.__dir__=this.__dir__,t.__filtered__=this.__filtered__,t.__iteratees__=oo(this.__iteratees__),t.__takeCount__=this.__takeCount__,t.__views__=oo(this.__views__),t},_r.prototype.reverse=function(){if(this.__filtered__){var t=new _r(this);t.__dir__=-1,t.__filtered__=!0}else(t=this.clone()).__dir__*=-1;return t},_r.prototype.value=function(){var t=this.__wrapped__.value(),e=this.__dir__,n=bs(t),r=e<0,i=n?t.length:0,o=function(t,e,n){for(var r=-1,i=n.length;++r=this.__values__.length;return{done:t,value:t?o:this.__values__[this.__index__++]}},mr.prototype.plant=function(t){for(var e,n=this;n instanceof yr;){var r=ha(n);r.__index__=0,r.__values__=o,e?i.__wrapped__=r:e=r;var i=r;n=n.__wrapped__}return i.__wrapped__=t,e},mr.prototype.reverse=function(){var t=this.__wrapped__;if(t instanceof _r){var e=t;return this.__actions__.length&&(e=new _r(this)),(e=e.reverse()).__actions__.push({func:Ha,args:[Ea],thisArg:o}),new br(e,this.__chain__)}return this.thru(Ea)},mr.prototype.toJSON=mr.prototype.valueOf=mr.prototype.value=function(){return Wi(this.__wrapped__,this.__actions__)},mr.prototype.first=mr.prototype.head,Me&&(mr.prototype[Me]=function(){return this}),mr}();Ie._=Pn,(i=function(){return Pn}.call(e,n,e,r))===o||(r.exports=i)}).call(this)}).call(e,n(1),n(16)(t))},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,n){var r;!function(e,n){"use strict";"object"==typeof t&&"object"==typeof t.exports?t.exports=e.document?n(e,!0):function(t){if(!t.document)throw new Error("jQuery requires a window with a document");return n(t)}:n(e)}("undefined"!=typeof window?window:this,function(n,i){"use strict";var o=[],a=n.document,s=Object.getPrototypeOf,u=o.slice,c=o.concat,l=o.push,f=o.indexOf,p={},d=p.toString,h=p.hasOwnProperty,v=h.toString,m=v.call(Object),g={},y=function(t){return"function"==typeof t&&"number"!=typeof t.nodeType},b=function(t){return null!=t&&t===t.window},_={type:!0,src:!0,noModule:!0};function w(t,e,n){var r,i=(e=e||a).createElement("script");if(i.text=t,n)for(r in _)n[r]&&(i[r]=n[r]);e.head.appendChild(i).parentNode.removeChild(i)}function x(t){return null==t?t+"":"object"==typeof t||"function"==typeof t?p[d.call(t)]||"object":typeof t}var C=function(t,e){return new C.fn.init(t,e)},T=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function k(t){var e=!!t&&"length"in t&&t.length,n=x(t);return!y(t)&&!b(t)&&("array"===n||0===e||"number"==typeof e&&e>0&&e-1 in t)}C.fn=C.prototype={jquery:"3.3.1",constructor:C,length:0,toArray:function(){return u.call(this)},get:function(t){return null==t?u.call(this):t<0?this[t+this.length]:this[t]},pushStack:function(t){var e=C.merge(this.constructor(),t);return e.prevObject=this,e},each:function(t){return C.each(this,t)},map:function(t){return this.pushStack(C.map(this,function(e,n){return t.call(e,n,e)}))},slice:function(){return this.pushStack(u.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(t){var e=this.length,n=+t+(t<0?e:0);return this.pushStack(n>=0&&n+~]|"+R+")"+R+"*"),W=new RegExp("="+R+"*([^\\]'\"]*?)"+R+"*\\]","g"),z=new RegExp(M),V=new RegExp("^"+P+"$"),X={ID:new RegExp("^#("+P+")"),CLASS:new RegExp("^\\.("+P+")"),TAG:new RegExp("^("+P+"|[*])"),ATTR:new RegExp("^"+F),PSEUDO:new RegExp("^"+M),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+R+"*(even|odd|(([+-]|)(\\d*)n|)"+R+"*(?:([+-]|)"+R+"*(\\d+)|))"+R+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+R+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+R+"*((?:-\\d)?\\d*)"+R+"*\\)|)(?=[^-]|$)","i")},K=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,G=/^[^{]+\{\s*\[native \w/,Q=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Y=/[+~]/,Z=new RegExp("\\\\([\\da-f]{1,6}"+R+"?|("+R+")|.)","ig"),tt=function(t,e,n){var r="0x"+e-65536;return r!=r||n?e:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},et=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,nt=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},rt=function(){p()},it=yt(function(t){return!0===t.disabled&&("form"in t||"label"in t)},{dir:"parentNode",next:"legend"});try{N.apply(E=D.call(w.childNodes),w.childNodes),E[w.childNodes.length].nodeType}catch(t){N={apply:E.length?function(t,e){j.apply(t,D.call(e))}:function(t,e){for(var n=t.length,r=0;t[n++]=e[r++];);t.length=n-1}}}function ot(t,e,r,i){var o,s,c,l,f,h,g,y=e&&e.ownerDocument,x=e?e.nodeType:9;if(r=r||[],"string"!=typeof t||!t||1!==x&&9!==x&&11!==x)return r;if(!i&&((e?e.ownerDocument||e:w)!==d&&p(e),e=e||d,v)){if(11!==x&&(f=Q.exec(t)))if(o=f[1]){if(9===x){if(!(c=e.getElementById(o)))return r;if(c.id===o)return r.push(c),r}else if(y&&(c=y.getElementById(o))&&b(e,c)&&c.id===o)return r.push(c),r}else{if(f[2])return N.apply(r,e.getElementsByTagName(t)),r;if((o=f[3])&&n.getElementsByClassName&&e.getElementsByClassName)return N.apply(r,e.getElementsByClassName(o)),r}if(n.qsa&&!$[t+" "]&&(!m||!m.test(t))){if(1!==x)y=e,g=t;else if("object"!==e.nodeName.toLowerCase()){for((l=e.getAttribute("id"))?l=l.replace(et,nt):e.setAttribute("id",l=_),s=(h=a(t)).length;s--;)h[s]="#"+l+" "+gt(h[s]);g=h.join(","),y=Y.test(t)&&vt(e.parentNode)||e}if(g)try{return N.apply(r,y.querySelectorAll(g)),r}catch(t){}finally{l===_&&e.removeAttribute("id")}}}return u(t.replace(B,"$1"),e,r,i)}function at(){var t=[];return function e(n,i){return t.push(n+" ")>r.cacheLength&&delete e[t.shift()],e[n+" "]=i}}function st(t){return t[_]=!0,t}function ut(t){var e=d.createElement("fieldset");try{return!!t(e)}catch(t){return!1}finally{e.parentNode&&e.parentNode.removeChild(e),e=null}}function ct(t,e){for(var n=t.split("|"),i=n.length;i--;)r.attrHandle[n[i]]=e}function lt(t,e){var n=e&&t,r=n&&1===t.nodeType&&1===e.nodeType&&t.sourceIndex-e.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===e)return-1;return t?1:-1}function ft(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function pt(t){return function(e){var n=e.nodeName.toLowerCase();return("input"===n||"button"===n)&&e.type===t}}function dt(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&it(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ht(t){return st(function(e){return e=+e,st(function(n,r){for(var i,o=t([],n.length,e),a=o.length;a--;)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}function vt(t){return t&&void 0!==t.getElementsByTagName&&t}for(e in n=ot.support={},o=ot.isXML=function(t){var e=t&&(t.ownerDocument||t).documentElement;return!!e&&"HTML"!==e.nodeName},p=ot.setDocument=function(t){var e,i,a=t?t.ownerDocument||t:w;return a!==d&&9===a.nodeType&&a.documentElement?(h=(d=a).documentElement,v=!o(d),w!==d&&(i=d.defaultView)&&i.top!==i&&(i.addEventListener?i.addEventListener("unload",rt,!1):i.attachEvent&&i.attachEvent("onunload",rt)),n.attributes=ut(function(t){return t.className="i",!t.getAttribute("className")}),n.getElementsByTagName=ut(function(t){return t.appendChild(d.createComment("")),!t.getElementsByTagName("*").length}),n.getElementsByClassName=G.test(d.getElementsByClassName),n.getById=ut(function(t){return h.appendChild(t).id=_,!d.getElementsByName||!d.getElementsByName(_).length}),n.getById?(r.filter.ID=function(t){var e=t.replace(Z,tt);return function(t){return t.getAttribute("id")===e}},r.find.ID=function(t,e){if(void 0!==e.getElementById&&v){var n=e.getElementById(t);return n?[n]:[]}}):(r.filter.ID=function(t){var e=t.replace(Z,tt);return function(t){var n=void 0!==t.getAttributeNode&&t.getAttributeNode("id");return n&&n.value===e}},r.find.ID=function(t,e){if(void 0!==e.getElementById&&v){var n,r,i,o=e.getElementById(t);if(o){if((n=o.getAttributeNode("id"))&&n.value===t)return[o];for(i=e.getElementsByName(t),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===t)return[o]}return[]}}),r.find.TAG=n.getElementsByTagName?function(t,e){return void 0!==e.getElementsByTagName?e.getElementsByTagName(t):n.qsa?e.querySelectorAll(t):void 0}:function(t,e){var n,r=[],i=0,o=e.getElementsByTagName(t);if("*"===t){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},r.find.CLASS=n.getElementsByClassName&&function(t,e){if(void 0!==e.getElementsByClassName&&v)return e.getElementsByClassName(t)},g=[],m=[],(n.qsa=G.test(d.querySelectorAll))&&(ut(function(t){h.appendChild(t).innerHTML="",t.querySelectorAll("[msallowcapture^='']").length&&m.push("[*^$]="+R+"*(?:''|\"\")"),t.querySelectorAll("[selected]").length||m.push("\\["+R+"*(?:value|"+L+")"),t.querySelectorAll("[id~="+_+"-]").length||m.push("~="),t.querySelectorAll(":checked").length||m.push(":checked"),t.querySelectorAll("a#"+_+"+*").length||m.push(".#.+[+~]")}),ut(function(t){t.innerHTML="";var e=d.createElement("input");e.setAttribute("type","hidden"),t.appendChild(e).setAttribute("name","D"),t.querySelectorAll("[name=d]").length&&m.push("name"+R+"*[*^$|!~]?="),2!==t.querySelectorAll(":enabled").length&&m.push(":enabled",":disabled"),h.appendChild(t).disabled=!0,2!==t.querySelectorAll(":disabled").length&&m.push(":enabled",":disabled"),t.querySelectorAll("*,:x"),m.push(",.*:")})),(n.matchesSelector=G.test(y=h.matches||h.webkitMatchesSelector||h.mozMatchesSelector||h.oMatchesSelector||h.msMatchesSelector))&&ut(function(t){n.disconnectedMatch=y.call(t,"*"),y.call(t,"[s!='']:x"),g.push("!=",M)}),m=m.length&&new RegExp(m.join("|")),g=g.length&&new RegExp(g.join("|")),e=G.test(h.compareDocumentPosition),b=e||G.test(h.contains)?function(t,e){var n=9===t.nodeType?t.documentElement:t,r=e&&e.parentNode;return t===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):t.compareDocumentPosition&&16&t.compareDocumentPosition(r)))}:function(t,e){if(e)for(;e=e.parentNode;)if(e===t)return!0;return!1},A=e?function(t,e){if(t===e)return f=!0,0;var r=!t.compareDocumentPosition-!e.compareDocumentPosition;return r||(1&(r=(t.ownerDocument||t)===(e.ownerDocument||e)?t.compareDocumentPosition(e):1)||!n.sortDetached&&e.compareDocumentPosition(t)===r?t===d||t.ownerDocument===w&&b(w,t)?-1:e===d||e.ownerDocument===w&&b(w,e)?1:l?I(l,t)-I(l,e):0:4&r?-1:1)}:function(t,e){if(t===e)return f=!0,0;var n,r=0,i=t.parentNode,o=e.parentNode,a=[t],s=[e];if(!i||!o)return t===d?-1:e===d?1:i?-1:o?1:l?I(l,t)-I(l,e):0;if(i===o)return lt(t,e);for(n=t;n=n.parentNode;)a.unshift(n);for(n=e;n=n.parentNode;)s.unshift(n);for(;a[r]===s[r];)r++;return r?lt(a[r],s[r]):a[r]===w?-1:s[r]===w?1:0},d):d},ot.matches=function(t,e){return ot(t,null,null,e)},ot.matchesSelector=function(t,e){if((t.ownerDocument||t)!==d&&p(t),e=e.replace(W,"='$1']"),n.matchesSelector&&v&&!$[e+" "]&&(!g||!g.test(e))&&(!m||!m.test(e)))try{var r=y.call(t,e);if(r||n.disconnectedMatch||t.document&&11!==t.document.nodeType)return r}catch(t){}return ot(e,d,null,[t]).length>0},ot.contains=function(t,e){return(t.ownerDocument||t)!==d&&p(t),b(t,e)},ot.attr=function(t,e){(t.ownerDocument||t)!==d&&p(t);var i=r.attrHandle[e.toLowerCase()],o=i&&S.call(r.attrHandle,e.toLowerCase())?i(t,e,!v):void 0;return void 0!==o?o:n.attributes||!v?t.getAttribute(e):(o=t.getAttributeNode(e))&&o.specified?o.value:null},ot.escape=function(t){return(t+"").replace(et,nt)},ot.error=function(t){throw new Error("Syntax error, unrecognized expression: "+t)},ot.uniqueSort=function(t){var e,r=[],i=0,o=0;if(f=!n.detectDuplicates,l=!n.sortStable&&t.slice(0),t.sort(A),f){for(;e=t[o++];)e===t[o]&&(i=r.push(o));for(;i--;)t.splice(r[i],1)}return l=null,t},i=ot.getText=function(t){var e,n="",r=0,o=t.nodeType;if(o){if(1===o||9===o||11===o){if("string"==typeof t.textContent)return t.textContent;for(t=t.firstChild;t;t=t.nextSibling)n+=i(t)}else if(3===o||4===o)return t.nodeValue}else for(;e=t[r++];)n+=i(e);return n},(r=ot.selectors={cacheLength:50,createPseudo:st,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(t){return t[1]=t[1].replace(Z,tt),t[3]=(t[3]||t[4]||t[5]||"").replace(Z,tt),"~="===t[2]&&(t[3]=" "+t[3]+" "),t.slice(0,4)},CHILD:function(t){return t[1]=t[1].toLowerCase(),"nth"===t[1].slice(0,3)?(t[3]||ot.error(t[0]),t[4]=+(t[4]?t[5]+(t[6]||1):2*("even"===t[3]||"odd"===t[3])),t[5]=+(t[7]+t[8]||"odd"===t[3])):t[3]&&ot.error(t[0]),t},PSEUDO:function(t){var e,n=!t[6]&&t[2];return X.CHILD.test(t[0])?null:(t[3]?t[2]=t[4]||t[5]||"":n&&z.test(n)&&(e=a(n,!0))&&(e=n.indexOf(")",n.length-e)-n.length)&&(t[0]=t[0].slice(0,e),t[2]=n.slice(0,e)),t.slice(0,3))}},filter:{TAG:function(t){var e=t.replace(Z,tt).toLowerCase();return"*"===t?function(){return!0}:function(t){return t.nodeName&&t.nodeName.toLowerCase()===e}},CLASS:function(t){var e=T[t+" "];return e||(e=new RegExp("(^|"+R+")"+t+"("+R+"|$)"))&&T(t,function(t){return e.test("string"==typeof t.className&&t.className||void 0!==t.getAttribute&&t.getAttribute("class")||"")})},ATTR:function(t,e,n){return function(r){var i=ot.attr(r,t);return null==i?"!="===e:!e||(i+="","="===e?i===n:"!="===e?i!==n:"^="===e?n&&0===i.indexOf(n):"*="===e?n&&i.indexOf(n)>-1:"$="===e?n&&i.slice(-n.length)===n:"~="===e?(" "+i.replace(q," ")+" ").indexOf(n)>-1:"|="===e&&(i===n||i.slice(0,n.length+1)===n+"-"))}},CHILD:function(t,e,n,r,i){var o="nth"!==t.slice(0,3),a="last"!==t.slice(-4),s="of-type"===e;return 1===r&&0===i?function(t){return!!t.parentNode}:function(e,n,u){var c,l,f,p,d,h,v=o!==a?"nextSibling":"previousSibling",m=e.parentNode,g=s&&e.nodeName.toLowerCase(),y=!u&&!s,b=!1;if(m){if(o){for(;v;){for(p=e;p=p[v];)if(s?p.nodeName.toLowerCase()===g:1===p.nodeType)return!1;h=v="only"===t&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&y){for(b=(d=(c=(l=(f=(p=m)[_]||(p[_]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]||[])[0]===x&&c[1])&&c[2],p=d&&m.childNodes[d];p=++d&&p&&p[v]||(b=d=0)||h.pop();)if(1===p.nodeType&&++b&&p===e){l[t]=[x,d,b];break}}else if(y&&(b=d=(c=(l=(f=(p=e)[_]||(p[_]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]||[])[0]===x&&c[1]),!1===b)for(;(p=++d&&p&&p[v]||(b=d=0)||h.pop())&&((s?p.nodeName.toLowerCase()!==g:1!==p.nodeType)||!++b||(y&&((l=(f=p[_]||(p[_]={}))[p.uniqueID]||(f[p.uniqueID]={}))[t]=[x,b]),p!==e)););return(b-=i)===r||b%r==0&&b/r>=0}}},PSEUDO:function(t,e){var n,i=r.pseudos[t]||r.setFilters[t.toLowerCase()]||ot.error("unsupported pseudo: "+t);return i[_]?i(e):i.length>1?(n=[t,t,"",e],r.setFilters.hasOwnProperty(t.toLowerCase())?st(function(t,n){for(var r,o=i(t,e),a=o.length;a--;)t[r=I(t,o[a])]=!(n[r]=o[a])}):function(t){return i(t,0,n)}):i}},pseudos:{not:st(function(t){var e=[],n=[],r=s(t.replace(B,"$1"));return r[_]?st(function(t,e,n,i){for(var o,a=r(t,null,i,[]),s=t.length;s--;)(o=a[s])&&(t[s]=!(e[s]=o))}):function(t,i,o){return e[0]=t,r(e,null,o,n),e[0]=null,!n.pop()}}),has:st(function(t){return function(e){return ot(t,e).length>0}}),contains:st(function(t){return t=t.replace(Z,tt),function(e){return(e.textContent||e.innerText||i(e)).indexOf(t)>-1}}),lang:st(function(t){return V.test(t||"")||ot.error("unsupported lang: "+t),t=t.replace(Z,tt).toLowerCase(),function(e){var n;do{if(n=v?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(n=n.toLowerCase())===t||0===n.indexOf(t+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var n=t.location&&t.location.hash;return n&&n.slice(1)===e.id},root:function(t){return t===h},focus:function(t){return t===d.activeElement&&(!d.hasFocus||d.hasFocus())&&!!(t.type||t.href||~t.tabIndex)},enabled:dt(!1),disabled:dt(!0),checked:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&!!t.checked||"option"===e&&!!t.selected},selected:function(t){return t.parentNode&&t.parentNode.selectedIndex,!0===t.selected},empty:function(t){for(t=t.firstChild;t;t=t.nextSibling)if(t.nodeType<6)return!1;return!0},parent:function(t){return!r.pseudos.empty(t)},header:function(t){return J.test(t.nodeName)},input:function(t){return K.test(t.nodeName)},button:function(t){var e=t.nodeName.toLowerCase();return"input"===e&&"button"===t.type||"button"===e},text:function(t){var e;return"input"===t.nodeName.toLowerCase()&&"text"===t.type&&(null==(e=t.getAttribute("type"))||"text"===e.toLowerCase())},first:ht(function(){return[0]}),last:ht(function(t,e){return[e-1]}),eq:ht(function(t,e,n){return[n<0?n+e:n]}),even:ht(function(t,e){for(var n=0;n=0;)t.push(r);return t}),gt:ht(function(t,e,n){for(var r=n<0?n+e:n;++r1?function(e,n,r){for(var i=t.length;i--;)if(!t[i](e,n,r))return!1;return!0}:t[0]}function _t(t,e,n,r,i){for(var o,a=[],s=0,u=t.length,c=null!=e;s-1&&(o[c]=!(a[c]=f))}}else g=_t(g===a?g.splice(h,g.length):g),i?i(null,a,g,u):N.apply(a,g)})}function xt(t){for(var e,n,i,o=t.length,a=r.relative[t[0].type],s=a||r.relative[" "],u=a?1:0,l=yt(function(t){return t===e},s,!0),f=yt(function(t){return I(e,t)>-1},s,!0),p=[function(t,n,r){var i=!a&&(r||n!==c)||((e=n).nodeType?l(t,n,r):f(t,n,r));return e=null,i}];u1&&bt(p),u>1&>(t.slice(0,u-1).concat({value:" "===t[u-2].type?"*":""})).replace(B,"$1"),n,u0,i=t.length>0,o=function(o,a,s,u,l){var f,h,m,g=0,y="0",b=o&&[],_=[],w=c,C=o||i&&r.find.TAG("*",l),T=x+=null==w?1:Math.random()||.1,k=C.length;for(l&&(c=a===d||a||l);y!==k&&null!=(f=C[y]);y++){if(i&&f){for(h=0,a||f.ownerDocument===d||(p(f),s=!v);m=t[h++];)if(m(f,a||d,s)){u.push(f);break}l&&(x=T)}n&&((f=!m&&f)&&g--,o&&b.push(f))}if(g+=y,n&&y!==g){for(h=0;m=e[h++];)m(b,_,a,s);if(o){if(g>0)for(;y--;)b[y]||_[y]||(_[y]=O.call(u));_=_t(_)}N.apply(u,_),l&&!o&&_.length>0&&g+e.length>1&&ot.uniqueSort(u)}return l&&(x=T,c=w),b};return n?st(o):o}(o,i))).selector=t}return s},u=ot.select=function(t,e,n,i){var o,u,c,l,f,p="function"==typeof t&&t,d=!i&&a(t=p.selector||t);if(n=n||[],1===d.length){if((u=d[0]=d[0].slice(0)).length>2&&"ID"===(c=u[0]).type&&9===e.nodeType&&v&&r.relative[u[1].type]){if(!(e=(r.find.ID(c.matches[0].replace(Z,tt),e)||[])[0]))return n;p&&(e=e.parentNode),t=t.slice(u.shift().value.length)}for(o=X.needsContext.test(t)?0:u.length;o--&&(c=u[o],!r.relative[l=c.type]);)if((f=r.find[l])&&(i=f(c.matches[0].replace(Z,tt),Y.test(u[0].type)&&vt(e.parentNode)||e))){if(u.splice(o,1),!(t=i.length&>(u)))return N.apply(n,i),n;break}}return(p||s(t,d))(i,e,!v,n,!e||Y.test(t)&&vt(e.parentNode)||e),n},n.sortStable=_.split("").sort(A).join("")===_,n.detectDuplicates=!!f,p(),n.sortDetached=ut(function(t){return 1&t.compareDocumentPosition(d.createElement("fieldset"))}),ut(function(t){return t.innerHTML="","#"===t.firstChild.getAttribute("href")})||ct("type|href|height|width",function(t,e,n){if(!n)return t.getAttribute(e,"type"===e.toLowerCase()?1:2)}),n.attributes&&ut(function(t){return t.innerHTML="",t.firstChild.setAttribute("value",""),""===t.firstChild.getAttribute("value")})||ct("value",function(t,e,n){if(!n&&"input"===t.nodeName.toLowerCase())return t.defaultValue}),ut(function(t){return null==t.getAttribute("disabled")})||ct(L,function(t,e,n){var r;if(!n)return!0===t[e]?e.toLowerCase():(r=t.getAttributeNode(e))&&r.specified?r.value:null}),ot}(n);C.find=$,C.expr=$.selectors,C.expr[":"]=C.expr.pseudos,C.uniqueSort=C.unique=$.uniqueSort,C.text=$.getText,C.isXMLDoc=$.isXML,C.contains=$.contains,C.escapeSelector=$.escape;var A=function(t,e,n){for(var r=[],i=void 0!==n;(t=t[e])&&9!==t.nodeType;)if(1===t.nodeType){if(i&&C(t).is(n))break;r.push(t)}return r},S=function(t,e){for(var n=[];t;t=t.nextSibling)1===t.nodeType&&t!==e&&n.push(t);return n},E=C.expr.match.needsContext;function O(t,e){return t.nodeName&&t.nodeName.toLowerCase()===e.toLowerCase()}var j=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function N(t,e,n){return y(e)?C.grep(t,function(t,r){return!!e.call(t,r,t)!==n}):e.nodeType?C.grep(t,function(t){return t===e!==n}):"string"!=typeof e?C.grep(t,function(t){return f.call(e,t)>-1!==n}):C.filter(e,t,n)}C.filter=function(t,e,n){var r=e[0];return n&&(t=":not("+t+")"),1===e.length&&1===r.nodeType?C.find.matchesSelector(r,t)?[r]:[]:C.find.matches(t,C.grep(e,function(t){return 1===t.nodeType}))},C.fn.extend({find:function(t){var e,n,r=this.length,i=this;if("string"!=typeof t)return this.pushStack(C(t).filter(function(){for(e=0;e1?C.uniqueSort(n):n},filter:function(t){return this.pushStack(N(this,t||[],!1))},not:function(t){return this.pushStack(N(this,t||[],!0))},is:function(t){return!!N(this,"string"==typeof t&&E.test(t)?C(t):t||[],!1).length}});var D,I=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(C.fn.init=function(t,e,n){var r,i;if(!t)return this;if(n=n||D,"string"==typeof t){if(!(r="<"===t[0]&&">"===t[t.length-1]&&t.length>=3?[null,t,null]:I.exec(t))||!r[1]&&e)return!e||e.jquery?(e||n).find(t):this.constructor(e).find(t);if(r[1]){if(e=e instanceof C?e[0]:e,C.merge(this,C.parseHTML(r[1],e&&e.nodeType?e.ownerDocument||e:a,!0)),j.test(r[1])&&C.isPlainObject(e))for(r in e)y(this[r])?this[r](e[r]):this.attr(r,e[r]);return this}return(i=a.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return t.nodeType?(this[0]=t,this.length=1,this):y(t)?void 0!==n.ready?n.ready(t):t(C):C.makeArray(t,this)}).prototype=C.fn,D=C(a);var L=/^(?:parents|prev(?:Until|All))/,R={children:!0,contents:!0,next:!0,prev:!0};function P(t,e){for(;(t=t[e])&&1!==t.nodeType;);return t}C.fn.extend({has:function(t){var e=C(t,this),n=e.length;return this.filter(function(){for(var t=0;t-1:1===n.nodeType&&C.find.matchesSelector(n,t))){o.push(n);break}return this.pushStack(o.length>1?C.uniqueSort(o):o)},index:function(t){return t?"string"==typeof t?f.call(C(t),this[0]):f.call(this,t.jquery?t[0]:t):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(t,e){return this.pushStack(C.uniqueSort(C.merge(this.get(),C(t,e))))},addBack:function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}}),C.each({parent:function(t){var e=t.parentNode;return e&&11!==e.nodeType?e:null},parents:function(t){return A(t,"parentNode")},parentsUntil:function(t,e,n){return A(t,"parentNode",n)},next:function(t){return P(t,"nextSibling")},prev:function(t){return P(t,"previousSibling")},nextAll:function(t){return A(t,"nextSibling")},prevAll:function(t){return A(t,"previousSibling")},nextUntil:function(t,e,n){return A(t,"nextSibling",n)},prevUntil:function(t,e,n){return A(t,"previousSibling",n)},siblings:function(t){return S((t.parentNode||{}).firstChild,t)},children:function(t){return S(t.firstChild)},contents:function(t){return O(t,"iframe")?t.contentDocument:(O(t,"template")&&(t=t.content||t),C.merge([],t.childNodes))}},function(t,e){C.fn[t]=function(n,r){var i=C.map(this,e,n);return"Until"!==t.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=C.filter(r,i)),this.length>1&&(R[t]||C.uniqueSort(i),L.test(t)&&i.reverse()),this.pushStack(i)}});var F=/[^\x20\t\r\n\f]+/g;function M(t){return t}function q(t){throw t}function B(t,e,n,r){var i;try{t&&y(i=t.promise)?i.call(t).done(e).fail(n):t&&y(i=t.then)?i.call(t,e,n):e.apply(void 0,[t].slice(r))}catch(t){n.apply(void 0,[t])}}C.Callbacks=function(t){t="string"==typeof t?function(t){var e={};return C.each(t.match(F)||[],function(t,n){e[n]=!0}),e}(t):C.extend({},t);var e,n,r,i,o=[],a=[],s=-1,u=function(){for(i=i||t.once,r=e=!0;a.length;s=-1)for(n=a.shift();++s-1;)o.splice(n,1),n<=s&&s--}),this},has:function(t){return t?C.inArray(t,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=a=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=a=[],n||e||(o=n=""),this},locked:function(){return!!i},fireWith:function(t,n){return i||(n=[t,(n=n||[]).slice?n.slice():n],a.push(n),e||u()),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},C.extend({Deferred:function(t){var e=[["notify","progress",C.Callbacks("memory"),C.Callbacks("memory"),2],["resolve","done",C.Callbacks("once memory"),C.Callbacks("once memory"),0,"resolved"],["reject","fail",C.Callbacks("once memory"),C.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},catch:function(t){return i.then(null,t)},pipe:function(){var t=arguments;return C.Deferred(function(n){C.each(e,function(e,r){var i=y(t[r[4]])&&t[r[4]];o[r[1]](function(){var t=i&&i.apply(this,arguments);t&&y(t.promise)?t.promise().progress(n.notify).done(n.resolve).fail(n.reject):n[r[0]+"With"](this,i?[t]:arguments)})}),t=null}).promise()},then:function(t,r,i){var o=0;function a(t,e,r,i){return function(){var s=this,u=arguments,c=function(){var n,c;if(!(t=o&&(r!==q&&(s=void 0,u=[n]),e.rejectWith(s,u))}};t?l():(C.Deferred.getStackHook&&(l.stackTrace=C.Deferred.getStackHook()),n.setTimeout(l))}}return C.Deferred(function(n){e[0][3].add(a(0,n,y(i)?i:M,n.notifyWith)),e[1][3].add(a(0,n,y(t)?t:M)),e[2][3].add(a(0,n,y(r)?r:q))}).promise()},promise:function(t){return null!=t?C.extend(t,i):i}},o={};return C.each(e,function(t,n){var a=n[2],s=n[5];i[n[1]]=a.add,s&&a.add(function(){r=s},e[3-t][2].disable,e[3-t][3].disable,e[0][2].lock,e[0][3].lock),a.add(n[3].fire),o[n[0]]=function(){return o[n[0]+"With"](this===o?void 0:this,arguments),this},o[n[0]+"With"]=a.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(t){var e=arguments.length,n=e,r=Array(n),i=u.call(arguments),o=C.Deferred(),a=function(t){return function(n){r[t]=this,i[t]=arguments.length>1?u.call(arguments):n,--e||o.resolveWith(r,i)}};if(e<=1&&(B(t,o.done(a(n)).resolve,o.reject,!e),"pending"===o.state()||y(i[n]&&i[n].then)))return o.then();for(;n--;)B(i[n],a(n),o.reject);return o.promise()}});var H=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;C.Deferred.exceptionHook=function(t,e){n.console&&n.console.warn&&t&&H.test(t.name)&&n.console.warn("jQuery.Deferred exception: "+t.message,t.stack,e)},C.readyException=function(t){n.setTimeout(function(){throw t})};var U=C.Deferred();function W(){a.removeEventListener("DOMContentLoaded",W),n.removeEventListener("load",W),C.ready()}C.fn.ready=function(t){return U.then(t).catch(function(t){C.readyException(t)}),this},C.extend({isReady:!1,readyWait:1,ready:function(t){(!0===t?--C.readyWait:C.isReady)||(C.isReady=!0,!0!==t&&--C.readyWait>0||U.resolveWith(a,[C]))}}),C.ready.then=U.then,"complete"===a.readyState||"loading"!==a.readyState&&!a.documentElement.doScroll?n.setTimeout(C.ready):(a.addEventListener("DOMContentLoaded",W),n.addEventListener("load",W));var z=function(t,e,n,r,i,o,a){var s=0,u=t.length,c=null==n;if("object"===x(n))for(s in i=!0,n)z(t,e,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,y(r)||(a=!0),c&&(a?(e.call(t,r),e=null):(c=e,e=function(t,e,n){return c.call(C(t),n)})),e))for(;s1,null,!0)},removeData:function(t){return this.each(function(){Z.remove(this,t)})}}),C.extend({queue:function(t,e,n){var r;if(t)return e=(e||"fx")+"queue",r=Y.get(t,e),n&&(!r||Array.isArray(n)?r=Y.access(t,e,C.makeArray(n)):r.push(n)),r||[]},dequeue:function(t,e){e=e||"fx";var n=C.queue(t,e),r=n.length,i=n.shift(),o=C._queueHooks(t,e);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===e&&n.unshift("inprogress"),delete o.stop,i.call(t,function(){C.dequeue(t,e)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(t,e){var n=e+"queueHooks";return Y.get(t,n)||Y.access(t,n,{empty:C.Callbacks("once memory").add(function(){Y.remove(t,[e+"queue",n])})})}}),C.fn.extend({queue:function(t,e){var n=2;return"string"!=typeof t&&(e=t,t="fx",n--),arguments.length\x20\t\r\n\f]+)/i,ht=/^$|^module$|\/(?:java|ecma)script/i,vt={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function mt(t,e){var n;return n=void 0!==t.getElementsByTagName?t.getElementsByTagName(e||"*"):void 0!==t.querySelectorAll?t.querySelectorAll(e||"*"):[],void 0===e||e&&O(t,e)?C.merge([t],n):n}function gt(t,e){for(var n=0,r=t.length;n-1)i&&i.push(o);else if(c=C.contains(o.ownerDocument,o),a=mt(f.appendChild(o),"script"),c&>(a),n)for(l=0;o=a[l++];)ht.test(o.type||"")&&n.push(o);return f}yt=a.createDocumentFragment().appendChild(a.createElement("div")),(bt=a.createElement("input")).setAttribute("type","radio"),bt.setAttribute("checked","checked"),bt.setAttribute("name","t"),yt.appendChild(bt),g.checkClone=yt.cloneNode(!0).cloneNode(!0).lastChild.checked,yt.innerHTML="",g.noCloneChecked=!!yt.cloneNode(!0).lastChild.defaultValue;var xt=a.documentElement,Ct=/^key/,Tt=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,kt=/^([^.]*)(?:\.(.+)|)/;function $t(){return!0}function At(){return!1}function St(){try{return a.activeElement}catch(t){}}function Et(t,e,n,r,i,o){var a,s;if("object"==typeof e){for(s in"string"!=typeof n&&(r=r||n,n=void 0),e)Et(t,s,n,r,e[s],o);return t}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=At;else if(!i)return t;return 1===o&&(a=i,(i=function(t){return C().off(t),a.apply(this,arguments)}).guid=a.guid||(a.guid=C.guid++)),t.each(function(){C.event.add(this,e,i,r,n)})}C.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,c,l,f,p,d,h,v,m=Y.get(t);if(m)for(n.handler&&(n=(o=n).handler,i=o.selector),i&&C.find.matchesSelector(xt,i),n.guid||(n.guid=C.guid++),(u=m.events)||(u=m.events={}),(a=m.handle)||(a=m.handle=function(e){return void 0!==C&&C.event.triggered!==e.type?C.event.dispatch.apply(t,arguments):void 0}),c=(e=(e||"").match(F)||[""]).length;c--;)d=v=(s=kt.exec(e[c])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=C.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=C.event.special[d]||{},l=C.extend({type:d,origType:v,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&C.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,l),l.handler.guid||(l.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,l):p.push(l),C.event.global[d]=!0)},remove:function(t,e,n,r,i){var o,a,s,u,c,l,f,p,d,h,v,m=Y.hasData(t)&&Y.get(t);if(m&&(u=m.events)){for(c=(e=(e||"").match(F)||[""]).length;c--;)if(d=v=(s=kt.exec(e[c])||[])[1],h=(s[2]||"").split(".").sort(),d){for(f=C.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;o--;)l=p[o],!i&&v!==l.origType||n&&n.guid!==l.guid||s&&!s.test(l.namespace)||r&&r!==l.selector&&("**"!==r||!l.selector)||(p.splice(o,1),l.selector&&p.delegateCount--,f.remove&&f.remove.call(t,l));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(t,h,m.handle)||C.removeEvent(t,d,m.handle),delete u[d])}else for(d in u)C.event.remove(t,d+e[c],n,r,!0);C.isEmptyObject(u)&&Y.remove(t,"handle events")}},dispatch:function(t){var e,n,r,i,o,a,s=C.event.fix(t),u=new Array(arguments.length),c=(Y.get(this,"events")||{})[s.type]||[],l=C.event.special[s.type]||{};for(u[0]=s,e=1;e=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==t.type||!0!==c.disabled)){for(o=[],a={},n=0;n-1:C.find(i,this,null,[c]).length),a[i]&&o.push(r);o.length&&s.push({elem:c,handlers:o})}return c=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,jt=/\s*$/g;function It(t,e){return O(t,"table")&&O(11!==e.nodeType?e:e.firstChild,"tr")&&C(t).children("tbody")[0]||t}function Lt(t){return t.type=(null!==t.getAttribute("type"))+"/"+t.type,t}function Rt(t){return"true/"===(t.type||"").slice(0,5)?t.type=t.type.slice(5):t.removeAttribute("type"),t}function Pt(t,e){var n,r,i,o,a,s,u,c;if(1===e.nodeType){if(Y.hasData(t)&&(o=Y.access(t),a=Y.set(e,o),c=o.events))for(i in delete a.handle,a.events={},c)for(n=0,r=c[i].length;n1&&"string"==typeof h&&!g.checkClone&&Nt.test(h))return t.each(function(i){var o=t.eq(i);v&&(e[0]=h.call(this,i,o.html())),Ft(o,e,n,r)});if(p&&(o=(i=wt(e,t[0].ownerDocument,!1,t,r)).firstChild,1===i.childNodes.length&&(i=o),o||r)){for(s=(a=C.map(mt(i,"script"),Lt)).length;f")},clone:function(t,e,n){var r,i,o,a,s,u,c,l=t.cloneNode(!0),f=C.contains(t.ownerDocument,t);if(!(g.noCloneChecked||1!==t.nodeType&&11!==t.nodeType||C.isXMLDoc(t)))for(a=mt(l),r=0,i=(o=mt(t)).length;r0&>(a,!f&&mt(t,"script")),l},cleanData:function(t){for(var e,n,r,i=C.event.special,o=0;void 0!==(n=t[o]);o++)if(G(n)){if(e=n[Y.expando]){if(e.events)for(r in e.events)i[r]?C.event.remove(n,r):C.removeEvent(n,r,e.handle);n[Y.expando]=void 0}n[Z.expando]&&(n[Z.expando]=void 0)}}}),C.fn.extend({detach:function(t){return Mt(this,t,!0)},remove:function(t){return Mt(this,t)},text:function(t){return z(this,function(t){return void 0===t?C.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=t)})},null,t,arguments.length)},append:function(){return Ft(this,arguments,function(t){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||It(this,t).appendChild(t)})},prepend:function(){return Ft(this,arguments,function(t){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var e=It(this,t);e.insertBefore(t,e.firstChild)}})},before:function(){return Ft(this,arguments,function(t){this.parentNode&&this.parentNode.insertBefore(t,this)})},after:function(){return Ft(this,arguments,function(t){this.parentNode&&this.parentNode.insertBefore(t,this.nextSibling)})},empty:function(){for(var t,e=0;null!=(t=this[e]);e++)1===t.nodeType&&(C.cleanData(mt(t,!1)),t.textContent="");return this},clone:function(t,e){return t=null!=t&&t,e=null==e?t:e,this.map(function(){return C.clone(this,t,e)})},html:function(t){return z(this,function(t){var e=this[0]||{},n=0,r=this.length;if(void 0===t&&1===e.nodeType)return e.innerHTML;if("string"==typeof t&&!jt.test(t)&&!vt[(dt.exec(t)||["",""])[1].toLowerCase()]){t=C.htmlPrefilter(t);try{for(;n=0&&(u+=Math.max(0,Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-o-u-s-.5))),u}function te(t,e,n){var r=Bt(t),i=Ut(t,e,r),o="border-box"===C.css(t,"boxSizing",!1,r),a=o;if(qt.test(i)){if(!n)return i;i="auto"}return a=a&&(g.boxSizingReliable()||i===t.style[e]),("auto"===i||!parseFloat(i)&&"inline"===C.css(t,"display",!1,r))&&(i=t["offset"+e[0].toUpperCase()+e.slice(1)],a=!0),(i=parseFloat(i)||0)+Zt(t,e,n||(o?"border":"content"),a,r,i)+"px"}function ee(t,e,n,r,i){return new ee.prototype.init(t,e,n,r,i)}C.extend({cssHooks:{opacity:{get:function(t,e){if(e){var n=Ut(t,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(t,e,n,r){if(t&&3!==t.nodeType&&8!==t.nodeType&&t.style){var i,o,a,s=J(e),u=Vt.test(e),c=t.style;if(u||(e=Qt(s)),a=C.cssHooks[e]||C.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(t,!1,r))?i:c[e];"string"===(o=typeof n)&&(i=it.exec(n))&&i[1]&&(n=ut(t,e,i),o="number"),null!=n&&n==n&&("number"===o&&(n+=i&&i[3]||(C.cssNumber[s]?"":"px")),g.clearCloneStyle||""!==n||0!==e.indexOf("background")||(c[e]="inherit"),a&&"set"in a&&void 0===(n=a.set(t,n,r))||(u?c.setProperty(e,n):c[e]=n))}},css:function(t,e,n,r){var i,o,a,s=J(e);return Vt.test(e)||(e=Qt(s)),(a=C.cssHooks[e]||C.cssHooks[s])&&"get"in a&&(i=a.get(t,!0,n)),void 0===i&&(i=Ut(t,e,r)),"normal"===i&&e in Kt&&(i=Kt[e]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),C.each(["height","width"],function(t,e){C.cssHooks[e]={get:function(t,n,r){if(n)return!zt.test(C.css(t,"display"))||t.getClientRects().length&&t.getBoundingClientRect().width?te(t,e,r):st(t,Xt,function(){return te(t,e,r)})},set:function(t,n,r){var i,o=Bt(t),a="border-box"===C.css(t,"boxSizing",!1,o),s=r&&Zt(t,e,r,a,o);return a&&g.scrollboxSize()===o.position&&(s-=Math.ceil(t["offset"+e[0].toUpperCase()+e.slice(1)]-parseFloat(o[e])-Zt(t,e,"border",!1,o)-.5)),s&&(i=it.exec(n))&&"px"!==(i[3]||"px")&&(t.style[e]=n,n=C.css(t,e)),Yt(0,n,s)}}}),C.cssHooks.marginLeft=Wt(g.reliableMarginLeft,function(t,e){if(e)return(parseFloat(Ut(t,"marginLeft"))||t.getBoundingClientRect().left-st(t,{marginLeft:0},function(){return t.getBoundingClientRect().left}))+"px"}),C.each({margin:"",padding:"",border:"Width"},function(t,e){C.cssHooks[t+e]={expand:function(n){for(var r=0,i={},o="string"==typeof n?n.split(" "):[n];r<4;r++)i[t+ot[r]+e]=o[r]||o[r-2]||o[0];return i}},"margin"!==t&&(C.cssHooks[t+e].set=Yt)}),C.fn.extend({css:function(t,e){return z(this,function(t,e,n){var r,i,o={},a=0;if(Array.isArray(e)){for(r=Bt(t),i=e.length;a1)}}),C.Tween=ee,ee.prototype={constructor:ee,init:function(t,e,n,r,i,o){this.elem=t,this.prop=n,this.easing=i||C.easing._default,this.options=e,this.start=this.now=this.cur(),this.end=r,this.unit=o||(C.cssNumber[n]?"":"px")},cur:function(){var t=ee.propHooks[this.prop];return t&&t.get?t.get(this):ee.propHooks._default.get(this)},run:function(t){var e,n=ee.propHooks[this.prop];return this.options.duration?this.pos=e=C.easing[this.easing](t,this.options.duration*t,0,1,this.options.duration):this.pos=e=t,this.now=(this.end-this.start)*e+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):ee.propHooks._default.set(this),this}},ee.prototype.init.prototype=ee.prototype,ee.propHooks={_default:{get:function(t){var e;return 1!==t.elem.nodeType||null!=t.elem[t.prop]&&null==t.elem.style[t.prop]?t.elem[t.prop]:(e=C.css(t.elem,t.prop,""))&&"auto"!==e?e:0},set:function(t){C.fx.step[t.prop]?C.fx.step[t.prop](t):1!==t.elem.nodeType||null==t.elem.style[C.cssProps[t.prop]]&&!C.cssHooks[t.prop]?t.elem[t.prop]=t.now:C.style(t.elem,t.prop,t.now+t.unit)}}},ee.propHooks.scrollTop=ee.propHooks.scrollLeft={set:function(t){t.elem.nodeType&&t.elem.parentNode&&(t.elem[t.prop]=t.now)}},C.easing={linear:function(t){return t},swing:function(t){return.5-Math.cos(t*Math.PI)/2},_default:"swing"},C.fx=ee.prototype.init,C.fx.step={};var ne,re,ie=/^(?:toggle|show|hide)$/,oe=/queueHooks$/;function ae(){re&&(!1===a.hidden&&n.requestAnimationFrame?n.requestAnimationFrame(ae):n.setTimeout(ae,C.fx.interval),C.fx.tick())}function se(){return n.setTimeout(function(){ne=void 0}),ne=Date.now()}function ue(t,e){var n,r=0,i={height:t};for(e=e?1:0;r<4;r+=2-e)i["margin"+(n=ot[r])]=i["padding"+n]=t;return e&&(i.opacity=i.width=t),i}function ce(t,e,n){for(var r,i=(le.tweeners[e]||[]).concat(le.tweeners["*"]),o=0,a=i.length;o1)},removeAttr:function(t){return this.each(function(){C.removeAttr(this,t)})}}),C.extend({attr:function(t,e,n){var r,i,o=t.nodeType;if(3!==o&&8!==o&&2!==o)return void 0===t.getAttribute?C.prop(t,e,n):(1===o&&C.isXMLDoc(t)||(i=C.attrHooks[e.toLowerCase()]||(C.expr.match.bool.test(e)?fe:void 0)),void 0!==n?null===n?void C.removeAttr(t,e):i&&"set"in i&&void 0!==(r=i.set(t,n,e))?r:(t.setAttribute(e,n+""),n):i&&"get"in i&&null!==(r=i.get(t,e))?r:null==(r=C.find.attr(t,e))?void 0:r)},attrHooks:{type:{set:function(t,e){if(!g.radioValue&&"radio"===e&&O(t,"input")){var n=t.value;return t.setAttribute("type",e),n&&(t.value=n),e}}}},removeAttr:function(t,e){var n,r=0,i=e&&e.match(F);if(i&&1===t.nodeType)for(;n=i[r++];)t.removeAttribute(n)}}),fe={set:function(t,e,n){return!1===e?C.removeAttr(t,n):t.setAttribute(n,n),n}},C.each(C.expr.match.bool.source.match(/\w+/g),function(t,e){var n=pe[e]||C.find.attr;pe[e]=function(t,e,r){var i,o,a=e.toLowerCase();return r||(o=pe[a],pe[a]=i,i=null!=n(t,e,r)?a:null,pe[a]=o),i}});var de=/^(?:input|select|textarea|button)$/i,he=/^(?:a|area)$/i;function ve(t){return(t.match(F)||[]).join(" ")}function me(t){return t.getAttribute&&t.getAttribute("class")||""}function ge(t){return Array.isArray(t)?t:"string"==typeof t&&t.match(F)||[]}C.fn.extend({prop:function(t,e){return z(this,C.prop,t,e,arguments.length>1)},removeProp:function(t){return this.each(function(){delete this[C.propFix[t]||t]})}}),C.extend({prop:function(t,e,n){var r,i,o=t.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&C.isXMLDoc(t)||(e=C.propFix[e]||e,i=C.propHooks[e]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(t,n,e))?r:t[e]=n:i&&"get"in i&&null!==(r=i.get(t,e))?r:t[e]},propHooks:{tabIndex:{get:function(t){var e=C.find.attr(t,"tabindex");return e?parseInt(e,10):de.test(t.nodeName)||he.test(t.nodeName)&&t.href?0:-1}}},propFix:{for:"htmlFor",class:"className"}}),g.optSelected||(C.propHooks.selected={get:function(t){var e=t.parentNode;return e&&e.parentNode&&e.parentNode.selectedIndex,null},set:function(t){var e=t.parentNode;e&&(e.selectedIndex,e.parentNode&&e.parentNode.selectedIndex)}}),C.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){C.propFix[this.toLowerCase()]=this}),C.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(y(t))return this.each(function(e){C(this).addClass(t.call(this,e,me(this)))});if((e=ge(t)).length)for(;n=this[u++];)if(i=me(n),r=1===n.nodeType&&" "+ve(i)+" "){for(a=0;o=e[a++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=ve(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(y(t))return this.each(function(e){C(this).removeClass(t.call(this,e,me(this)))});if(!arguments.length)return this.attr("class","");if((e=ge(t)).length)for(;n=this[u++];)if(i=me(n),r=1===n.nodeType&&" "+ve(i)+" "){for(a=0;o=e[a++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");i!==(s=ve(r))&&n.setAttribute("class",s)}return this},toggleClass:function(t,e){var n=typeof t,r="string"===n||Array.isArray(t);return"boolean"==typeof e&&r?e?this.addClass(t):this.removeClass(t):y(t)?this.each(function(n){C(this).toggleClass(t.call(this,n,me(this),e),e)}):this.each(function(){var e,i,o,a;if(r)for(i=0,o=C(this),a=ge(t);e=a[i++];)o.hasClass(e)?o.removeClass(e):o.addClass(e);else void 0!==t&&"boolean"!==n||((e=me(this))&&Y.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===t?"":Y.get(this,"__className__")||""))})},hasClass:function(t){var e,n,r=0;for(e=" "+t+" ";n=this[r++];)if(1===n.nodeType&&(" "+ve(me(n))+" ").indexOf(e)>-1)return!0;return!1}});var ye=/\r/g;C.fn.extend({val:function(t){var e,n,r,i=this[0];return arguments.length?(r=y(t),this.each(function(n){var i;1===this.nodeType&&(null==(i=r?t.call(this,n,C(this).val()):t)?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=C.map(i,function(t){return null==t?"":t+""})),(e=C.valHooks[this.type]||C.valHooks[this.nodeName.toLowerCase()])&&"set"in e&&void 0!==e.set(this,i,"value")||(this.value=i))})):i?(e=C.valHooks[i.type]||C.valHooks[i.nodeName.toLowerCase()])&&"get"in e&&void 0!==(n=e.get(i,"value"))?n:"string"==typeof(n=i.value)?n.replace(ye,""):null==n?"":n:void 0}}),C.extend({valHooks:{option:{get:function(t){var e=C.find.attr(t,"value");return null!=e?e:ve(C.text(t))}},select:{get:function(t){var e,n,r,i=t.options,o=t.selectedIndex,a="select-one"===t.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r-1)&&(n=!0);return n||(t.selectedIndex=-1),o}}}}),C.each(["radio","checkbox"],function(){C.valHooks[this]={set:function(t,e){if(Array.isArray(e))return t.checked=C.inArray(C(t).val(),e)>-1}},g.checkOn||(C.valHooks[this].get=function(t){return null===t.getAttribute("value")?"on":t.value})}),g.focusin="onfocusin"in n;var be=/^(?:focusinfocus|focusoutblur)$/,_e=function(t){t.stopPropagation()};C.extend(C.event,{trigger:function(t,e,r,i){var o,s,u,c,l,f,p,d,v=[r||a],m=h.call(t,"type")?t.type:t,g=h.call(t,"namespace")?t.namespace.split("."):[];if(s=d=u=r=r||a,3!==r.nodeType&&8!==r.nodeType&&!be.test(m+C.event.triggered)&&(m.indexOf(".")>-1&&(m=(g=m.split(".")).shift(),g.sort()),l=m.indexOf(":")<0&&"on"+m,(t=t[C.expando]?t:new C.Event(m,"object"==typeof t&&t)).isTrigger=i?2:3,t.namespace=g.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=void 0,t.target||(t.target=r),e=null==e?[t]:C.makeArray(e,[t]),p=C.event.special[m]||{},i||!p.trigger||!1!==p.trigger.apply(r,e))){if(!i&&!p.noBubble&&!b(r)){for(c=p.delegateType||m,be.test(c+m)||(s=s.parentNode);s;s=s.parentNode)v.push(s),u=s;u===(r.ownerDocument||a)&&v.push(u.defaultView||u.parentWindow||n)}for(o=0;(s=v[o++])&&!t.isPropagationStopped();)d=s,t.type=o>1?c:p.bindType||m,(f=(Y.get(s,"events")||{})[t.type]&&Y.get(s,"handle"))&&f.apply(s,e),(f=l&&s[l])&&f.apply&&G(s)&&(t.result=f.apply(s,e),!1===t.result&&t.preventDefault());return t.type=m,i||t.isDefaultPrevented()||p._default&&!1!==p._default.apply(v.pop(),e)||!G(r)||l&&y(r[m])&&!b(r)&&((u=r[l])&&(r[l]=null),C.event.triggered=m,t.isPropagationStopped()&&d.addEventListener(m,_e),r[m](),t.isPropagationStopped()&&d.removeEventListener(m,_e),C.event.triggered=void 0,u&&(r[l]=u)),t.result}},simulate:function(t,e,n){var r=C.extend(new C.Event,n,{type:t,isSimulated:!0});C.event.trigger(r,null,e)}}),C.fn.extend({trigger:function(t,e){return this.each(function(){C.event.trigger(t,e,this)})},triggerHandler:function(t,e){var n=this[0];if(n)return C.event.trigger(t,e,n,!0)}}),g.focusin||C.each({focus:"focusin",blur:"focusout"},function(t,e){var n=function(t){C.event.simulate(e,t.target,C.event.fix(t))};C.event.special[e]={setup:function(){var r=this.ownerDocument||this,i=Y.access(r,e);i||r.addEventListener(t,n,!0),Y.access(r,e,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=Y.access(r,e)-1;i?Y.access(r,e,i):(r.removeEventListener(t,n,!0),Y.remove(r,e))}}});var we=n.location,xe=Date.now(),Ce=/\?/;C.parseXML=function(t){var e;if(!t||"string"!=typeof t)return null;try{e=(new n.DOMParser).parseFromString(t,"text/xml")}catch(t){e=void 0}return e&&!e.getElementsByTagName("parsererror").length||C.error("Invalid XML: "+t),e};var Te=/\[\]$/,ke=/\r?\n/g,$e=/^(?:submit|button|image|reset|file)$/i,Ae=/^(?:input|select|textarea|keygen)/i;function Se(t,e,n,r){var i;if(Array.isArray(e))C.each(e,function(e,i){n||Te.test(t)?r(t,i):Se(t+"["+("object"==typeof i&&null!=i?e:"")+"]",i,n,r)});else if(n||"object"!==x(e))r(t,e);else for(i in e)Se(t+"["+i+"]",e[i],n,r)}C.param=function(t,e){var n,r=[],i=function(t,e){var n=y(e)?e():e;r[r.length]=encodeURIComponent(t)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(t)||t.jquery&&!C.isPlainObject(t))C.each(t,function(){i(this.name,this.value)});else for(n in t)Se(n,t[n],e,i);return r.join("&")},C.fn.extend({serialize:function(){return C.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var t=C.prop(this,"elements");return t?C.makeArray(t):this}).filter(function(){var t=this.type;return this.name&&!C(this).is(":disabled")&&Ae.test(this.nodeName)&&!$e.test(t)&&(this.checked||!pt.test(t))}).map(function(t,e){var n=C(this).val();return null==n?null:Array.isArray(n)?C.map(n,function(t){return{name:e.name,value:t.replace(ke,"\r\n")}}):{name:e.name,value:n.replace(ke,"\r\n")}}).get()}});var Ee=/%20/g,Oe=/#.*$/,je=/([?&])_=[^&]*/,Ne=/^(.*?):[ \t]*([^\r\n]*)$/gm,De=/^(?:GET|HEAD)$/,Ie=/^\/\//,Le={},Re={},Pe="*/".concat("*"),Fe=a.createElement("a");function Me(t){return function(e,n){"string"!=typeof e&&(n=e,e="*");var r,i=0,o=e.toLowerCase().match(F)||[];if(y(n))for(;r=o[i++];)"+"===r[0]?(r=r.slice(1)||"*",(t[r]=t[r]||[]).unshift(n)):(t[r]=t[r]||[]).push(n)}}function qe(t,e,n,r){var i={},o=t===Re;function a(s){var u;return i[s]=!0,C.each(t[s]||[],function(t,s){var c=s(e,n,r);return"string"!=typeof c||o||i[c]?o?!(u=c):void 0:(e.dataTypes.unshift(c),a(c),!1)}),u}return a(e.dataTypes[0])||!i["*"]&&a("*")}function Be(t,e){var n,r,i=C.ajaxSettings.flatOptions||{};for(n in e)void 0!==e[n]&&((i[n]?t:r||(r={}))[n]=e[n]);return r&&C.extend(!0,t,r),t}Fe.href=we.href,C.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:we.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(we.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Pe,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":C.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(t,e){return e?Be(Be(t,C.ajaxSettings),e):Be(C.ajaxSettings,t)},ajaxPrefilter:Me(Le),ajaxTransport:Me(Re),ajax:function(t,e){"object"==typeof t&&(e=t,t=void 0),e=e||{};var r,i,o,s,u,c,l,f,p,d,h=C.ajaxSetup({},e),v=h.context||h,m=h.context&&(v.nodeType||v.jquery)?C(v):C.event,g=C.Deferred(),y=C.Callbacks("once memory"),b=h.statusCode||{},_={},w={},x="canceled",T={readyState:0,getResponseHeader:function(t){var e;if(l){if(!s)for(s={};e=Ne.exec(o);)s[e[1].toLowerCase()]=e[2];e=s[t.toLowerCase()]}return null==e?null:e},getAllResponseHeaders:function(){return l?o:null},setRequestHeader:function(t,e){return null==l&&(t=w[t.toLowerCase()]=w[t.toLowerCase()]||t,_[t]=e),this},overrideMimeType:function(t){return null==l&&(h.mimeType=t),this},statusCode:function(t){var e;if(t)if(l)T.always(t[T.status]);else for(e in t)b[e]=[b[e],t[e]];return this},abort:function(t){var e=t||x;return r&&r.abort(e),k(0,e),this}};if(g.promise(T),h.url=((t||h.url||we.href)+"").replace(Ie,we.protocol+"//"),h.type=e.method||e.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(F)||[""],null==h.crossDomain){c=a.createElement("a");try{c.href=h.url,c.href=c.href,h.crossDomain=Fe.protocol+"//"+Fe.host!=c.protocol+"//"+c.host}catch(t){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=C.param(h.data,h.traditional)),qe(Le,h,e,T),l)return T;for(p in(f=C.event&&h.global)&&0==C.active++&&C.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!De.test(h.type),i=h.url.replace(Oe,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(Ee,"+")):(d=h.url.slice(i.length),h.data&&(h.processData||"string"==typeof h.data)&&(i+=(Ce.test(i)?"&":"?")+h.data,delete h.data),!1===h.cache&&(i=i.replace(je,"$1"),d=(Ce.test(i)?"&":"?")+"_="+xe+++d),h.url=i+d),h.ifModified&&(C.lastModified[i]&&T.setRequestHeader("If-Modified-Since",C.lastModified[i]),C.etag[i]&&T.setRequestHeader("If-None-Match",C.etag[i])),(h.data&&h.hasContent&&!1!==h.contentType||e.contentType)&&T.setRequestHeader("Content-Type",h.contentType),T.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+Pe+"; q=0.01":""):h.accepts["*"]),h.headers)T.setRequestHeader(p,h.headers[p]);if(h.beforeSend&&(!1===h.beforeSend.call(v,T,h)||l))return T.abort();if(x="abort",y.add(h.complete),T.done(h.success),T.fail(h.error),r=qe(Re,h,e,T)){if(T.readyState=1,f&&m.trigger("ajaxSend",[T,h]),l)return T;h.async&&h.timeout>0&&(u=n.setTimeout(function(){T.abort("timeout")},h.timeout));try{l=!1,r.send(_,k)}catch(t){if(l)throw t;k(-1,t)}}else k(-1,"No Transport");function k(t,e,a,s){var c,p,d,_,w,x=e;l||(l=!0,u&&n.clearTimeout(u),r=void 0,o=s||"",T.readyState=t>0?4:0,c=t>=200&&t<300||304===t,a&&(_=function(t,e,n){for(var r,i,o,a,s=t.contents,u=t.dataTypes;"*"===u[0];)u.shift(),void 0===r&&(r=t.mimeType||e.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||t.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(h,T,a)),_=function(t,e,n,r){var i,o,a,s,u,c={},l=t.dataTypes.slice();if(l[1])for(a in t.converters)c[a.toLowerCase()]=t.converters[a];for(o=l.shift();o;)if(t.responseFields[o]&&(n[t.responseFields[o]]=e),!u&&r&&t.dataFilter&&(e=t.dataFilter(e,t.dataType)),u=o,o=l.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=c[u+" "+o]||c["* "+o]))for(i in c)if((s=i.split(" "))[1]===o&&(a=c[u+" "+s[0]]||c["* "+s[0]])){!0===a?a=c[i]:!0!==c[i]&&(o=s[0],l.unshift(s[1]));break}if(!0!==a)if(a&&t.throws)e=a(e);else try{e=a(e)}catch(t){return{state:"parsererror",error:a?t:"No conversion from "+u+" to "+o}}}return{state:"success",data:e}}(h,_,T,c),c?(h.ifModified&&((w=T.getResponseHeader("Last-Modified"))&&(C.lastModified[i]=w),(w=T.getResponseHeader("etag"))&&(C.etag[i]=w)),204===t||"HEAD"===h.type?x="nocontent":304===t?x="notmodified":(x=_.state,p=_.data,c=!(d=_.error))):(d=x,!t&&x||(x="error",t<0&&(t=0))),T.status=t,T.statusText=(e||x)+"",c?g.resolveWith(v,[p,x,T]):g.rejectWith(v,[T,x,d]),T.statusCode(b),b=void 0,f&&m.trigger(c?"ajaxSuccess":"ajaxError",[T,h,c?p:d]),y.fireWith(v,[T,x]),f&&(m.trigger("ajaxComplete",[T,h]),--C.active||C.event.trigger("ajaxStop")))}return T},getJSON:function(t,e,n){return C.get(t,e,n,"json")},getScript:function(t,e){return C.get(t,void 0,e,"script")}}),C.each(["get","post"],function(t,e){C[e]=function(t,n,r,i){return y(n)&&(i=i||r,r=n,n=void 0),C.ajax(C.extend({url:t,type:e,dataType:i,data:n,success:r},C.isPlainObject(t)&&t))}}),C._evalUrl=function(t){return C.ajax({url:t,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,throws:!0})},C.fn.extend({wrapAll:function(t){var e;return this[0]&&(y(t)&&(t=t.call(this[0])),e=C(t,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&e.insertBefore(this[0]),e.map(function(){for(var t=this;t.firstElementChild;)t=t.firstElementChild;return t}).append(this)),this},wrapInner:function(t){return y(t)?this.each(function(e){C(this).wrapInner(t.call(this,e))}):this.each(function(){var e=C(this),n=e.contents();n.length?n.wrapAll(t):e.append(t)})},wrap:function(t){var e=y(t);return this.each(function(n){C(this).wrapAll(e?t.call(this,n):t)})},unwrap:function(t){return this.parent(t).not("body").each(function(){C(this).replaceWith(this.childNodes)}),this}}),C.expr.pseudos.hidden=function(t){return!C.expr.pseudos.visible(t)},C.expr.pseudos.visible=function(t){return!!(t.offsetWidth||t.offsetHeight||t.getClientRects().length)},C.ajaxSettings.xhr=function(){try{return new n.XMLHttpRequest}catch(t){}};var He={0:200,1223:204},Ue=C.ajaxSettings.xhr();g.cors=!!Ue&&"withCredentials"in Ue,g.ajax=Ue=!!Ue,C.ajaxTransport(function(t){var e,r;if(g.cors||Ue&&!t.crossDomain)return{send:function(i,o){var a,s=t.xhr();if(s.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(a in t.xhrFields)s[a]=t.xhrFields[a];for(a in t.mimeType&&s.overrideMimeType&&s.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest"),i)s.setRequestHeader(a,i[a]);e=function(t){return function(){e&&(e=r=s.onload=s.onerror=s.onabort=s.ontimeout=s.onreadystatechange=null,"abort"===t?s.abort():"error"===t?"number"!=typeof s.status?o(0,"error"):o(s.status,s.statusText):o(He[s.status]||s.status,s.statusText,"text"!==(s.responseType||"text")||"string"!=typeof s.responseText?{binary:s.response}:{text:s.responseText},s.getAllResponseHeaders()))}},s.onload=e(),r=s.onerror=s.ontimeout=e("error"),void 0!==s.onabort?s.onabort=r:s.onreadystatechange=function(){4===s.readyState&&n.setTimeout(function(){e&&r()})},e=e("abort");try{s.send(t.hasContent&&t.data||null)}catch(t){if(e)throw t}},abort:function(){e&&e()}}}),C.ajaxPrefilter(function(t){t.crossDomain&&(t.contents.script=!1)}),C.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(t){return C.globalEval(t),t}}}),C.ajaxPrefilter("script",function(t){void 0===t.cache&&(t.cache=!1),t.crossDomain&&(t.type="GET")}),C.ajaxTransport("script",function(t){var e,n;if(t.crossDomain)return{send:function(r,i){e=C(" diff --git a/resources/assets/js/components/bills/Index.vue b/resources/assets/js/components/bills/Index.vue new file mode 100644 index 0000000000..fd09b9396d --- /dev/null +++ b/resources/assets/js/components/bills/Index.vue @@ -0,0 +1,138 @@ + + + + diff --git a/resources/assets/js/components/passport/AuthorizedClients.vue b/resources/assets/js/components/passport/AuthorizedClients.vue new file mode 100644 index 0000000000..ca4f03d0a0 --- /dev/null +++ b/resources/assets/js/components/passport/AuthorizedClients.vue @@ -0,0 +1,114 @@ + + + + + diff --git a/resources/assets/js/components/passport/Clients.vue b/resources/assets/js/components/passport/Clients.vue new file mode 100644 index 0000000000..70aaccf50a --- /dev/null +++ b/resources/assets/js/components/passport/Clients.vue @@ -0,0 +1,353 @@ + + + + + diff --git a/resources/assets/js/components/passport/PersonalAccessTokens.vue b/resources/assets/js/components/passport/PersonalAccessTokens.vue new file mode 100644 index 0000000000..fa7d8e0668 --- /dev/null +++ b/resources/assets/js/components/passport/PersonalAccessTokens.vue @@ -0,0 +1,300 @@ + + + + + diff --git a/resources/assets/js/lang.js b/resources/assets/js/lang.js new file mode 100644 index 0000000000..fca5bd28c0 --- /dev/null +++ b/resources/assets/js/lang.js @@ -0,0 +1,30 @@ +/* + * lang.js + * Copyright (c) 2018 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 . + */ + +// Inside my /resources/assets/js/lang.js +import lang from 'lang.js'; +import messages from './messages'; + +const Lang = new lang({messages}); + +Lang.setLocale(window.language); +Lang.setFallback('en_US'); + +export default Lang; \ No newline at end of file diff --git a/resources/assets/js/messages.js b/resources/assets/js/messages.js new file mode 100644 index 0000000000..d8c4ad68ad --- /dev/null +++ b/resources/assets/js/messages.js @@ -0,0 +1 @@ +module.exports = {"de_DE.components":{"personal_access_tokens":"Personal access tokens"},"de_DE.list":{"account":"Konto","account_on_spectre":"Konto (Spectre)","account_type":"Kontotyp","accounts_count":"Anzahl Konten","active":"Aktiv?","amount":"Betrag","attachments_count":"Anzahl Anh\u00e4nge","automatch":"Automatisch erkennen?","balanceDiff":"Balance difference","balance_after":"Kontostand nachher","balance_before":"Kontostand vorher","bill":"Rechnung","bills_count":"Anzahl Rechnungen","blocked_code":"Blockcode","book_date":"Buchungsdatum","budget":"Budget","budget_count":"Anzahl Budgets","buttons":"Schaltfl\u00e4chen","categories_count":"Anzahl Kategorien","category":"Kategorie","completed":"Abgeschlossen","create_date":"Erstellt am","created_at":"Erstellt am","currentBalance":"Aktueller Kontostand","date":"Datum","deposit":"Einlage","description":"Beschreibung","destination":"Empf\u00e4nger","destination_account":"Zielkonto","do_import":"Von diesem Konto importieren","due_date":"F\u00e4lligkeitstermin","email":"E-Mail","export_jobs_count":"Anzahl exportierter Jobs","from":"Von","has_two_factor":"Nutzt 2FA","iban":"IBAN","icon":"Icon","id":"Id","import_jobs_count":"Anzahl importierter Jobs","interal_reference":"Interner Verweis","interest_date":"Zinstermin","internal_reference":"Interne Referenz","invoice_date":"Rechnungsdatum","inward":"Inward description","is_admin":"Ist Admin","is_blocked":"Ist blockiert","journals_count":"Anzahl der Zahlungsvorg\u00e4nge","lastActivity":"Letzte Aktivit\u00e4t","matchesOn":"Zusammengef\u00fchrt am","matchingAmount":"Betrag","name":"Name","next_expected_match":"N\u00e4chste erwartete \u00dcbereinstimmung","notes":"Notizen","number_of_transactions":"Anzahl der Zahlungsvorg\u00e4nge","outward":"Outward description","paid_current_period":"Diese Periode bezahlt","payment_date":"Zahlungsdatum","piggy_bank":"Sparschwein","process_date":"Bearbeitungsdatum","reconcile":"Abgleichen","registered_at":"Registriert am","repeat_freq":"Wiederholungen","role":"Rolle","rule_and_groups_count":"Anzahl Regeln und Regelgruppen","source":"Quelle","source_account":"Quellkonto","split_number":"Geteilt #","sum":"Summe","sum_deposits":"Summe der Einzahlungen","sum_excluding_transfers":"Summe (ohne Umbuchungen)","sum_transfers":"Summe der Umbuchungen","sum_withdrawals":"Summe der Ausgaben","tags":"Tags","tags_count":"Anzahl Tags","to":"An","total_amount":"Gesamtbetrag","transfer":"\u00dcberweisung","type":"Typ","update_date":"Aktualisiert am","updated_at":"Aktualisiert am","withdrawal":"Ausgabe"},"en_US.components":{"not_expected_period":"Not expected this period","not_or_not_yet":"Not (yet)","personal_access_tokens":"Personal access tokens"},"en_US.list":{"account":"Account","account_on_spectre":"Account (Spectre)","account_type":"Account type","accounts_count":"Number of accounts","active":"Is active?","amount":"Amount","attachments_count":"Number of attachments","automatch":"Auto match?","balanceDiff":"Balance difference","balance_after":"Balance after","balance_before":"Balance before","bill":"Bill","bills_count":"Number of bills","blocked_code":"Block code","book_date":"Book date","budget":"Budget","budget_count":"Number of budgets","buttons":"Buttons","categories_count":"Number of categories","category":"Category","completed":"Completed","create_date":"Created at","created_at":"Created at","currentBalance":"Current balance","date":"Date","deposit":"Deposit","description":"Description","destination":"Destination","destination_account":"Destination account","do_import":"Import from this account","due_date":"Due date","email":"Email","export_jobs_count":"Number of export jobs","from":"From","has_two_factor":"Has 2FA","iban":"IBAN","icon":"Icon","id":"ID","import_jobs_count":"Number of import jobs","interal_reference":"Internal reference","interest_date":"Interest date","internal_reference":"Internal reference","invoice_date":"Invoice date","inward":"Inward description","is_admin":"Is admin","is_blocked":"Is blocked","journals_count":"Number of transactions","lastActivity":"Last activity","matchesOn":"Matched on","matchingAmount":"Amount","name":"Name","next_expected_match":"Next expected match","notes":"Notes","number_of_transactions":"Number of transactions","outward":"Outward description","paid_current_period":"Paid this period","payment_date":"Payment date","piggy_bank":"Piggy bank","process_date":"Processing date","reconcile":"Reconcile","registered_at":"Registered at","repeat_freq":"Repeats","role":"Role","rule_and_groups_count":"Number of rules and rule groups","source":"Source","source_account":"Source account","split_number":"Split #","sum":"Sum","sum_deposits":"Sum of deposits","sum_excluding_transfers":"Sum (excluding transfers)","sum_transfers":"Sum of transfers","sum_withdrawals":"Sum of withdrawals","tags":"Tags","tags_count":"Number of tags","to":"To","total_amount":"Total amount","transfer":"Transfer","type":"Type","update_date":"Updated at","updated_at":"Updated at","withdrawal":"Withdrawal"},"es_ES.components":{"personal_access_tokens":"Personal access tokens"},"es_ES.list":{"account":"Cuenta","account_on_spectre":"Cuenta (espectro)","account_type":"Tipo de cuenta","accounts_count":"N\u00famero de cuentas","active":"\u00bfEst\u00e1 Activo?","amount":"Monto","attachments_count":"N\u00fam. de datos adjuntos","automatch":"\u00bfBuscar coincidencia automaticamente?","balanceDiff":"Diferencia de equilibrio","balance_after":"Balance despu\u00e9s de la","balance_before":"Balance antes de ","bill":"Factura","bills_count":"N\u00famero de facturas","blocked_code":"Bloque de c\u00f3digo","book_date":"Libro fecha","budget":"Presupuesto","budget_count":"N\u00famero de presupuestos","buttons":"Botones","categories_count":"N\u00famero de categor\u00edas","category":"Categor\u00eda","completed":"Completado","create_date":"Fecha de creaci\u00f3n","created_at":"Fecha de creaci\u00f3n","currentBalance":"Balance actual","date":"Fecha","deposit":"Dep\u00f3sito","description":"Descripci\u00f3n","destination":"Destino","destination_account":"Cuenta destino","do_import":"Importar desde esta cuenta","due_date":"Fecha de vencimiento","email":"Correo electr\u00f3nico","export_jobs_count":"N\u00famero de operaciones de exportaci\u00f3n","from":"Desde","has_two_factor":"Tiene 2FA","iban":"IBAN","icon":"Icono","id":"Identificaci\u00f3n","import_jobs_count":"N\u00famero de operaciones de importaci\u00f3n","interal_reference":"Referencia interna","interest_date":"Tasa de inter\u00e9s","internal_reference":"Referencia interna","invoice_date":"Fecha de facturaci\u00f3n","inward":"Descripci\u00f3n interna","is_admin":"\u00bfEs el administrador?","is_blocked":"Est\u00e1 bloqueado","journals_count":"N\u00famero de transacciones","lastActivity":"Actividad m\u00e1s reciente","matchesOn":"Encontrado en","matchingAmount":"Monto","name":"Nombre","next_expected_match":"Pr\u00f3xima coincidencia esperada","notes":"Notas","number_of_transactions":"N\u00famero de transacciones","outward":"Descripci\u00f3n externa","paid_current_period":"Pagado este per\u00edodo","payment_date":"Fecha de pago","piggy_bank":"Alcancilla","process_date":"Fecha de procesamiento","reconcile":"Reconciliar","registered_at":"Registrado el","repeat_freq":"Repetici\u00f3n:","role":"Rol","rule_and_groups_count":"N\u00famero de reglas y grupos de reglas","source":"Origen","source_account":"Cuenta origen","split_number":"Divisi\u00f3n #","sum":"Suma","sum_deposits":"Suma de depositos","sum_excluding_transfers":"Suma (excluyendo transferencias)","sum_transfers":"Suma de transferencias","sum_withdrawals":"Suma de retiros","tags":"Etiquetas","tags_count":"N\u00famero de etiquetas","to":"Hasta","total_amount":"Total","transfer":"Trasferencia","type":"Tipo","update_date":"Fecha de modificaci\u00f3n","updated_at":"Actualizado en","withdrawal":"Retiro"},"fr_FR.components":{"personal_access_tokens":"Personal access tokens"},"fr_FR.list":{"account":"Compte","account_on_spectre":"Account (Spectre)","account_type":"Type de compte","accounts_count":"Nombre de comptes","active":"Actif ?","amount":"Montant","attachments_count":"Nombre de pi\u00e8ces jointes","automatch":"Correspondance automatique ?","balanceDiff":"Diff\u00e9rence d'\u00e9quilibre","balance_after":"Solde apr\u00e8s","balance_before":"Solde avant","bill":"Facture","bills_count":"Nombre de factures","blocked_code":"Code de blocage","book_date":"Date de r\u00e9servation","budget":"Budget","budget_count":"Nombre de budgets","buttons":"Boutons","categories_count":"Nombre de cat\u00e9gories","category":"Cat\u00e9gorie","completed":"Termin\u00e9","create_date":"Cr\u00e9\u00e9 le","created_at":"Cr\u00e9\u00e9 le","currentBalance":"Solde courant","date":"Date","deposit":"D\u00e9p\u00f4t","description":"Description","destination":"Destination","destination_account":"Compte destinataire","do_import":"Import from this account","due_date":"\u00c9ch\u00e9ance","email":"E-mail","export_jobs_count":"Nombre de travaux export\u00e9s","from":"Depuis","has_two_factor":"A 2FA","iban":"Num\u00e9ro IBAN","icon":"Ic\u00f4ne","id":"Identifiant","import_jobs_count":"Nombre de travaux import\u00e9s","interal_reference":"R\u00e9f\u00e9rence interne","interest_date":"Date des int\u00e9r\u00eats","internal_reference":"R\u00e9f\u00e9rence interne","invoice_date":"Date de facturation","inward":"Description vers l\u2019int\u00e9rieur","is_admin":"Est admin","is_blocked":"Est bloqu\u00e9","journals_count":"Nombre d'op\u00e9rations","lastActivity":"Activit\u00e9 r\u00e9cente","matchesOn":"Correspond \u00e0","matchingAmount":"Montant","name":"Nom","next_expected_match":"Prochaine association attendue","notes":"Notes","number_of_transactions":"Nombre de transactions","outward":"Description de l\u2019ext\u00e9rieur","paid_current_period":"Pay\u00e9 cette p\u00e9riode","payment_date":"Date de paiement","piggy_bank":"Tirelire","process_date":"Date de traitement","reconcile":"Rapprocher","registered_at":"Enregistr\u00e9 le","repeat_freq":"R\u00e9p\u00e9titions","role":"R\u00f4le","rule_and_groups_count":"Nombre de r\u00e8gles et de groupes de r\u00e8gles","source":"Source","source_account":"Compte d'origine","split_number":"Segmenter en","sum":"Somme","sum_deposits":"Somme des d\u00e9p\u00f4ts","sum_excluding_transfers":"Somme (hors transferts)","sum_transfers":"Somme des transferts","sum_withdrawals":"Somme des retraits","tags":"Tags","tags_count":"Nombre d\u2019\u00e9tiquettes","to":"\u00c0","total_amount":"Montant total","transfer":"Transfert","type":"Type","update_date":"Mis \u00e0 jour le","updated_at":"Mis \u00e0 jour le","withdrawal":"Retrait"},"id_ID.components":{"personal_access_tokens":"Personal access tokens"},"id_ID.list":{"account":"Akun","account_on_spectre":"Account (Spectre)","account_type":"Jenis akun","accounts_count":"Jumlah rekening","active":"Aktif?","amount":"Jumlah","attachments_count":"Jumlah lampiran","automatch":"Pencocokan otomatis?","balanceDiff":"Perbedaan saldo","balance_after":"Saldo setelahnya","balance_before":"Saldo Sebelumnya","bill":"Tagihan","bills_count":"Jumlah tagihan","blocked_code":"Kode blok","book_date":"Tanggal Buku","budget":"Anggaran","budget_count":"Jumlah anggaran","buttons":"Tombol","categories_count":"Jumlah kategori","category":"Kategori","completed":"Lengkap","create_date":"Dibuat pada","created_at":"Dibuat di","currentBalance":"Saldo saat ini","date":"Tanggal","deposit":"Simpanan","description":"Deskripsi","destination":"Tujuan","destination_account":"Akun tujuan","do_import":"Import from this account","due_date":"Tenggat waktu","email":"Email","export_jobs_count":"Jumlah pekerjaan ekspor","from":"Dari","has_two_factor":"Memiliki 2FA","iban":"IBAN","icon":"Ikon","id":"ID","import_jobs_count":"Jumlah pekerjaan impor","interal_reference":"Referensi Internal","interest_date":"Tanggal Bunga","internal_reference":"Referensi Internal","invoice_date":"Tanggal Faktur","inward":"Deskripsi dalam","is_admin":"Apakah admin","is_blocked":"Diblokir","journals_count":"Jumlah transaksi","lastActivity":"Aktifitas terakhir","matchesOn":"Cocok di","matchingAmount":"Jumlah","name":"Nama","next_expected_match":"Transaksi yang diharapkan berikutnya","notes":"Catatan","number_of_transactions":"Jumlah transaksi","outward":"Deskripsi luar","paid_current_period":"Membayar periode ini","payment_date":"Tanggal pembayaran","piggy_bank":"Celengan","process_date":"Tanggal pemrosesan","reconcile":"Menyesuaikan","registered_at":"Terdaftar di","repeat_freq":"Berulang","role":"Peran","rule_and_groups_count":"Jumlah aturan dan kelompok aturan","source":"Sumber","source_account":"Akun sumber","split_number":"Split #","sum":"Jumlah","sum_deposits":"Jumlah simpanan","sum_excluding_transfers":"Jumlah (tidak termasuk transfer)","sum_transfers":"Jumlah transfer","sum_withdrawals":"Jumlah penarikan","tags":"Tags","tags_count":"Jumlah label","to":"Untuk","total_amount":"Jumlah total","transfer":"Transfer","type":"Jenis","update_date":"Diperbarui pada","updated_at":"Diperbarui pada","withdrawal":"Penarikan"},"nl_NL.components":{"personal_access_tokens":"Persoonlijke toegangstokens"},"nl_NL.list":{"account":"Rekening","account_on_spectre":"Rekening (Spectre)","account_type":"Accounttype","accounts_count":"Aantal rekeningen","active":"Actief?","amount":"Bedrag","attachments_count":"Aantal bijlagen","automatch":"Automatisch herkennen?","balanceDiff":"Saldoverschil","balance_after":"Saldo na","balance_before":"Saldo voor","bill":"Contract","bills_count":"Aantal contracten","blocked_code":"Reden voor blokkade","book_date":"Boekdatum","budget":"Budget","budget_count":"Aantal budgetten","buttons":"Knoppen","categories_count":"Aantal categorie\u00ebn","category":"Categorie","completed":"Opgeslagen","create_date":"Aangemaakt op","created_at":"Gemaakt op","currentBalance":"Huidig saldo","date":"Datum","deposit":"Inkomsten","description":"Omschrijving","destination":"Doel","destination_account":"Doelrekening","do_import":"Importeer van deze rekening","due_date":"Vervaldatum","email":"E-mail","export_jobs_count":"Aantal export-jobs","from":"Van","has_two_factor":"Heeft 2FA","iban":"IBAN","icon":"Icoon","id":"ID","import_jobs_count":"Aantal import-jobs","interal_reference":"Interne verwijzing","interest_date":"Rentedatum","internal_reference":"Interne referentie","invoice_date":"Factuurdatum","inward":"Binnenwaartse beschrijving","is_admin":"Is beheerder","is_blocked":"Is geblokkeerd","journals_count":"Aantal transacties","lastActivity":"Laatste activiteit","matchesOn":"Wordt herkend","matchingAmount":"Bedrag","name":"Naam","next_expected_match":"Volgende verwachte match","notes":"Notities","number_of_transactions":"Aantal transacties","outward":"Buitenwaartse beschrijving","paid_current_period":"Betaald deze periode","payment_date":"Betalingsdatum","piggy_bank":"Spaarpotje","process_date":"Verwerkingsdatum","reconcile":"Afstemmen","registered_at":"Geregistreerd op","repeat_freq":"Herhaling","role":"Rol","rule_and_groups_count":"Aantal regels en regelgroepen","source":"Bron","source_account":"Bronrekening","split_number":"Split #","sum":"Som","sum_deposits":"Som van inkomsten","sum_excluding_transfers":"Som (zonder overschrijvingen)","sum_transfers":"Som van overschrijvingen","sum_withdrawals":"Som van uitgaven","tags":"Tags","tags_count":"Aantal tags","to":"Naar","total_amount":"Totaalbedrag","transfer":"Overschrijving","type":"Type","update_date":"Bijgewerkt op","updated_at":"Bijgewerkt op","withdrawal":"Uitgave"},"pl_PL.components":{"personal_access_tokens":"Osobisty kod dost\u0119powy"},"pl_PL.list":{"account":"Konto","account_on_spectre":"Konto (Spectre)","account_type":"Typ konta","accounts_count":"Liczba kont","active":"Jest aktywny?","amount":"Kwota","attachments_count":"Liczba za\u0142\u0105cznik\u00f3w","automatch":"Auto dopasowanie?","balanceDiff":"R\u00f3\u017cnica sald","balance_after":"Saldo po","balance_before":"Saldo przed","bill":"Rachunek","bills_count":"Liczba rachunk\u00f3w","blocked_code":"Kod blokady","book_date":"Data ksi\u0119gowania","budget":"Bud\u017cet","budget_count":"Liczba bud\u017cet\u00f3w","buttons":"Przyciski","categories_count":"Liczba kategorii","category":"Kategoria","completed":"Zako\u0144czone","create_date":"Utworzono","created_at":"Utworzono","currentBalance":"Bie\u017c\u0105ce saldo","date":"Data","deposit":"Wp\u0142ata","description":"Opis","destination":"Cel","destination_account":"Konto docelowe","do_import":"Importuj z tego konta","due_date":"Termin realizacji","email":"Adres E-Mail","export_jobs_count":"Liczba zada\u0144 eksportu","from":"Z","has_two_factor":"Ma dwustopniow\u0105 autoryzacj\u0119","iban":"IBAN","icon":"Ikona","id":"ID","import_jobs_count":"Liczba zada\u0144 importu","interal_reference":"Wewn\u0119trzny numer","interest_date":"Stopa procentowa","internal_reference":"Wewn\u0119trzny numer","invoice_date":"Data faktury","inward":"Opis wewn\u0119trzny","is_admin":"Jest administratorem","is_blocked":"Jest zablokowany","journals_count":"Liczba transakcji","lastActivity":"Ostatnia aktywno\u015b\u0107","matchesOn":"Dopasowanie","matchingAmount":"Kwota","name":"Nazwa","next_expected_match":"Nast\u0119pne oczekiwane dopasowanie","notes":"Notatki","number_of_transactions":"Liczba transakcji","outward":"Opis zewn\u0119trzny","paid_current_period":"Zap\u0142acono w tym okresie","payment_date":"Data p\u0142atno\u015bci","piggy_bank":"Skarbonka","process_date":"Przetworzono","reconcile":"Uzgodnij","registered_at":"Zarejestrowano","repeat_freq":"Powtarza si\u0119","role":"Rola","rule_and_groups_count":"Liczba regu\u0142 i grup regu\u0142","source":"\u0179r\u00f3d\u0142o","source_account":"Konto \u017ar\u00f3d\u0142owe","split_number":"# podzia\u0142u","sum":"Suma","sum_deposits":"Suma wp\u0142at","sum_excluding_transfers":"Suma (bez transfer\u00f3w)","sum_transfers":"Suma transfer\u00f3w","sum_withdrawals":"Suma wyp\u0142at","tags":"Tagi","tags_count":"Liczba tag\u00f3w","to":"Do","total_amount":"\u0141\u0105czna kwota","transfer":"Transfer","type":"Typ","update_date":"Zaktualizowano","updated_at":"Zaktualizowano","withdrawal":"Wyp\u0142ata"},"pt_BR.components":{"personal_access_tokens":"Tokens de acesso pessoal"},"pt_BR.list":{"account":"Conta","account_on_spectre":"Conta (Spectre)","account_type":"Tipo de conta","accounts_count":"N\u00famero de Contas","active":"Est\u00e1 ativo?","amount":"Total","attachments_count":"N\u00famero de anexos","automatch":"Correspond\u00eancia autom\u00e1tica?","balanceDiff":"Diferen\u00e7a de saldo","balance_after":"Saldo depois","balance_before":"Saldo Antes","bill":"Fatura","bills_count":"N\u00famero de contas","blocked_code":"Bloco de c\u00f3digo","book_date":"Data reserva","budget":"Or\u00e7amento","budget_count":"N\u00famero de or\u00e7amentos","buttons":"Bot\u00f5es","categories_count":"N\u00famero de categorias","category":"Categoria","completed":"Completo","create_date":"Criado em","created_at":"Criado em","currentBalance":"Saldo atual","date":"Data","deposit":"Dep\u00f3sito","description":"Descri\u00e7\u00e3o","destination":"Destino","destination_account":"Conta de destino","do_import":"Importar desta conta","due_date":"Prazo","email":"Email","export_jobs_count":"N\u00famero de jobs de exporta\u00e7\u00e3o","from":"De","has_two_factor":"Tem 2FA","iban":"IBAN","icon":"\u00cdcone","id":"ID","import_jobs_count":"N\u00famero de jobs de importa\u00e7\u00e3o","interal_reference":"Refer\u00eancia interna","interest_date":"Data de interesse","internal_reference":"Refer\u00eancia interna","invoice_date":"Data da Fatura","inward":"Descri\u00e7\u00e3o interna","is_admin":"\u00c9 admin","is_blocked":"Est\u00e1 bloqueado","journals_count":"N\u00famero de transa\u00e7\u00f5es","lastActivity":"\u00daltima atividade","matchesOn":"Correspondido em","matchingAmount":"Total","name":"Nome","next_expected_match":"Pr\u00f3ximo correspondente esperado","notes":"Notas","number_of_transactions":"N\u00famero de transa\u00e7\u00f5es","outward":"Descri\u00e7\u00e3o externa","paid_current_period":"Pago este per\u00edodo","payment_date":"Data de pagamento","piggy_bank":"Cofrinho","process_date":"Data de processamento","reconcile":"Pago","registered_at":"Registrado em","repeat_freq":"Repeti\u00e7\u00f5es","role":"Papel","rule_and_groups_count":"N\u00famero de regras e grupos de regras","source":"Fonte","source_account":"Conta de origem","split_number":"Dividir #","sum":"Soma","sum_deposits":"Soma dos dep\u00f3sitos","sum_excluding_transfers":"Soma (excluindo transfer\u00eancias)","sum_transfers":"Soma das transfer\u00eancias","sum_withdrawals":"Soma de retiradas","tags":"Indexadores","tags_count":"N\u00famero de tags","to":"At\u00e9","total_amount":"Valor total","transfer":"Transfer\u00eancia","type":"Tipo","update_date":"Atualizado em","updated_at":"Atualizado em","withdrawal":"Retirada"},"ru_RU.components":{"personal_access_tokens":"\u041f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e\u043a\u0435\u043d \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430"},"ru_RU.list":{"account":"\u0421\u0447\u0451\u0442","account_on_spectre":"\u0421\u0447\u0451\u0442 (Spectre)","account_type":"\u0422\u0438\u043f \u043f\u0440\u043e\u0444\u0438\u043b\u044f","accounts_count":"\u0412\u0441\u0435\u0433\u043e \u0441\u0447\u0435\u0442\u043e\u0432","active":"\u0410\u043a\u0442\u0438\u0432\u0435\u043d?","amount":"\u0421\u0443\u043c\u043c\u0430","attachments_count":"\u0412\u0441\u0435\u0433\u043e \u0432\u043b\u043e\u0436\u0435\u043d\u0438\u0439","automatch":"\u0410\u0432\u0442\u043e\u043f\u043e\u0434\u0431\u043e\u0440?","balanceDiff":"\u0420\u0430\u0437\u043d\u043e\u0441\u0442\u044c \u0431\u0430\u043b\u0430\u043d\u0441\u0430","balance_after":"\u0411\u0430\u043b\u0430\u043d\u0441 \u043f\u043e\u0441\u043b\u0435","balance_before":"\u0411\u0430\u043b\u0430\u043d\u0441 \u0434\u043e","bill":"\u0421\u0447\u0435\u0442 \u043a \u043e\u043f\u043b\u0430\u0442\u0435","bills_count":"\u0412\u0441\u0435\u0433\u043e \u0441\u0447\u0435\u0442\u043e\u0432 \u043a \u043e\u043f\u043b\u0430\u0442\u0435","blocked_code":"\u041a\u043e\u0434 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438","book_date":"\u0417\u0430\u0431\u0440\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c","budget":"\u0411\u044e\u0434\u0436\u0435\u0442","budget_count":"\u0412\u0441\u0435\u0433\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439 \u0431\u044e\u0434\u0436\u0435\u0442\u0430","buttons":"\u041a\u043d\u043e\u043f\u043a\u0438","categories_count":"\u0412\u0441\u0435\u0433\u043e \u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u0439","category":"\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f","completed":"\u0417\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e","create_date":"\u0421\u043e\u0437\u0434\u0430\u043d","created_at":"\u0421\u043e\u0437\u0434\u0430\u043d","currentBalance":"\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u0431\u0430\u043b\u0430\u043d\u0441","date":"\u0414\u0430\u0442\u0430","deposit":"\u0414\u043e\u0445\u043e\u0434","description":"\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","destination":"\u041f\u043e\u043b\u0443\u0447\u0430\u0442\u0435\u043b\u044c","destination_account":"\u0421\u0447\u0435\u0442 \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f","do_import":"\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441 \u044d\u0442\u043e\u0433\u043e \u0441\u0447\u0451\u0442\u0430","due_date":"\u0421\u0440\u043e\u043a","email":"E-mail","export_jobs_count":"\u0417\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0443","from":"\u041e\u0442\u043a\u0443\u0434\u0430","has_two_factor":"\u0417\u0430\u0449\u0438\u0442\u0430 (2FA)?","iban":"IBAN","icon":"\u0417\u043d\u0430\u0447\u043e\u043a","id":"ID","import_jobs_count":"\u0417\u0430\u0434\u0430\u0447\u0438 \u043f\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0443","interal_reference":"\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0441\u0441\u044b\u043b\u043a\u0430","interest_date":"\u041f\u0440\u043e\u0446\u0435\u043d\u0442\u044b","internal_reference":"\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0441\u0441\u044b\u043b\u043a\u0430","invoice_date":"\u0414\u0430\u0442\u0430 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0447\u0451\u0442\u0430","inward":"\u0412\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","is_admin":"\u0410\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440?","is_blocked":"\u0417\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d?","journals_count":"\u0412\u0441\u0435\u0433\u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439","lastActivity":"\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c","matchesOn":"\u0421\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043d\u0430","matchingAmount":"\u0421\u0443\u043c\u043c\u0430","name":"\u0418\u043c\u044f","next_expected_match":"\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442","notes":"\u0417\u0430\u043c\u0435\u0442\u043a\u0438","number_of_transactions":"\u0412\u0441\u0435\u0433\u043e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439","outward":"\u0412\u043d\u0435\u0448\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435","paid_current_period":"\u041e\u043f\u043b\u0430\u0442\u0438\u0442\u044c \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u0435\u0440\u0438\u043e\u0434","payment_date":"\u0414\u0430\u0442\u0430 \u043f\u043b\u0430\u0442\u0435\u0436\u0430","piggy_bank":"\u041a\u043e\u043f\u0438\u043b\u043a\u0430","process_date":"\u0414\u0430\u0442\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f","reconcile":"\u0421\u0432\u0435\u0440\u043a\u0430","registered_at":"\u0414\u0430\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438","repeat_freq":"\u041f\u043e\u0432\u0442\u043e\u0440\u044b","role":"\u0420\u043e\u043b\u044c","rule_and_groups_count":"\u0412\u0441\u0435\u0433\u043e \u043f\u0440\u0430\u0432\u0438\u043b \u0438 \u0433\u0440\u0443\u043f\u043f \u043f\u0440\u0430\u0432\u0438\u043b","source":"\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a","source_account":"\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0441\u0447\u0435\u0442","split_number":"\u0427\u0430\u0441\u0442\u044c \u2116","sum":"\u0421\u0443\u043c\u043c\u0430","sum_deposits":"\u0421\u0443\u043c\u043c\u0430 \u0434\u043e\u0445\u043e\u0434\u043e\u0432","sum_excluding_transfers":"\u0421\u0443\u043c\u043c\u0430 (\u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u0432)","sum_transfers":"\u0421\u0443\u043c\u043c\u0430 \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u043e\u0432","sum_withdrawals":"\u0421\u0443\u043c\u043c\u0430 \u0440\u0430\u0441\u0445\u043e\u0434\u043e\u0432","tags":"\u041c\u0435\u0442\u043a\u0438","tags_count":"\u0412\u0441\u0435\u0433\u043e \u043c\u0435\u0442\u043e\u043a","to":"\u041a\u0443\u0434\u0430","total_amount":"\u0418\u0442\u043e\u0433\u043e","transfer":"\u041f\u0435\u0440\u0435\u0432\u043e\u0434","type":"\u0422\u0438\u043f","update_date":"\u041e\u0431\u043d\u043e\u0432\u043b\u0451\u043d","updated_at":"\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435","withdrawal":"\u0420\u0430\u0441\u0445\u043e\u0434"},"tr_TR.components":{"personal_access_tokens":"Personal access tokens"},"tr_TR.list":{"account":"Hesap","account_on_spectre":"Account (Spectre)","account_type":"Hesap T\u00fcr\u00fc","accounts_count":"Hesap Say\u0131s\u0131","active":"Aktif mi?","amount":"Miktar","attachments_count":"Eklerin say\u0131s\u0131","automatch":"Otomatik e\u015fle\u015ftir?","balanceDiff":"Bakiye fark\u0131","balance_after":"Sonraki bakiye","balance_before":"\u00d6nceki bakiye","bill":"Fatura","bills_count":"Fatura say\u0131s\u0131","blocked_code":"Blok kodu","book_date":"Kitap tarihi","budget":"B\u00fct\u00e7e","budget_count":"B\u00fct\u00e7elerin say\u0131s\u0131","buttons":"Tu\u015flar","categories_count":"Kategori say\u0131s\u0131","category":"Kategori","completed":"Tamamland\u0131","create_date":"Tarihinde olu\u015fturuldu","created_at":"Tarihinde olu\u015fturuldu","currentBalance":"Cari bakiye","date":"Tarih","deposit":"Yat\u0131r","description":"A\u00e7\u0131klama","destination":"Hedef","destination_account":"Hedef Hesap","do_import":"Import from this account","due_date":"Biti\u015f tarihi","email":"E-posta","export_jobs_count":"\u0130hracat say\u0131s\u0131","from":"Kimden","has_two_factor":"2FA var","iban":"IBAN numaras\u0131","icon":"Simge","id":"Kimlik","import_jobs_count":"\u0130thalat say\u0131s\u0131","interal_reference":"Dahili referans","interest_date":"Faiz tarihi","internal_reference":"Dahili referans","invoice_date":"Fatura tarihi","inward":"Dahili a\u00e7\u0131klama","is_admin":"Y\u00f6netici mi","is_blocked":"Engellendi","journals_count":"\u0130\u015flem Say\u0131s\u0131","lastActivity":"Son Etkinlik","matchesOn":"E\u015fle\u015fti","matchingAmount":"Miktar","name":"\u0130sim","next_expected_match":"Beklenen sonraki e\u015fle\u015fme","notes":"Notlar","number_of_transactions":"\u0130\u015flem say\u0131s\u0131","outward":"D\u0131\u015fa a\u00e7\u0131klama","paid_current_period":"Bu d\u00f6nemde \u00f6denen","payment_date":"\u00d6deme tarihi","piggy_bank":"Kumbara","process_date":"\u0130\u015flem tarihi","reconcile":"Onaylanm\u0131\u015f","registered_at":"\u015eurada kay\u0131tl\u0131","repeat_freq":"Tekrarlar","role":"Rol","rule_and_groups_count":"Kurallar\u0131n ve kural gruplar\u0131n\u0131n say\u0131s\u0131","source":"Kaynak","source_account":"Kaynak Hesap","split_number":"Ay\u0131r #","sum":"Toplam","sum_deposits":"Toplam para yat\u0131rma","sum_excluding_transfers":"Toplam (transferler hari\u00e7)","sum_transfers":"Transferlerin toplam\u0131","sum_withdrawals":"Para \u00e7ekme toplam\u0131","tags":"Tags","tags_count":"Etiket say\u0131s\u0131","to":"Al\u0131c\u0131","total_amount":"Toplam Tutar","transfer":"Transfer","type":"T\u00fcr","update_date":"Tarihinde g\u00fcncellendi","updated_at":"Tarihinde g\u00fcncellendi","withdrawal":"Para \u00c7ekme"}}; \ No newline at end of file diff --git a/resources/assets/sass/_variables.scss b/resources/assets/sass/_variables.scss new file mode 100644 index 0000000000..53202ac152 --- /dev/null +++ b/resources/assets/sass/_variables.scss @@ -0,0 +1,38 @@ + +// Body +$body-bg: #f5f8fa; + +// Borders +$laravel-border-color: darken($body-bg, 10%); +$list-group-border: $laravel-border-color; +$navbar-default-border: $laravel-border-color; +$panel-default-border: $laravel-border-color; +$panel-inner-border: $laravel-border-color; + +// Brands +$brand-primary: #3097D1; +$brand-info: #8eb4cb; +$brand-success: #2ab27b; +$brand-warning: #cbb956; +$brand-danger: #bf5329; + +// Typography +$icon-font-path: "~bootstrap-sass/assets/fonts/bootstrap/"; +$font-family-sans-serif: "Raleway", sans-serif; +$font-size-base: 14px; +$line-height-base: 1.6; +$text-color: #636b6f; + +// Navbar +$navbar-default-bg: #fff; + +// Buttons +$btn-default-color: $text-color; + +// Inputs +$input-border: lighten($text-color, 40%); +$input-border-focus: lighten($brand-primary, 25%); +$input-color-placeholder: lighten($text-color, 30%); + +// Panels +$panel-default-heading-bg: #fff; diff --git a/resources/assets/sass/app.scss b/resources/assets/sass/app.scss new file mode 100644 index 0000000000..ba8b3cd21d --- /dev/null +++ b/resources/assets/sass/app.scss @@ -0,0 +1,9 @@ + +// Variables +@import "variables"; + +// Bootstrap +@import "~bootstrap-sass/assets/stylesheets/bootstrap"; + +// Font awesome +@import "~font-awesome/css/font-awesome"; \ No newline at end of file diff --git a/resources/lang/de_DE/breadcrumbs.php b/resources/lang/de_DE/breadcrumbs.php index bb3e302e00..ac1fe157a1 100644 --- a/resources/lang/de_DE/breadcrumbs.php +++ b/resources/lang/de_DE/breadcrumbs.php @@ -51,5 +51,5 @@ return [ 'createTag' => 'Neuen Tag erstellen', 'edit_tag' => 'Tag ":tag" bearbeiten', 'delete_tag' => 'Tag ":tag" löschen', - 'delete_journal_link' => 'Verbindung zwischen Transaktionen löschen', + 'delete_journal_link' => 'Transaktions-Verknüpfung löschen', ]; diff --git a/resources/lang/de_DE/components.php b/resources/lang/de_DE/components.php new file mode 100644 index 0000000000..9c9467852c --- /dev/null +++ b/resources/lang/de_DE/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Persönliche Zugangs-Tokens', + + // bills: + 'not_expected_period' => 'Unerwarteter Zeitraum', + 'not_or_not_yet' => '(Noch) nicht', +]; \ No newline at end of file diff --git a/resources/lang/de_DE/config.php b/resources/lang/de_DE/config.php index 3cdedd8691..dd2f34cb93 100644 --- a/resources/lang/de_DE/config.php +++ b/resources/lang/de_DE/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'de', - 'locale' => 'de, Deutsch, de_DE, de_DE.utf8, de_DE.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e. %B %Y', - 'date_time' => '%e %B %Y, @ %T', - 'specific_day' => '%e. %B %Y', - 'week_in_year' => 'KW %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'de', + 'locale' => 'de, Deutsch, de_DE, de_DE.utf8, de_DE.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e. %B %Y', + 'date_time' => '%e %B %Y, @ %T', + 'specific_day' => '%e. %B %Y', + 'week_in_year' => 'KW %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'Do MMMM YYYY @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/de_DE/firefly.php b/resources/lang/de_DE/firefly.php index 69331a717f..30c421ff00 100644 --- a/resources/lang/de_DE/firefly.php +++ b/resources/lang/de_DE/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Zurücksetzen', 'want_to_login' => 'Ich möchte mich anmelden', 'button_register' => 'Registrieren', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Autorisierungsanfrage', + 'authorization_request_intro' => ':client bittet um Erlaubnis, auf Ihre Finanzverwaltung zuzugreifen. Möchten Sie :client erlauben auf diese Datensätze zuzugreifen?', + 'scopes_will_be_able' => 'Diese Anwendung kann:', + 'button_authorize' => 'Erlauben', // check for updates: 'update_check_title' => 'Nach Updates suchen', @@ -181,7 +188,7 @@ return [ 'admin_update_check_now_title' => 'Auf Update überprüfen', 'admin_update_check_now_explain' => 'Wenn Sie den Knopf drücken, wird Firefly III sehen, ob Ihre aktuelle Version die neueste ist.', 'check_for_updates_button' => 'Jetzt prüfen!', - 'update_new_version_alert' => 'A new version of Firefly III is available. You are running v:your_version, the latest version is v:new_version which was released on :date.', + 'update_new_version_alert' => 'Eine neue Version von Firefly III ist verfügbar. Sie verwenden v:your_version, die neueste Version ist v:new_version und wurde um :date veröffentlicht.', 'update_current_version_alert' => 'Sie verwenden Version v:version. Dies ist die neueste verfügbare Version.', 'update_newer_version_alert' => 'Sie verwenden v:your_version, welches neuer als die neueste Version (v:new_version) ist.', 'update_check_error' => 'Beim Suchen nach Updates ist ein Fehler aufgetreten. Bitte sehen Sie sich die Log-Dateien an.', @@ -211,8 +218,8 @@ return [ // export data: 'import_and_export' => 'Import und Export', 'export_data' => 'Daten exportieren', - 'export_and_backup_data' => 'Export data', - 'export_data_intro' => 'Use the exported data to move to a new financial application. Please note that these files are not meant as a backup. They do not contain enough meta-data to fully restore a new Firefly III installation. If you want to make a backup of your data, please backup the database directly.', + 'export_and_backup_data' => 'Daten exportieren', + 'export_data_intro' => 'Verwenden Sie die exportierten Daten, um zu einer neuen Finanzanwendung zu wechseln. Bitte beachten Sie, dass diese Dateien nicht als Backup gedacht sind. Sie enthalten nicht genügend Metadaten, um eine neue Firefly III-Installation vollständig wiederherzustellen. Wenn Sie Ihre Daten sichern möchten, sichern Sie bitte die Datenbank direkt.', 'export_format' => 'Export-Format', 'export_format_csv' => 'Durch Komma getrennte Werte (CSV-Datei)', 'export_format_mt940' => 'MT940 kompatibles Format', @@ -334,31 +341,31 @@ return [ 'rule_trigger_budget_is_choice' => 'Budget ist..', 'rule_trigger_budget_is' => 'Budget ist ":trigger_value"', 'rule_trigger_tag_is_choice' => '(A) Tag ist..', - 'rule_trigger_tag_is' => 'A tag is ":trigger_value"', + 'rule_trigger_tag_is' => 'Tag ist ":trigger_value"', 'rule_trigger_has_attachments_choice' => 'Hat zumindest so viele Anhänge', 'rule_trigger_has_attachments' => 'Hat zumindest :trigger_value Anhäng(e)', 'rule_trigger_store_journal' => 'Wenn eine Transaktion erstellt wird', 'rule_trigger_update_journal' => 'Wenn eine Transaktion aktualisiert wird', 'rule_trigger_has_no_category_choice' => 'ohne Kategorie', 'rule_trigger_has_no_category' => 'Transaktion ohne Kategorie', - 'rule_trigger_has_any_category_choice' => 'Has a (any) category', - 'rule_trigger_has_any_category' => 'Transaction has a (any) category', + 'rule_trigger_has_any_category_choice' => 'Hat eine (beliebige) Kategorie', + 'rule_trigger_has_any_category' => 'Transaktion hat eine (beliebige) Kategorie', 'rule_trigger_has_no_budget_choice' => 'Hat kein Budget', 'rule_trigger_has_no_budget' => 'Transaktion ohne Budget', - 'rule_trigger_has_any_budget_choice' => 'Has a (any) budget', - 'rule_trigger_has_any_budget' => 'Transaction has a (any) budget', + 'rule_trigger_has_any_budget_choice' => 'Hat ein (beliebiges) Budget', + 'rule_trigger_has_any_budget' => 'Transaktion hat ein (beliebiges) Budget', 'rule_trigger_has_no_tag_choice' => 'Hat keine(n) Tag(s)', - 'rule_trigger_has_no_tag' => 'Transaction has no tag(s)', - 'rule_trigger_has_any_tag_choice' => 'Has one or more (any) tags', - 'rule_trigger_has_any_tag' => 'Transaction has one or more (any) tags', - 'rule_trigger_any_notes_choice' => 'Has (any) notes', - 'rule_trigger_any_notes' => 'Transaction has (any) notes', + 'rule_trigger_has_no_tag' => 'Transaktion hat keine(n) Tag(s)', + 'rule_trigger_has_any_tag_choice' => 'Hat einen oder mehrere (beliebige) Tags', + 'rule_trigger_has_any_tag' => 'Transaktion hat einen oder mehrere (beliebige) Tags', + 'rule_trigger_any_notes_choice' => 'Hat (beliebige) Notizen', + 'rule_trigger_any_notes' => 'Die Transaktion hat (beliebige) Notizen', 'rule_trigger_no_notes_choice' => 'Hat keine Notizen', - 'rule_trigger_no_notes' => 'Transaction has no notes', + 'rule_trigger_no_notes' => 'Transaktion hat keine Notizen', 'rule_trigger_notes_are_choice' => 'Notizen sind..', - 'rule_trigger_notes_are' => 'Notes are ":trigger_value"', + 'rule_trigger_notes_are' => 'Notizen sind ":trigger_value"', 'rule_trigger_notes_contain_choice' => 'Notizen enthalten..', - 'rule_trigger_notes_contain' => 'Notes contain ":trigger_value"', + 'rule_trigger_notes_contain' => 'Notizen enthalten ":trigger_value"', 'rule_trigger_notes_start_choice' => 'Notizen beginnen mit..', 'rule_trigger_notes_start' => 'Notes start with ":trigger_value"', 'rule_trigger_notes_end_choice' => 'Notizen enden mit ..', @@ -499,10 +506,10 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'secure_pw_should' => 'Soll ich die Box ankreuzen?', 'secure_pw_long_password' => 'Wenn Sie gerade ein langes, Single-Use-Passwort für Firefly III mit einem Kennwortgenerator generiert haben: Nein.', 'secure_pw_short' => 'Wenn Sie gerade das Passwort eingegeben haben, welches Sie immer verwenden: Bitte ja.', - 'personal_access_token' => 'Persönlicher Zugangs-Token', - 'explain_access_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your access token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', - 'regenerate_access_token' => 'Zugangs-Token neu erstellen', - 'token_regenerated' => 'Ein neuer Zugangs-Token wurde generiert', + 'command_line_token' => 'Befehlszeilen Token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Befehlszeilen-Token erneut generieren', + 'token_regenerated' => 'Ein neues Befehlszeilen-Token wurde generiert', 'change_your_email' => 'E-Mail Adresse ändern', 'email_verification' => 'Eine E-Mail-Nachricht wird an Ihre alte UND neue E-Mail-Adresse gesendet. Aus Sicherheitsgründen können Sie sich erst anmelden, wenn Sie Ihre neue E-Mail-Adresse bestätigt haben. Wenn Sie sich nicht sicher sind, ob Ihre Firefly III-Installation E-Mails versenden kann, verwenden Sie bitte diese Funktion nicht. Wenn Sie Administrator sind, können Sie dies in der Administration testen.', 'email_changed_logout' => 'Sie müssen Ihre E-Mail-Adresse bestätigen, um sich anmelden zu können.', @@ -619,8 +626,8 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'between_amounts' => 'zwischen :low und :high.', 'repeats' => 'Wiederholungen', 'connected_journals' => 'Verknüpfte Überweisungen', - 'auto_match_on' => 'Automatically matched by Firefly III', - 'auto_match_off' => 'Not automatically matched by Firefly III', + 'auto_match_on' => 'Automatisch von Firefly III zugeordnet', + 'auto_match_off' => 'Nicht automatisch von Firefly III zugeordnet', 'next_expected_match' => 'Nächste erwartete Übereinstimmung', 'delete_bill' => 'Rechnung ":name" löschen', 'deleted_bill' => 'Rechnung ":name" gelöscht', @@ -635,8 +642,6 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'rescanned_bill' => 'Alles gescannt.', 'average_bill_amount_year' => 'Durchschnittliche Rechnungssumme (:year)', 'average_bill_amount_overall' => 'Durchschnittliche Rechnungssumme (gesamt)', - 'not_or_not_yet' => '(noch) nicht', - 'not_expected_period' => 'Diesen Zeitraum nicht erwartet', 'bill_is_active' => 'Rechnung ist aktiv', 'bill_expected_between' => 'Expected between :start and :end', 'bill_will_automatch' => 'Rechnung wird automatisch mit passenden Transaktionen verknüpft', @@ -677,17 +682,17 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'amount_cannot_be_zero' => 'Der Betrag darf nicht Null sein', 'end_of_reconcile_period' => 'End of reconcile period: :period', 'start_of_reconcile_period' => 'Start of reconcile period: :period', - 'start_balance' => 'Start balance', - 'end_balance' => 'End balance', + 'start_balance' => 'Startguthaben', + 'end_balance' => 'Endsaldo', 'update_balance_dates_instruction' => 'Match the amounts and dates above to your bank statement, and press "Start reconciling"', 'select_transactions_instruction' => 'Select the transactions that appear on your bank statement.', 'select_range_and_balance' => 'First verify the date-range and balances. Then press "Start reconciling"', 'date_change_instruction' => 'If you change the date range now, any progress will be lost.', - 'update_selection' => 'Update selection', + 'update_selection' => 'Auswahl aktualisieren', 'store_reconcile' => 'Store reconciliation', 'reconciliation_transaction' => 'Reconciliation transaction', - 'Reconciliation' => 'Reconciliation', - 'reconciliation' => 'Reconciliation', + 'Reconciliation' => 'Kontenabgleich', + 'reconciliation' => 'Kontenabgleich', 'reconcile_options' => 'Reconciliation options', 'reconcile_range' => 'Reconciliation range', 'start_reconcile' => 'Start reconciling', @@ -780,7 +785,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'notes' => 'Notizen', // new user: - 'welcome' => 'Welcome to Firefly III!', + 'welcome' => 'Willkommen bei Firefly III!', 'submit' => 'Absenden', 'getting_started' => 'Erste Schritte', 'to_get_started' => 'Es ist schön, dass Sie Firefly III erfolgreich installiert haben. Um mit diesem Tool zu beginnen, geben Sie bitte den Namen Ihrer Bank und das Guthaben Ihres Hauptkontos ein. Machen Sie sich keine Sorgen, wenn Sie mehrere Konten haben. Sie können diese später hinzufügen. Dies ist nur der Anfang.', @@ -874,9 +879,9 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'inactive' => 'Inaktiv', 'active' => 'Aktiv', 'difference' => 'Unterschied', - 'money_flowing_in' => 'In', - 'money_flowing_out' => 'Out', - 'topX' => 'top :number', + 'money_flowing_in' => 'Rein', + 'money_flowing_out' => 'Raus', + 'topX' => 'Topnummer :number', 'show_full_list' => 'Zeige die gesamte Liste', 'show_only_top' => 'Nur die Top :number anzeigen', 'report_type' => 'Typ des Berichts', @@ -884,7 +889,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'report_type_audit' => 'Übersicht der Transaktionen (Prüfung)', 'report_type_category' => 'Kategorie-Bericht', 'report_type_budget' => 'Budgetbericht', - 'report_type_tag' => 'Tag report', + 'report_type_tag' => 'Tag Report', 'report_type_account' => 'Expense/revenue account report', 'more_info_help' => 'Weitere Informationen über diese Art von Berichten finden Sie in der Hilfe. Drücken Sie hierfür das (?)-Symbol in der oberen rechten Ecke.', 'report_included_accounts' => 'Eingezogene Konten', @@ -903,9 +908,9 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'report_has_no_extra_options' => 'Dieser Bericht hat keine zusätzliche Optionen', 'reports_submit' => 'Zeige Bericht', 'end_after_start_date' => 'Enddatum des Berichts muss nach dem Startdatum liegen.', - 'select_category' => 'Select category(ies)', + 'select_category' => 'Kategorie(n) auswählen', 'select_budget' => 'Select budget(s).', - 'select_tag' => 'Select tag(s).', + 'select_tag' => 'Schlagworte wählen.', 'income_per_category' => 'Einnahmen pro Kategorie', 'expense_per_category' => 'Ausgaben pro Kategorie', 'expense_per_budget' => 'Ausgaben pro Budget', @@ -1128,7 +1133,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', // import index page: 'import_index_title' => 'Daten in Firefly III importieren', 'import_index_sub_title' => 'Index', - 'import_general_index_intro' => 'Willkommen beim Importassistenten von Firefly. Es gibt einige Möglichkeiten, Daten in Firefly III zu importieren, die hier als Schaltflächen angezeigt werden.', + 'import_general_index_intro' => 'Willkommen beim Importassistenten von Firefly III. Es gibt einige Möglichkeiten, Daten in Firefly III zu importieren, die hier als Schaltflächen angezeigt werden.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Diese Funktion ist nicht verfügbar, wenn Sie Firefly III in einer Sandstorm.io-Umgebung verwenden.', diff --git a/resources/lang/de_DE/form.php b/resources/lang/de_DE/form.php index 2856625cc6..77eede5c96 100644 --- a/resources/lang/de_DE/form.php +++ b/resources/lang/de_DE/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Sind Sie sicher, dass Sie den Tag ":name" löschen möchten?', 'journal_link_areYouSure' => 'Sind Sie sicher, dass Sie die Verknüpfung zwischen :source und :destination löschen möchten?', 'linkType_areYouSure' => 'Are you sure you want to delete the link type ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Das Löschen von Dingen in Firefly ist dauerhaft und kann nicht rückgängig gemacht werden.', + 'permDeleteWarning' => 'Das Löschen von Dingen in Firefly III ist dauerhaft und kann nicht rückgängig gemacht werden.', 'mass_make_selection' => 'Sie können das Löschen von Elementen verhindern, indem Sie die Checkbox entfernen.', 'delete_all_permanently' => 'Ausgewähltes dauerhaft löschen', 'update_all_journals' => 'Diese Transaktionen aktualisieren', diff --git a/resources/lang/de_DE/help.php b/resources/lang/de_DE/help.php index 28bd88927c..e0f87c3acd 100644 --- a/resources/lang/de_DE/help.php +++ b/resources/lang/de_DE/help.php @@ -1,4 +1,25 @@ . + */ + declare(strict_types=1); /** diff --git a/resources/lang/de_DE/import.php b/resources/lang/de_DE/import.php index 39445186d3..e9c578b0bd 100644 --- a/resources/lang/de_DE/import.php +++ b/resources/lang/de_DE/import.php @@ -33,11 +33,11 @@ return [ 'status_ready_config' => 'Download der Konfiguration', 'status_ready_start' => 'Starte den Import', 'status_ready_share' => 'Bitte denken Sie darüber nach ihre Konfiguration herunterzuladen und in der Übersicht der Import-Einstellungen zu teilen. Dieses erlaubt es anderen Nutzern von Firefly III ihre Daten unkomplizierter zu importieren.', - 'status_job_new' => 'The job is brand new.', - 'status_job_configuring' => 'The import is being configured.', + 'status_job_new' => 'Die Aufgabe ist neu.', + 'status_job_configuring' => 'Der Import wird konfiguriert.', 'status_job_configured' => 'Der Import ist konfiguriert.', 'status_job_running' => 'Der Import läuft.. Bitte warten..', - 'status_job_error' => 'The job has generated an error.', + 'status_job_error' => 'Ein Fehler ist aufgetreten.', 'status_job_finished' => 'Der Import ist abgeschlossen!', 'status_running_title' => 'Der Import läuft', 'status_running_placeholder' => 'Bitte warten Sie auf eine Aktualisierung...', @@ -49,8 +49,8 @@ return [ 'status_bread_crumb' => 'Importstatus', 'status_sub_title' => 'Importstatus', 'config_sub_title' => 'Import einrichten', - 'status_finished_job' => 'The :count transactions imported can be found in tag :tag.', - 'status_finished_no_tag' => 'Firefly III has not collected any journals from your import file.', + 'status_finished_job' => 'Die :count importierten Transaktionen finden Sie im Tag :tag.', + 'status_finished_no_tag' => 'Firefly III hat keine Daten aus Ihrer Import-Datei gesammelt.', 'import_with_key' => 'Import mit Schlüssel \':key\'', // file, upload something @@ -95,7 +95,7 @@ return [ 'csv_roles_submit' => 'Fortfahren mit Schritt 4/4', // not csv, but normal warning - 'roles_warning' => 'At the very least, mark one column as the amount-column. It is advisable to also select a column for the description, date and the opposing account.', + 'roles_warning' => 'Markieren Sie mindestens die Spalte, die den jeweiligen Betrag enthält. Darüber hinaus sollten eine Spalte für die Beschreibung, das Datum und das Gegenkonto ausgewählt werden.', 'foreign_amount_warning' => 'Wenn Sie eine Spalte als Fremdwährung markieren, müssen Sie auch die Spalte festlegen, welche angibt, welche Währung es ist.', // file, map data 'file_map_title' => 'Import Einrichten (4/4) - Import mit bereits vorhandenen Daten verknüpfen', @@ -104,36 +104,36 @@ return [ 'file_map_field_mapped_to' => 'Zugeordnet zu', 'map_do_not_map' => '(keine Zuordnung)', 'file_map_submit' => 'Starte den Import', - 'file_nothing_to_map' => 'There is no data present in your file that you can map to existing values. Please press "Start the import" to continue.', + 'file_nothing_to_map' => 'Ihree Datei enthält keine Daten, die bestehenden Werten zugeordnet werden können. Klicken Sie "Import starten" um fortzufahren.', // map things. 'column__ignore' => '(diese Spalte ignorieren)', 'column_account-iban' => 'Bestandskonto (IBAN)', - 'column_account-id' => 'Asset account ID (matching FF3)', + 'column_account-id' => 'Eigenes Konto', 'column_account-name' => 'Bestandskonto (Name)', 'column_amount' => 'Betrag', 'column_amount_foreign' => 'Betrag (in Fremdwährung)', - 'column_amount_debit' => 'Amount (debit column)', - 'column_amount_credit' => 'Amount (credit column)', + 'column_amount_debit' => 'Betrag (Debitoren-Spalte)', + 'column_amount_credit' => 'Betrag (Guthaben-Spalte)', 'column_amount-comma-separated' => 'Betrag (Komma als Dezimaltrennzeichen)', - 'column_bill-id' => 'Bill ID (matching FF3)', + 'column_bill-id' => 'Rechnung (ID übereinstimmend mit FF3)', 'column_bill-name' => 'Name der Rechnung', - 'column_budget-id' => 'Budget ID (matching FF3)', + 'column_budget-id' => 'Budget (ID übereinstimmend mit FF3)', 'column_budget-name' => 'Budgetname', - 'column_category-id' => 'Category ID (matching FF3)', + 'column_category-id' => 'Kategorie (ID übereinstimmend mit FF3)', 'column_category-name' => 'Name der Kategorie', 'column_currency-code' => 'Währungsstandard (ISO 4217)', 'column_foreign-currency-code' => 'Fremdwährungscode (ISO 4217)', - 'column_currency-id' => 'Currency ID (matching FF3)', - 'column_currency-name' => 'Currency name (matching FF3)', - 'column_currency-symbol' => 'Currency symbol (matching FF3)', + 'column_currency-id' => 'Währung (ID übereinstimmend mit FF3)', + 'column_currency-name' => 'Währungsname (übereinstimmend mit FF3)', + 'column_currency-symbol' => 'Währungssysmbol (übereinstimmend mit FF3)', 'column_date-interest' => 'Datum der Zinsberechnung', 'column_date-book' => 'Buchungsdatum der Überweisung', 'column_date-process' => 'Verarbeitungsdatum der Überweisung', 'column_date-transaction' => 'Datum', 'column_description' => 'Beschreibung', 'column_opposing-iban' => 'Zielkonto (IBAN)', - 'column_opposing-id' => 'Opposing account ID (matching FF3)', + 'column_opposing-id' => 'Zielkonto (vgl. ID in FF3)', 'column_external-id' => 'Externe ID', 'column_opposing-name' => 'Zielkonto (Name)', 'column_rabo-debit-credit' => 'Rabobank specific debit/credit indicator', @@ -157,10 +157,10 @@ return [ // Spectre 'spectre_title' => 'Importieren mit Spectre', 'spectre_prerequisites_title' => 'Voraussetzungen für einen Import von Spectre', - 'spectre_prerequisites_text' => 'In order to import data using the Spectre API, you must provide Firefly III with two secret values. They can be found on the secrets page.', + 'spectre_prerequisites_text' => 'Um Daten mithilfe der Spectre-API importieren zu können, müssen einige Daten angegeben werden. Diese finden Sie auf der Secrets-Seite bei Saltedge.', 'spectre_enter_pub_key' => 'Der Import funktioniert nur, wenn Sie diesen öffentlichen Schlüssel auf Ihrer Sicherheitsseite eingeben.', - 'spectre_accounts_title' => 'Select accounts to import from', - 'spectre_accounts_text' => 'Each account on the left below has been found by Spectre and can be imported into Firefly III. Please select the asset account that should hold any given transactions. If you do not wish to import from any particular account, remove the check from the checkbox.', + 'spectre_accounts_title' => 'Import-Konten auswählen', + 'spectre_accounts_text' => 'Die Konten auf der linken Seite wurde von Spectre gefunden und können für den Import verwendet werden. Ordnen Sie jeweils ein eigenes Konto zu, in das die Transktionen importiert werden sollen. Konten ohne Häkchen werden beim Import ignoriert.', 'spectre_do_import' => 'Ja, von diesem Konto importieren', // keys from "extra" array: @@ -176,7 +176,7 @@ return [ 'spectre_extra_key_credit_limit' => 'Kreditlimit', 'spectre_extra_key_interest_rate' => 'Zinssatz', 'spectre_extra_key_expiry_date' => 'Ablaufdatum', - 'spectre_extra_key_open_date' => 'Open date', + 'spectre_extra_key_open_date' => 'Anfangsdatum', 'spectre_extra_key_current_time' => 'Aktuelle Uhrzeit', 'spectre_extra_key_current_date' => 'Aktuelles Datum', 'spectre_extra_key_cards' => 'Karten', diff --git a/resources/lang/de_DE/intro.php b/resources/lang/de_DE/intro.php index 0734ba115c..da53e9f9b9 100644 --- a/resources/lang/de_DE/intro.php +++ b/resources/lang/de_DE/intro.php @@ -31,13 +31,13 @@ return [ // create account: 'accounts_create_iban' => 'Geben Sie Ihren Konten eine gültige IBAN. Dies könnte einen Datenimport in Zukunft sehr einfach machen.', - 'accounts_create_asset_opening_balance' => 'Assets accounts may have an "opening balance", indicating the start of this account\'s history in Firefly III.', + 'accounts_create_asset_opening_balance' => 'Anlagekonten können eine "Eröffnungsbilanz" haben, welche den Beginn der Historie dieses Kontos in Firefly III angibt.', 'accounts_create_asset_currency' => 'Firefly III unterstützt mehrere Währungen. Anlagenkonten haben eine Hauptwährung, die Sie hier einstellen müssen.', 'accounts_create_asset_virtual' => 'Es kann manchmal helfen, Ihrem Konto ein virtuelles Gleichgewicht zu geben: eine zusätzliche Menge, die dem tatsächlichen Kontostand immer hinzugefügt oder daraus entfernt wird.', // budgets index 'budgets_index_intro' => 'Mit Budgets verwalten Sie Ihre Finanzen und bilden damit eine der Kernfunktionen von Firefly III.', - 'budgets_index_set_budget' => 'Set your total budget for every period so Firefly III can tell you if you have budgeted all available money.', + 'budgets_index_set_budget' => 'Stellen Sie Ihr Gesamtbudget für jeden Zeitraum ein, damit Firefly III Ihnen mitteilen kann, ob Sie das verfügbare Geld budgetiert haben.', 'budgets_index_see_expenses_bar' => 'Dieser Balken wird sich langsam füllen, wenn Sie Geld ausgeben.', 'budgets_index_navigate_periods' => 'Navigieren Sie durch Zeiträume, um die Budgets im Voraus zu setzen.', 'budgets_index_new_budget' => 'Erstellen Sie neue Budgets, wie Sie es für richtig halten.', diff --git a/resources/lang/de_DE/list.php b/resources/lang/de_DE/list.php index e66b42d507..dab95996b0 100644 --- a/resources/lang/de_DE/list.php +++ b/resources/lang/de_DE/list.php @@ -21,22 +21,22 @@ declare(strict_types=1); return [ - 'buttons' => 'Schaltfläche', + 'buttons' => 'Schaltflächen', 'icon' => 'Icon', 'id' => 'Id', 'create_date' => 'Erstellt am', 'update_date' => 'Aktualisiert am', 'updated_at' => 'Aktualisiert am', - 'balance_before' => 'Bilanz vor', - 'balance_after' => 'Bilanz nach', + 'balance_before' => 'Kontostand vorher', + 'balance_after' => 'Kontostand nachher', 'name' => 'Name', 'role' => 'Rolle', 'currentBalance' => 'Aktueller Kontostand', 'active' => 'Aktiv?', 'lastActivity' => 'Letzte Aktivität', 'balanceDiff' => 'Balance difference', - 'matchesOn' => 'Übereinstimmung am', - 'account_type' => 'Art des Kontos', + 'matchesOn' => 'Zusammengeführt am', + 'account_type' => 'Kontotyp', 'created_at' => 'Erstellt am', 'account' => 'Konto', 'matchingAmount' => 'Betrag', @@ -99,7 +99,7 @@ return [ 'sum_withdrawals' => 'Summe der Ausgaben', 'sum_deposits' => 'Summe der Einzahlungen', 'sum_transfers' => 'Summe der Umbuchungen', - 'reconcile' => 'Reconcile', + 'reconcile' => 'Abgleichen', 'account_on_spectre' => 'Konto (Spectre)', - 'do_import' => 'Import from this account', + 'do_import' => 'Von diesem Konto importieren', ]; diff --git a/resources/lang/de_DE/passwords.php b/resources/lang/de_DE/passwords.php index 47184514cf..dc0170529f 100644 --- a/resources/lang/de_DE/passwords.php +++ b/resources/lang/de_DE/passwords.php @@ -23,7 +23,7 @@ declare(strict_types=1); return [ 'password' => 'Passwörter müssen mindestens 6 Zeichen lang sein und übereinstimmen.', 'user' => 'Wir können keinen Benutzer mit dieser E-Mail Adresse finden.', - 'token' => 'Der Token zum Zurücksetzen des Passwortes ist ungültig.', + 'token' => 'Das Token zum Zurücksetzen des Passwortes ist ungültig.', 'sent' => 'Wir haben Ihnen einen Link zum Zurücksetzen des Passworts zugesendet!', 'reset' => 'Ihr Passwort wurde zurückgesetzt!', 'blocked' => 'Netter Versuch.', diff --git a/resources/lang/de_DE/validation.php b/resources/lang/de_DE/validation.php index 285c1a67f0..18d65b7309 100644 --- a/resources/lang/de_DE/validation.php +++ b/resources/lang/de_DE/validation.php @@ -22,12 +22,20 @@ declare(strict_types=1); return [ 'iban' => 'Dies ist keine gültige IBAN.', - 'unique_account_number_for_user' => 'Es sieht so aus, als ob diese Kontonummer bereits verwendet würde.', + 'unique_account_number_for_user' => 'Diese Kontonummer scheint bereits verwendet zu sein.', + 'unique_iban_for_user' => 'Dieser IBAN scheint bereits verwendet zu werden.', 'deleted_user' => 'Aufgrund von Sicherheitsbeschränkungen ist eine Registrierung mit dieser E-Mail-Adresse nicht zugelassen.', - 'rule_trigger_value' => 'Dieser Wert ist für den ausgewählten Trigger ungültig.', + 'rule_trigger_value' => 'Dieser Wert ist für den ausgewählten Auslöser ungültig.', 'rule_action_value' => 'Dieser Wert ist für die gewählte Aktion ungültig.', 'file_already_attached' => 'Die hochgeladene Datei ":name" ist diesem Objekt bereits angehängt.', 'file_attached' => 'Datei ":name" erfolgreich hochgeladen.', + 'must_exist' => 'Die ID in Feld :attribute existiert nicht in der Datenbank.', + 'all_accounts_equal' => 'Alle Konten in diesem Feld müssen identisch sein.', + 'invalid_selection' => 'Die Auswahl ist ungültig', + 'belongs_user' => 'Dieser Wert ist für dieses Feld ungültig.', + 'at_least_one_transaction' => 'Sie brauchen mindestens eine Transaktion.', + 'require_currency_info' => 'Der Inhalt dieses Feldes ist ohne Währungsinformationen ungültig.', + 'equal_description' => 'Die Transaktionsbeschreibung darf nicht der globalen Beschreibung entsprechen.', 'file_invalid_mime' => 'Die Datei ":name" ist vom Typ ":mime", welcher nicht zum Upload zugelassen ist.', 'file_too_large' => 'Die Datei ":name" ist zu groß.', 'belongs_to_user' => 'Der Wert von :attribute ist nicht bekannt', @@ -60,7 +68,7 @@ return [ 'exists' => ':attribute ist ungültig.', 'image' => ':attribute muss ein Bild sein.', 'in' => ':attribute ist ungültig.', - 'integer' => ':attribute muss eine ganze Zahl sein.', + 'integer' => ':attribute muss eine Ganzzahl sein.', 'ip' => ':attribute muss eine gültige IP-Adresse sein.', 'json' => ':attribute muss ein gültiger JSON-String sein.', 'max.numeric' => ':attribute darf nicht größer als :max sein.', @@ -84,6 +92,7 @@ return [ 'required_without_all' => ':attribute Feld ist notwendig, falls kein :values vorhanden ist.', 'same' => ':attribute und :other müssen übereinstimmen.', 'size.numeric' => ':attribute muss :size sein.', + 'amount_min_over_max' => 'Der Mindestbetrag darf nicht größer als der Höchstbetrag sein.', 'size.file' => ':attribute muss :size Kilobytes groß sein.', 'size.string' => ':attribute muss :size Zeichen enthalten.', 'size.array' => ':attribute muss :size Elemente enthalten.', @@ -92,45 +101,47 @@ return [ 'url' => ':attribute Format ist ungültig.', 'timezone' => ':attribute muss in einem gültigen Bereich liegen.', '2fa_code' => ':attribute Feld ist ungültig.', - 'dimensions' => 'Das :attribute hat ungültige Bilddimensionen.', - 'distinct' => ':attribute enthält einen doppelten Wert.', + 'dimensions' => 'Das :attribute hat eine ungültige Auflösung.', + 'distinct' => 'Der Wert von :attribute existiert bereits.', 'file' => 'Das :attribute muss eine Datei sein.', 'in_array' => ':attribute existiert nicht in :other.', 'present' => 'Das :attribute Feld muss vorhanden sein.', 'amount_zero' => 'Der Gesamtbetrag darf nicht Null sein', 'secure_password' => 'Das ist kein sicheres Passwort. Bitte versuchen Sie es erneut. Weitere Informationen finden Sie unter https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'E-Mail-Adresse', - 'description' => 'Beschreibung', - 'amount' => 'Betrag', - 'name' => 'Name', - 'targetamount' => 'Zielbetrag', - 'openingBalanceDate' => 'Eröffnungsbilanzdatum', - 'openingBalance' => 'Eröffnungsbilanz', - 'match' => 'match', - 'amount_min' => 'Mindestbetrag', - 'amount_max' => 'Höchstbetrag', - 'title' => 'Titel', - 'tag' => 'tag', - 'rule-action-value.1' => 'rule action value #1', - 'rule-action-value.2' => 'rule action value #2', - 'rule-action-value.3' => 'rule action value #3', - 'rule-action-value.4' => 'rule action value #4', - 'rule-action-value.5' => 'rule action value #5', - 'rule-action.1' => 'rule action #1', - 'rule-action.2' => 'rule action #2', - 'rule-action.3' => 'rule action #3', - 'rule-action.4' => 'rule action #4', - 'rule-action.5' => 'rule action #5', - 'rule-trigger-value.1' => 'rule trigger value #1', - 'rule-trigger-value.2' => 'rule trigger value #2', - 'rule-trigger-value.3' => 'rule trigger value #3', - 'rule-trigger-value.4' => 'rule trigger value #4', - 'rule-trigger-value.5' => 'rule trigger value #5', - 'rule-trigger.1' => 'Regel #1 auslösen', - 'rule-trigger.2' => 'Regel #2 auslösen', - 'rule-trigger.3' => 'Regel #3 auslösen', - 'rule-trigger.4' => 'Regel 4 auslösen', - 'rule-trigger.5' => 'Regel #5 auslösen', + 'email' => 'E-Mail Adresse', + 'description' => 'Beschreibung', + 'amount' => 'Betrag', + 'name' => 'Name', + 'piggy_bank_id' => 'Sparschwein ID', + 'targetamount' => 'Zielbetrag', + 'openingBalanceDate' => 'Datum des Eröffnungskontostands', + 'openingBalance' => 'Eröffnungskontostand', + 'match' => 'Übereinstimmung', + 'amount_min' => 'Mindestbetrag', + 'amount_max' => 'Höchstbetrag', + 'title' => 'Bezeichnung', + 'tag' => 'Tag', + 'transaction_description' => 'Transaktionsbeschreibung', + 'rule-action-value.1' => 'rule action value #1', + 'rule-action-value.2' => 'rule action value #2', + 'rule-action-value.3' => 'rule action value #3', + 'rule-action-value.4' => 'rule action value #4', + 'rule-action-value.5' => 'rule action value #5', + 'rule-action.1' => 'rule action #1', + 'rule-action.2' => 'rule action #2', + 'rule-action.3' => 'rule action #3', + 'rule-action.4' => 'rule action #4', + 'rule-action.5' => 'rule action #5', + 'rule-trigger-value.1' => 'rule trigger value #1', + 'rule-trigger-value.2' => 'rule trigger value #2', + 'rule-trigger-value.3' => 'rule trigger value #3', + 'rule-trigger-value.4' => 'rule trigger value #4', + 'rule-trigger-value.5' => 'rule trigger value #5', + 'rule-trigger.1' => 'Regel #1 auslösen', + 'rule-trigger.2' => 'Regel #2 auslösen', + 'rule-trigger.3' => 'Regel #3 auslösen', + 'rule-trigger.4' => 'Regel 4 auslösen', + 'rule-trigger.5' => 'Regel #5 auslösen', ], ]; diff --git a/resources/lang/en_US/components.php b/resources/lang/en_US/components.php new file mode 100644 index 0000000000..fae0f0f10b --- /dev/null +++ b/resources/lang/en_US/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Personal access tokens', + + // bills: + 'not_expected_period' => 'Not expected this period', + 'not_or_not_yet' => 'Not (yet)', +]; \ No newline at end of file diff --git a/resources/lang/en_US/config.php b/resources/lang/en_US/config.php index 3d6cca0315..71d15b1baa 100644 --- a/resources/lang/en_US/config.php +++ b/resources/lang/en_US/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'en', - 'locale' => 'en, English, en_US, en_US.utf8, en_US.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%B %e, %Y', - 'date_time' => '%B %e, %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Week %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'en', + 'locale' => 'en, English, en_US, en_US.utf8, en_US.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%B %e, %Y', + 'date_time' => '%B %e, %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Week %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 5e41772e02..e9c24d484a 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Reset', 'want_to_login' => 'I want to login', 'button_register' => 'Register', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Authorization Request', + 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', + 'scopes_will_be_able' => 'This application will be able to:', + 'button_authorize' => 'Authorize', // check for updates: 'update_check_title' => 'Check for updates', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Should I check the box?', 'secure_pw_long_password' => 'If you just generated a long, single-use password for Firefly III using some kind of password generator: no.', 'secure_pw_short' => 'If you just entered the password you always use: Please yes.', - 'personal_access_token' => 'Personal access token', - 'explain_access_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your access token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', - 'regenerate_access_token' => 'Regenerate access token', - 'token_regenerated' => 'A new token was generated', + 'command_line_token' => 'Command line token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Regenerate command line token', + 'token_regenerated' => 'A new command line token was generated', 'change_your_email' => 'Change your email address', 'email_verification' => 'An email message will be sent to your old AND new email address. For security purposes, you will not be able to login until you verify your new email address. If you are unsure if your Firefly III installation is capable of sending email, please do not use this feature. If you are an administrator, you can test this in the Administration.', 'email_changed_logout' => 'Until you verify your email address, you cannot login.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Rescanned everything.', 'average_bill_amount_year' => 'Average bill amount (:year)', 'average_bill_amount_overall' => 'Average bill amount (overall)', - 'not_or_not_yet' => 'Not (yet)', - 'not_expected_period' => 'Not expected this period', 'bill_is_active' => 'Bill is active', 'bill_expected_between' => 'Expected between :start and :end', 'bill_will_automatch' => 'Bill will automatically linked to matching transactions', @@ -1127,7 +1132,7 @@ return [ // import index page: 'import_index_title' => 'Import data into Firefly III', 'import_index_sub_title' => 'Index', - 'import_general_index_intro' => 'Welcome to Firefly\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', + 'import_general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'This function is not available when you are using Firefly III within a Sandstorm.io environment.', diff --git a/resources/lang/en_US/form.php b/resources/lang/en_US/form.php index 0032a58c3a..fda485df3f 100644 --- a/resources/lang/en_US/form.php +++ b/resources/lang/en_US/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?', 'journal_link_areYouSure' => 'Are you sure you want to delete the link between :source and :destination?', 'linkType_areYouSure' => 'Are you sure you want to delete the link type ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Deleting stuff from Firely is permanent and cannot be undone.', + 'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.', 'mass_make_selection' => 'You can still prevent items from being deleted by removing the checkbox.', 'delete_all_permanently' => 'Delete selected permanently', 'update_all_journals' => 'Update these transactions', diff --git a/resources/lang/en_US/import.php b/resources/lang/en_US/import.php index f079bd6dd4..d0be62eb6c 100644 --- a/resources/lang/en_US/import.php +++ b/resources/lang/en_US/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Import status', 'config_sub_title' => 'Set up your import', 'status_finished_job' => 'The :count transactions imported can be found in tag :tag.', - 'status_finished_no_tag' => 'Firefly III has not collected any journals from your import file.', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'import_with_key' => 'Import with key \':key\'', // file, upload something diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php index 0e67946c18..db12a84f92 100644 --- a/resources/lang/en_US/validation.php +++ b/resources/lang/en_US/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'This is not a valid IBAN.', 'unique_account_number_for_user' => 'It looks like this account number is already in use.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', 'deleted_user' => 'Due to security constraints, you cannot register using this email address.', 'rule_trigger_value' => 'This value is invalid for the selected trigger.', 'rule_action_value' => 'This value is invalid for the selected action.', 'file_already_attached' => 'Uploaded file ":name" is already attached to this object.', 'file_attached' => 'Succesfully uploaded file ":name".', + 'must_exist' => 'The ID in field :attribute does not exist in the database.', + 'all_accounts_equal' => 'All accounts in this field must be equal.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'This value is invalid for this field.', + 'at_least_one_transaction' => 'Need at least one transaction.', + 'require_currency_info' => 'The content of this field is invalid without currency information.', + 'equal_description' => 'Transaction description should not equal global description.', 'file_invalid_mime' => 'File ":name" is of type ":mime" which is not accepted as a new upload.', 'file_too_large' => 'File ":name" is too large.', 'belongs_to_user' => 'The value of :attribute is unknown', @@ -84,6 +92,7 @@ return [ 'required_without_all' => 'The :attribute field is required when none of :values are present.', 'same' => 'The :attribute and :other must match.', 'size.numeric' => 'The :attribute must be :size.', + 'amount_min_over_max' => 'The minimum amount cannot be larger than the maximum amount.', 'size.file' => 'The :attribute must be :size kilobytes.', 'size.string' => 'The :attribute must be :size characters.', 'size.array' => 'The :attribute must contain :size items.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'The total amount cannot be zero', 'secure_password' => 'This is not a secure password. Please try again. For more information, visit https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'email address', - 'description' => 'description', - 'amount' => 'amount', - 'name' => 'name', - 'targetamount' => 'target amount', - 'openingBalanceDate' => 'opening balance date', - 'openingBalance' => 'opening balance', - 'match' => 'match', - 'amount_min' => 'minimum amount', - 'amount_max' => 'maximum amount', - 'title' => 'title', - 'tag' => 'tag', - 'rule-action-value.1' => 'rule action value #1', - 'rule-action-value.2' => 'rule action value #2', - 'rule-action-value.3' => 'rule action value #3', - 'rule-action-value.4' => 'rule action value #4', - 'rule-action-value.5' => 'rule action value #5', - 'rule-action.1' => 'rule action #1', - 'rule-action.2' => 'rule action #2', - 'rule-action.3' => 'rule action #3', - 'rule-action.4' => 'rule action #4', - 'rule-action.5' => 'rule action #5', - 'rule-trigger-value.1' => 'rule trigger value #1', - 'rule-trigger-value.2' => 'rule trigger value #2', - 'rule-trigger-value.3' => 'rule trigger value #3', - 'rule-trigger-value.4' => 'rule trigger value #4', - 'rule-trigger-value.5' => 'rule trigger value #5', - 'rule-trigger.1' => 'rule trigger #1', - 'rule-trigger.2' => 'rule trigger #2', - 'rule-trigger.3' => 'rule trigger #3', - 'rule-trigger.4' => 'rule trigger #4', - 'rule-trigger.5' => 'rule trigger #5', + 'email' => 'email address', + 'description' => 'description', + 'amount' => 'amount', + 'name' => 'name', + 'piggy_bank_id' => 'piggy bank ID', + 'targetamount' => 'target amount', + 'openingBalanceDate' => 'opening balance date', + 'openingBalance' => 'opening balance', + 'match' => 'match', + 'amount_min' => 'minimum amount', + 'amount_max' => 'maximum amount', + 'title' => 'title', + 'tag' => 'tag', + 'transaction_description' => 'transaction description', + 'rule-action-value.1' => 'rule action value #1', + 'rule-action-value.2' => 'rule action value #2', + 'rule-action-value.3' => 'rule action value #3', + 'rule-action-value.4' => 'rule action value #4', + 'rule-action-value.5' => 'rule action value #5', + 'rule-action.1' => 'rule action #1', + 'rule-action.2' => 'rule action #2', + 'rule-action.3' => 'rule action #3', + 'rule-action.4' => 'rule action #4', + 'rule-action.5' => 'rule action #5', + 'rule-trigger-value.1' => 'rule trigger value #1', + 'rule-trigger-value.2' => 'rule trigger value #2', + 'rule-trigger-value.3' => 'rule trigger value #3', + 'rule-trigger-value.4' => 'rule trigger value #4', + 'rule-trigger-value.5' => 'rule trigger value #5', + 'rule-trigger.1' => 'rule trigger #1', + 'rule-trigger.2' => 'rule trigger #2', + 'rule-trigger.3' => 'rule trigger #3', + 'rule-trigger.4' => 'rule trigger #4', + 'rule-trigger.5' => 'rule trigger #5', ], ]; diff --git a/resources/lang/es_ES/auth.php b/resources/lang/es_ES/auth.php new file mode 100644 index 0000000000..0174bb37e5 --- /dev/null +++ b/resources/lang/es_ES/auth.php @@ -0,0 +1,37 @@ +. + */ +declare(strict_types=1); + +return [ + /* + |-------------------------------------------------------------------------- + | Authentication Language Lines + |-------------------------------------------------------------------------- + | + | The following language lines are used during authentication for various + | messages that we need to display to the user. You are free to modify + | these language lines according to your application's requirements. + | + */ + + 'failed' => 'Las credenciales no coinciden con los registros.', + 'throttle' => 'Demasiados intentos de inicio de sesión. Por favor reintente en :seconds segundos.', +]; diff --git a/resources/lang/es_ES/bank.php b/resources/lang/es_ES/bank.php new file mode 100644 index 0000000000..ef0d636f91 --- /dev/null +++ b/resources/lang/es_ES/bank.php @@ -0,0 +1,24 @@ +. + */ +declare(strict_types=1); + +return [ +]; diff --git a/resources/lang/es_ES/breadcrumbs.php b/resources/lang/es_ES/breadcrumbs.php new file mode 100644 index 0000000000..61ad6a28b6 --- /dev/null +++ b/resources/lang/es_ES/breadcrumbs.php @@ -0,0 +1,55 @@ +. + */ +declare(strict_types=1); + +return [ + 'home' => 'Inicio', + 'edit_currency' => 'Editar moneda ":name"', + 'delete_currency' => 'Eliminar moneda ":name"', + 'newPiggyBank' => 'Crear nueva alcancía', + 'edit_piggyBank' => 'Editar alcancía ":name"', + 'preferences' => 'Preferencias', + 'profile' => 'Perfil', + 'changePassword' => 'Cambiar contraseña', + 'change_email' => 'Cambiar su dirección de correo electrónico', + 'bills' => 'Facturas', + 'newBill' => 'Nueva factura', + 'edit_bill' => 'Editar factura ":name"', + 'delete_bill' => 'Eliminar factura ":name"', + 'reports' => 'Reportes', + 'search_result' => 'Resultados de la búsqueda para ":query"', + 'withdrawal_list' => 'Gastos', + 'deposit_list' => 'Ganancia, ingresos y depósitos', + 'transfer_list' => 'Transferencias', + 'transfers_list' => 'Transferencias', + 'reconciliation_list' => 'Reconciliaciones', + 'create_withdrawal' => 'Crear nuevo retiro', + 'create_deposit' => 'Crear nuevo depósito', + 'create_transfer' => 'Crear nueva transferencia', + 'edit_journal' => 'Editar transacción ":description"', + 'edit_reconciliation' => 'Editar ":description"', + 'delete_journal' => 'Eliminar transacción ":description"', + 'tags' => 'Etiquetas', + 'createTag' => 'Crear nueva etiqueta', + 'edit_tag' => 'Editar etiqueta ":tag"', + 'delete_tag' => 'Eliminar etiqueta ":tag"', + 'delete_journal_link' => 'Eliminar enlace entre transacciones', +]; diff --git a/resources/lang/es_ES/components.php b/resources/lang/es_ES/components.php new file mode 100644 index 0000000000..4adfc3819b --- /dev/null +++ b/resources/lang/es_ES/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Tokens de acceso personal', + + // bills: + 'not_expected_period' => 'No se esperaba este período', + 'not_or_not_yet' => 'No (todavía)', +]; \ No newline at end of file diff --git a/resources/lang/es_ES/config.php b/resources/lang/es_ES/config.php new file mode 100644 index 0000000000..8d2ea86b8a --- /dev/null +++ b/resources/lang/es_ES/config.php @@ -0,0 +1,40 @@ +. + */ +declare(strict_types=1); + +return [ + 'html_language' => 'es', + 'locale' => 'es, Spanish, es_ES, es_ES.utf8, es_ES.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%B %e, %Y', + 'date_time' => '%B %e, %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Semana %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', +]; diff --git a/resources/lang/es_ES/csv.php b/resources/lang/es_ES/csv.php new file mode 100644 index 0000000000..d61316b632 --- /dev/null +++ b/resources/lang/es_ES/csv.php @@ -0,0 +1,24 @@ +. + */ +declare(strict_types=1); + +return [ +]; diff --git a/resources/lang/es_ES/demo.php b/resources/lang/es_ES/demo.php new file mode 100644 index 0000000000..858ff8d21d --- /dev/null +++ b/resources/lang/es_ES/demo.php @@ -0,0 +1,35 @@ +. + */ +declare(strict_types=1); + +return [ + 'no_demo_text' => 'Lamentablemente no hay textos de ayuda para esta página.', + 'see_help_icon' => 'Sin embargo, el ícono en la esquina superior-derecha puede tener más información.', + 'index' => '¡Bienvenido a Firefly III! En esta página tendrá una vista rápida de sus finanzas. Para más información, mire sus cuentas rarr; Asset Accounts y, claro, las páginas de presupuestos y reportes. O simplemente investigue la aplicación por su cuenta.', + 'accounts-index' => 'Las cajas de ahorro son sus cuentas de banco personales. Las cuentas de gastos contienen sus gastos habituales como compras y salidas con amigos. Las cuentas de ingresos repesentan ingresos de su trabajo u otras fuentes. En esta página puede editarlas o eliminarlas.', + 'budgets-index' => 'Esta página le muestra una visión general de sus presupuestos. La barra superior muestra la cantidad que está disponible para ser presupuestado. Esto se puede personalizar para cualquier período haciendo clic en la cantidad a la derecha. La cantidad que has gastado hasta ahora se muestra en la barra de abajo. Debajo están los gastos por presupuesto y lo que ha presupuestado para ellos.', + 'reports-index-start' => 'Firefly III da soporte a un buen numero de tipos de reportes. Lea sobre ellos haciendo clic en el icono en el tope de la esquina derecha.', + 'reports-index-examples' => 'Asegúrese de revisar estos ejemplos: un resumen financiero mensual, un resumen financiero anual y una vista general del presupuesto.', + 'currencies-index' => 'Firefly III admite múltiples monedas. A pesar de que la moneda por defecto es el Euro, se puede seleccionar el Dólar de EE.UU, y muchas otras monedas. Como se puede ver se ha incluido una pequeña selección de monedas, pero puedes agregar tu propia moneda si lo deseas. Sin embargo, cambiar la moneda predeterminada no cambiará la moneda de las transacciones existentes: Firefly III admite el uso de varias monedas al mismo tiempo.', + 'transactions-index' => 'Estos gastos, depósitos y transferencias no son particularmente imaginativos. Se han generado automáticamente.', + 'piggy-banks-index' => 'Como puede ver, hay tres alcancías. Utilice los botones más y menos para influir en la cantidad de dinero en cada alcancía. Haga clic en el nombre de la alcancía para ver la administración de cada una.', + 'import-index' => 'Por supuesto, cualquier archivo CSV puede ser importado dentro de Firefly III', +]; diff --git a/resources/lang/es_ES/firefly.php b/resources/lang/es_ES/firefly.php new file mode 100644 index 0000000000..db1f7af44c --- /dev/null +++ b/resources/lang/es_ES/firefly.php @@ -0,0 +1,1186 @@ +. + */ +declare(strict_types=1); + +return [ + // general stuff: + 'close' => 'Cerrar', + 'actions' => 'Acciones', + 'edit' => 'Editar', + 'delete' => 'Eliminar', + 'welcomeBack' => '¿Qué está pasando?', + 'everything' => 'Todo', + 'today' => 'hoy', + 'customRange' => 'Rango personalizado', + 'apply' => 'Aplicar', + 'select_date' => 'Seleccionar fecha...', + 'cancel' => 'Cancelar', + 'from' => 'Desde', + 'to' => 'Hasta', + 'showEverything' => 'Mostrar todo', + 'never' => 'Nunca', + 'no_results_for_empty_search' => 'Su búsqueda estaba vacía, por lo que no se encontró nada.', + 'removed_amount' => 'Eliminado :amount', + 'added_amount' => 'Añadido :amount', + 'asset_account_role_help' => 'Las opciones extras como resultado de su elección se pueden establecer más tarde.', + 'Opening balance' => 'Balance inicial', + 'create_new_stuff' => 'Crear nueva etiqueta', + 'new_withdrawal' => 'Nuevo retiro', + 'create_new_transaction' => 'Crear una nueva transacción', + 'go_to_asset_accounts' => 'Ver tus cuentas de activos', + 'go_to_budgets' => 'Ir a tus presupuestos', + 'go_to_categories' => 'Ir a tus categorías', + 'go_to_bills' => 'Ir a tus cuentas', + 'go_to_expense_accounts' => 'Ver tus cuentas de gastos', + 'go_to_revenue_accounts' => 'Ver tus cuentas de ingresos', + 'go_to_piggies' => 'Ir a tu alcancía', + 'new_deposit' => 'Nuevo depósito', + 'new_transfer' => 'Nueva transferencia', + 'new_transfers' => 'Nueva transferencia', + 'new_asset_account' => 'Nueva cuenta de activo', + 'new_expense_account' => 'Nueva cuenta de gastos', + 'new_revenue_account' => 'Nueva cuenta de ingresos', + 'new_budget' => 'Nuevo presupuesto', + 'new_bill' => 'Nueva factura', + 'block_account_logout' => 'Tu sesión ha sido cerrada. Las cuentas bloqueadas no pueden utilizar este sitio. ¿Registrarte con una dirección válida de correo electrónico?', + 'flash_success' => '¡Operación correcta!', + 'flash_info' => 'Mensaje', + 'flash_warning' => '¡Atención!', + 'flash_error' => '¡Error!', + 'flash_info_multiple' => 'Hay un mensaje| Hay :count mensajes', + 'flash_error_multiple' => 'Hay un error|Hay unos :count errores', + 'net_worth' => 'Valor Neto', + 'route_has_no_help' => 'No hay datos en este registro.', + 'help_for_this_page' => 'Ayuda para esta pagina', + 'no_help_could_be_found' => 'No se encontró un texto de ayuda.', + 'no_help_title' => 'Disculpas, un error ha ocurrido.', + 'two_factor_welcome' => 'Hola %{user}!', + 'two_factor_enter_code' => 'Para continuar, introduce tu código de autenticación de dos pasos. La aplicación puede generarlo para usted.', + 'two_factor_code_here' => 'Ingresar código aquí', + 'two_factor_title' => 'Autenticación en dos pasos', + 'authenticate' => 'Autentificar', + 'two_factor_forgot_title' => 'Autenticación en dos pasos perdida', + 'two_factor_forgot' => 'Olvidé mi cosa de dos factores.', + 'two_factor_lost_header' => '¿Perdiste tu autentificación de dos factores?', + 'two_factor_lost_intro' => 'Por desgracia, esto no es algo que se pueda restablecer desde la interfaz web. Tienes dos opciones.', + 'two_factor_lost_fix_self' => 'Si usted ejecuta su propia instancia de Firefly III, revise los registros en storage/logs para tener instrucciones.', + 'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, :site_owner and ask them to reset your two factor authentication y pidale a ellos restablecer su autenticacion de dos factores.', + 'warning_much_data' => ':days días de datos pueden tomar tiempo en cargarse.', + 'registered' => '¡Te has registrado con éxito!', + 'Default asset account' => 'Cuenta de ingresos por defecto', + 'no_budget_pointer' => 'Parece que aún no tienes presupuestos. Debe crear algunos en la página presupuestos. Los presupuestos pueden ayudarle a realizar un seguimiento de los gastos.', + 'Savings account' => 'Cuenta de ahorros', + 'Credit card' => 'Tarjeta de crédito', + 'source_accounts' => 'Cuenta(s) origen', + 'destination_accounts' => 'Cuenta(s) destino', + 'user_id_is' => 'Tu id de usuario es :user', + 'field_supports_markdown' => 'Este campo admite Markdown.', + 'need_more_help' => 'Si necesita más ayuda con Firefly III, por favor abre un ticket en Github.', + 'reenable_intro_text' => 'También puede volver a activar la guía de introducción.', + 'intro_boxes_after_refresh' => 'Los cuadros de introducción volverán a aparecer cuando actualices la página.', + 'show_all_no_filter' => 'Mostrar todas las transacciones sin agruparlas por fecha.', + 'expenses_by_category' => 'Gastos por categoría', + 'expenses_by_budget' => 'Gastos por presupuesto', + 'income_by_category' => 'Ingresos por categoría', + 'expenses_by_asset_account' => 'Gastos por cuenta de ingresos', + 'expenses_by_expense_account' => 'Gastos por cuenta de egresos', + 'cannot_redirect_to_account' => 'Firefly III no puede redirigirlo a la pagina correcta. Disculpas.', + 'sum_of_expenses' => 'Total gastos', + 'sum_of_income' => 'Total ingresos', + 'spent_in_specific_budget' => 'Gastado en el presupuesto ":budget"', + 'sum_of_expenses_in_budget' => 'Gastar todo en el presupuesto ":budget"', + 'left_in_budget_limit' => 'Dejar de gastar acorde del presupuesto', + 'current_period' => 'Período actual', + 'show_the_current_period_and_overview' => 'Mostrar el período actual y el resumen', + 'pref_languages_locale' => 'Para que un idioma distinto al inglés funcione correctamente, su sistema operativo debe disponer de la información regional correcta. Si no está disponible, los datos de divisas, fechas y cantidades pueden tener un formato incorrecto.', + 'budget_in_period' => 'Todas las transacciones para presupuesto ":name"entre:start y :end', + 'chart_budget_in_period' => 'Recuadro para todas las transacciones de presupuesto:name entre:start y:end', + 'chart_account_in_period' => 'Recuadro para todas las transacciones de presupuesto ":name"entre :start y:end', + 'chart_category_in_period' => 'Recuadro para todas las transacciones por categoria ":name"entre:start y :end', + 'chart_category_all' => 'Recuadro para todas las transacciones por categoria ":name"', + 'clone_withdrawal' => 'Clonar este retiro', + 'clone_deposit' => 'Clonar este deposito', + 'clone_transfer' => 'Duplicar esta transferencia', + 'multi_select_no_selection' => 'Ninguno seleccionado', + 'multi_select_select_all' => 'Seleccionar todo', + 'multi_select_n_selected' => 'seleccionado', + 'multi_select_all_selected' => 'Todos seleccionados', + 'multi_select_filter_placeholder' => 'Buscar...', + 'intro_next_label' => 'Siguiente', + 'intro_prev_label' => 'Anterior', + 'intro_skip_label' => 'Saltar', + 'intro_done_label' => 'Listo', + 'between_dates_breadcrumb' => 'Entre inicio y fin', + 'all_journals_without_budget' => 'Todas las transacciones sin presupuesto', + 'journals_without_budget' => 'Transacciones sin un presupuesto', + 'all_journals_without_category' => 'Todas las transacciones sin una categoría', + 'journals_without_category' => 'Transacciones sin una categoría', + 'all_journals_for_account' => 'Todas las transacciones de la cuenta :name', + 'chart_all_journals_for_account' => 'Cuadro de todas las transacciones de la cuenta :name', + 'journals_in_period_for_account' => 'Todas las transacciones por cuenta :name entre :start y :end', + 'transferred' => 'Transferido', + 'all_withdrawal' => 'Todos los gastos', + 'all_transactions' => 'Todas las transacciones', + 'title_withdrawal_between' => 'Todos los gastos entre :start y :end', + 'all_deposit' => 'Todos los ingresos', + 'title_deposit_between' => 'Toda ganacia entre :start y :end', + 'all_transfers' => 'Todas las transferencias', + 'title_transfers_between' => 'Todas las transferencias entre :start y :end', + 'all_transfer' => 'Todas las transferencias', + 'all_journals_for_tag' => 'Todas las transacciones etiquetadas como ":tag"', + 'title_transfer_between' => 'Todas las transferencias entre :start y :end', + 'all_journals_for_category' => 'Todas las transacciones por categoria :name', + 'all_journals_for_budget' => 'Todas las transacciones para el presupuesto :name', + 'chart_all_journals_for_budget' => 'Recuadro de todas las transacciones para presupuesto :name', + 'journals_in_period_for_category' => 'Todas las transacciones para la categoría :name entre :start y :end', + 'journals_in_period_for_tag' => 'Todas las transacciones para etiquetas :tag entre :start y :end', + 'not_available_demo_user' => 'La característica que usted trata de acceder no es válida para usuarios del demo.', + 'exchange_rate_instructions' => 'La cuenta de activos "@nombre" solo acepta transacciones en @moneda_nativa. Si usted desea usar @moneda_extranjera, asegurese que la cantidad en @moneda_nativa sea conocida también:', + 'transfer_exchange_rate_instructions' => 'Cuentas de activos de origen "@source-name" solo acepta transacciones en" @source-currency. cuenta de activos de destino "dest-name" solo acepta transacciones en @dest-currency. Usted debe proveer la cantidad transferida en ambas monedas.', + 'transaction_data' => 'Datos de transacción', + 'invalid_server_configuration' => 'Configuración del servidor no válida', + 'invalid_locale_settings' => 'FireFly III no puede formatear cantidades monetarias porque a su servidor le faltan los paquetes requeridos. Hay instrucciones de cómo hacer esto.', + 'quickswitch' => 'Cambio rápido', + 'sign_in_to_start' => 'Iniciar sesión para comenzar su sesión', + 'sign_in' => 'Iniciar sesión', + 'register_new_account' => 'Registrar una nueva cuenta', + 'forgot_my_password' => 'He perdido mi contraseña', + 'problems_with_input' => 'Hubo algunos problemas con su entrada.', + 'reset_password' => 'Reestablecer su contraseña', + 'button_reset_password' => 'Reestablecer contraseña', + 'reset_button' => 'Reiniciar', + 'want_to_login' => 'Yo quiero entrar al sistema', + 'button_register' => 'Registrar', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v: version Solicitud de autorización', + 'authorization_request_intro' => ': el cliente está solicitando permiso para acceder a su administración financiera. ¿Desea autorizar : cliente para acceder a estos registros?', + 'scopes_will_be_able' => 'Esta aplicación podrá:', + 'button_authorize' => 'Autorizar', + + // check for updates: + 'update_check_title' => 'Ver actualizaciones', + 'admin_update_check_title' => 'Automáticamente chequear actualizaciones', + 'admin_update_check_explain' => 'Firefly III puede chequear actualizaciones automáticamente. cuando usted habilita esta configuración, contactara Github para ver si hay disponible una nueva versión de Firefly III. Cuando sea así, usted tendrá una notificación. Usted puede probar esta notificación usando el boton de la derecha. Por favor indique abajo si quiere que Firefly III chequee actualizaciones.', + 'check_for_updates_permission' => 'Firefly III puede chequear actualizaciones, pero necesita su permiso para hacerlo. Por favor diríjase a administracionpara indicar si desea que esta presentación sea habilitada.', + 'updates_ask_me_later' => 'Preguntarme mas tarde', + 'updates_do_not_check' => 'No buscar actualizaciones', + 'updates_enable_check' => 'Habilitar el buscar actualizaciones', + 'admin_update_check_now_title' => 'Ver actualizaciones ahora', + 'admin_update_check_now_explain' => 'SI usted presiona el botón, Firefly III vera si su actual versión es la última.', + 'check_for_updates_button' => '¡Ver ahora!', + 'update_new_version_alert' => 'Una nueva versión de Firefly III esta disponible. Usted esta ejecutando v:your_version, la ultima versión es v:new_version que se lanzo en :date.', + 'update_current_version_alert' => 'Usted esta ejecutando v:version, que es la ultima versión disponible.', + 'update_newer_version_alert' => 'Usted esta ejecutando v:your_version, que es mas nueva que la versión anterior, v:new_version.', + 'update_check_error' => 'Un error ha ocurrido mientras se verificaban las actualizaciones. Por favor ver los archivos de registro.', + + // search + 'search' => 'Buscar', + 'search_query' => 'Consulta', + 'search_found_transactions' => 'Transacciones encontradas:', + 'general_search_error' => 'Se ha producido un error durante la búsqueda. Por favor, compruebe los archivos de registro para obtener más información.', + 'search_box' => 'Buscar', + 'search_box_intro' => 'Bienvenido a la función de búsqueda de Firefly III. Introduce tu consulta de búsqueda en el cuadro. Asegúrate de revisar el archivo de ayuda porque el buscador es bastante avanzado.', + 'search_error' => 'Error durante la búsqueda', + 'search_searching' => 'Buscando...', + 'search_results' => 'Buscar resultados', + + // repeat frequencies: + 'repeat_freq_yearly' => 'anualmente', + 'repeat_freq_half-year' => 'cada medio año', + 'repeat_freq_quarterly' => 'trimestralmente', + 'repeat_freq_monthly' => 'mensualmente', + 'repeat_freq_weekly' => 'semanalmente', + 'weekly' => 'semanalmente', + 'quarterly' => 'trimestralmente', + 'half-year' => 'cada medio año', + 'yearly' => 'anualmente', + + // export data: + 'import_and_export' => 'Importar y exportar', + 'export_data' => 'Exportar datos', + 'export_and_backup_data' => 'Exportar datos', + 'export_data_intro' => 'Use los datos exportados para pasar a una nueva aplicación financiera. Por favor tenga en cuenta que estos archivos no son un respaldo. No contienen suficiente metadatos para restaurar completamente una nueva instalación de Firefly III. Si usted desea realizar un respaldo de sus datos, por favor haga un respaldo de la base de datos directamente.', + 'export_format' => 'Formato de exportación', + 'export_format_csv' => 'Las comas separan valores (archivos CSV)', + 'export_format_mt940' => 'MT940 formato compatible', + 'include_old_uploads_help' => 'Firefly III no arroja los archivos originales CVS que usted importo en el pasado. Usted puede incluirlos en su informe.', + 'do_export' => 'Exportar', + 'export_status_never_started' => 'La exportación no ha comenzado aun', + 'export_status_make_exporter' => 'Creando cosa del exportador...', + 'export_status_collecting_journals' => 'Recolectando sus transacciones...', + 'export_status_collected_journals' => '¡Recolectadas sus transacciones!', + 'export_status_converting_to_export_format' => 'Convirtiendo tus transacciones...', + 'export_status_converted_to_export_format' => '¡Convertidas tus transacciones!', + 'export_status_creating_journal_file' => 'Creando el archivo de exportación...', + 'export_status_created_journal_file' => '¡El archivo de exportación creado!', + 'export_status_collecting_attachments' => 'Recolectando todos tus accesorios...', + 'export_status_collected_attachments' => '¡Recolectados todos sus accesorios!', + 'export_status_collecting_old_uploads' => 'Recolectando todas sus cargas anteriores...', + 'export_status_collected_old_uploads' => 'Recolectando todas sus cargas anteriores!', + 'export_status_creating_zip_file' => 'Creando un archivo zip...', + 'export_status_created_zip_file' => '¡Se creo un archivo zip!', + 'export_status_finished' => 'Exportación ha acabado con éxito! Hurra!', + 'export_data_please_wait' => 'Espera, por favor...', + + // rules + 'rules' => 'Reglas', + 'rule_name' => 'Nombre de la regla', + 'rule_triggers' => 'La regla dispara cuando', + 'rule_actions' => 'La regla será', + 'new_rule' => 'Nueva regla', + 'new_rule_group' => 'Nuevo grupo de reglas', + 'rule_priority_up' => 'Dar una regla mas prioritaria', + 'rule_priority_down' => 'Dar una regla menos prioritaria', + 'make_new_rule_group' => 'Hacer un nuevo grupo de reglas', + 'store_new_rule_group' => 'Almacenar nuevo grupo de reglas', + 'created_new_rule_group' => 'Nuevo grupo de reglas ":title" guardado!', + 'updated_rule_group' => 'Grupo de reglas actualizado exitosamente ":title".', + 'edit_rule_group' => 'Editar grupo de reglas ":title"', + 'delete_rule_group' => 'Eliminar grupo de reglas ":title"', + 'deleted_rule_group' => 'Eliminar grupo de reglas ":title"', + 'update_rule_group' => 'Actualizar grupo de reglas', + 'no_rules_in_group' => 'No hay reglas en este grupo', + 'move_rule_group_up' => 'Mover la regla hacia arriba', + 'move_rule_group_down' => 'Mover el grupo de reglas hacia abajo', + 'save_rules_by_moving' => 'Guardar esta(s) regla(s) moviéndola(s) a otro grupo:', + 'make_new_rule' => 'Hacer nueva regla en grupo de regla ":title"', + 'rule_help_stop_processing' => 'Al marcar esta casilla, las reglas posteriores de este grupo no se ejecutarán.', + 'rule_help_active' => 'Las reglas inactivas nunca se ejecutan.', + 'stored_new_rule' => 'Guardar la nueva regla con titulo ":title"', + 'deleted_rule' => 'Regla eliminada con titulo ":title"', + 'store_new_rule' => 'Almacenar nueva regla', + 'updated_rule' => 'Regla eliminada con titulo ":title"', + 'default_rule_group_name' => 'Reglaspredeterminada', + 'default_rule_group_description' => 'Todas las reglas que no pertenecen a ningún grupo.', + 'default_rule_name' => 'Su primera regla por defecto', + 'default_rule_description' => 'Esta regla es un ejemplo. Puedes eliminarlo de forma segura.', + 'default_rule_trigger_description' => 'El Hombre que Vendió el Mundo', + 'default_rule_trigger_from_account' => 'David Bowie', + 'default_rule_action_prepend' => 'Comprado el mundo de ', + 'default_rule_action_set_category' => 'Grandes gastos', + 'trigger' => 'Disparador', + 'trigger_value' => 'Disparador en valor', + 'stop_processing_other_triggers' => 'Pare el procesamiento de otros disparadores', + 'add_rule_trigger' => 'Añadir nuevo disparador', + 'action' => 'Acción', + 'action_value' => 'Valor de acción', + 'stop_executing_other_actions' => 'Dejar de ejecutar otras acciones', + 'add_rule_action' => 'Añadir nueva acción', + 'edit_rule' => 'Editar regla ":title"', + 'delete_rule' => 'Eliminar regla ":title"', + 'update_rule' => 'Regla de actualización', + 'test_rule_triggers' => 'Ver transacciones que coinciden', + 'warning_transaction_subset' => 'Por razones de actuación esta lista esta limitada a :max_num_transactions y puede solo mostrar un subconjunto de transacciones coincidentes', + 'warning_no_matching_transactions' => 'No se encontraron transacciones que coinciden. por favor tome nota por motivos de rendimiento, solo el ultimo :num_transactions transacciones han sido chequeadas.', + 'warning_no_valid_triggers' => 'No se proveen disparadores validos.', + 'apply_rule_selection' => 'Aplique la regla ":title" a una seleccion de sus transacciones', + 'apply_rule_selection_intro' => 'Las reglas como ":title" normalmente sólo se aplican a transacciones nuevas o actualizadas, pero puedes indicarle a Firefly III que las ejecute en una selección de transacciones existentes. Esto puede ser útil si has actualizado una regla y necesitas que los cambios se apliquen a todas tus otras transacciones.', + 'include_transactions_from_accounts' => 'Introduzca transacciones desde estas cuentas', + 'applied_rule_selection' => 'Regla ":title" ha sido aplicada a su seleccion.', + 'execute' => 'Ejecutar', + 'apply_rule_group_selection' => 'Aplique la regla de grupo ":title" a una selección de sus transacciones', + 'apply_rule_group_selection_intro' => 'Los grupos de reglas como ":title" normalmente sólo se aplican a transacciones nuevas o actualizadas, pero puedes indicarle a Firefly III que ejecute todas las reglas de este grupo en una selección de transacciones existentes. Esto puede ser útil si has actualizado un grupo de reglas y necesitas que los cambios se apliquen a todas tus otras transacciones.', + 'applied_rule_group_selection' => 'Grupo de reglas ":title" ha sido aplicada a su selección.', + + // actions and triggers + 'rule_trigger_user_action' => 'La acción del usuario es ":trigger_value"', + 'rule_trigger_from_account_starts_choice' => 'Cuenta de origen comienza con..', + 'rule_trigger_from_account_starts' => 'La fuente de la cuenta comienza con ":trigger_value"', + 'rule_trigger_from_account_ends_choice' => 'Cuenta de origen termina con..', + 'rule_trigger_from_account_ends' => 'La fuente de la cuenta termina en ":trigger_value"', + 'rule_trigger_from_account_is_choice' => 'La cuenta de origen es..', + 'rule_trigger_from_account_is' => 'La fuente de la cuenta es ":trigger_value"', + 'rule_trigger_from_account_contains_choice' => 'La cuenta de origen contiene..', + 'rule_trigger_from_account_contains' => 'La fuente de la cuenta contiene ":trigger_value"', + 'rule_trigger_to_account_starts_choice' => 'La cuenta de destino comienza con..', + 'rule_trigger_to_account_starts' => 'La cuenta de destino comienza con ":trigger_value"', + 'rule_trigger_to_account_ends_choice' => 'La cuenta de destino termina con..', + 'rule_trigger_to_account_ends' => 'La cuenta de destino termina con ":trigger_value"', + 'rule_trigger_to_account_is_choice' => 'Cuenta destino es..', + 'rule_trigger_to_account_is' => 'La cuenta de destino es ":trigger_value"', + 'rule_trigger_to_account_contains_choice' => 'Cuenta destino contiene..', + 'rule_trigger_to_account_contains' => 'La cuenta destino contiene ":trigger_value"', + 'rule_trigger_transaction_type_choice' => 'Transacción es del tipo..', + 'rule_trigger_transaction_type' => 'La transacción es de tipo ":trigger_value"', + 'rule_trigger_category_is_choice' => 'Categoría es..', + 'rule_trigger_category_is' => 'Categoría es ":trigger_value"', + 'rule_trigger_amount_less_choice' => 'Cantidad es menos de..', + 'rule_trigger_amount_less' => 'La cantidad es menor que :trigger_value', + 'rule_trigger_amount_exactly_choice' => 'Cantidad es..', + 'rule_trigger_amount_exactly' => 'Cantidad es :trigger_value', + 'rule_trigger_amount_more_choice' => 'Cantidad es mas de..', + 'rule_trigger_amount_more' => 'El monto es mas que :trigger_value', + 'rule_trigger_description_starts_choice' => 'Descripción comienza con..', + 'rule_trigger_description_starts' => 'La descripción comienza con ":trigger_value"', + 'rule_trigger_description_ends_choice' => 'Descripción termina con..', + 'rule_trigger_description_ends' => 'La descripción termina con ":trigger_value"', + 'rule_trigger_description_contains_choice' => 'Descripción contiene..', + 'rule_trigger_description_contains' => 'La descripción contiene ":trigger_value"', + 'rule_trigger_description_is_choice' => 'Descripción es..', + 'rule_trigger_description_is' => 'La descripción es ":trigger_value"', + 'rule_trigger_budget_is_choice' => 'Presupuesto es..', + 'rule_trigger_budget_is' => 'Presupuesto es ":trigger_value"', + 'rule_trigger_tag_is_choice' => '(una) etiqueta es..', + 'rule_trigger_tag_is' => 'Una etiqueta es ":trigger_value"', + 'rule_trigger_has_attachments_choice' => 'Tiene al menos tantos archivos adjuntos', + 'rule_trigger_has_attachments' => 'Tiene al menos :trigger_value anexo (s)', + 'rule_trigger_store_journal' => 'Cuando la transacción es creada', + 'rule_trigger_update_journal' => 'Cuando la transacción es actualizada', + 'rule_trigger_has_no_category_choice' => 'No tiene categoría', + 'rule_trigger_has_no_category' => 'La transacción no tiene categoría', + 'rule_trigger_has_any_category_choice' => 'Tiene (cualquier) categoría', + 'rule_trigger_has_any_category' => 'La transacción tiene (cualquier) categoría', + 'rule_trigger_has_no_budget_choice' => 'No tiene presupuesto', + 'rule_trigger_has_no_budget' => 'Transacción no tiene presupuesto', + 'rule_trigger_has_any_budget_choice' => 'Tiene un (cualquier) presupuesto', + 'rule_trigger_has_any_budget' => 'La transacción tiene (cualquier) presupuesto', + 'rule_trigger_has_no_tag_choice' => 'No tiene etiqueta(s)', + 'rule_trigger_has_no_tag' => 'La transacción no tiene etiqueta(s)', + 'rule_trigger_has_any_tag_choice' => 'Tiene una o mas (cualquier) etiquetas', + 'rule_trigger_has_any_tag' => 'La transacción tiene una o mas (cualquier) etiquetas', + 'rule_trigger_any_notes_choice' => 'Tiene (cualquier) notas', + 'rule_trigger_any_notes' => 'La transacción tiene (cualquier) notas', + 'rule_trigger_no_notes_choice' => 'No tiene notas', + 'rule_trigger_no_notes' => 'Transacción no tiene notas', + 'rule_trigger_notes_are_choice' => 'Notas son..', + 'rule_trigger_notes_are' => 'Las notas son ":trigger_value"', + 'rule_trigger_notes_contain_choice' => 'Las notas contienen..', + 'rule_trigger_notes_contain' => 'Las notas contienen ":trigger_value"', + 'rule_trigger_notes_start_choice' => 'Las notas comienzan con..', + 'rule_trigger_notes_start' => 'Las notas comienzan con ":trigger_value"', + 'rule_trigger_notes_end_choice' => 'Las notas terminan con..', + 'rule_trigger_notes_end' => 'Las notas terminan con ":trigger_value"', + 'rule_action_set_category' => 'Establecer categoría en ":action_value"', + 'rule_action_clear_category' => 'Borrar categoría', + 'rule_action_set_budget' => 'Establecer presupuesto en ":action_value "', + 'rule_action_clear_budget' => 'Borrar presupuesto', + 'rule_action_add_tag' => 'Añadir etiqueta ":action_value"', + 'rule_action_remove_tag' => 'Quitar la etiqueta ":action_value"', + 'rule_action_remove_all_tags' => 'Eliminar todas las etiquetas', + 'rule_action_set_description' => 'Establecer la descripcion en ":action_value"', + 'rule_action_append_description' => 'Anexar la descripción con ":action_value"', + 'rule_action_prepend_description' => 'Anteponer la descripción con ":action_value"', + 'rule_action_set_category_choice' => 'Establecer categoría para..', + 'rule_action_clear_category_choice' => 'Eliminar cualquier categoría', + 'rule_action_set_budget_choice' => 'Establecer presupuesto para..', + 'rule_action_clear_budget_choice' => 'Eliminar cualquier presupuesto', + 'rule_action_add_tag_choice' => 'Añadir etiqueta..', + 'rule_action_remove_tag_choice' => 'Eliminar etiqueta..', + 'rule_action_remove_all_tags_choice' => 'Eliminar todas las etiquetas', + 'rule_action_set_description_choice' => 'Establecer descripción para..', + 'rule_action_append_description_choice' => 'Adjuntar descripción con..', + 'rule_action_prepend_description_choice' => 'Anteponer descripción con..', + 'rule_action_set_source_account_choice' => 'Configurar cuenta de origen para...', + 'rule_action_set_source_account' => 'Establecer cuenta de origen en :action_value', + 'rule_action_set_destination_account_choice' => 'Establecer cuenta de destino en...', + 'rule_action_set_destination_account' => 'Establecer cuenta de destino en :action_value', + 'rule_action_append_notes_choice' => 'Anexar notas con..', + 'rule_action_append_notes' => 'Anexar notas con ":action_value"', + 'rule_action_prepend_notes_choice' => 'Prepara notas con..', + 'rule_action_prepend_notes' => 'Prepara notas con ":action_value"', + 'rule_action_clear_notes_choice' => 'Eliminar cualquier nota', + 'rule_action_clear_notes' => 'Eliminar cualquier nota', + 'rule_action_set_notes_choice' => 'Establecer notas para..', + 'rule_action_set_notes' => 'Establecer notas para:action_value', + + 'rules_have_read_warning' => '¿Has leído la advertencia?', + 'apply_rule_warning' => 'Advertencia: Ejecutando una regla (grupo) en una gran selección de transacciones podría tomar años, y podría exceder el tiempo de espera. Si lo hace, la regla (grupo) solo se aplicara a un subconjunto desconocido de sus transacciones. Esto podría dejar a su administración financiera en ruinas. por favor tenga cuidado.', + + // tags + 'store_new_tag' => 'Almacenar nueva etiqueta', + 'update_tag' => 'Actualizar etiqueta', + 'no_location_set' => 'Ubicación no establecida.', + 'meta_data' => 'Meta Datos', + 'location' => 'Ubicación', + 'without_date' => 'Sin fecha', + 'result' => 'Resultado', + 'sums_apply_to_range' => 'Todas las sumas aplican al rango seleccionado', + 'mapbox_api_key' => 'Para usar el mapa, obtenga una clave API de MapboxAbra su.env y introduzca este código después de MAPBOX_API_KEY=.', + 'press_tag_location' => 'Haga clic o pulse de forma prolongada para definir la ubicación de la etiqueta.', + 'clear_location' => 'Eliminar ubicación', + + // preferences + 'pref_home_screen_accounts' => 'Cuentas de la pantalla de inicio', + 'pref_home_screen_accounts_help' => '¿Qué cuentas se deben mostrar en la página de inicio?', + 'pref_view_range' => 'Rango de vision', + 'pref_view_range_help' => 'Algunos gráficos se agrupan automáticamente en periodos. ¿que periodo prefiere usted?', + 'pref_1D' => 'Un dia', + 'pref_1W' => 'Una semana', + 'pref_1M' => 'Un mes', + 'pref_3M' => 'Tres meses (trimestre)', + 'pref_6M' => 'Seis meses', + 'pref_1Y' => 'Un año', + 'pref_languages' => 'Idiomas', + 'pref_languages_help' => 'Firefly III apoya varios idiomas. cual usted prefiere?', + 'pref_custom_fiscal_year' => 'Configuraciónes del año fiscal', + 'pref_custom_fiscal_year_label' => 'Habilitado', + 'pref_custom_fiscal_year_help' => 'En países que utilizan año fiscal diferente del 1 al 31 de diciembre, usted puede cambiarlo y especificar los días de inicio / y termino del año fiscal', + 'pref_fiscal_year_start_label' => 'Fecha de inicio del año fiscal', + 'pref_two_factor_auth' => 'Verificación en 2 pasos', + 'pref_two_factor_auth_help' => 'Cuando usted habilita la verificación en 2 pasos ( también conocida como autenticacion de dos factores) usted agrega una capa adicional de seguridad a su cuenta. usted inicia la sesión que conoce (código de verificación). los códigos de generación son generados por una aplicación de su teléfono, tales como Authy o Google Authenticador.', + 'pref_enable_two_factor_auth' => 'Permita la verificación de 2 pasos', + 'pref_two_factor_auth_disabled' => 'Codigo de verificacion en 2 pasos removido y inabilitado', + 'pref_two_factor_auth_remove_it' => 'No olvide eliminar la cuenta de su aplicación de autenticacion!', + 'pref_two_factor_auth_code' => 'Verificar código', + 'pref_two_factor_auth_code_help' => 'Escanee el código QR con una aplicación en su teléfono como Authy o Google autenticator y ingrese el código generado.', + 'pref_two_factor_auth_reset_code' => 'Reiniciar código de verificación', + 'pref_two_factor_auth_remove_code' => 'Eliminar el código de verificación', + 'pref_two_factor_auth_remove_will_disable' => '(Esto también desactivara la autenticacion de dos factores)', + 'pref_save_settings' => 'Guardar la configuración', + 'saved_preferences' => '¡Preferencias guardadas!', + 'preferences_general' => 'General', + 'preferences_frontpage' => 'Pantalla de inicio', + 'preferences_security' => 'Seguridad', + 'preferences_layout' => 'Diseño', + 'pref_home_show_deposits' => 'Mostrar los depósitos en la pantalla de inicio', + 'pref_home_show_deposits_info' => 'La pantalla de inicio ya muestra sus cuentas de gastos. ¿debería mostrar también su cuenta de ingresos?', + 'pref_home_do_show_deposits' => 'Si, muestrales', + 'successful_count' => 'de cual :count exitoso', + 'list_page_size_title' => 'Tamaño de pagina', + 'list_page_size_help' => 'Cualquier lista de cosas (cuentas, transacciones, etc) muestra como mucho esta cantidad por pagina.', + 'list_page_size_label' => 'Tamaño de pagina', + 'between_dates' => '(:start y :end)', + 'pref_optional_fields_transaction' => 'Campos opcionales para transacciones', + 'pref_optional_fields_transaction_help' => 'Por defecto no todos los campos se habilitan al crear una nueva transacción (debido al desorden). abajo usted puede habilitar estos campos si usted piensa que pueden ser útiles. por supuesto, cualquier campo que este desactivado, pero ya completado, sera visible a pesar de la configuración.', + 'optional_tj_date_fields' => 'Campos de fecha', + 'optional_tj_business_fields' => 'Campos comerciales', + 'optional_tj_attachment_fields' => 'Campos de datos adjuntos', + 'pref_optional_tj_interest_date' => 'Fecha de intereses', + 'pref_optional_tj_book_date' => 'Fecha del libro de registro', + 'pref_optional_tj_process_date' => 'Fecha de procesamiento', + 'pref_optional_tj_due_date' => 'Fecha de caducidad', + 'pref_optional_tj_payment_date' => 'Fecha de pago', + 'pref_optional_tj_invoice_date' => 'Fecha de la factura', + 'pref_optional_tj_internal_reference' => 'Referencia interna', + 'pref_optional_tj_notes' => 'Notas', + 'pref_optional_tj_attachments' => 'Adjuntos', + 'optional_field_meta_dates' => 'Fechas', + 'optional_field_meta_business' => 'Negocios', + 'optional_field_attachments' => 'Adjuntos', + 'optional_field_meta_data' => 'Opcional meta datos', + + // profile: + 'change_your_password' => 'Cambie su contraseña', + 'delete_account' => 'Eliminar cuenta', + 'current_password' => 'Contraseña actual', + 'new_password' => 'Nueva contraseña', + 'new_password_again' => 'Nueva contraseña (de nuevo)', + 'delete_your_account' => 'Borre su cuenta', + 'delete_your_account_help' => 'Eliminando su cuenta también eliminara cualquier otra cuenta, transacciones,cualquierque podría haber salvado en Firefly III. se habrá IDO.', + 'delete_your_account_password' => 'Introduzca su contraseña para continuar.', + 'password' => 'Contraseña', + 'are_you_sure' => '¿Esta usted seguro? usted no puede deshacer esto.', + 'delete_account_button' => 'Borre su cuenta', + 'invalid_current_password' => 'Contraseña actual invalida!', + 'password_changed' => 'Contraseña cambiada!', + 'should_change' => 'La idea es cambiar su contraseña.', + 'invalid_password' => 'Contraseña invalida!', + 'what_is_pw_security' => '¿Que es "verificar la seguridad de contraseña?', + 'secure_pw_title' => 'Como escoger una contraseña segura', + 'secure_pw_history' => 'En agosto de 2017 el conocido investigador de seguridad Troy Hunt publicó una lista de 306 millones de contraseñas robadas. Estas contraseñas fueron robadas durante intrusiones a empresas como LinkedIn, Adobe y NeoPets (y muchos más).', + 'secure_pw_check_box' => 'Chequeando la casilla, Firefly III enviara el hash SHA1 de su contraseña al el sitio web de Troy Hunt para ver si esta en la lista.Esto le impedira a usted de usar contraseñas inseguras como se recomienda en la ultima NISH Publicación especial sobre este tema.', + 'secure_pw_sha1' => '¿Pero pensé que SHA1 estaba dañado?', + 'secure_pw_hash_speed' => 'Si, pero no en este contexto. Como usted puede leer en el sitio web que detalla como rompieron SHA1-hash. Ahora solo toma 10,000 años usando una sola maquina GPU.', + 'secure_pw_hash_security' => 'Esta colisión no seria igual a su contraseña, ni seria útil en (un sitio como) Firefly III. Esta aplicación no usa SHA1 para la verificación de contraseña. así que es seguro chequear esta casilla. Su contraseña es cifrada y enviada a travez de HTTPS.', + 'secure_pw_should' => '¿Debo chequear la casilla?', + 'secure_pw_long_password' => 'Si usted acaba de generar una contraseña larga de un solo uso para Firefly III usando algún tipo de generador de contraseñas:no.', + 'secure_pw_short' => 'Si usted acaba de entrar la contraseña que siempre usa:Por favor si .', + 'command_line_token' => 'Token de linea de comando', + 'explain_command_line_token' => 'Necesita este token para realizar opciones de línea de comando, como importar o exportar datos. Sin él, dichos comandos confidenciales no funcionarán. No compartas tu token de línea de comando. Nadie te lo pedirá, ni siquiera a nosotros. Si crees que lo has perdido, o si estás paranoico, regenera tu token pulsando el botón.', + 'regenerate_command_line_token' => 'Regenerar token de línea de comando', + 'token_regenerated' => 'Se generó un nuevo token de línea de comandos', + 'change_your_email' => 'Cambie su dirección de correo', + 'email_verification' => 'Un mensaje de correo electrónico sera enviado a su nueva dirección de correo viejas y nuevas. por motivos de seguridad, usted no podrá iniciar sesión hasta que verifique su nueva dirección de correo electrónico. Si no esta seguro de si su instalación Firefly III puede enviar correos electrónicos, por favor no use esta función. Si usted es administrador, usted puede probar esto en la administracion.', + 'email_changed_logout' => 'Hasta que usted verifique su dirección de correo electrónico, usted no puede iniciar sesión.', + 'login_with_new_email' => 'Usted puede ahora iniciar sesión con su nueva dirección de correo electrónico.', + 'login_with_old_email' => 'Usted puede ahora iniciar sesión con su vieja dirección de correo electrónico otra vez.', + + // attachments + 'nr_of_attachments' => 'Un archivo adjunto:count archivos adjuntos', + 'attachments' => 'Archivos adjuntos', + 'edit_attachment' => 'Editar cuenta de archivos ":name"', + 'update_attachment' => 'Actualizar archivo adjunto', + 'delete_attachment' => 'Eliminar archivo adjunto ":name"', + 'attachment_deleted' => 'Eliminar archivo adjunto ":name"', + 'attachment_updated' => 'Actualizar archivo adjunto ":name"', + 'upload_max_file_size' => 'Tamaño máximo de archivo::size', + + // transaction index + 'title_expenses' => 'Gastos', + 'title_withdrawal' => 'Gastos', + 'title_revenue' => 'Ingresos / salarios', + 'title_deposit' => 'Ingresos / salarios', + 'title_transfer' => 'Transferencias', + 'title_transfers' => 'Transferencias', + + // convert stuff: + 'convert_is_already_type_Withdrawal' => 'Esta transferencia ya es un retiro: crwdn: crwdn', + 'convert_is_already_type_Deposit' => 'Esta transacción ya es un deposito', + 'convert_is_already_type_Transfer' => 'Esta transacción ya es una transferencia', + 'convert_to_Withdrawal' => 'Convierta ":description" a un retiro', + 'convert_to_Deposit' => 'Convierta ":description" en un deposito', + 'convert_to_Transfer' => 'Convierta ":description" en una transferencia', + 'convert_options_WithdrawalDeposit' => 'Convertir una retirada de efectivo en un depósito', + 'convert_options_WithdrawalTransfer' => 'Convertir una retirada de efectivo en una transferencia', + 'convert_options_DepositTransfer' => 'Convertir un depósito en una transferencia', + 'convert_options_DepositWithdrawal' => 'Convertir un depósito en una retirada de efectivo', + 'convert_options_TransferWithdrawal' => 'Convertir una transferencia en una retirada de efectivo', + 'convert_options_TransferDeposit' => 'Convertir una transferencia en un depósito', + 'convert_Withdrawal_to_deposit' => 'Convierta este retiro: crwdn en un deposito', + 'convert_Withdrawal_to_transfer' => 'Convierta este retiro en una transferencia', + 'convert_Deposit_to_withdrawal' => 'Convierta este deposito en un retiro: crwdn', + 'convert_Deposit_to_transfer' => 'Convierta este deposito en una transferencia', + 'convert_Transfer_to_deposit' => 'Convierta esta transferencia en un deposito', + 'convert_Transfer_to_withdrawal' => 'Convierta esta transferencia en un retiro: crwdn', + 'convert_please_set_revenue_source' => 'Por favor elija la cuenta de ingresos de donde vendrá el dinero.', + 'convert_please_set_asset_destination' => 'Por favor elija la cuenta de activos a donde el dinero se destinara.', + 'convert_please_set_expense_destination' => 'Por favor elija la cuenta de gastos a la que ira el dinero.', + 'convert_please_set_asset_source' => 'Por favor elija la cuenta de activos de donde vendrá el dinero.', + 'convert_explanation_withdrawal_deposit' => 'Si usted convierte este retiro :crwdn en un deposito,:amount sera depositado en :sourceNameen vez de tomar de el.', + 'convert_explanation_withdrawal_transfer' => 'Si usted convierte esto ;crwdn:gr:0:gr:crwdn; en una transferencia, :amount sera transferido desde :sourceName a una nueva cuenta de ingresos, en lugar de pagarse a :destinationName.', + 'convert_explanation_deposit_withdrawal' => 'Si usted convierte este deposito en un retiro, :amount se eliminara de :destinationName en vez de añadirse a él.', + 'convert_explanation_deposit_transfer' => 'Si convierte este deposito en una transferencia,:amount sera transferido desde una cuenta de activos de su elección :destinationName.', + 'convert_explanation_transfer_withdrawal' => 'Si convierte esta transferencia en un retiroc :crwdn:amount ira desde :sourceName a un nuevo destino como gastos , en vez de como una transferencia.', + 'convert_explanation_transfer_deposit' => 'Si convierte esta transferencia en un deposito,:amount sera depositado en la cuenta ::destinationName en vez de ser transferida allí.', + 'converted_to_Withdrawal' => 'La transacción se convirtió en un retiro: crwdn', + 'converted_to_Deposit' => 'La transacción se ha convertido en un deposito', + 'converted_to_Transfer' => 'La transacción se convirtió en transferencia', + 'invalid_convert_selection' => 'L a cuenta que usted ha selecionado ya esta en uso o no existe.', + + // create new stuff: + 'create_new_withdrawal' => 'Crear nuevo retiro: crwdn', + 'create_new_deposit' => 'Crear nuevo deposito', + 'create_new_transfer' => 'Crear nueva transferencia', + 'create_new_asset' => 'Crear nueva cuenta de activos', + 'create_new_expense' => 'Crear nueva cuenta de gastos', + 'create_new_revenue' => 'Crear nueva cuenta de ingresos', + 'create_new_piggy_bank' => 'Crear nueva alcancia', + 'create_new_bill' => 'Crear nueva factura', + + // currencies: + 'create_currency' => 'Crear nueva moneda', + 'store_currency' => 'Almacenar nueva moneda', + 'update_currency' => 'Actualizar moneda', + 'new_default_currency' => ':name es ahora moneda por defecto.', + 'cannot_delete_currency' => 'No puede eliminar :name porque todavía esta en uso.', + 'deleted_currency' => 'Moneda :name eliminada', + 'created_currency' => 'Moneda :name creada', + 'updated_currency' => 'Moneda :name actualizada', + 'ask_site_owner' => 'Por favor pregunte :owner por agregar,elimine o edite monedas.', + 'currencies_intro' => 'Firefly III respalda varias monedas que usted puede establecer y habilitar aquí.', + 'make_default_currency' => 'hacer por defecto', + 'default_currency' => 'en mora', + + // forms: + 'mandatoryFields' => 'Campos obligatorios', + 'optionalFields' => 'Campos opcionales', + 'options' => 'Opciones', + + // budgets: + 'create_new_budget' => 'Crear un nuevo presupuesto', + 'store_new_budget' => 'Almacene el nuevo presupuesto', + 'stored_new_budget' => 'Almacenar el nuevo presupuesto ":name"', + 'available_between' => 'Disponible entre :start y :end', + 'transactionsWithoutBudget' => 'Gastos sin presupuesto', + 'transactions_no_budget' => 'Gastos sin presupuesto entre :start y :end', + 'spent_between' => 'Gasto entre :start y :end', + 'createBudget' => 'Nuevo presupuesto', + 'inactiveBudgets' => 'Presupuestos inactivos', + 'without_budget_between' => 'Transacciones sin presupuesto entre :start y :end', + 'delete_budget' => 'Eliminar presupuesto ":name"', + 'deleted_budget' => 'Presupuesto eliminado ":name"', + 'edit_budget' => 'Editar presupuesto ":name"', + 'updated_budget' => 'Presupuesto actualizado ":name"', + 'update_amount' => 'Actualizar monto', + 'update_budget' => 'Actualizar presupuesto', + 'update_budget_amount_range' => 'Cantidad disponible (esperada) actualizada entre :start y :end', + 'budget_period_navigator' => 'Periodo navegador', + 'info_on_available_amount' => '¿ que tengo disponible?', + 'available_amount_indication' => 'Use estos montos para obtener una indicación de cual podría ser el presupuesto total.', + 'suggested' => 'Sugerido', + 'average_between' => 'Promedio entre :start y :end', + + // bills: + 'matching_on' => 'Emparejar en', + 'between_amounts' => 'entre :low y :high.', + 'repeats' => 'Repeticiones', + 'connected_journals' => 'Transacciones conectadas', + 'auto_match_on' => 'Automáticamente igualado por Firefly III', + 'auto_match_off' => 'No igualado automaticamente por Firefly III', + 'next_expected_match' => 'Siguiente partido esperado', + 'delete_bill' => 'Eliminar factura ":name"', + 'deleted_bill' => 'Eliminar factura ":name"', + 'edit_bill' => 'Editar factura ":name"', + 'more' => 'Mas', + 'rescan_old' => 'Volver a analizar transacciones viejas', + 'update_bill' => 'Actualizar factura', + 'updated_bill' => 'Actualizar factura ":name"', + 'store_new_bill' => 'Almacenar nueva factura', + 'stored_new_bill' => 'Almacenar nueva factura ":name"', + 'cannot_scan_inactive_bill' => 'Las facturas inactivas no pueden ser escaneadas.', + 'rescanned_bill' => 'Volver a escanear todo.', + 'average_bill_amount_year' => 'Monto promedio de la factura (:year)', + 'average_bill_amount_overall' => 'Monto promedio de la factura (sobretodo)', + 'bill_is_active' => 'Bill esta activo', + 'bill_expected_between' => 'Esperado entre :start y :end', + 'bill_will_automatch' => 'Bill se vinculara automáticamente a transacciones coincidentes', + 'skips_over' => 'salta sobre', + + + // accounts: + 'details_for_asset' => 'Detalles para la cuenta de activos ":name"', + 'details_for_expense' => 'Detalles para la cuenta de gastos ":name"', + 'details_for_revenue' => 'Detalles para la cuenta de ingresos ": nombre"', + 'details_for_cash' => 'Detalle para la cuenta de efectivo ":name"', + 'store_new_asset_account' => 'Almacenar nueva cuenta de activos', + 'store_new_expense_account' => 'Almacenar cuenta nueva de gastos', + 'store_new_revenue_account' => 'Almacenar cuenta nueva de ingresos', + 'edit_asset_account' => 'Editar cuenta de activos ":name"', + 'edit_expense_account' => 'Editar cuenta de gastos ":name"', + 'edit_revenue_account' => 'Editar cuenta de ganancias ":name"', + 'delete_asset_account' => 'Eliminar cuenta de activo ":name"', + 'delete_expense_account' => 'Eliminar cuenta de gastos ":name"', + 'delete_revenue_account' => 'Eliminar cuenta de ganancias ":name"', + 'asset_deleted' => 'Se ha eliminado exitosamente la cuenta de activos ":name"', + 'expense_deleted' => 'Exitosamente eliminado la cuenta de gastos ":name"', + 'revenue_deleted' => 'Exitosamente eliminado cuenta de ganacias ":name"', + 'update_asset_account' => 'Actualizar cuenta de activos', + 'update_expense_account' => 'Actualizar cuenta de gastos', + 'update_revenue_account' => 'Actualizar cuenta de ingresos', + 'make_new_asset_account' => 'Crear nueva cuenta de activo', + 'make_new_expense_account' => 'Crear nueva cuenta de gastos', + 'make_new_revenue_account' => 'Crear nueva cuenta de ingresos', + 'asset_accounts' => 'Cuenta de activos', + 'expense_accounts' => 'Cuentas de gastos', + 'revenue_accounts' => 'Cuentas de ingresos', + 'cash_accounts' => 'Cuentas de efectivo', + 'Cash account' => 'Cuenta de efectivo', + 'reconcile_account' => 'Reconciliar cuenta ":account"', + 'delete_reconciliation' => 'Eliminar reconciliacion', + 'update_reconciliation' => 'Actualizar reconciliacion', + 'amount_cannot_be_zero' => 'El monto no puede ser cero', + 'end_of_reconcile_period' => 'Fin del periodo de reconciliacion::period', + 'start_of_reconcile_period' => 'Inicio de periodo de reconciliación::period', + 'start_balance' => 'Balance inicial', + 'end_balance' => 'Balance final', + 'update_balance_dates_instruction' => 'Coinciden con las cantidades y fechas sobre su estado de cuenta, y presione "comenzar reconciliación"', + 'select_transactions_instruction' => 'Seleccione las transacciones que aparecen en su estado bancario.', + 'select_range_and_balance' => 'Primero verifique el rango de las fechas y los saldos. luego presione "comenzar reconciliación"', + 'date_change_instruction' => 'Si usted cambia el rango de las fechas ahora, se perderá cualquier progreso.', + 'update_selection' => 'Selección de actualización', + 'store_reconcile' => 'Guardar reconciliación', + 'reconciliation_transaction' => 'Transacción de reconciliación', + 'Reconciliation' => 'Reconciliacion', + 'reconciliation' => 'Reconciliacion', + 'reconcile_options' => 'Opciones de reconciliacion', + 'reconcile_range' => 'Rango de reconciliacion', + 'start_reconcile' => 'Comienzo de reconciliación', + 'cash' => 'efectivo', + 'account_type' => 'Tipo de cuenta', + 'save_transactions_by_moving' => 'Guarde estas transacción (es) moviendolas a otra cuenta:', + 'stored_new_account' => 'Nueva cuenta ":name" almacenada!', + 'updated_account' => 'Cuenta actualizada ":name"', + 'credit_card_options' => 'Opciones de tarjeta de crédito', + 'no_transactions_account' => 'No hay transacciones ( en este periodo) para cuenta de activos ":name".', + 'no_data_for_chart' => 'No hay suficiente información (todavía) para generar este gráfico.', + 'select_more_than_one_account' => 'Por favor seleccione mas de una cuenta', + 'select_more_than_one_category' => 'Por favor seleccione mas de una categoría', + 'select_more_than_one_budget' => 'Por favor seleccione mas de un presupuesto', + 'select_more_than_one_tag' => 'Por favor seleccione mas de una etiqueta', + 'account_default_currency' => 'Si usted selecciona otra moneda, las nuevas transacciones de esta cuenta tendrán esta moneda preseleccionada.', + 'reconcile_has_more' => 'Su libro principal de Firefly III tiene mas dinero de lo que su banco afirma debería tener, Hay varias opciones. por favor elija que hacer. luego, presione "confirmar reconciliación".', + 'reconcile_has_less' => 'Su libro principal de Firefly III tiene menos dinero de el que su banco dice que usted debería tener. hay varias opciones. Por favor elija que hacer, luego presione " Confirmar reconciliación".', + 'reconcile_is_equal' => 'Su libro principal de Firefly III y sus estados de cuenta coinciden. No hay nada que hacer. por favor presione "Confirmar reconciliación" para confirmar su entrada.', + 'create_pos_reconcile_transaction' => 'Borre las transacciones seleccionadas, y cree una corrección agregando :amount a esta cuenta de activo.', + 'create_neg_reconcile_transaction' => 'Borre las transacciones seleccionadas, y cree una corrección eliminando :amount de esta cuenta de activo.', + 'reconcile_do_nothing' => 'Borre la transacciones seleccionadas, pero no las corrija.', + 'reconcile_go_back' => 'Usted puede siempre editar o eliminar una corrección mas tarde.', + 'must_be_asset_account' => 'Usted solo puede reconciliar cuentas de activos', + 'reconciliation_stored' => 'Reconciliación almacenada', + 'reconcilliation_transaction_title' => 'Reconciliación (:from a :to)', + 'reconcile_this_account' => 'Reconciliar esta cuenta', + 'confirm_reconciliation' => 'Confirmar la reconciliacion', + 'submitted_start_balance' => 'Balance final enviado', + 'selected_transactions' => 'Transacciones seleccionadas (:count)', + 'already_cleared_transactions' => 'Transacciones ya despejadas (:count)', + 'submitted_end_balance' => 'Balance final enviado', + 'initial_balance_description' => 'Balance inicial para ":account"', + + // categories: + 'new_category' => 'Nueva categoría', + 'create_new_category' => 'Crear una nueva categoria', + 'without_category' => 'Sin categoría', + 'update_category' => 'Actualizar categoría', + 'updated_category' => 'Actualizar categoría ":name"', + 'categories' => 'Categorías', + 'edit_category' => 'Editar categoría ":name"', + 'no_category' => '(sin categoría)', + 'category' => 'Categoria', + 'delete_category' => 'Eliminar categoría ":name"', + 'deleted_category' => 'Categoría eliminada ":name"', + 'store_category' => 'Guardar nueva categoria', + 'stored_category' => 'Nueva categoría guardada ":name"', + 'without_category_between' => 'Sin categoría entre :start y:end', + + // transactions: + 'update_withdrawal' => 'Actualización de retiro', + 'update_deposit' => 'Actualización de deposito', + 'update_transfer' => 'Actualización de transferencia', + 'updated_withdrawal' => 'Retiro actualizado', + 'updated_deposit' => 'Actualización de deposito ":description"', + 'updated_transfer' => 'Transferencia actualizada ":description"', + 'delete_withdrawal' => 'Eliminar;crwdn:gr:0:gr:crwdn; ":description"', + 'delete_deposit' => 'Eliminar deposito ":description"', + 'delete_transfer' => 'Eliminar transferencia ":description"', + 'deleted_withdrawal' => 'Eliminado exitosamente', + 'deleted_deposit' => 'Deposito eliminado exitosamente ":description"', + 'deleted_transfer' => 'Transferencia eliminada exitosamente ":description"', + 'stored_journal' => 'Nueva transacción creada exitosamente ":description"', + 'select_transactions' => 'Seleccionar transacciones', + 'rule_group_select_transactions' => 'Aplicar ":title" a las transacciones', + 'rule_select_transactions' => 'Aplicar ":title" a las transacciones', + 'stop_selection' => 'Pare de seleccionas transacciones', + 'reconcile_selected' => 'Reconciliar', + 'mass_delete_journals' => 'Eliminar un numero de transacciones', + 'mass_edit_journals' => 'Editar un numero de transacciones', + 'mass_bulk_journals' => 'Bulk editar un numero de transacciones', + 'mass_bulk_journals_explain' => 'Si usted no desea cambiar sus transacciones a una mediante la función de edición masiva, usted puede actualizarlas de una sola vez. simplemente seleccione la categoría, las etiquetas o el presupuesto preferidos en los campos de abajo, y todas las transacciones de la tabla se actualizaran.', + 'bulk_set_new_values' => 'Use las entradas abajo para establecer nuevos valores. Si usted los deja vacíos, serán vacíos para todos. también, tenga en cuenta que solo los retiros tendrán un presupuesto.', + 'no_bulk_category' => 'No actualizar la categoria', + 'no_bulk_budget' => 'No actualizar el presupuesto', + 'no_bulk_tags' => 'No actualizar etiqueta(s)', + 'bulk_edit' => 'Edición masiva', + 'cannot_edit_other_fields' => 'Usted no puede editar en masa otros campos ademas de los que están aquí, porque no hay espacio para mostrarlos. siga el enlace y editelo uno a uno, si usted necesita editar estos campos.', + 'no_budget' => '(no budget)', + 'no_budget_squared' => '(sin presupuesto)', + 'perm-delete-many' => 'Eliminar muchos elementos de una sola vez puede ser perturbador. Por favor sea cuidadoso.', + 'mass_deleted_transactions_success' => 'Eliminar :amount transacción (es).', + 'mass_edited_transactions_success' => 'Actualizado :amount transacción (es)', + 'opt_group_no_account_type' => '(Sin tipo de cuenta)', + 'opt_group_defaultAsset' => 'Cuenta de ingresos por mora', + 'opt_group_savingAsset' => 'Cuenta de ahorros', + 'opt_group_sharedAsset' => 'Cuenta de activos compartidas', + 'opt_group_ccAsset' => 'Tarjetas de credito', + 'notes' => 'Notas', + + // new user: + 'welcome' => 'Bienvenido a Firefly III!', + 'submit' => 'Enviar', + 'getting_started' => 'Comenzando', + 'to_get_started' => 'Es bueno ver que usted ha instalado con éxito Firefly III. Para comenzar con esta regla, por favor ingrese el nombre de su banco y el saldo de su cuenta de cheques principal. No se preocupe todavía si tiene varias cuentas. usted puede agregarlas luego. Es solo que Firefly III necesita algo para empezar.', + 'savings_balance_text' => 'Firefly II creara automáticamente una cuenta de ahorros para usted. Por + defecto. No abra dinero en su cuenta de ahorros. pero si le dice a Firefly III el saldo se almacenara como tal.', + 'finish_up_new_user' => 'Eso es! Usted puede continuar presionando. Usted sera llevado al indice de Firefly III.', + 'stored_new_accounts_new_user' => 'Hurra! Sus nuevas cuentas han sido almacenadas.', + + // home page: + 'yourAccounts' => 'Tus cuentas', + 'budgetsAndSpending' => 'Presupuestos y gastos', + 'savings' => 'Ahorros', + 'newWithdrawal' => 'Nuevo gasto', + 'newDeposit' => 'Nuevo deposito', + 'newTransfer' => 'Nueva transferencia', + 'bills_to_pay' => 'Facturas por pagar', + 'per_day' => 'Por dia', + 'left_to_spend_per_day' => 'Dejar para gastar por dia', + 'bills_paid' => 'Facturas pagadas', + + // menu and titles, should be recycled as often as possible: + 'currency' => 'Moneda', + 'preferences' => 'Preferencias', + 'logout' => 'Cerrar sesión', + 'toggleNavigation' => 'Activar navegación', + 'searchPlaceholder' => 'Buscar...', + 'version' => 'Versión', + 'dashboard' => 'Panel de control', + 'currencies' => 'Divisas', + 'accounts' => 'Cuentas', + 'Asset account' => 'Cuenta de activos', + 'Default account' => 'Cuenta de activos', + 'Expense account' => 'Cuenta de gastos', + 'Revenue account' => 'Cuenta de ganancia', + 'Initial balance account' => 'Cuenta de balance inicial', + 'budgets' => 'Presupuestos', + 'tags' => 'Etiquetas', + 'reports' => 'Informes', + 'transactions' => 'Transacciones', + 'expenses' => 'Gastos', + 'income' => 'Ingresos / salarios', + 'transfers' => 'Transferencias', + 'moneyManagement' => 'Gestión del dinero', + 'piggyBanks' => 'Huchas', + 'bills' => 'Facturas', + 'withdrawal' => 'Retiro', + 'opening_balance' => 'Saldo inicial', + 'deposit' => 'Depósito', + 'account' => 'Cuenta', + 'transfer' => 'Transferencia', + 'Withdrawal' => 'Retiro', + 'Deposit' => 'Depósito', + 'Transfer' => 'Transferencia', + 'bill' => 'Factura', + 'yes' => 'Si', + 'no' => 'No', + 'amount' => 'Cantidad', + 'overview' => 'Resumen', + 'saveOnAccount' => 'Guardar en cuenta', + 'unknown' => 'Desconocido', + 'daily' => 'Diario', + 'monthly' => 'Mensual', + 'profile' => 'Perfil', + 'errors' => 'Errores', + + // reports: + 'report_default' => 'Reporte financiero por defecto entre :start y :end', + 'report_audit' => 'Transacción general del historial entre :start y :end', + 'report_category' => 'Reporte de categoría entre :start y :end', + 'report_account' => 'Cuentas de Gastos/ingresos reporta entre :start y :end', + 'report_budget' => 'Reporte de presupuesto entre :start y :end', + 'report_tag' => 'Reporte de etiqueta entre :start y :end', + 'quick_link_reports' => 'Enlaces rápidos', + 'quick_link_default_report' => 'Reporte financiero por defecto', + 'quick_link_audit_report' => 'Resumen del historial de transacciones', + 'report_this_month_quick' => 'Mes en curso, todas las cuentas', + 'report_this_year_quick' => 'Año en curso, todas las cuentas', + 'report_this_fiscal_year_quick' => 'Año fiscal en curso, todas las cuentas', + 'report_all_time_quick' => 'Todo el tiempo, todas las cuentas', + 'reports_can_bookmark' => 'Recuerda que los informes pueden ser marcados como favoritos.', + 'incomeVsExpenses' => 'Ingresos vs. gastos', + 'accountBalances' => 'Balances de cuentas', + 'balanceStart' => 'Balance al inicio de un periodo', + 'balanceEnd' => 'Balance al final de un periodo', + 'splitByAccount' => 'Separada por cuenta', + 'coveredWithTags' => 'Cubierta con etiquetas', + 'leftUnbalanced' => 'Izquierda desbalanceada', + 'leftInBudget' => 'Dejado en el presupuesto', + 'sumOfSums' => 'Suma de sumas', + 'noCategory' => '(sin categoría)', + 'notCharged' => 'No cargado (todavía)', + 'inactive' => 'Inactivo', + 'active' => 'Activo', + 'difference' => 'Diferente', + 'money_flowing_in' => 'Dentro', + 'money_flowing_out' => 'Fuera', + 'topX' => 'tope :number', + 'show_full_list' => 'Mostrar lista entera', + 'show_only_top' => 'Mostrar solo tope :number', + 'report_type' => 'Tipo de reporte', + 'report_type_default' => 'Reporte financiero por mora', + 'report_type_audit' => 'Resumen del historial de transacciones (auditar)', + 'report_type_category' => 'Reporte de categoría', + 'report_type_budget' => 'Reporte de presupuesto', + 'report_type_tag' => 'Reporte de etiqueta', + 'report_type_account' => 'Reporte de cuenta de gastos/ingresos', + 'more_info_help' => 'Puedes encontrar más información sobre estos tipos de informes en las páginas de ayuda. Pulsa el icono (?) En la esquina superior derecha.', + 'report_included_accounts' => 'Cuentas incluidas', + 'report_date_range' => 'Rango de fechas', + 'report_preset_ranges' => 'Rangos preestablecidos', + 'shared' => 'Compartido', + 'fiscal_year' => 'Año fiscal', + 'income_entry' => 'Ingresos de la cuenta ":name" entre :start y :end', + 'expense_entry' => 'Gastos a cuenta ":name" entre :start y :end', + 'category_entry' => 'Gastos en categoría ":name" entre :start y :end', + 'budget_spent_amount' => 'Gastos en presupuesto ":budget" entre :start y :end', + 'balance_amount' => 'Gastos en presupuesto ":budget" pago desde la cuenta ":account" entre :start y :end', + 'no_audit_activity' => 'Ninguna actividad fue registrada en la cuenta :account_name entre :start y :end.', + 'audit_end_balance' => 'Saldo de cuenta de :account_name en el final de :end fue :balance', + 'reports_extra_options' => 'Opciones adicionales', + 'report_has_no_extra_options' => 'Este informe no tiene opciones adicionales', + 'reports_submit' => 'Ver informe', + 'end_after_start_date' => 'Fecha final de reporte debe ser después de la fecha de inicio.', + 'select_category' => 'Seleccionar categoría (as)', + 'select_budget' => 'Seleccionar presupuesto (s).', + 'select_tag' => 'Seleccionar etiqueta (s).', + 'income_per_category' => 'Ingresos por categoria', + 'expense_per_category' => 'Gastos por categoria', + 'expense_per_budget' => 'Gastos por presupuestos', + 'income_per_account' => 'Ingresos por cuenta', + 'expense_per_account' => 'Gastos por cuenta', + 'expense_per_tag' => 'Gastos por etiqueta', + 'income_per_tag' => 'Ingreso por etiqueta', + 'include_expense_not_in_budget' => 'Gastos incluidos que no están en el presupuesto (s) seleccionado', + 'include_expense_not_in_account' => 'Gastos incluidos que no están en la cuenta (s) seleccionada', + 'include_expense_not_in_category' => 'Gastos incluidos que no están en la categoría (s) seleccionada', + 'include_income_not_in_category' => 'Ingresos incluidos que no estan en la categoria (s) seleccionada', + 'include_income_not_in_account' => 'Ingresos incluidos que no están en la cuenta (s) seleccionada', + 'include_income_not_in_tags' => 'Ingresos incluidos no en la etiqueta (s) seleccionadas', + 'include_expense_not_in_tags' => 'Gastos incluidos no seleccionados con etiqueta', + 'everything_else' => 'Todo lo demas', + 'income_and_expenses' => 'Ingresos y gastos', + 'spent_average' => 'Gastado (promedio)', + 'income_average' => 'Ingresos (promedio)', + 'transaction_count' => 'Cuenta de transacciones', + 'average_spending_per_account' => 'Promedio de gasto por cuenta', + 'average_income_per_account' => 'Promedio de ingreso por cuenta', + 'total' => 'Total', + 'description' => 'Descripción', + 'sum_of_period' => 'Suma de período', + 'average_in_period' => 'Promedio en el período', + 'account_role_defaultAsset' => 'Cuentas de ingresos por defecto', + 'account_role_sharedAsset' => 'Compartir cuenta de ingresos', + 'account_role_savingAsset' => 'Cuentas de ahorros', + 'account_role_ccAsset' => 'Tarjeta de Crédito', + 'budget_chart_click' => 'Por favor de click el nombre del presupuesto en la tabla de arriba para ver el cuadro.', + 'category_chart_click' => 'Por favor de click en el nombre de categoría en la tabla de arriba para ver el cuadro.', + 'in_out_accounts' => 'Ganado y gastado por combinación', + 'in_out_per_category' => 'Ganado y gastado por categoría', + 'out_per_budget' => 'Gasto por presupuesto', + 'select_expense_revenue' => 'Seleccione cuenta de gastos/ingresos', + + // charts: + 'chart' => 'Grafico', + 'month' => 'Mes', + 'budget' => 'Presupuesto', + 'spent' => 'Gastado', + 'spent_in_budget' => 'Gastado en presupuesto', + 'left_to_spend' => 'Dejar para gastar', + 'earned' => 'Ganado', + 'overspent' => 'Sobrepasadas', + 'left' => 'Izquierda', + 'max-amount' => 'Monto máximo', + 'min-amount' => 'Monto minimo', + 'journal-amount' => 'Entrada actual de factura', + 'name' => 'Nombre', + 'date' => 'Fecha', + 'paid' => 'Pagado', + 'unpaid' => 'No pagado', + 'day' => 'Día', + 'budgeted' => 'Presupuestado', + 'period' => 'Período', + 'balance' => 'Balance', + 'sum' => 'Suma', + 'average' => 'Promedio', + 'balanceFor' => 'Saldo por :name', + + // piggy banks: + 'add_money_to_piggy' => 'Añadir dinero a la alcancía ":name"', + 'piggy_bank' => 'Alcancía', + 'new_piggy_bank' => 'Nueva alcancía', + 'store_piggy_bank' => 'Archivar nueva alcancía', + 'stored_piggy_bank' => 'Archivar nueva alcancía ":name"', + 'account_status' => 'Estado de cuenta', + 'left_for_piggy_banks' => 'Apartado para las huchas', + 'sum_of_piggy_banks' => 'Total de huchas', + 'saved_so_far' => 'Guardado hasta el momento', + 'left_to_save' => 'Izquierda para guardar', + 'suggested_amount' => 'Sugerir monto mensual para guardar', + 'add_money_to_piggy_title' => 'Añadir dinero a la alcancía ":name"', + 'remove_money_from_piggy_title' => 'Quitar dinero de la alcancía ":name"', + 'add' => 'Añadir', + 'no_money_for_piggy' => 'Usted no tiene dinero para colocar en esta alcancía.', + + 'remove' => 'Eliminar', + 'max_amount_add' => 'La cantidad máxima que usted puede agregar es', + 'max_amount_remove' => 'La cantidad máxima que usted puede retirar es', + 'update_piggy_button' => 'Actualizar alcancia', + 'update_piggy_title' => 'Actualizar alcancía ":name"', + 'updated_piggy_bank' => 'Actualizar alcancía ":name"', + 'details' => 'Detalles', + 'events' => 'Eventos', + 'target_amount' => 'Cantidad objetivo', + 'start_date' => 'Fecha de inicio', + 'target_date' => 'Fecha objetivo', + 'no_target_date' => 'Sin fecha de objetivo', + 'table' => 'Mesa', + 'delete_piggy_bank' => 'Eliminar alcancía ":name"', + 'cannot_add_amount_piggy' => 'No se pudo agregar :amount a ":name.".', + 'cannot_remove_from_piggy' => 'No se pudo eliminar :amount de :name.', + 'deleted_piggy_bank' => 'Eliminar alcancía ":name"', + 'added_amount_to_piggy' => 'Agregado :amount a ":name"', + 'removed_amount_from_piggy' => 'Eliminado :amount de :name', + + // tags + 'delete_tag' => 'Eliminar etiqueta ":tag"', + 'deleted_tag' => 'Eliminar etiqueta ":tag"', + 'new_tag' => 'Hacer nueva etiqueta', + 'edit_tag' => 'Editar etiqueta ":tag"', + 'updated_tag' => 'Actualizar etiqueta ":tag"', + 'created_tag' => 'Etiqueta ":tag" ha sido creado!', + + 'transaction_journal_information' => 'Información de transacción', + 'transaction_journal_meta' => 'Información Meta', + 'total_amount' => 'Monto total', + 'number_of_decimals' => 'Número de decimales', + + // administration + 'administration' => 'Administración', + 'user_administration' => 'Administración de usuarios', + 'list_all_users' => 'Todos los usuarios', + 'all_users' => 'Todo usuario', + 'instance_configuration' => 'Configuracion', + 'firefly_instance_configuration' => 'Opciones de configuración de Firefly III', + 'setting_single_user_mode' => 'Modo de usuario único', + 'setting_single_user_mode_explain' => 'Por defecto, Firefly III solo acepta un (1) registro: Usted. Esta es una medida de seguridad que impide que otros utilicen su instancia a menos que usted lo permita. Los registros futuros están bloqueados. Cuando usted desbloquee esta casilla, otros pueden usar su instancia también, suponiendo que puedan alcanzarla ( cuando este conectada a Internet).', + 'store_configuration' => 'Configuración de tienda', + 'single_user_administration' => 'Administración de usuarios para :email', + 'edit_user' => 'Editar usuario :email', + 'hidden_fields_preferences' => 'No todos los campos están visibles ahora. Debes habilitarlos en tu configuración.', + 'user_data_information' => 'Datos del usuario', + 'user_information' => 'Información del usuario', + 'total_size' => 'tamaño total', + 'budget_or_budgets' => 'presupuesto(s)', + 'budgets_with_limits' => 'presupuesto(s) con el importe configurado', + 'nr_of_rules_in_total_groups' => ':count_rules reglas en :count_groups grupo de reglas', + 'tag_or_tags' => 'etiqueta (s)', + 'configuration_updated' => 'La configuración ha sido actualizada', + 'setting_is_demo_site' => 'Sitio de demostracion', + 'setting_is_demo_site_explain' => 'Si usted chequea esta casilla, esta instalación se comportara como si fuera el sitio de demostración, que puede tener efectos secundarios extraños.', + 'block_code_bounced' => 'Mensaje (s) de correo rebotados', + 'block_code_expired' => 'Cuenta de demostración vencida', + 'no_block_code' => 'No hay razón para el bloqueo o usuario bloqueado', + 'block_code_email_changed' => 'El usuario no ha confirmado aun una nueva dirección de correo', + 'admin_update_email' => 'Contrario a la pagina de perfil, El usuario NO se notificara que su dirección de correo ha cambiado!', + 'update_user' => 'Actualizar usuario', + 'updated_user' => 'Los datos del usuario han sido cambiados.', + 'delete_user' => 'Eliminar usuario :email', + 'user_deleted' => 'El usuario ha sido eliminado', + 'send_test_email' => 'Enviar mensaje de correo electrónico de prueba', + 'send_test_email_text' => 'Para ver si su instalación es capaz de enviar correos electrónicos, presione este botón.Usted no vera un error aquí ( si hay)los archivos de registro reflejaran cualquier error . Usted puede presionar este botón tantas veces como lo desee. No hay control de spam. el mensaje sera enviado a :emaily llegara en breve.', + 'send_message' => 'Enviar mensaje', + 'send_test_triggered' => 'La prueba fue disparada. Chequee su bandeja de entrada y archivos de registro.', + + // links + 'journal_link_configuration' => 'Configuración de enlaces de transacción', + 'create_new_link_type' => 'Crear un nuevo tipo de enlace', + 'store_new_link_type' => 'Almacenar nuevo tipo de enlace', + 'update_link_type' => 'Actualizar tipo de enlace', + 'edit_link_type' => 'Editar tipo de enlace ":name"', + 'updated_link_type' => 'Actualizar tipo de enlace ":name"', + 'delete_link_type' => 'Eliminar tipo de enlace ":name"', + 'deleted_link_type' => 'Eliminar tipo de enlace ":name"', + 'stored_new_link_type' => 'Guardar nuevo tipo de enlace ":name"', + 'cannot_edit_link_type' => 'No puede editar el tipo de enlace ":name"', + 'link_type_help_name' => 'Ie "Duplicados"', + 'link_type_help_inward' => 'Ie."duplicados"', + 'link_type_help_outward' => 'Ie."esta duplicado por"', + 'save_connections_by_moving' => 'Guarde el enlace entre estas transacción (es) moviendolas a otro tipo de enlace:', + 'do_not_save_connection' => '(no guarde la conexión)', + 'link_transaction' => 'Transacción de enlace', + 'link_to_other_transaction' => 'Enlace de transacción a otra transacción', + 'select_transaction_to_link' => 'Seleccione una transacción para enlazar esta transacción a', + 'this_transaction' => 'Esta transacción', + 'transaction' => 'Transaccion', + 'comments' => 'Comentarios', + 'to_link_not_found' => 'Si la transacción que usted desea vincular no aparece en lista, simplemente ingrese su ID.', + 'invalid_link_selection' => 'No se puede vincular esta transacción', + 'journals_linked' => 'Las transacciones están vinculadas.', + 'journals_error_linked' => 'Estas transacciones ya están vinculadas.', + 'journal_links' => 'Enlaces de transacciones', + 'this_withdrawal' => 'Este retiro', + 'this_deposit' => 'Este deposito', + 'this_transfer' => 'Esta transferencia', + 'overview_for_link' => 'Visión en conjunto para el tipo de enlace ":name"', + 'source_transaction' => 'Transacción fuente', + 'link_description' => 'Descripción de enlace', + 'destination_transaction' => 'Transacción de destino', + 'delete_journal_link' => 'Elimine el link entre :source y :destination', + 'deleted_link' => 'Enlace borrado', + + // link translations: + 'relates to_inward' => 'relacionado con', + 'is (partially) refunded by_inward' => 'es (parcialmente) es devuelto por', + 'is (partially) paid for by_inward' => 'es(parcialmente) pagado por', + 'is (partially) reimbursed by_inward' => 'es(parcialmente) reembolsado por', + 'relates to_outward' => 'relacionado con', + '(partially) refunds_outward' => '(parcialmente) reembolso', + '(partially) pays for_outward' => '(parcialmente) paga por', + '(partially) reimburses_outward' => '(parcialmente) reembolsa', + + // split a transaction: + 'splits' => 'Divisiones', + 'add_another_split' => 'Añadir otra división', + 'split-transactions' => 'Transacciones divididas', + 'do_split' => 'Hacer un división', + 'split_this_withdrawal' => 'Dividir este retiro', + 'split_this_deposit' => 'Dividir este deposito', + 'split_this_transfer' => 'Dividir esta transferencia', + 'cannot_edit_multiple_source' => 'Usted no puede editar transacciones divididas #:id con descripción ":description" porque contiene múltiples cuentas de origen.', + 'cannot_edit_multiple_dest' => 'Usted no puede editar transacciones divididas #:id con descripción ":description" porque contiene múltiples cuentas destino.', + 'cannot_edit_reconciled' => 'Usted no puede editar transacciones #:id con descripción ":description" porque se ha marcado como reconciliado.', + 'cannot_edit_opening_balance' => 'Usted no puede editar el balance de apertura de una cuenta.', + 'no_edit_multiple_left' => 'Usted ha seleccionado transacciones no validas para editar.', + 'cannot_convert_split_journal' => 'No se puede convertir una transacción dividida', + + // import bread crumbs and titles: + 'import' => 'Importar', + 'import_data' => 'Importar datos', + 'import_general_index_file' => 'Importar un archivo', + 'import_from_bunq' => 'Importar de bunq', + 'import_using_spectre' => 'Importar usando Spectre', + 'import_using_plaid' => 'Importar usando cuadros', + 'import_config_bread_crumb' => 'Configure su importación', + + // import index page: + 'import_index_title' => 'Importar datos a Firefly III', + 'import_index_sub_title' => 'Índice', + 'import_general_index_intro' => 'Bienvenido a la rutina de importación de Firefly III. Hay algunas formas de importar datos a Firefly III, que se muestran aquí como botones.', + + // sandstorm.io errors and messages: + 'sandstorm_not_available' => 'Esta función no esta disponible cuando usted esta utilizando Firefly III dentro de un ambiente Sandstorm.io.', + + // empty lists? no objects? instructions: + 'no_accounts_title_asset' => '¡Vamos a crear una cuenta de activos!', + 'no_accounts_intro_asset' => 'Usted aun no tiene cuenta de activos. las cuentas de activos son sus cuentas principales: sus cuentas de cheques, cuenta de ahorros, cuenta compartida o incluso su tarjeta de crédito.', + 'no_accounts_imperative_asset' => 'Para comenzar a utilizar Firefly III Usted debe crear al menos una cuenta de activo. Vamos a hacerlo ahora:', + 'no_accounts_create_asset' => 'Crear una cuenta de activos', + 'no_accounts_title_expense' => '¡Vamos a crear una cuenta de gastos!', + 'no_accounts_intro_expense' => 'Usted aun no tiene cuentas de gastos. Las cuentas de gastos son los lugares donde se gasta dinero, tales como tiendas y supermercados.', + 'no_accounts_imperative_expense' => 'Las cuentas de gastos se crean automáticamente cuando crea transacciones, pero usted puede crear una manualmente también. si usted quiere. vamos a crear una ahora:', + 'no_accounts_create_expense' => 'Crear una cuenta de gastos', + 'no_accounts_title_revenue' => '¡Vamos a crear una cuenta de ingresos!', + 'no_accounts_intro_revenue' => 'Usted no tiene cuentas de ingresos aun. Cuentas de ingresos son los lugares donde usted recibe dinero, como su empleador.', + 'no_accounts_imperative_revenue' => 'Las cuentas de ganancias se crean automáticamente cuando usted crea transacciones, pero usted puede crear una manualmente también, si usted quiere. vamos a crear una ahora:', + 'no_accounts_create_revenue' => 'Crear una cuenta de ingresos', + 'no_budgets_title_default' => 'Vamos a crear un presupuesto', + 'no_budgets_intro_default' => 'Todavía no tienes presupuestos. Los presupuestos se usan para organizar tus gastos en grupos, a los que puedes asignar un tope para limitarlos.', + 'no_budgets_imperative_default' => 'Los presupuestos son las herramientas básicas de la gestión financiera. Vamos a crear uno ahora:', + 'no_budgets_create_default' => 'Crear un presupuesto', + 'no_categories_title_default' => '¡Vamos a crear una categoría!', + 'no_categories_intro_default' => 'Todavía no tienes categorías. Las categorías se utilizan para ajustar sus transacciones y etiquetarlas con su categoría designada.', + 'no_categories_imperative_default' => 'Las categorías se crean automáticamente al crear transacciones, pero también puedes crearlas manualmente. Vamos a crear una:', + 'no_categories_create_default' => 'Crear una categoría', + 'no_tags_title_default' => '¡Vamos a crear una etiqueta!', + 'no_tags_intro_default' => 'Todavía no tienes etiquetas. Las etiquetas se utilizan para ajustar tus transacciones y etiquetarlas con palabras clave específicas.', + 'no_tags_imperative_default' => 'Las etiquetas se crean automáticamente al crear transacciones, pero también puedes crearlas manualmente. Vamos a crear una:', + 'no_tags_create_default' => 'Crear etiqueta', + 'no_transactions_title_withdrawal' => '¡Vamos a crear un gasto!', + 'no_transactions_intro_withdrawal' => 'Usted no tiene gastos todavía. Usted debe crear gastos paran comenzar a administrar sus finanzas.', + 'no_transactions_imperative_withdrawal' => '¿Has gastado algo de dinero? Entonces usted debería escribirlo:', + 'no_transactions_create_withdrawal' => 'Crear un gasto', + 'no_transactions_title_deposit' => '¡Vamos a crear algún ingreso!', + 'no_transactions_intro_deposit' => 'Usted no tiene gastos grabados todavía. Usted debe crear entradas de ingresos para comenzar a gerenciar sus finanzas.', + 'no_transactions_imperative_deposit' => '¿ A recibido usted algún dinero? Entonces usted debería escribirlo:', + 'no_transactions_create_deposit' => 'Cree un deposito', + 'no_transactions_title_transfers' => '¡Vamos a crear una tranferencia!', + 'no_transactions_intro_transfers' => 'Usted no tiene transferencias aun. Cuando usted mueve dinero entre cuentas de activos, se registra como una transferencia.', + 'no_transactions_imperative_transfers' => '¿Has movido algo de dinero? Entonces usted debería escribirlo:', + 'no_transactions_create_transfers' => 'Crear una transferencia', + 'no_piggies_title_default' => '¡Vamos a crear una alcancía!', + 'no_piggies_intro_default' => 'Aún no tienes huchas. Puedes crear huchas para dividir tus ahorros y hacer un seguimiento de para qué estás ahorrando.', + 'no_piggies_imperative_default' => '¿Usted tiene cosas para la cual usted esta ahorrando dinero? Cree una alcancía y haga seguimiento:', + 'no_piggies_create_default' => 'Crear una nueva alcancía', + 'no_bills_title_default' => '¡Vamos a crear una factura!', + 'no_bills_intro_default' => 'Usted no tiene facturas aun. Usted puede crear facturas para hacer un seguimiento de los gastos regulares, como su alquiler o el seguro.', + 'no_bills_imperative_default' => '¿Tienes facturas periódicas? Crea una factura y haz un seguimiento de tus pagos:', + 'no_bills_create_default' => 'Crear una factura', +]; diff --git a/resources/lang/es_ES/form.php b/resources/lang/es_ES/form.php new file mode 100644 index 0000000000..14197cc0a8 --- /dev/null +++ b/resources/lang/es_ES/form.php @@ -0,0 +1,210 @@ +. + */ +declare(strict_types=1); + +return [ + // new user: + 'bank_name' => 'Banco', + 'bank_balance' => 'Saldo', + 'savings_balance' => 'Salgo de ahorro', + 'credit_card_limit' => 'Límite de la tarjeta de crédito', + 'automatch' => 'Coinciden automáticamente', + 'skip' => 'Saltar', + 'name' => 'Nombre', + 'active' => 'Activo', + 'amount_min' => 'Importe mínimo', + 'amount_max' => 'Importe máximo', + 'match' => 'Encuentros en', + 'repeat_freq' => 'Repetición', + 'journal_currency_id' => 'Divisa', + 'currency_id' => 'Divisa', + 'attachments' => 'Adjuntos', + 'journal_amount' => 'Importe', + 'journal_source_account_name' => 'Cuenta de ingresos (origen)', + 'journal_source_account_id' => 'Cuenta de activos (origen)', + 'BIC' => 'BIC', + 'verify_password' => 'Verificar la seguridad de contraseña', + 'source_account' => 'Cuenta origen', + 'destination_account' => 'Cuenta destino', + 'journal_destination_account_id' => 'Cuenta de activos (destino)', + 'asset_destination_account' => 'Cuenta de activos (destino)', + 'asset_source_account' => 'Cuenta de activos (origen)', + 'journal_description' => 'Descripción', + 'note' => 'Notas', + 'split_journal' => 'Dividir esta transacción', + 'split_journal_explanation' => 'Dividir esta transacción en múltiples partes', + 'currency' => 'Divisa', + 'account_id' => 'Cuenta', + 'budget_id' => 'Presupuesto', + 'openingBalance' => 'Saldo inicial', + 'tagMode' => 'Modo de etiqueta', + 'tag_position' => 'Etiquetar ubicación', + 'virtualBalance' => 'Saldo virtual', + 'targetamount' => 'Cantidad objetivo', + 'accountRole' => 'Tipo de cuenta', + 'openingBalanceDate' => 'Fecha del saldo inicial', + 'ccType' => 'Plan de pagos con tarjeta de crédito', + 'ccMonthlyPaymentDate' => 'Fecha de pago mensual de la tarjeta de crédito', + 'piggy_bank_id' => 'Hucha', + 'returnHere' => 'Volver aquí', + 'returnHereExplanation' => 'Después de guardar, vuelve aquí para crear otro.', + 'returnHereUpdateExplanation' => 'Después de actualizar, vuelve aquí.', + 'description' => 'Descripción', + 'expense_account' => 'Cuenta de gastos', + 'revenue_account' => 'Cuenta de ingresos', + 'decimal_places' => 'Lugares decimales', + 'exchange_rate_instruction' => 'Monedas extranjeras', + 'source_amount' => 'Importe (origen)', + 'destination_amount' => 'Importe (destino)', + 'native_amount' => 'Cantidad nativa', + 'new_email_address' => 'Nueva dirección de email', + 'verification' => 'Verificación', + 'api_key' => 'Clave de API', + 'remember_me' => 'Recordarme', + + 'source_account_asset' => 'Cuenta de origen (cuenta de activos)', + 'destination_account_expense' => 'Cuenta de destino (cuenta de gastos)', + 'destination_account_asset' => 'Cuenta de destino (cuenta de activos)', + 'source_account_revenue' => 'Cuenta de origen (cuenta de ingresos)', + 'type' => 'Tipo', + 'convert_Withdrawal' => 'Convertir extracción', + 'convert_Deposit' => 'Convertir depósito', + 'convert_Transfer' => 'Convertir transferencia', + + 'amount' => 'Importe', + 'date' => 'Fecha', + 'interest_date' => 'Fecha de interés', + 'book_date' => 'Fecha de registro', + 'process_date' => 'Fecha de procesamiento', + 'category' => 'Categoría', + 'tags' => 'Etiquetas', + 'deletePermanently' => 'Borrar permanentemente', + 'cancel' => 'Cancelar', + 'targetdate' => 'Fecha tope', + 'startdate' => 'Fecha de inicio', + 'tag' => 'Etiqueta', + 'under' => 'Debajo', + 'symbol' => 'Símbolo', + 'code' => 'Código', + 'iban' => 'IBAN', + 'accountNumber' => 'Número de cuenta', + 'creditCardNumber' => 'Número de la tarjeta de crédito', + 'has_headers' => 'Encabezados', + 'date_format' => 'Formato de fecha', + 'specifix' => 'Banco- o archivo de soluciones especificas', + 'attachments[]' => 'Adjuntos', + 'store_new_withdrawal' => 'Guardar rueva retirada de efectivo', + 'store_new_deposit' => 'Guardar nuevo depósito', + 'store_new_transfer' => 'Guardar nueva transferencia', + 'add_new_withdrawal' => 'Añadir rueva retirada de efectivo', + 'add_new_deposit' => 'Añadir nuevo depósito', + 'add_new_transfer' => 'Añadir nueva transferencia', + 'title' => 'Título', + 'notes' => 'Notas', + 'filename' => 'Nombre de fichero', + 'mime' => 'Tipo Mime', + 'size' => 'Tamaño', + 'trigger' => 'Disparador', + 'stop_processing' => 'Detener el procesamiento', + 'start_date' => 'Inicio del rango', + 'end_date' => 'Final del rango', + 'export_start_range' => 'Inicio del rango de exportación', + 'export_end_range' => 'Fin del rango de exportación', + 'export_format' => 'Formato del archivo', + 'include_attachments' => 'Incluir archivos adjuntos subidos', + 'include_old_uploads' => 'Incluir datos importados', + 'accounts' => 'Exportar transacciones de estas cuentas', + 'delete_account' => 'Borrar cuenta ":name"', + 'delete_bill' => 'Eliminar factura ":name"', + 'delete_budget' => 'Eliminar presupuesto ":name"', + 'delete_category' => 'Eliminar categoría ":name"', + 'delete_currency' => 'Eliminar divisa ":name"', + 'delete_journal' => 'Eliminar la transacción con descripción ":description"', + 'delete_attachment' => 'Eliminar adjunto ":name"', + 'delete_rule' => 'Eliminar regla ":title"', + 'delete_rule_group' => 'Eliminar grupo de reglas ":title"', + 'delete_link_type' => 'Eliminar tipo de enlace ":name"', + 'delete_user' => 'Eliminar usuario ":email"', + 'user_areYouSure' => 'Si elimina usuario ":email", todo desaparecerá. No hay deshacer, recuperar ni nada. Si te eliminas, perderás el acceso a esta instancia de Firefly III.', + 'attachment_areYouSure' => '¿Seguro que quieres eliminar el archivo adjunto llamado "name"?', + 'account_areYouSure' => '¿Seguro que quieres eliminar la cuenta llamada ":name"?', + 'bill_areYouSure' => '¿Seguro que quieres eliminar la factura llamada ":name"?', + 'rule_areYouSure' => '¿Seguro que quieres eliminar la regla titulada ":title"?', + 'ruleGroup_areYouSure' => '¿Seguro que quieres eliminar el grupo de reglas titulado ":title"?', + 'budget_areYouSure' => '¿Seguro que quieres eliminar el presupuesto llamado ":name"?', + 'category_areYouSure' => '¿Seguro que quieres eliminar la categoría llamada ":name"?', + 'currency_areYouSure' => '¿Está seguro que desea eliminar la moneda denominada ":name"?', + 'piggyBank_areYouSure' => '¿Está seguro que desea eliminar la hucha llamada ":name"?', + 'journal_areYouSure' => '¿Estás seguro de que deseas eliminar la transacción descrita ":description"?', + 'mass_journal_are_you_sure' => '¿Usted esta seguro de querer eliminar estas transacciones?', + 'tag_areYouSure' => '¿Seguro que quieres eliminar la etiqueta ":tag"?', + 'journal_link_areYouSure' => '¿Seguro que quieres eliminar el vínculo entre :source y :destination?', + 'linkType_areYouSure' => '¿Estás seguro de que deseas eliminar el tipo de vínculo ":name" (":inward" / ":outward")?', + 'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.', + 'mass_make_selection' => 'Aún puede evitar que se eliminen elementos quitando la casilla de verificación.', + 'delete_all_permanently' => 'Eliminar selección permanentemente', + 'update_all_journals' => 'Actualiza estas transacciones', + 'also_delete_transactions' => 'La única transacción conectada a esta cuenta también se eliminará. | Todas las :count transacciones conectadas a esta cuenta también se eliminarán.', + 'also_delete_connections' => 'La única transacción vinculada con este tipo de enlace perderá esta conexión. | Todas las :count transacciones vinculadas con este tipo de enlace perderán su conexión.', + 'also_delete_rules' => 'La única regla conectada a este grupo de reglas también se eliminará. | Todas las :count reglas conectadas a este grupo de reglas también se eliminarán.', + 'also_delete_piggyBanks' => 'La única alcancía conectada a esta cuenta también se eliminará. | Todas las :count alcancías conectadas a esta cuenta también se eliminará.', + 'bill_keep_transactions' => 'La única transacción conectada a esta factura no se eliminará. | Todas las :count transacciones conectadas a esta factura evitarán la eliminación.', + 'budget_keep_transactions' => 'La única transacción conectada a este presupuesto no se eliminará. | Todas las :count transacciones conectadas a este presupuesto evitarán la eliminación.', + 'category_keep_transactions' => 'La única transacción conectada a esta categoría no se eliminará. | Todas las :count transacciones conectadas a esta categoría evitarán la eliminación.', + 'tag_keep_transactions' => 'La única transacción conectada a esta etiqueta no se eliminará. | Todas las :count transacciones conectadas a esta etiqueta evitarán la eliminación.', + 'check_for_updates' => 'Ver actualizaciones', + + 'email' => 'Correo electrónico', + 'password' => 'Contraseña', + 'password_confirmation' => 'Contraseña (otra vez)', + 'blocked' => '¿Está bloqueado?', + 'blocked_code' => 'Razón del bloqueo', + + // admin + 'domain' => 'Dominio', + 'single_user_mode' => 'Deshabilitar registro de usuario', + 'is_demo_site' => 'Está en modo demostración', + + // import + 'import_file' => 'Importar archivo', + 'configuration_file' => 'Archivo de configuración', + 'import_file_type' => 'Importar tipo de archivo', + 'csv_comma' => 'Una coma (,)', + 'csv_semicolon' => 'Un punto y coma (;)', + 'csv_tab' => 'Un tabulador (invisible)', + 'csv_delimiter' => 'Delimitador de campo CSV', + 'csv_import_account' => 'Cuenta de importación predeterminada', + 'csv_config' => 'Configuración de importación de CSV', + 'client_id' => 'Identificación del cliente', + 'service_secret' => 'Servicio secreto', + 'app_secret' => 'Secreto de aplicación', + 'public_key' => 'Llave pública', + 'country_code' => 'Código del país', + 'provider_code' => 'Banco o proveedor de datos', + + 'due_date' => 'Fecha de vencimiento', + 'payment_date' => 'Fecha de pago', + 'invoice_date' => 'Fecha de la factura', + 'internal_reference' => 'Referencia interna', + 'inward' => 'Descripción interna', + 'outward' => 'Descripción externa', + 'rule_group_id' => 'Grupo de reglas', +]; diff --git a/resources/lang/es_ES/import.php b/resources/lang/es_ES/import.php new file mode 100644 index 0000000000..aa0652a4b9 --- /dev/null +++ b/resources/lang/es_ES/import.php @@ -0,0 +1,190 @@ +. + */ +declare(strict_types=1); + +return [ + // status of import: + 'status_wait_title' => 'Por favor espere...', + 'status_wait_text' => 'Esta caja va a desaparecer en un momento.', + 'status_fatal_title' => 'Un error fatal ha ocurrido', + 'status_fatal_text' => 'Un error fatal ocurrió, del cual la rutina de importación no se puede recuperar. Por favor, vea la explicación en rojo a continuación.', + 'status_fatal_more' => 'Si el error es de tiempo en espera, la importación se detendrá a mitad de camino. Para algunas configuraciones de servidor, es simplemente que el servidor se detuvo mientras la importación se sigue ejecutando en segundo plano. Para verificar esto, revise los archivos de logs. Si el problema persiste, considere importar a través de la linea de comando.', + 'status_ready_title' => 'La Importación esta lista para comenzar', + 'status_ready_text' => 'La importación está lista para comenzar. Toda la configuración que necesitaba hacer ya está hecha. Por favor descargue el archivo de configuración. Le ayudará con la importación en caso de que no vaya según lo planeado. Para ejecutar la importación, puede ejecutar el siguiente comando en su consola, o utilizar la importación a través de la interfaz web. Dependiendo de su configuración, la importación de la consola le ofrecerá más comentarios de ayuda.', + 'status_ready_noconfig_text' => 'La importación está lista para comenzar. Toda la configuración que necesitaba hacer ya está hecha. Para ejecutar la importación, puede ejecutar el siguiente comando en su consola, o utilizar la importación a través de la interfaz web. Dependiendo de su configuración, la importación de la consola le ofrecerá más comentarios de ayuda.', + 'status_ready_config' => 'Configuración de descarga', + 'status_ready_start' => 'Comenzar la importación', + 'status_ready_share' => 'Por favor considere descargar su configuración y compartirla en centro de configuración de importación. Esto permitirá a otros usuarios de Firefly III importar sus archivos de manera más fácil.', + 'status_job_new' => 'El trabajo es completamente nuevo.', + 'status_job_configuring' => 'La importación se está configurando.', + 'status_job_configured' => 'La importación está configurada.', + 'status_job_running' => 'La importación se está ejecutando... Por favor, espere.', + 'status_job_error' => 'El trabajo generó un error.', + 'status_job_finished' => '¡La importación ha terminado!', + 'status_running_title' => 'La importación se está ejecutando', + 'status_running_placeholder' => 'Por favor espere por la actualización...', + 'status_finished_title' => 'Rutina de importación terminada', + 'status_finished_text' => 'La rutina de importación ha importado sus datos.', + 'status_errors_title' => 'Errores durante la importación', + 'status_errors_single' => 'Ha ocurrido un error durante la importación. No parece ser fatal.', + 'status_errors_multi' => 'Algunos errores ocurrieron durante la importación. No parecen ser fatales.', + 'status_bread_crumb' => 'Estado de la importación', + 'status_sub_title' => 'Estado de la importación', + 'config_sub_title' => 'Configure su importación', + 'status_finished_job' => 'Las :count transacciones importadas pueden ser encontradas en la etiqueta .', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', + 'import_with_key' => 'Importar con la clave \':key\'', + + // file, upload something + 'file_upload_title' => 'Confirguración de importación (1/4) - Suba su archivo', + 'file_upload_text' => 'Esta rutina le ayudará a importar archivos de su banco a Firefly III. Por favor revise las páginas de ayuda en la esquina superior derecha.', + 'file_upload_fields' => 'Campos', + 'file_upload_help' => 'Seleccione sus archivos', + 'file_upload_config_help' => 'Si previamente ha importado datos en Firefly III, puede tener un archivo de configuración, el cual preestablecerá valores de configuración para usted. Para algunos bancos, otros usuarios han proporcionado amablemente sus archivos de configuración', + 'file_upload_type_help' => 'Seleccione el tipo de archivo que subirá', + 'file_upload_submit' => 'Subir archivos', + + // file, upload types + 'import_file_type_csv' => 'CSV (valores separados por comas)', + + // file, initial config for CSV + 'csv_initial_title' => 'Configuración de importación (2/4) - Configuración básica CSV de importación', + 'csv_initial_text' => 'Para poder importar su archivo correctamente, por favor valide las opciones a continuación.', + 'csv_initial_box' => 'Configuración de importación de CSV simple', + 'csv_initial_box_title' => 'Opciones de configuración para importación de CSV simple', + 'csv_initial_header_help' => 'Marque esta casilla si la primera fila de su archivo CSV son los títulos de las columnas.', + 'csv_initial_date_help' => 'Formato de fecha y hora en el CSV. siga un formato como esta paginaindica.El valor por defecto.', + 'csv_initial_delimiter_help' => 'Elija el delimitador de campos de su archivo de entrada. si no esta seguro, la coma es la opción.', + 'csv_initial_import_account_help' => 'Si su archivo CSV NO contiene información sobre su (s) cuenta (s) de activos. Use este menú desplegable para seleccionar a que cuenta pertenecen las transacciones en el archivo CSV.', + 'csv_initial_submit' => 'Continúe con el paso 3/4', + + // file, new options: + 'file_apply_rules_title' => 'Aplicar reglas', + 'file_apply_rules_description' => 'Aplique sus reglas. tenga en cuenta que esto reduce significativamente la importación.', + 'file_match_bills_title' => 'Unir facturas', + 'file_match_bills_description' => 'Haga coincidir sus facturas con los retiros recién creados. Tenga en cuenta que esto reduce significativamente la importación.', + + // file, roles config + 'csv_roles_title' => 'Configuración de importación (3/4) defina el rol de cada columna', + 'csv_roles_text' => 'Cada columna en su archivo CSV contiene cierto datos. Por favor indique que tipo de datos debe esperar el importador. la opción de "map" datos significa que enlazara cada entrada encontrada en la columna con un valor en su base de datos. A menudo una columna mapeada es la columna que contiene el IBAN ya presentes en su base de datos.', + 'csv_roles_table' => 'Tabla', + 'csv_roles_column_name' => 'Nombre de la columna', + 'csv_roles_column_example' => 'Datos de ejemplo de columna', + 'csv_roles_column_role' => 'Significado de los datos de la columna', + 'csv_roles_do_map_value' => 'Mapear estos valores', + 'csv_roles_column' => 'Columna', + 'csv_roles_no_example_data' => 'No hay datos de ejemplo disponibles', + 'csv_roles_submit' => 'Continúe en el paso 4/4', + + // not csv, but normal warning + 'roles_warning' => 'Por lo menos, marque una columna como la columna de importe. también es aconsejable seleccionar una columna para la descripción. la fecha y la cuenta contraria.', + 'foreign_amount_warning' => 'Si usted marca una columna que contiene un importe en una moneda extranjera, usted también debe establecer la columna que contiene que moneda es.', + // file, map data + 'file_map_title' => 'Configuración de importación (4/4) - Conecta datos de importación a los datos de Firefly III', + 'file_map_text' => 'En las siguientes tablas, el valor de la izquierda muestra información encontrada en el Csv cargado. Es su tarea mapear este valor, si es posible, a un valor ya presente en su base de datos. Firefly Iii respetara este mapeo. Si no hay un valor hacia el cual mapear o no se desea mapear un valor especifico, no seleccione ninguno.', + 'file_map_field_value' => 'Valor del campo', + 'file_map_field_mapped_to' => 'Asignado a', + 'map_do_not_map' => '(no mapear)', + 'file_map_submit' => 'Comenzar la importación', + 'file_nothing_to_map' => 'No hay datos presentes en su archivo que pueda asignar a los valores existentes. Por favor presione "comenzar la importación" para continuar.', + + // map things. + 'column__ignore' => '(Ignorar esta columna)', + 'column_account-iban' => 'Caja de ahorros (IBAN)', + 'column_account-id' => 'Identificación de Cuenta de ingresos (coincide con FF3)', + 'column_account-name' => 'Caja de ahorros (nombre)', + 'column_amount' => 'Cantidad', + 'column_amount_foreign' => 'Monto ( en moneda extranjera)', + 'column_amount_debit' => 'Cantidad (columna de débito)', + 'column_amount_credit' => 'Cantidad (columna de crédito)', + 'column_amount-comma-separated' => 'Cantidad (coma como decimal separador)', + 'column_bill-id' => 'ID factura (coincide FF3)', + 'column_bill-name' => 'Nombre de la factura', + 'column_budget-id' => 'ID presupuesto (coincide FF3)', + 'column_budget-name' => 'Nombre del presupuesto', + 'column_category-id' => 'ID de categoría (coincide FF3)', + 'column_category-name' => 'Nombre de la categoría', + 'column_currency-code' => 'Código de la moneda (ISO 4217)', + 'column_foreign-currency-code' => 'Código de moneda extranjera ( ISO 4217)', + 'column_currency-id' => 'ID de moneda (coincide FF3)', + 'column_currency-name' => 'Nombre de moneda (coincide FF3)', + 'column_currency-symbol' => 'Símbolo de moneda (coincide FF3)', + 'column_date-interest' => 'Fecha de cálculo de intereses', + 'column_date-book' => 'Fecha de registro de la transacción', + 'column_date-process' => 'Fecha del proceso de transacción', + 'column_date-transaction' => 'Fecha', + 'column_description' => 'Descripción', + 'column_opposing-iban' => 'Cuenta opuesta (IBAN)', + 'column_opposing-id' => 'ID de cuenta opuesta (coincide FF3)', + 'column_external-id' => 'Identificación externa', + 'column_opposing-name' => 'Cuenta opuesta (nombre)', + 'column_rabo-debit-credit' => 'Indicador especifico débito/crédito de Rabobank', + 'column_ing-debit-credit' => 'Indicador especifico débito/crédito de ING', + 'column_sepa-ct-id' => 'ID transferencia de crédito extremo a extremo', + 'column_sepa-ct-op' => 'Transferencia de crédito a cuenta opuesta SEPA', + 'column_sepa-db' => 'SEPA débito directo', + 'column_tags-comma' => 'Etiquetas ( separadas por comas)', + 'column_tags-space' => 'Etiquetas ( separadas por espacio)', + 'column_account-number' => 'Cuenta de archivos ( numero de cuenta)', + 'column_opposing-number' => 'Cuenta opuesta (numero de cuenta)', + 'column_note' => 'Nota (s)', + + // prerequisites + 'prerequisites' => 'Prerequisitos', + + // bunq + 'bunq_prerequisites_title' => 'Pre requisitos para una importación de bunq', + 'bunq_prerequisites_text' => 'Para importar de bunq, usted necesita obtener una clave API. usted puede hacerlo a través de la aplicación.', + + // Spectre + 'spectre_title' => 'Importar usando Spectre', + 'spectre_prerequisites_title' => 'Pre requisitos para una importación usando Spectre', + 'spectre_prerequisites_text' => 'Para importar datos usando la API de Spectre, Usted debe proveer FIrefly III dos valores secretos. Se pueden encontrar en pagina secretas.', + 'spectre_enter_pub_key' => 'La importación solo funcionara cuando ingrese esta clave publica en su pagina secreta.', + 'spectre_accounts_title' => 'Seleccionar cuentas para importar desde', + 'spectre_accounts_text' => 'Cada cuenta a la izquierda abajo ha sido encontrada por Spectre y puede ser importada en Firefly III. Por favor seleccione la cuenta de activo que debe contener cualquier transacción determinada. Si usted no desea importar desde una cuenta en particular, elimine el cheque de la casilla de verificación.', + 'spectre_do_import' => 'Si, importar desde esta cuenta', + + // keys from "extra" array: + 'spectre_extra_key_iban' => 'IBAN', + 'spectre_extra_key_swift' => 'SWIFT', + 'spectre_extra_key_status' => 'Estatus', + 'spectre_extra_key_card_type' => 'Tipo de tarjeta', + 'spectre_extra_key_account_name' => 'Nombre de la cuenta', + 'spectre_extra_key_client_name' => 'Nombre del cliente', + 'spectre_extra_key_account_number' => 'Numero de cuenta', + 'spectre_extra_key_blocked_amount' => 'Monto bloqueado', + 'spectre_extra_key_available_amount' => 'Monto disponible', + 'spectre_extra_key_credit_limit' => 'Limite de credito', + 'spectre_extra_key_interest_rate' => 'Tasa de interés', + 'spectre_extra_key_expiry_date' => 'Fecha de vencimiento', + 'spectre_extra_key_open_date' => 'Fecha de apertura', + 'spectre_extra_key_current_time' => 'Tiempo actual', + 'spectre_extra_key_current_date' => 'Fecha actual', + 'spectre_extra_key_cards' => 'Tarjetas', + 'spectre_extra_key_units' => 'Unidades', + 'spectre_extra_key_unit_price' => 'Precio unitario', + 'spectre_extra_key_transactions_count' => 'Cuenta de transacciones', + + // various other strings: + 'imported_from_account' => 'Importado de ":account"', +]; + diff --git a/resources/lang/es_ES/intro.php b/resources/lang/es_ES/intro.php new file mode 100644 index 0000000000..384efe1e89 --- /dev/null +++ b/resources/lang/es_ES/intro.php @@ -0,0 +1,133 @@ +. + */ +declare(strict_types=1); + +return [ + // index + 'index_intro' => 'Bienvenido a la página de índice de Firefly III. Por favor tómate tu tiempo para revisar esta guía y que puedas hacerte una idea de cómo funciona Firefly III.', + 'index_accounts-chart' => 'Este gráfico muestra el saldo actual de tus cuentas. Puedes seleccionar las cuentas que se muestran en él desde tus preferencias.', + 'index_box_out_holder' => 'Esta pequeña caja y las cajas a continuación te darán una visión rápida de tu situación financiera.', + 'index_help' => 'Si alguna vez necesitas ayuda en una página o formulario, pulsa este botón.', + 'index_outro' => 'La mayoría de las páginas de Firefly III comenzarán con una pequeña introducción como ésta. Por favor, ponte en contacto conmigo si tienes preguntas o comentarios. ¡Disfruta!', + 'index_sidebar-toggle' => 'Para crear nuevas transacciones, cuentas u otros elementos, utiliza el menú bajo este icono.', + + // create account: + 'accounts_create_iban' => 'Indica un IBAN válido en tus cuentas. Esto facilitará la importación de datos en el futuro.', + 'accounts_create_asset_opening_balance' => 'Cuentas de ingreso deben tener un "saldo de apertura", indicando el inicio del historial de la cuenta en Firefly III.', + 'accounts_create_asset_currency' => 'Firefly III admite múltiples divisas. Las cuentas tienen una divisa principal, que debes indicar aquí.', + 'accounts_create_asset_virtual' => 'A veces puede ayudar el darle a tu cuenta un balance virtual: una cantidad extra que se añade o resta siempre del balance real.', + + // budgets index + 'budgets_index_intro' => 'Los presupuestos se utilizan para administrar sus finanzas y son una de las funciones básicas de Firefly III.', + 'budgets_index_set_budget' => 'Coloque su total presupuesto para cada periodo y así Firefly III puede decirle si usted si has presupuestado todo el dinero disponible.', + 'budgets_index_see_expenses_bar' => 'Gastar dinero irá llenando poco a poco esta barra.', + 'budgets_index_navigate_periods' => 'Navega a través de períodos para configurar fácilmente presupuestos con anticipación.', + 'budgets_index_new_budget' => 'Crea nuevos presupuestos como mejor te parezca.', + 'budgets_index_list_of_budgets' => 'Use esta tabla para establecer el monto de cada presupuesto y ver como usted lo está haciendo.', + 'budgets_index_outro' => 'Para aprender mas acerca de los presupuestos, revise el icono de ayuda en el tope de la esquina derecha.', + + // reports (index) + 'reports_index_intro' => 'Utilice estos reportes para tener información detallada en sus finanzas.', + 'reports_index_inputReportType' => 'Escoge un tipo de reporte. Revise las páginas de ayuda para ver lo que te muestra cada reporte.', + 'reports_index_inputAccountsSelect' => 'Usted puede excluir o incluir cuentas de activos como mejor le cuadre.', + 'reports_index_inputDateRange' => 'El rango de fecha seleccionada depende completamente de usted: de un día a 10 años.', + 'reports_index_extra-options-box' => 'Dependiendo del informe que usted haya seleccionado, usted puede seleccionar filtros y opciones extras aquí. Mire este recuadro cuando usted cambie los tipos de informes.', + + // reports (reports) + 'reports_report_default_intro' => 'Este informe le dará un rápido y comprensivo resumen de sus finanzas. Si usted desea ver algo mas, ¡por favor no dude en ponerse en contacto conmigo!', + 'reports_report_audit_intro' => 'Este informe le dará información detallada en sus cuentas de activos.', + 'reports_report_audit_optionsBox' => 'Use estos recuadros de verificación para ver u ocultar las columnas que a usted le interesa.', + + 'reports_report_category_intro' => 'Este informe le dará una idea en una o múltiples categorías.', + 'reports_report_category_pieCharts' => 'Estos gráficos le darán una idea de sus gastos e ingresos por categoría o por cuenta.', + 'reports_report_category_incomeAndExpensesChart' => 'Estos gráficos muestran sus gastos e ingresos por categoría.', + + 'reports_report_tag_intro' => 'Este informe le dará una idea de una o múltiples etiquetas.', + 'reports_report_tag_pieCharts' => 'Este gráfico le dará una idea de gastos e ingresos por etiqueta, cuenta, categoría o presupuesto.', + 'reports_report_tag_incomeAndExpensesChart' => 'Estos gráficos le muestran gastos e ingresos por etiqueta.', + + 'reports_report_budget_intro' => 'Este informe le dará una idea de uno o múltiples presupuestos.', + 'reports_report_budget_pieCharts' => 'Estos gráficos le dará a usted una idea de los gastos por presupuesto o por cuenta.', + 'reports_report_budget_incomeAndExpensesChart' => 'Este gráfico le muestra sus gastos por presupuesto.', + + // create transaction + 'transactions_create_switch_box' => 'Utilice estos botones para cambiar rápidamente el tipo de transacción que usted desea guardar.', + 'transactions_create_ffInput_category' => 'Usted puede libremente escribir en este campo. Previamente cree categorías que se sugerirán.', + 'transactions_create_withdrawal_ffInput_budget' => 'Vincula su retiro con un presupuesto para un mejor control financiero.', + 'transactions_create_withdrawal_currency_dropdown_amount' => 'Use esta lista desplegable cuando su retiro esta en otra moneda.', + 'transactions_create_deposit_currency_dropdown_amount' => 'Use esta lista desplegable cuando su deposito este en otra moneda.', + 'transactions_create_transfer_ffInput_piggy_bank_id' => 'Seleccione una alcancía y vincule esta transferencia con sus ahorros.', + + // piggy banks index: + 'piggy-banks_index_saved' => 'Este campo le muestra cuanto usted ha ahorrado en cada alcancía.', + 'piggy-banks_index_button' => 'Junto con esta barra de progresoo hay dos botones (+ y -) para añadir o eliminar dinero de cada alcancía.', + 'piggy-banks_index_accountStatus' => 'Para cada cuenta de activos con al menos una alcancía, el estado esta listado en esta tabla.', + + // create piggy + 'piggy-banks_create_name' => '¿Cuál es tu meta? ¿Un nuevo sofá, una cámara, dinero para emergencias?', + 'piggy-banks_create_date' => 'Usted puede establecer una fecha objetivo o una fecha limite para su alcancía.', + + // show piggy + 'piggy-banks_show_piggyChart' => 'Este informe le mostrara la historia de esta alcancía.', + 'piggy-banks_show_piggyDetails' => 'Algunos detalles sobre tu alcancía', + 'piggy-banks_show_piggyEvents' => 'Cualquier adición o eliminación también se ponen en lista aquí.', + + // bill index + 'bills_index_paid_in_period' => 'Este campo indica cuando la factura fue pagada por última vez.', + 'bills_index_expected_in_period' => 'Este campo indica para cada factura si se espera que llegue la próxima factura.', + + // show bill + 'bills_show_billInfo' => 'Esta tabla muestra alguna información general acerca de esta factura.', + 'bills_show_billButtons' => 'Use este botón para volver a escanear transacciones viejas, para que ellos coincidan con esta factura.', + 'bills_show_billChart' => 'Este gráfico muestra las transacciones vinculadas con esta factura.', + + // create bill + 'bills_create_name' => 'Use un nombre descriptivo como "alquiler" o "seguro de salud".', + 'bills_create_match' => 'Para hacer coincidir transacciones, use términos de esas transacciones o de la cuenta de gastos involucrada. Todas las palabras deben coincidir.', + 'bills_create_amount_min_holder' => 'Seleccione un monto mínimo y uno máximo para esta factura.', + 'bills_create_repeat_freq_holder' => 'Muchas facturas se repiten mensualmente, pero usted puede establecer otra frecuencia aquí.', + 'bills_create_skip_holder' => 'Si una factura se repite cada 2 semanas por ejemplo, el campo "omitir" debe establecerse en "1" para omitir cada otra semana.', + + // rules index + 'rules_index_intro' => 'Firefly III le permite administrar reglas, que automáticamente se aplicaran para cualquier transacción que cree o edite.', + 'rules_index_new_rule_group' => 'Usted puede combinar reglas en grupos para una administración mas fácil.', + 'rules_index_new_rule' => 'Crear tantas reglas como usted quiera.', + 'rules_index_prio_buttons' => 'Ordenarlos de la forma que mejor le parezca.', + 'rules_index_test_buttons' => 'Usted puede probar sus reglas o aplicarlas a transacciones existentes.', + 'rules_index_rule-triggers' => 'Las reglas tienen "disparadores" y "acciones" que usted puede ordenar arrastrando y soltando.', + 'rules_index_outro' => '¡Asegúrese de revisar las paginas de ayuda usando el icono (?) en el tope derecho!', + + // create rule: + 'rules_create_mandatory' => 'Elija un titulo descriptivo, y establezca cuando la regla deba ser botada.', + 'rules_create_ruletriggerholder' => 'Añadir tantos desencadenantes como desee, pero recuerde que TODOS los desencadenadores deben coincidir antes de que cualquier acción sea eliminada.', + 'rules_create_test_rule_triggers' => 'Use este botón para ser cuales transacciones coincidirán con su regla.', + 'rules_create_actions' => 'Establezca tantas acciones como usted lo desee.', + + // preferences + 'preferences_index_tabs' => 'Mas opciones están disponibles detrás de estas pestañas.', + + // currencies + 'currencies_index_intro' => 'Firefly III da soporte a múltiples monedas, que usted puede cambiar en esta página.', + 'currencies_index_default' => 'Firefly III tiene una moneda por defecto. Usted por supuesto puede siempre cambiarla usando estos botones.', + + // create currency + 'currencies_create_code' => 'Este código debe ser compatible con ISO (Google para su nueva moneda).', +]; diff --git a/resources/lang/es_ES/list.php b/resources/lang/es_ES/list.php new file mode 100644 index 0000000000..8b3527ab45 --- /dev/null +++ b/resources/lang/es_ES/list.php @@ -0,0 +1,105 @@ +. + */ +declare(strict_types=1); + +return [ + 'buttons' => 'Botones', + 'icon' => 'Icono', + 'id' => 'Identificación', + 'create_date' => 'Fecha de creación', + 'update_date' => 'Fecha de modificación', + 'updated_at' => 'Actualizado en', + 'balance_before' => 'Balance antes de ', + 'balance_after' => 'Balance después de la', + 'name' => 'Nombre', + 'role' => 'Rol', + 'currentBalance' => 'Balance actual', + 'active' => '¿Está Activo?', + 'lastActivity' => 'Actividad más reciente', + 'balanceDiff' => 'Diferencia de equilibrio', + 'matchesOn' => 'Encontrado en', + 'account_type' => 'Tipo de cuenta', + 'created_at' => 'Fecha de creación', + 'account' => 'Cuenta', + 'matchingAmount' => 'Monto', + 'split_number' => 'División #', + 'destination' => 'Destino', + 'source' => 'Origen', + 'next_expected_match' => 'Próxima coincidencia esperada', + 'automatch' => '¿Buscar coincidencia automaticamente?', + 'repeat_freq' => 'Repetición:', + 'description' => 'Descripción', + 'amount' => 'Monto', + 'internal_reference' => 'Referencia interna', + 'date' => 'Fecha', + 'interest_date' => 'Tasa de interés', + 'book_date' => 'Libro fecha', + 'process_date' => 'Fecha de procesamiento', + 'due_date' => 'Fecha de vencimiento', + 'payment_date' => 'Fecha de pago', + 'invoice_date' => 'Fecha de facturación', + 'interal_reference' => 'Referencia interna', + 'notes' => 'Notas', + 'from' => 'Desde', + 'piggy_bank' => 'Alcancilla', + 'to' => 'Hasta', + 'budget' => 'Presupuesto', + 'category' => 'Categoría', + 'bill' => 'Factura', + 'withdrawal' => 'Retiro', + 'deposit' => 'Depósito', + 'transfer' => 'Trasferencia', + 'type' => 'Tipo', + 'completed' => 'Completado', + 'iban' => 'IBAN', + 'paid_current_period' => 'Pagado este período', + 'email' => 'Correo electrónico', + 'registered_at' => 'Registrado el', + 'is_blocked' => 'Está bloqueado', + 'is_admin' => '¿Es el administrador?', + 'has_two_factor' => 'Tiene 2FA', + 'blocked_code' => 'Bloque de código', + 'source_account' => 'Cuenta origen', + 'destination_account' => 'Cuenta destino', + 'accounts_count' => 'Número de cuentas', + 'journals_count' => 'Número de transacciones', + 'attachments_count' => 'Núm. de datos adjuntos', + 'bills_count' => 'Número de facturas', + 'categories_count' => 'Número de categorías', + 'export_jobs_count' => 'Número de operaciones de exportación', + 'import_jobs_count' => 'Número de operaciones de importación', + 'budget_count' => 'Número de presupuestos', + 'rule_and_groups_count' => 'Número de reglas y grupos de reglas', + 'tags_count' => 'Número de etiquetas', + 'tags' => 'Etiquetas', + 'inward' => 'Descripción interna', + 'outward' => 'Descripción externa', + 'number_of_transactions' => 'Número de transacciones', + 'total_amount' => 'Total', + 'sum' => 'Suma', + 'sum_excluding_transfers' => 'Suma (excluyendo transferencias)', + 'sum_withdrawals' => 'Suma de retiros', + 'sum_deposits' => 'Suma de depositos', + 'sum_transfers' => 'Suma de transferencias', + 'reconcile' => 'Reconciliar', + 'account_on_spectre' => 'Cuenta (espectro)', + 'do_import' => 'Importar desde esta cuenta', +]; diff --git a/resources/lang/es_ES/pagination.php b/resources/lang/es_ES/pagination.php new file mode 100644 index 0000000000..da73ae7b5b --- /dev/null +++ b/resources/lang/es_ES/pagination.php @@ -0,0 +1,26 @@ +. + */ +declare(strict_types=1); + +return [ + 'previous' => '« Anterior', + 'next' => 'Siguiente »', +]; diff --git a/resources/lang/es_ES/passwords.php b/resources/lang/es_ES/passwords.php new file mode 100644 index 0000000000..593d7a97cd --- /dev/null +++ b/resources/lang/es_ES/passwords.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + 'password' => 'Las contraseñas deben tener al menos seis caracteres y coincidir entre sí.', + 'user' => 'No podemos encontrar un usuario con esa dirección de correo electrónico.', + 'token' => 'Este token para reestablecer la contraseña no es válido.', + 'sent' => 'Te enviamos un correo con el link para reestablecer tu contraseña!', + 'reset' => 'Tu contraseña fue reestablecida!', + 'blocked' => 'Buen intento.', +]; diff --git a/resources/lang/es_ES/validation.php b/resources/lang/es_ES/validation.php new file mode 100644 index 0000000000..1a579ff6a1 --- /dev/null +++ b/resources/lang/es_ES/validation.php @@ -0,0 +1,147 @@ +. + */ +declare(strict_types=1); + +return [ + 'iban' => 'Este no es un IBAN válido.', + 'unique_account_number_for_user' => 'Parece que este número de cuenta ya está en uso.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', + 'deleted_user' => 'Debido a restricciones de seguridad, no se puede registrar utilizando esta dirección de correo electrónico.', + 'rule_trigger_value' => 'Este valor es incorrecto para el disparador seleccionado.', + 'rule_action_value' => 'Este valor es incorrecto para la acción seleccionada.', + 'file_already_attached' => 'El archivo ":name" ya ha sido añadido a este objeto.', + 'file_attached' => 'Archivo cargado con exito ":name".', + 'must_exist' => 'ID introducido en :attribute el atributo no existe en la base de datos.', + 'all_accounts_equal' => 'Todas las cuentas en este campo deben ser iguales.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'Este valor no es válido para este campo.', + 'at_least_one_transaction' => 'Se necesita al menos una transacción.', + 'require_currency_info' => 'El contenido de este campo no es válido sin la información montearia.', + 'equal_description' => 'Transaction description should not equal global description.', + 'file_invalid_mime' => 'El archivo ":name" es de tipo ":mime", el cual no se acepta.', + 'file_too_large' => 'El archivo ":name" es demasiado grande.', + 'belongs_to_user' => 'El valor de :attribute es desconocido', + 'accepted' => 'El :attribute debe ser aceptado.', + 'bic' => 'Esto no es un BIC válido.', + 'more' => ':attribute debe ser mayor que cero.', + 'active_url' => 'El campo :attribute no es una URL válida.', + 'after' => 'El campo :attribute debe ser una fecha posterior a :date.', + 'alpha' => 'El campo :attribute sólo puede contener letras.', + 'alpha_dash' => 'El campo :attribute sólo puede contener letras, números y guiones.', + 'alpha_num' => 'El campo :attribute sólo puede contener letras y números.', + 'array' => 'El campo :attribute debe ser un arreglo.', + 'unique_for_user' => 'Ya hay una entrada con esto :attribute.', + 'before' => 'El campo :attribute debe contener una fecha anterior a :date.', + 'unique_object_for_user' => 'Este nombre ya está en uso', + 'unique_account_for_user' => 'Este nombre cuenta ya está en uso', + 'between.numeric' => 'El atributo :attribute debe estar entre :min y :max.', + 'between.file' => 'El atributo :attribute debe estar entre :min y :max kilobytes.', + 'between.string' => 'El atributo :attribute debe estar entre :min y :max caracteres.', + 'between.array' => 'El atributo :attribute debe estar entre :min y :max items.', + 'boolean' => 'El campo :attribute debe ser verdadero o falso.', + 'confirmed' => 'La confirmación de :attribute no coincide.', + 'date' => 'El campo :attribute no es una fecha válida.', + 'date_format' => 'El campo :attribute no corresponde con el formato :format.', + 'different' => 'Los campos :attribute y :other han de ser diferentes.', + 'digits' => 'El campo :attribute debe contener un número de :digits dígitos.', + 'digits_between' => 'El campo :attribute debe contener entre :min y :max dígitos.', + 'email' => 'El campo :attribute no corresponde con una dirección de e-mail válida.', + 'filled' => 'El campo :attribute es requerido.', + 'exists' => 'El campo :attribute seleccionado no es correcto.', + 'image' => 'El campo :attribute debe ser una imagen.', + 'in' => 'El campo :attribute seleccionado es inválido.', + 'integer' => 'El campo :attribute debe ser un entero.', + 'ip' => 'El campo :attribute debe contener una dirección IP válida.', + 'json' => 'El campo :attribute debe ser una cadena JSON válida.', + 'max.numeric' => 'El campo :attribute no puede ser mayor que :max.', + 'max.file' => 'El campo :attribute no puede ser mayor :max de kilobytes.', + 'max.string' => 'El campo :attribute debe contener menos de :max caracteres.', + 'max.array' => 'El campo :attribute debe contener al menos :max elementos.', + 'mimes' => 'El campo :attribute debe ser un archivo de tipo :values.', + 'min.numeric' => 'El campo :attribute debe ser al menos :min.', + 'min.file' => 'El campo :attribute debe ser al menos :min kilobytes.', + 'min.string' => 'El campo :attribute debe contener al menos :min caracteres.', + 'min.array' => 'El campo :attribute debe tener al menos :min elementos.', + 'not_in' => 'El campo :attribute seleccionado es incorrecto.', + 'numeric' => 'El campo :attribute debe ser un número.', + 'regex' => 'El formato del campo :attribute no es válido.', + 'required' => 'El campo :attribute es obligatorio.', + 'required_if' => 'El campo :attribute es obligatorio cuando el campo :other es :value.', + 'required_unless' => 'El campo :attribute es obligatorio a menos que :other se encuentre en :values.', + 'required_with' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_with_all' => 'El campo :attribute es obligatorio cuando :values está presente.', + 'required_without' => 'El campo :attribute es obligatorio cuando :values no está presente.', + 'required_without_all' => 'El campo :attribute es obligatorio cuando ningún campo :values está presente.', + 'same' => 'El campo atributo :attribute y :other deben coincidir.', + 'size.numeric' => 'El tamaño de :attribute debe ser :size.', + 'amount_min_over_max' => 'La cantidad mínima no puede ser mayor que la cantidad máxima.', + 'size.file' => 'El tamaño de :attribute debe ser :size kilobytes.', + 'size.string' => 'El campo :attribute debe tener :size caracteres.', + 'size.array' => 'El campo :attribute debe contener :size elementos.', + 'unique' => 'El elemento :attribute ya está en uso.', + 'string' => 'El :attribute debería ser una cadena de caracteres.', + 'url' => 'El formato del campo :attribute no es válido.', + 'timezone' => 'El campo :attribute debe contener una zona válida.', + '2fa_code' => 'El campo :attribute no es válido.', + 'dimensions' => 'Las dimensiones de la imagen :attribute son incorrectas.', + 'distinct' => 'El campo :attribute tiene un valor duplicado.', + 'file' => 'El campo :attribute debe ser un fichero.', + 'in_array' => 'El campo :attribute no existe en :other.', + 'present' => 'El campo :attribute debe estar presente.', + 'amount_zero' => 'La cantidad total no puede ser cero', + 'secure_password' => 'Esta contraseña no es segura. Por favor inténtalo de nuevo. Para más información, visita https://goo.gl/NCh2tN', + 'attributes' => [ + 'email' => 'dirección de correo electrónico', + 'description' => 'descripcion', + 'amount' => 'monto', + 'name' => 'nombre', + 'piggy_bank_id' => 'ID de hucha', + 'targetamount' => 'monto objetivo', + 'openingBalanceDate' => 'fecha de balance de apertura', + 'openingBalance' => 'balance de apertura', + 'match' => 'emparejar', + 'amount_min' => 'monto minimo', + 'amount_max' => 'monto maximo', + 'title' => 'titulo', + 'tag' => 'etiqueta', + 'transaction_description' => 'Descripción de la transacción', + 'rule-action-value.1' => 'valor de acción de la regla #1', + 'rule-action-value.2' => 'valor de acción de regla # 2', + 'rule-action-value.3' => 'valor de acción de regla # 3', + 'rule-action-value.4' => 'valor de acción de regla # 4', + 'rule-action-value.5' => 'valor de accion de regla # 5', + 'rule-action.1' => 'acción de regla # 1', + 'rule-action.2' => 'acción de regla # 2', + 'rule-action.3' => 'acción de regla # 3', + 'rule-action.4' => 'acción de regla # 4', + 'rule-action.5' => 'acción de regla # 5', + 'rule-trigger-value.1' => 'valor de disparo de regla #1', + 'rule-trigger-value.2' => 'valor de disparo de regla # 2', + 'rule-trigger-value.3' => 'valor de disparo de regla # 3', + 'rule-trigger-value.4' => 'valor de disparo de regla # 4', + 'rule-trigger-value.5' => 'valor de disparo de regla #5', + 'rule-trigger.1' => 'disparo de regla # 1', + 'rule-trigger.2' => 'disparo de regla #2', + 'rule-trigger.3' => 'disparo de regla #3', + 'rule-trigger.4' => 'disparo de regla #4', + 'rule-trigger.5' => 'disparo de regla#5', + ], +]; diff --git a/resources/lang/fr_FR/components.php b/resources/lang/fr_FR/components.php new file mode 100644 index 0000000000..fae0f0f10b --- /dev/null +++ b/resources/lang/fr_FR/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Personal access tokens', + + // bills: + 'not_expected_period' => 'Not expected this period', + 'not_or_not_yet' => 'Not (yet)', +]; \ No newline at end of file diff --git a/resources/lang/fr_FR/config.php b/resources/lang/fr_FR/config.php index e672331dc5..5c774ae250 100644 --- a/resources/lang/fr_FR/config.php +++ b/resources/lang/fr_FR/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'fr', - 'locale' => 'fr, French, fr_FR, fr_FR.utf8, fr_FR.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%B %e %Y @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Semaine %W %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'fr', + 'locale' => 'fr, French, fr_FR, fr_FR.utf8, fr_FR.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%B %e %Y @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Semaine %W %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/fr_FR/firefly.php b/resources/lang/fr_FR/firefly.php index 636ca3716c..3a53b6837c 100644 --- a/resources/lang/fr_FR/firefly.php +++ b/resources/lang/fr_FR/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Réinitialiser', 'want_to_login' => 'Je veux me connecter', 'button_register' => 'S\'inscrire', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Authorization Request', + 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', + 'scopes_will_be_able' => 'This application will be able to:', + 'button_authorize' => 'Authorize', // check for updates: 'update_check_title' => 'Vérifier les mises à jour', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Dois-je cocher la case ?', 'secure_pw_long_password' => 'Si vous venez de générer un long mot de passe unique pour Firefly III à l\'aide d\'un type de générateur de mot de passe : non.', 'secure_pw_short' => 'Si vous venez d\'entrer le mot de passe que vous utilisez toujours : oui.', - 'personal_access_token' => 'Token d\'accès personnel', - 'explain_access_token' => 'Vous avez besoin de ce token pour exécuter des opérations optionnelles en ligne de commandes telles qu\'import et export de données. Sans celui-ci, de telles commandes sensibles ne fonctionneront pas. Personne ne vous le demandera, pas même moi. Si vous craignez de le perdre, ou si vous êtes parano, régénérez ce token à l\'aide du bouton.', - 'regenerate_access_token' => 'Régénérer le token d\'accès', - 'token_regenerated' => 'Un nouveau token a été généré', + 'command_line_token' => 'Command line token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Regenerate command line token', + 'token_regenerated' => 'A new command line token was generated', 'change_your_email' => 'Changer votre adresse e-mail', 'email_verification' => 'Un e-mail sera envoyé à votre ancienne ET votre nouvelle adresse. Pour des raisons de sécurité, vous ne pourrez pas vous connecter jusqu\'à ce que vous ayez vérifié votre nouvelle adresse. Si vous n\'êtes pas certain que votre installation de Firefly III soit capable d\'envoyer un e-mail, n\'utilisez pas cette fonctionnalité. Si vous êtes un administrateur, vous pouvez tester l\'envoi des e-mails en allant dans le menu Administration.', 'email_changed_logout' => 'Vous ne pouvez pas vous connecter tant que vous n\'aurez pas vérifié votre adresse e-mail.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Réanalyser tout.', 'average_bill_amount_year' => 'Montant moyen des factures ( :year)', 'average_bill_amount_overall' => 'Montant moyen de la facture (global)', - 'not_or_not_yet' => 'Pas du tout (pas encore)', - 'not_expected_period' => 'Cette période n\'est pas prévue', 'bill_is_active' => 'Facture en cours', 'bill_expected_between' => 'Attendu entre le :start et le :end', 'bill_will_automatch' => 'La facture sera automatiquement liée aux transactions correspondantes', @@ -678,9 +683,9 @@ return [ 'start_of_reconcile_period' => 'Début de la période de rapprochement : :period', 'start_balance' => 'Solde initial', 'end_balance' => 'Solde de clotûre', - 'update_balance_dates_instruction' => 'Faites correspondre les montants et les dates ci-dessus à votre relevé bancaire et appuyez sur "Démarrer le rapprochement"', + 'update_balance_dates_instruction' => 'Faites correspondre les montants et les dates ci-dessus à votre relevé bancaire et appuyez sur "Commencer le rapprochement"', 'select_transactions_instruction' => 'Sélectionnez les transactions qui apparaissent sur votre relevé bancaire.', - 'select_range_and_balance' => 'Vérifiez d\'abord la plage des dates et les soldes. Puis appuyez sur "Démarrer le rapprochement"', + 'select_range_and_balance' => 'Vérifiez d\'abord la plage des dates et les soldes. Puis appuyez sur "Commencer le rapprochement"', 'date_change_instruction' => 'Si vous modifiez la plage des dates maintenant, toute progression sera perdue.', 'update_selection' => 'Mettre à jour la sélection', 'store_reconcile' => 'Stocker le rapprochement', @@ -1127,7 +1132,7 @@ return [ // import index page: 'import_index_title' => 'Importer des données dans Firefly III', 'import_index_sub_title' => 'Index', - 'import_general_index_intro' => 'Bienvenue dans la routine d\'importation de Firefly. Il existe différentes façons d\'importer des données dans Firefly III, affichées ici sous forme de boutons.', + 'import_general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Cette fonction n\'est pas disponible lorsque vous utilisez Firefly III dans un environnement Sandstorm.io.', diff --git a/resources/lang/fr_FR/form.php b/resources/lang/fr_FR/form.php index 20904dc807..5aacce4723 100644 --- a/resources/lang/fr_FR/form.php +++ b/resources/lang/fr_FR/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le tag ":tag" ?', 'journal_link_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le lien entre :source et :destination?', 'linkType_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le type de lien ":name" (":inward" / ":outward") ?', - 'permDeleteWarning' => 'Supprimer quelque chose dans Firefly est permanent et ne peut pas être annulé.', + 'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.', 'mass_make_selection' => 'Vous pouvez toujours empêcher des éléments d’être supprimés en décochant la case à cocher.', 'delete_all_permanently' => 'Supprimer la selection définitivement', 'update_all_journals' => 'Mettre à jour ces opérations', diff --git a/resources/lang/fr_FR/help.php b/resources/lang/fr_FR/help.php index 0f23bd7edd..3df7080096 100644 --- a/resources/lang/fr_FR/help.php +++ b/resources/lang/fr_FR/help.php @@ -1,4 +1,25 @@ . + */ + declare(strict_types=1); /** diff --git a/resources/lang/fr_FR/import.php b/resources/lang/fr_FR/import.php index 86e7cdd00f..d8b5eaaaf1 100644 --- a/resources/lang/fr_FR/import.php +++ b/resources/lang/fr_FR/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Statut d\'importation', 'config_sub_title' => 'Configurez votre importation', 'status_finished_job' => 'The :count transactions imported can be found in tag :tag.', - 'status_finished_no_tag' => 'Firefly III has not collected any journals from your import file.', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'import_with_key' => 'Importer avec la clé \':key\'', // file, upload something diff --git a/resources/lang/fr_FR/validation.php b/resources/lang/fr_FR/validation.php index 405bb7e911..d025e5bb46 100644 --- a/resources/lang/fr_FR/validation.php +++ b/resources/lang/fr_FR/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Il ne s\'agit pas d\'un IBAN valide.', 'unique_account_number_for_user' => 'Il semble que ce numéro de compte est déjà utilisé.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', 'deleted_user' => 'Compte tenu des contraintes de sécurité, vous ne pouvez pas vous inscrire en utilisant cette adresse e-mail.', 'rule_trigger_value' => 'Cette valeur n’est pas valide pour le déclencheur sélectionné.', 'rule_action_value' => 'Cette valeur n’est pas valide pour l’action sélectionnée.', 'file_already_attached' => 'Le fichier téléchargé ":name" est déjà attaché à cet objet.', 'file_attached' => 'Envoi du fichier ":name" avec succès.', + 'must_exist' => 'The ID in field :attribute does not exist in the database.', + 'all_accounts_equal' => 'All accounts in this field must be equal.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'This value is invalid for this field.', + 'at_least_one_transaction' => 'Need at least one transaction.', + 'require_currency_info' => 'The content of this field is invalid without currency information.', + 'equal_description' => 'Transaction description should not equal global description.', 'file_invalid_mime' => 'Le fichier ":name" est du type ":mime" ce qui n\'est pas accepté pour un nouvel envoi.', 'file_too_large' => 'Le fichier ":name" est trop grand.', 'belongs_to_user' => 'La valeur de :attribute est inconnue', @@ -84,6 +92,7 @@ return [ 'required_without_all' => 'Le champ :attribute est requis quand aucun de :values n\'est présent.', 'same' => 'Les champs :attribute et :other doivent être identiques.', 'size.numeric' => 'La valeur de :attribute doit être :size.', + 'amount_min_over_max' => 'The minimum amount cannot be larger than the maximum amount.', 'size.file' => 'La taille du fichier de :attribute doit être de :size kilo-octets.', 'size.string' => 'Le texte de :attribute doit contenir :size caractères.', 'size.array' => 'Le tableau :attribute doit contenir :size éléments.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Le montant total ne peut pas être zéro', 'secure_password' => 'Ce n’est pas un mot de passe sécurisé. S’il vous plaît essayer de nouveau. Pour plus d’informations, visitez https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'adresse email', - 'description' => 'description', - 'amount' => 'montant', - 'name' => 'nom', - 'targetamount' => 'montant cible', - 'openingBalanceDate' => 'date du solde initial', - 'openingBalance' => 'solde initial', - 'match' => 'correspondance', - 'amount_min' => 'montant minimum', - 'amount_max' => 'montant maximum', - 'title' => 'titre', - 'tag' => 'tag', - 'rule-action-value.1' => 'valeur d\'action de la règle #1', - 'rule-action-value.2' => 'valeur d\'action de la règle #2', - 'rule-action-value.3' => 'valeur d\'action de la règle #3', - 'rule-action-value.4' => 'valeur d\'action de la règle #4', - 'rule-action-value.5' => 'valeur d\'action de la règle #5', - 'rule-action.1' => 'action de règle #1', - 'rule-action.2' => 'action de règle #2', - 'rule-action.3' => 'action de règle #3', - 'rule-action.4' => 'action de règle #4', - 'rule-action.5' => 'action de règle #5', - 'rule-trigger-value.1' => 'valeur seuil de déclenchement de la règle #1', - 'rule-trigger-value.2' => 'valeur seuil de déclenchement de la règle #2', - 'rule-trigger-value.3' => 'valeur seuil de déclenchement de la règle #3', - 'rule-trigger-value.4' => 'valeur seuil de déclenchement de la règle #4', - 'rule-trigger-value.5' => 'valeur seuil de déclenchement de la règle #5', - 'rule-trigger.1' => 'déclencheur de règle #1', - 'rule-trigger.2' => 'déclencheur de règle #2', - 'rule-trigger.3' => 'déclencheur de règle #3', - 'rule-trigger.4' => 'déclencheur de règle #4', - 'rule-trigger.5' => 'déclencheur de règle #4', + 'email' => 'adresse email', + 'description' => 'description', + 'amount' => 'montant', + 'name' => 'nom', + 'piggy_bank_id' => 'piggy bank ID', + 'targetamount' => 'montant cible', + 'openingBalanceDate' => 'date du solde initial', + 'openingBalance' => 'solde initial', + 'match' => 'correspondance', + 'amount_min' => 'montant minimum', + 'amount_max' => 'montant maximum', + 'title' => 'titre', + 'tag' => 'tag', + 'transaction_description' => 'transaction description', + 'rule-action-value.1' => 'valeur d\'action de la règle #1', + 'rule-action-value.2' => 'valeur d\'action de la règle #2', + 'rule-action-value.3' => 'valeur d\'action de la règle #3', + 'rule-action-value.4' => 'valeur d\'action de la règle #4', + 'rule-action-value.5' => 'valeur d\'action de la règle #5', + 'rule-action.1' => 'action de règle #1', + 'rule-action.2' => 'action de règle #2', + 'rule-action.3' => 'action de règle #3', + 'rule-action.4' => 'action de règle #4', + 'rule-action.5' => 'action de règle #5', + 'rule-trigger-value.1' => 'valeur seuil de déclenchement de la règle #1', + 'rule-trigger-value.2' => 'valeur seuil de déclenchement de la règle #2', + 'rule-trigger-value.3' => 'valeur seuil de déclenchement de la règle #3', + 'rule-trigger-value.4' => 'valeur seuil de déclenchement de la règle #4', + 'rule-trigger-value.5' => 'valeur seuil de déclenchement de la règle #5', + 'rule-trigger.1' => 'déclencheur de règle #1', + 'rule-trigger.2' => 'déclencheur de règle #2', + 'rule-trigger.3' => 'déclencheur de règle #3', + 'rule-trigger.4' => 'déclencheur de règle #4', + 'rule-trigger.5' => 'déclencheur de règle #4', ], ]; diff --git a/resources/lang/id_ID/components.php b/resources/lang/id_ID/components.php new file mode 100644 index 0000000000..fae0f0f10b --- /dev/null +++ b/resources/lang/id_ID/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Personal access tokens', + + // bills: + 'not_expected_period' => 'Not expected this period', + 'not_or_not_yet' => 'Not (yet)', +]; \ No newline at end of file diff --git a/resources/lang/id_ID/config.php b/resources/lang/id_ID/config.php index 2fd4ff1ecc..3aacdec3fa 100644 --- a/resources/lang/id_ID/config.php +++ b/resources/lang/id_ID/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'id', - 'locale' => 'id, Bahasa Indonesia, id_ID, id_ID.utf8, id_ID.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%e %B %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Minggu %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'id', + 'locale' => 'id, Bahasa Indonesia, id_ID, id_ID.utf8, id_ID.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%e %B %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Minggu %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/id_ID/firefly.php b/resources/lang/id_ID/firefly.php index 58fc0a344c..a8697dd99a 100644 --- a/resources/lang/id_ID/firefly.php +++ b/resources/lang/id_ID/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Reset', 'want_to_login' => 'I want to login', 'button_register' => 'Register', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Authorization Request', + 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', + 'scopes_will_be_able' => 'This application will be able to:', + 'button_authorize' => 'Authorize', // check for updates: 'update_check_title' => 'Check for updates', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Haruskah saya mencentang kotaknya?', 'secure_pw_long_password' => 'Jika Anda baru saja menghasilkan kata sandi penggunaan tunggal yang hebat untuk Firefly III menggunakan beberapa jenis generator kata kunci: tidak.', 'secure_pw_short' => 'Jika Anda baru memasukkan kata sandi yang selalu Anda gunakan: Please yes.', - 'personal_access_token' => 'Token akses pribadi', - 'explain_access_token' => 'Anda memerlukan token ini untuk melakukan opsi baris perintah, seperti mengimpor atau mengekspor data. Tanpa itu, perintah sensitif semacam itu tidak akan berhasil. Jangan berbagi token akses Anda. Tidak ada yang akan menanyakan token ini, bahkan saya pun tidak. Jika Anda takut kehilangan ini, atau saat Anda paranoid, pulihkan token ini dengan menggunakan tombolnya.', - 'regenerate_access_token' => 'Regenerasi token akses', - 'token_regenerated' => 'Token baru dihasilkan', + 'command_line_token' => 'Command line token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Regenerate command line token', + 'token_regenerated' => 'A new command line token was generated', 'change_your_email' => 'Ubah alamat email anda', 'email_verification' => 'Pesan email akan dikirim ke alamat email lama DAN baru Anda. Untuk tujuan keamanan, Anda tidak dapat masuk sampai Anda memverifikasi alamat email baru Anda. Jika Anda tidak yakin apakah instalasi Firefly III Anda bisa mengirim email, tolong jangan gunakan fitur ini. Jika Anda seorang administrator, Anda dapat mengujinya di Administrasi.', 'email_changed_logout' => 'Sampai Anda memverifikasi alamat email Anda, Anda tidak dapat login.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Rescanned semuanya.', 'average_bill_amount_year' => 'Jumlah tagihan rata-rata (:year)', 'average_bill_amount_overall' => 'Jumlah tagihan rata-rata (keseluruhan)', - 'not_or_not_yet' => 'Belum)', - 'not_expected_period' => 'Tidak diharapkan periode ini', 'bill_is_active' => 'Tagihan aktif', 'bill_expected_between' => 'Diharapkan antara :start dan :end', 'bill_will_automatch' => 'Tagihan akan secara otomatis terhubung ke transaksi yang sesuai', @@ -1127,7 +1132,7 @@ return [ // import index page: 'import_index_title' => 'Impor data ke Firefly III', 'import_index_sub_title' => 'Indeks', - 'import_general_index_intro' => 'Selamat datang di rutinitas impor Firefly. Ada beberapa cara untuk mengimpor data ke Firefly III, yang ditampilkan di sini sebagai tombol.', + 'import_general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Fungsi ini tidak tersedia saat Anda menggunakan Firefly III di dalam lingkungan Sandstorm.io.', diff --git a/resources/lang/id_ID/form.php b/resources/lang/id_ID/form.php index e81300934a..1842886da6 100644 --- a/resources/lang/id_ID/form.php +++ b/resources/lang/id_ID/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Yakin ingin menghapus tag ":tag"?', 'journal_link_areYouSure' => 'Yakin ingin menghapus tautan antara :source and :destination?', 'linkType_areYouSure' => 'Yakin ingin menghapus jenis tautan ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Menghapus barang dari Firely bersifat permanen dan tidak dapat dibatalkan.', + 'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.', 'mass_make_selection' => 'Anda masih dapat mencegah agar item dihapus dengan menghapus kotak centang.', 'delete_all_permanently' => 'Hapus yang dipilih secara permanen', 'update_all_journals' => 'Perbarui transaksi ini', diff --git a/resources/lang/id_ID/import.php b/resources/lang/id_ID/import.php index 5c3c76abe6..6e1c02c83c 100644 --- a/resources/lang/id_ID/import.php +++ b/resources/lang/id_ID/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Status impor', 'config_sub_title' => 'Siapkan impor Anda', 'status_finished_job' => 'The :count transactions imported can be found in tag :tag.', - 'status_finished_no_tag' => 'Firefly III has not collected any journals from your import file.', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'import_with_key' => 'Impor dengan kunci \':key\'', // file, upload something diff --git a/resources/lang/id_ID/validation.php b/resources/lang/id_ID/validation.php index e4c07c4b90..3d1fd3f1f5 100644 --- a/resources/lang/id_ID/validation.php +++ b/resources/lang/id_ID/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Ini bukan IBAN yang valid.', 'unique_account_number_for_user' => 'Sepertinya nomor rekening ini sudah digunakan.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', 'deleted_user' => 'Kerena kendala keamanan, anda tidak bisa mendaftar menggunkan alamat email ini.', 'rule_trigger_value' => 'Nilai ini tidak validi untuk trigger yang dipilih.', 'rule_action_value' => 'Nilai ini tidak valid untuk tindakan yang dipilih.', 'file_already_attached' => 'Upload file ";name" sudah terpasang pada objek ini.', 'file_attached' => 'File yang diupload dengan sukses ":name.', + 'must_exist' => 'The ID in field :attribute does not exist in the database.', + 'all_accounts_equal' => 'All accounts in this field must be equal.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'This value is invalid for this field.', + 'at_least_one_transaction' => 'Need at least one transaction.', + 'require_currency_info' => 'The content of this field is invalid without currency information.', + 'equal_description' => 'Transaction description should not equal global description.', 'file_invalid_mime' => 'File ":name" adalah tipe ":mime" yang tidak diterima sebagai upload baru.', 'file_too_large' => 'File "; name" terlalu besar.', 'belongs_to_user' => 'Nilai dari :attribute tidak diketahui', @@ -84,6 +92,7 @@ return [ 'required_without_all' => 'Bidang :attribute diperlukan ketika tidak ada satupun :values ada.', 'same' => ':attribute dan :other harus cocok.', 'size.numeric' => ':attribute harus :size.', + 'amount_min_over_max' => 'The minimum amount cannot be larger than the maximum amount.', 'size.file' => ':attribute harus kilobyte :size.', 'size.string' => ':attribute harus karakter :size.', 'size.array' => ':attribute harus berisi item :size.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Jumlah total tidak boleh nol', 'secure_password' => 'Ini bukan kata sandi yang aman. Silahkan coba lagi. Untuk informasi lebih lanjut, kunjungi https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'email address', - 'description' => 'description', - 'amount' => 'amount', - 'name' => 'name', - 'targetamount' => 'target amount', - 'openingBalanceDate' => 'opening balance date', - 'openingBalance' => 'opening balance', - 'match' => 'match', - 'amount_min' => 'minimum amount', - 'amount_max' => 'maximum amount', - 'title' => 'title', - 'tag' => 'tag', - 'rule-action-value.1' => 'rule action value #1', - 'rule-action-value.2' => 'rule action value #2', - 'rule-action-value.3' => 'rule action value #3', - 'rule-action-value.4' => 'rule action value #4', - 'rule-action-value.5' => 'rule action value #5', - 'rule-action.1' => 'rule action #1', - 'rule-action.2' => 'rule action #2', - 'rule-action.3' => 'rule action #3', - 'rule-action.4' => 'rule action #4', - 'rule-action.5' => 'rule action #5', - 'rule-trigger-value.1' => 'rule trigger value #1', - 'rule-trigger-value.2' => 'rule trigger value #2', - 'rule-trigger-value.3' => 'rule trigger value #3', - 'rule-trigger-value.4' => 'rule trigger value #4', - 'rule-trigger-value.5' => 'rule trigger value #5', - 'rule-trigger.1' => 'rule trigger #1', - 'rule-trigger.2' => 'rule trigger #2', - 'rule-trigger.3' => 'rule trigger #3', - 'rule-trigger.4' => 'rule trigger #4', - 'rule-trigger.5' => 'rule trigger #5', + 'email' => 'email address', + 'description' => 'description', + 'amount' => 'amount', + 'name' => 'name', + 'piggy_bank_id' => 'piggy bank ID', + 'targetamount' => 'target amount', + 'openingBalanceDate' => 'opening balance date', + 'openingBalance' => 'opening balance', + 'match' => 'match', + 'amount_min' => 'minimum amount', + 'amount_max' => 'maximum amount', + 'title' => 'title', + 'tag' => 'tag', + 'transaction_description' => 'transaction description', + 'rule-action-value.1' => 'rule action value #1', + 'rule-action-value.2' => 'rule action value #2', + 'rule-action-value.3' => 'rule action value #3', + 'rule-action-value.4' => 'rule action value #4', + 'rule-action-value.5' => 'rule action value #5', + 'rule-action.1' => 'rule action #1', + 'rule-action.2' => 'rule action #2', + 'rule-action.3' => 'rule action #3', + 'rule-action.4' => 'rule action #4', + 'rule-action.5' => 'rule action #5', + 'rule-trigger-value.1' => 'rule trigger value #1', + 'rule-trigger-value.2' => 'rule trigger value #2', + 'rule-trigger-value.3' => 'rule trigger value #3', + 'rule-trigger-value.4' => 'rule trigger value #4', + 'rule-trigger-value.5' => 'rule trigger value #5', + 'rule-trigger.1' => 'rule trigger #1', + 'rule-trigger.2' => 'rule trigger #2', + 'rule-trigger.3' => 'rule trigger #3', + 'rule-trigger.4' => 'rule trigger #4', + 'rule-trigger.5' => 'rule trigger #5', ], ]; diff --git a/resources/lang/nl_NL/components.php b/resources/lang/nl_NL/components.php new file mode 100644 index 0000000000..ca86e4a33d --- /dev/null +++ b/resources/lang/nl_NL/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Persoonlijke toegangstokens', + + // bills: + 'not_expected_period' => 'Niet verwacht deze periode', + 'not_or_not_yet' => '(nog) niet', +]; \ No newline at end of file diff --git a/resources/lang/nl_NL/config.php b/resources/lang/nl_NL/config.php index c1cd4dd746..4128c1abc5 100644 --- a/resources/lang/nl_NL/config.php +++ b/resources/lang/nl_NL/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'nl', - 'locale' => 'nl, Dutch, nl_NL, nl_NL.utf8, nl_NL.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%e %B %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'week %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'nl', + 'locale' => 'nl, Dutch, nl_NL, nl_NL.utf8, nl_NL.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%e %B %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'week %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'D MMMM YYYY', + 'date_time_js' => 'D MMMM YYYY @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/nl_NL/firefly.php b/resources/lang/nl_NL/firefly.php index ed533459de..4ceaac77e5 100644 --- a/resources/lang/nl_NL/firefly.php +++ b/resources/lang/nl_NL/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Reset', 'want_to_login' => 'Ik wil inloggen', 'button_register' => 'Registreren', + 'authorization' => 'Toestemming', + + // API access + 'authorization_request' => 'Firefly III v:version autorisatieverzoek', + 'authorization_request_intro' => ':client vraagt ​​toestemming om toegang te krijgen tot je financiële administratie. Wil je :client autoriseren om toegang te krijgen tot je gegevens?', + 'scopes_will_be_able' => 'Deze applicatie krijgt toegang tot:', + 'button_authorize' => 'Toestaan', // check for updates: 'update_check_title' => 'Op updates controleren', @@ -433,7 +440,7 @@ return [ 'pref_two_factor_auth_help' => 'Als je authenticatie in twee stappen (ook wel twee-factor authenticatie genoemd) inschakelt voeg je een extra beveiligingslaag toe aan je account. Je logt in met iets dat je weet (je wachtwoord) en iets dat je hebt (een verificatiecode). Verificatiecodes worden gegeneerd door apps op je telefoon, zoals Authy en Google Authenticator.', 'pref_enable_two_factor_auth' => 'Authenticatie in twee stappen inschakelen', 'pref_two_factor_auth_disabled' => 'Je verificatiecode voor authenticatie in twee stappen is verwijderd, en uitgeschakeld', - 'pref_two_factor_auth_remove_it' => 'Vergeet niet om je Firefly account uit je authenticatie appje te verwijderen!', + 'pref_two_factor_auth_remove_it' => 'Vergeet niet om je Firefly III account uit je authenticatie appje te verwijderen!', 'pref_two_factor_auth_code' => 'Bevestig de code', 'pref_two_factor_auth_code_help' => 'Scan deze QR code met een app op je telefoon (zoals Authy of Google Authenticator). Vul de code die je terug krijgt hier in.', 'pref_two_factor_auth_reset_code' => 'Reset de verificatiecode', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Vinkje zetten of niet?', 'secure_pw_long_password' => 'Als je net een lang wachtwoord hebt gegenereerd met een password generator tool: nee.', 'secure_pw_short' => 'Gebruik je het wachtwoord dat je altijd gebruikt? Ja, doen!', - 'personal_access_token' => 'Persoonlijk toegangstoken', - 'explain_access_token' => 'Je hebt dit token nodig als je commando\'s op de commandline draait, zoals het invoeren of uitvoeren van data. Zonder dit token werken zulke gevoelige opdrachten niet. Deel je toegangstoken niet. Niemand zal hier naar vragen, zelfs ik niet. Als je bang bent dat-ie op straat ligt, genereer dan een nieuw token.', - 'regenerate_access_token' => 'Genereer nieuw token', - 'token_regenerated' => 'Er is een nieuw token gegenereerd', + 'command_line_token' => 'Opdrachtprompt-token', + 'explain_command_line_token' => 'Je hebt dit token nodig als je commando\'s op de commandline draait, zoals het invoeren of uitvoeren van data. Zonder dit token werken zulke gevoelige opdrachten niet. Deel je opdrachtprompt-token niet. Niemand zal hier naar vragen, zelfs ik niet. Als je bang bent dat-ie op straat ligt, genereer dan een nieuw token.', + 'regenerate_command_line_token' => 'Nieuw opdrachtprompt-token genereren', + 'token_regenerated' => 'Er is een nieuw opdrachtprompt-token gegenereerd', 'change_your_email' => 'Verander je emailadres', 'email_verification' => 'Het systeem verstuurt een mailtje naar je oude EN nieuwe emailadres. Uit veiligheidsoverwegingen ben je zometeen uitgelogd en kan je pas weer inloggen als je je emailadres hebt bevestigd. Doe dit niet als je niet zeker weet of je Firefly III installatie wel mail kan versturen. Als je een admin bent, test dit dan eerst in de administratie.', 'email_changed_logout' => 'Je kan niet inloggen tot je je emailadres bevestigd.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Alles is opnieuw gescand.', 'average_bill_amount_year' => 'Gemiddeld contractbedrag (:year)', 'average_bill_amount_overall' => 'Gemiddeld contractbedrag (gehele periode)', - 'not_or_not_yet' => '(nog) niet', - 'not_expected_period' => 'Niet verwacht deze periode', 'bill_is_active' => 'Contract is actief', 'bill_expected_between' => 'Verwacht tussen :start en :end', 'bill_will_automatch' => 'Waar van toepassing wordt dit contract automatisch gekoppeld aan transacties', @@ -1127,7 +1132,7 @@ return [ // import index page: 'import_index_title' => 'Gegevens importeren in Firefly III', 'import_index_sub_title' => 'Index', - 'import_general_index_intro' => 'Dit is de import-routine van Firefly. Er zijn verschillende manieren om gegevens te importeren in Firefly III, hier als knoppen weergegeven.', + 'import_general_index_intro' => 'Dit is de import-routine van Firefly III. Er zijn verschillende manieren om gegevens te importeren in Firefly III, hier als knoppen weergegeven.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Deze functie werkt niet als je Firefly III gebruikt in combinatie met Sandstorm.IO.', diff --git a/resources/lang/nl_NL/form.php b/resources/lang/nl_NL/form.php index 39a3771efb..5397b2e7b5 100644 --- a/resources/lang/nl_NL/form.php +++ b/resources/lang/nl_NL/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Weet je zeker dat je de tag met naam ":tag" wilt verwijderen?', 'journal_link_areYouSure' => 'Weet je zeker dat je de koppeling tussen :source en :destination wilt verwijderen?', 'linkType_areYouSure' => 'Weet je zeker dat je linktype ":name" (":inward" / ":outward") wilt verwijderen?', - 'permDeleteWarning' => 'Dingen verwijderen uit Firefly is permanent en kan niet ongedaan gemaakt worden.', + 'permDeleteWarning' => 'Dingen verwijderen uit Firefly III is permanent en kan niet ongedaan gemaakt worden.', 'mass_make_selection' => 'Je kan items alsnog redden van de ondergang door het vinkje weg te halen.', 'delete_all_permanently' => 'Verwijder geselecteerde items permanent', 'update_all_journals' => 'Wijzig deze transacties', diff --git a/resources/lang/nl_NL/help.php b/resources/lang/nl_NL/help.php index e60d763a5f..c89e127c12 100644 --- a/resources/lang/nl_NL/help.php +++ b/resources/lang/nl_NL/help.php @@ -1,4 +1,25 @@ . + */ + declare(strict_types=1); /** diff --git a/resources/lang/nl_NL/validation.php b/resources/lang/nl_NL/validation.php index f738002932..c12b9ff77a 100644 --- a/resources/lang/nl_NL/validation.php +++ b/resources/lang/nl_NL/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Dit is niet een geldige IBAN.', 'unique_account_number_for_user' => 'Het lijkt erop dat dit rekeningnummer al in gebruik is.', + 'unique_iban_for_user' => 'Het lijkt erop dat deze IBAN al in gebruik is.', 'deleted_user' => 'Je kan je niet registreren met dit e-mailadres.', 'rule_trigger_value' => 'Deze waarde is niet geldig voor de geselecteerde trigger.', 'rule_action_value' => 'Deze waarde is niet geldig voor de geselecteerde actie.', 'file_already_attached' => 'Het geuploade bestand ":name" is al gelinkt aan deze transactie.', 'file_attached' => 'Bestand met naam ":name" is met succes geuploaded.', + 'must_exist' => 'Het ID in veld :attribute bestaat niet.', + 'all_accounts_equal' => 'Alle rekeningen in dit veld moeten gelijk zijn.', + 'invalid_selection' => 'Ongeldige selectie', + 'belongs_user' => 'Deze waarde is ongeldig voor dit veld.', + 'at_least_one_transaction' => 'Er is op zijn minst één transactie nodig.', + 'require_currency_info' => 'De inhoud van dit veld is ongeldig zonder valutagegevens.', + 'equal_description' => 'Transactiebeschrijving mag niet gelijk zijn aan globale beschrijving.', 'file_invalid_mime' => 'Bestand ":name" is van het type ":mime", en die kan je niet uploaden.', 'file_too_large' => 'Bestand ":name" is te groot.', 'belongs_to_user' => 'De waarde van :attribute is onbekend', @@ -84,6 +92,7 @@ return [ 'required_without_all' => ':attribute is verplicht als :values niet ingevuld zijn.', 'same' => ':attribute en :other moeten overeenkomen.', 'size.numeric' => ':attribute moet :size zijn.', + 'amount_min_over_max' => 'Het minimumbedrag mag niet groter zijn dan het maximale bedrag.', 'size.file' => ':attribute moet :size kilobyte zijn.', 'size.string' => ':attribute moet :size karakters zijn.', 'size.array' => ':attribute moet :size items bevatten.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Het totaalbedrag kan niet nul zijn', 'secure_password' => 'Dit is geen sterk wachtwoord. Probeer het nog een keer. Zie ook: https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'e-mailadres', - 'description' => 'omschrijving', - 'amount' => 'bedrag', - 'name' => 'naam', - 'targetamount' => 'doelbedrag', - 'openingBalanceDate' => 'startsaldodatum', - 'openingBalance' => 'startsaldo', - 'match' => 'overeenkomst', - 'amount_min' => 'minimumbedrag', - 'amount_max' => 'maximumbedrag', - 'title' => 'titel', - 'tag' => 'tag', - 'rule-action-value.1' => 'actiewaarde #1', - 'rule-action-value.2' => 'actiewaarde #2', - 'rule-action-value.3' => 'actiewaarde #3', - 'rule-action-value.4' => 'actiewaarde #4', - 'rule-action-value.5' => 'actiewaarde #5', - 'rule-action.1' => 'regelactie #1', - 'rule-action.2' => 'regelactie #2', - 'rule-action.3' => 'regelactie #3', - 'rule-action.4' => 'regelactie #4', - 'rule-action.5' => 'regelactie #5', - 'rule-trigger-value.1' => 'triggerwaarde #1', - 'rule-trigger-value.2' => 'triggerwaarde #2', - 'rule-trigger-value.3' => 'triggerwaarde #3', - 'rule-trigger-value.4' => 'triggerwaarde #4', - 'rule-trigger-value.5' => 'triggerwaarde #5', - 'rule-trigger.1' => 'regeltrigger #1', - 'rule-trigger.2' => 'regeltrigger #2', - 'rule-trigger.3' => 'regeltrigger #3', - 'rule-trigger.4' => 'regeltrigger #4', - 'rule-trigger.5' => 'regeltrigger #5', + 'email' => 'e-mailadres', + 'description' => 'omschrijving', + 'amount' => 'bedrag', + 'name' => 'naam', + 'piggy_bank_id' => 'spaarpot ID', + 'targetamount' => 'doelbedrag', + 'openingBalanceDate' => 'startsaldodatum', + 'openingBalance' => 'startsaldo', + 'match' => 'overeenkomst', + 'amount_min' => 'minimumbedrag', + 'amount_max' => 'maximumbedrag', + 'title' => 'titel', + 'tag' => 'tag', + 'transaction_description' => 'transactiebeschrijving', + 'rule-action-value.1' => 'actiewaarde #1', + 'rule-action-value.2' => 'actiewaarde #2', + 'rule-action-value.3' => 'actiewaarde #3', + 'rule-action-value.4' => 'actiewaarde #4', + 'rule-action-value.5' => 'actiewaarde #5', + 'rule-action.1' => 'regelactie #1', + 'rule-action.2' => 'regelactie #2', + 'rule-action.3' => 'regelactie #3', + 'rule-action.4' => 'regelactie #4', + 'rule-action.5' => 'regelactie #5', + 'rule-trigger-value.1' => 'triggerwaarde #1', + 'rule-trigger-value.2' => 'triggerwaarde #2', + 'rule-trigger-value.3' => 'triggerwaarde #3', + 'rule-trigger-value.4' => 'triggerwaarde #4', + 'rule-trigger-value.5' => 'triggerwaarde #5', + 'rule-trigger.1' => 'regeltrigger #1', + 'rule-trigger.2' => 'regeltrigger #2', + 'rule-trigger.3' => 'regeltrigger #3', + 'rule-trigger.4' => 'regeltrigger #4', + 'rule-trigger.5' => 'regeltrigger #5', ], ]; diff --git a/resources/lang/pl_PL/components.php b/resources/lang/pl_PL/components.php new file mode 100644 index 0000000000..81a7bd017f --- /dev/null +++ b/resources/lang/pl_PL/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Osobisty kod dostępowy', + + // bills: + 'not_expected_period' => 'Nie oczekiwany w tym okresie', + 'not_or_not_yet' => 'Nie (jeszcze)', +]; \ No newline at end of file diff --git a/resources/lang/pl_PL/config.php b/resources/lang/pl_PL/config.php index 6df562fa42..92fc995503 100644 --- a/resources/lang/pl_PL/config.php +++ b/resources/lang/pl_PL/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'pl', - 'locale' => 'pl, Polish, polski, pl_PL, pl_PL.utf8, pl_PL.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%e %B %Y o %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Tydzień %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'pl', + 'locale' => 'pl, Polish, polski, pl_PL, pl_PL.utf8, pl_PL.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%e %B %Y o %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Tydzień %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'D MMMM YYYY', + 'date_time_js' => 'D MMMM YYYY [o] HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Tydzień] w. YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/pl_PL/firefly.php b/resources/lang/pl_PL/firefly.php index 06066d366a..1b516f7f21 100644 --- a/resources/lang/pl_PL/firefly.php +++ b/resources/lang/pl_PL/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Zresetuj', 'want_to_login' => 'Chcę się zalogować', 'button_register' => 'Zarejestruj', + 'authorization' => 'Autoryzacja', + + // API access + 'authorization_request' => 'Żądanie autoryzacji Firefly III v:version', + 'authorization_request_intro' => ':client prosi o pozwolenie na dostęp do Twojej administracji finansowej. Czy chcesz pozwolić :client na dostęp do tych danych?', + 'scopes_will_be_able' => 'Ta aplikacja będzie mogła:', + 'button_authorize' => 'Autoryzuj', // check for updates: 'update_check_title' => 'Sprawdź aktualizacje', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Czy powinienem zaznaczyć to pole?', 'secure_pw_long_password' => 'Jeśli wygenerowałeś długie, jednorazowe hasło dla Firefly III, używając pewnego rodzaju generatora haseł: no.', 'secure_pw_short' => 'Jeśli wpisałeś hasło, którego zawsze używasz: tak, proszę.', - 'personal_access_token' => 'Osobisty kod dostępowy', - 'explain_access_token' => 'Potrzebujesz tego kodu aby wykonywać operacje (takie jak importowanie lub eksportowanie danych) za pomocą wiersza poleceń. Bez niego takie wrażliwe polecenia nie będą działać. Nie udostępniaj nikomu swojego kodu dostępowego. Nikt nie zapyta Cię o ten kod, nawet ja. Jeżeli obawiasz się, że straciłeś go lub jesteś paranoikiem, wygeneruj nowy kod używając przycisku.', - 'regenerate_access_token' => 'Wygeneruj nowy kod', - 'token_regenerated' => 'Nowy kod dostępowy został wygenerowany', + 'command_line_token' => 'Token wiersza poleceń', + 'explain_command_line_token' => 'Potrzebujesz tego tokenu aby wykonywać operacje (takie jak importowanie lub eksportowanie danych) za pomocą wiersza poleceń. Bez niego takie wrażliwe polecenia nie będą działać. Nie udostępniaj nikomu swojego tokenu. Nikt Cię o niego nie zapyta, nawet ja. Jeżeli obawiasz się, że straciłeś go lub jesteś paranoikiem, wygeneruj nowy token używając przycisku.', + 'regenerate_command_line_token' => 'Wygeneruj nowy token wiersza poleceń', + 'token_regenerated' => 'Wygenerowano nowy token wiersza poleceń', 'change_your_email' => 'Zmień swój adres e-mail', 'email_verification' => 'Wiadomość e-mail zostanie wysłana na stary ORAZ nowy adres e-mail. Ze względów bezpieczeństwa, nie będziesz mógł się zalogować, dopóki nie zweryfikujesz nowego adresu e-mail. Jeśli nie masz pewności, czy twoja instalacja Firefly III umożliwia wysyłanie wiadomości e-mail, nie korzystaj z tej funkcji. Jeśli jesteś administratorem, możesz przetestować to w panelu administracyjnym.', 'email_changed_logout' => 'Dopóki nie zweryfikujesz swojego adresu e-mail, nie możesz się zalogować.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Zeskanowano wszystko.', 'average_bill_amount_year' => 'Średnia kwota rachunku (:year)', 'average_bill_amount_overall' => 'Średnia kwota rachunku (ogólnie)', - 'not_or_not_yet' => 'Nie (jeszcze)', - 'not_expected_period' => 'Nie oczekiwany w tym okresie', 'bill_is_active' => 'Rachunek jest aktywny', 'bill_expected_between' => 'Oczekiwano między :start a :end', 'bill_will_automatch' => 'Rachunek będzie automatycznie powiązany z pasującymi transakcjami', diff --git a/resources/lang/pl_PL/form.php b/resources/lang/pl_PL/form.php index 777b1ed0fd..3fe5e33b97 100644 --- a/resources/lang/pl_PL/form.php +++ b/resources/lang/pl_PL/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Czy na pewno chcesz usunąć tag ":tag"?', 'journal_link_areYouSure' => 'Czy na pewno chcesz usunąć powiązanie między :source a :destination?', 'linkType_areYouSure' => 'Czy na pewno chcesz usunąć typ łącza ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Usuwanie rzeczy z Firefly jest trwałe i nie można tego cofnąć.', + 'permDeleteWarning' => 'Usuwanie rzeczy z Firefly III jest trwałe i nie można tego cofnąć.', 'mass_make_selection' => 'Nadal możesz zapobiec usunięciu elementów, odznaczając je.', 'delete_all_permanently' => 'Trwale usuń zaznaczone', 'update_all_journals' => 'Zmodyfikuj te transakcje', diff --git a/resources/lang/pl_PL/help.php b/resources/lang/pl_PL/help.php index 1715bbe160..25fe523ab7 100644 --- a/resources/lang/pl_PL/help.php +++ b/resources/lang/pl_PL/help.php @@ -1,4 +1,25 @@ . + */ + declare(strict_types=1); /** diff --git a/resources/lang/pl_PL/import.php b/resources/lang/pl_PL/import.php index 261ec8417d..a2a686e984 100644 --- a/resources/lang/pl_PL/import.php +++ b/resources/lang/pl_PL/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Status importu', 'config_sub_title' => 'Skonfiguruj import', 'status_finished_job' => 'Zaimportowane transakcje (:count) znajdują się w tagu :tag.', - 'status_finished_no_tag' => 'Firefly III nie zaimportował żadnych wpisów z twojego pliku.', + 'status_finished_no_tag' => 'Firefly III nie zaimportował żadnych transakcji z twojego pliku.', 'import_with_key' => 'Import z kluczem \':key\'', // file, upload something diff --git a/resources/lang/pl_PL/validation.php b/resources/lang/pl_PL/validation.php index ae1868dd04..4563203afa 100644 --- a/resources/lang/pl_PL/validation.php +++ b/resources/lang/pl_PL/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'To nie jest prawidłowy IBAN.', 'unique_account_number_for_user' => 'Wygląda na to, że ten numer konta jest już w użyciu.', + 'unique_iban_for_user' => 'Wygląda na to, że ten IBAN jest już w użyciu.', 'deleted_user' => 'Ze względu na zabezpieczenia nie możesz się zarejestrować używając tego adresu e-mail.', 'rule_trigger_value' => 'Ta wartość jest nieprawidłowa dla wybranego wyzwalacza.', 'rule_action_value' => 'Ta wartość jest nieprawidłowa dla wybranej akcji.', 'file_already_attached' => 'Przesłany plik ":name" jest już dołączony do tego obiektu.', 'file_attached' => 'Pomyślnie wgrano plik ":name".', + 'must_exist' => 'Identyfikator w polu :attribute nie istnieje w bazie danych.', + 'all_accounts_equal' => 'Wszystkie konta w tym polu muszą być takie same.', + 'invalid_selection' => 'Twój wybór jest nieprawidłowy', + 'belongs_user' => 'Ta wartość jest nieprawidłowa dla tego pola.', + 'at_least_one_transaction' => 'Wymaga co najmniej jednej transakcji.', + 'require_currency_info' => 'Treść tego pola jest nieprawidłowa bez informacji o walucie.', + 'equal_description' => 'Opis transakcji nie powinien być równy globalnemu opisowi.', 'file_invalid_mime' => 'Plik ":name" jest typu ":mime", który nie jest akceptowany jako nowy plik do przekazania.', 'file_too_large' => 'Plik ":name" jest zbyt duży.', 'belongs_to_user' => 'Wartość :attribute jest nieznana', @@ -84,6 +92,7 @@ return [ 'required_without_all' => ':attribute jest wymagane, gdy żadna z wartości :values nie jest podana.', 'same' => 'Pole :attribute oraz :other muszą się zgadzać.', 'size.numeric' => ':attribute musi być wielkości :size.', + 'amount_min_over_max' => 'Minimalna kwota nie może być większa niż maksymalna kwota.', 'size.file' => ':attribute musi mieć :size kilobajtów.', 'size.string' => ':attribute musi mieć :size znaków.', 'size.array' => ':attribute musi zawierać :size elementów.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Całkowita kwota nie może być zerem', 'secure_password' => 'To nie jest bezpieczne hasło. Proszę spróbować ponownie. Aby uzyskać więcej informacji odwiedź https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'adres e-mail', - 'description' => 'opis', - 'amount' => 'kwota', - 'name' => 'nazwa', - 'targetamount' => 'kwota docelowa', - 'openingBalanceDate' => 'data salda otwarcia', - 'openingBalance' => 'bilans otwarcia', - 'match' => 'dopasowanie', - 'amount_min' => 'minimalna kwota', - 'amount_max' => 'maksymalna kwota', - 'title' => 'tytuł', - 'tag' => 'tag', - 'rule-action-value.1' => 'wartość akcji reguły #1', - 'rule-action-value.2' => 'wartość akcji reguły #2', - 'rule-action-value.3' => 'wartość akcji reguły #3', - 'rule-action-value.4' => 'wartość akcji reguły #4', - 'rule-action-value.5' => 'wartość akcji reguły #5', - 'rule-action.1' => 'akcja reguły #1', - 'rule-action.2' => 'akcja reguły #2', - 'rule-action.3' => 'akcja reguły #3', - 'rule-action.4' => 'akcja reguły #4', - 'rule-action.5' => 'akcja reguły #5', - 'rule-trigger-value.1' => 'wartość wyzwalacza reguły #1', - 'rule-trigger-value.2' => 'wartość wyzwalacza reguły #2', - 'rule-trigger-value.3' => 'wartość wyzwalacza reguły #3', - 'rule-trigger-value.4' => 'wartość wyzwalacza reguły #4', - 'rule-trigger-value.5' => 'wartość wyzwalacza reguły #5', - 'rule-trigger.1' => 'wyzwalacz reguły #1', - 'rule-trigger.2' => 'wyzwalacz reguły #2', - 'rule-trigger.3' => 'wyzwalacz reguły #3', - 'rule-trigger.4' => 'wyzwalacz reguły #4', - 'rule-trigger.5' => 'wyzwalacz reguły #5', + 'email' => 'adres e-mail', + 'description' => 'opis', + 'amount' => 'kwota', + 'name' => 'nazwa', + 'piggy_bank_id' => 'identyfikator skarbonki', + 'targetamount' => 'kwota docelowa', + 'openingBalanceDate' => 'data salda otwarcia', + 'openingBalance' => 'bilans otwarcia', + 'match' => 'dopasowanie', + 'amount_min' => 'minimalna kwota', + 'amount_max' => 'maksymalna kwota', + 'title' => 'tytuł', + 'tag' => 'tag', + 'transaction_description' => 'opis transakcji', + 'rule-action-value.1' => 'wartość akcji reguły #1', + 'rule-action-value.2' => 'wartość akcji reguły #2', + 'rule-action-value.3' => 'wartość akcji reguły #3', + 'rule-action-value.4' => 'wartość akcji reguły #4', + 'rule-action-value.5' => 'wartość akcji reguły #5', + 'rule-action.1' => 'akcja reguły #1', + 'rule-action.2' => 'akcja reguły #2', + 'rule-action.3' => 'akcja reguły #3', + 'rule-action.4' => 'akcja reguły #4', + 'rule-action.5' => 'akcja reguły #5', + 'rule-trigger-value.1' => 'wartość wyzwalacza reguły #1', + 'rule-trigger-value.2' => 'wartość wyzwalacza reguły #2', + 'rule-trigger-value.3' => 'wartość wyzwalacza reguły #3', + 'rule-trigger-value.4' => 'wartość wyzwalacza reguły #4', + 'rule-trigger-value.5' => 'wartość wyzwalacza reguły #5', + 'rule-trigger.1' => 'wyzwalacz reguły #1', + 'rule-trigger.2' => 'wyzwalacz reguły #2', + 'rule-trigger.3' => 'wyzwalacz reguły #3', + 'rule-trigger.4' => 'wyzwalacz reguły #4', + 'rule-trigger.5' => 'wyzwalacz reguły #5', ], ]; diff --git a/resources/lang/pt_BR/components.php b/resources/lang/pt_BR/components.php new file mode 100644 index 0000000000..7c4b0246f7 --- /dev/null +++ b/resources/lang/pt_BR/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Tokens de acesso pessoal', + + // bills: + 'not_expected_period' => 'Não esperado neste período', + 'not_or_not_yet' => 'Não (ainda)', +]; \ No newline at end of file diff --git a/resources/lang/pt_BR/config.php b/resources/lang/pt_BR/config.php index 3ab5a29a32..d2c895ed73 100644 --- a/resources/lang/pt_BR/config.php +++ b/resources/lang/pt_BR/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'pt-br', - 'locale' => 'pt-br, pt_BR, pt_BR.utf8, pt_BR.UTF-8', - 'month' => '%B %Yü', - 'month_and_day' => '%e de %B de %Y', - 'date_time' => '%B %e, %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Semana %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Yü', + 'html_language' => 'pt-br', + 'locale' => 'pt-br, pt_BR, pt_BR.utf8, pt_BR.UTF-8', + 'month' => '%B %Yü', + 'month_and_day' => '%e de %B de %Y', + 'date_time' => '%B %e, %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Semana %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Yü', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/pt_BR/firefly.php b/resources/lang/pt_BR/firefly.php index e14bf54914..f06e8d38c0 100644 --- a/resources/lang/pt_BR/firefly.php +++ b/resources/lang/pt_BR/firefly.php @@ -100,7 +100,7 @@ return [ 'expenses_by_category' => 'Despesa por categoria', 'expenses_by_budget' => 'Despesas pelo orçamento', 'income_by_category' => 'Receitas por categoria', - 'expenses_by_asset_account' => 'Despesas por contas ativas', + 'expenses_by_asset_account' => 'Despesas por conta de ativos', 'expenses_by_expense_account' => 'Despesas por conta de despesa', 'cannot_redirect_to_account' => 'Firefly III não pode redirecioná-lo para a página correta. Minhas desculpas.', 'sum_of_expenses' => 'Soma das despesas', @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Redefinir', 'want_to_login' => 'Eu quero fazer o login', 'button_register' => 'Registrar', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Pedido de autorização', + 'authorization_request_intro' => ':client está pedindo permissão para acessar sua administração financeira. Gostaria de autorizar :client para acessar esses registros?', + 'scopes_will_be_able' => 'Esta aplicação será capaz de:', + 'button_authorize' => 'Autorizar', // check for updates: 'update_check_title' => 'Verificar Atualizações', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Devo verificar a caixa?', 'secure_pw_long_password' => 'Se você apenas gerou uma senha longa e de uso único para o Firefly III usando algum tipo de gerador de senhas: não.', 'secure_pw_short' => 'Se você acabou de inserir a senha que você usa sempre: Por favor, sim.', - 'personal_access_token' => 'Token de acesso de pessoal', - 'explain_access_token' => 'Você precisa desse token para executar opções de linha de comando, como importar ou exportar dados. Sem isso, tais comandos sensíveis não funcionarão. Não compartilhe seu token de acesso. Ninguém pedirá por este token, nem mesmo eu. Se você tem medo de perder isso, ou quando você é paranóico, regenere esse token usando o botão.', - 'regenerate_access_token' => 'Regenerar o token de acesso', - 'token_regenerated' => 'Um novo token foi gerado', + 'command_line_token' => 'Token de linha de comando', + 'explain_command_line_token' => 'Você precisa desse token para executar opções de linha de comando, como importar ou exportar dados. Sem isso, tais comandos sensíveis não funcionarão. Não compartilhe seu token de acesso. Ninguém pedirá por este token, nem mesmo eu. Se você tem medo de perder isso, ou quando você se preocupar, regenere esse token usando o botão.', + 'regenerate_command_line_token' => 'Regenerar token de linha de comando', + 'token_regenerated' => 'Foi gerado um novo token de linha de comando', 'change_your_email' => 'Altere seu endereço de email', 'email_verification' => 'Uma mensagem de e-mail será enviada para o seu antigo e novo endereço de e-mail. Por motivos de segurança, você não poderá fazer o login até verificar seu novo endereço de e-mail. Se você não tem certeza se a sua instalação do Firefly III é capaz de enviar e-mails, não use esse recurso. Se você é um administrador, você pode testar isso no Administração.', 'email_changed_logout' => 'Até que você verifique seu endereço de e-mail, não pode iniciar sessão.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Tudo examinado novamente.', 'average_bill_amount_year' => 'Média de fatura (:year)', 'average_bill_amount_overall' => 'Média de fatura (geral)', - 'not_or_not_yet' => 'Não (ainda)', - 'not_expected_period' => 'Não esperado neste período', 'bill_is_active' => 'Fatura está ativa', 'bill_expected_between' => 'Esperado entre :start e :end', 'bill_will_automatch' => 'A fatura será automaticamente vinculada a transações correspondentes', @@ -710,7 +715,7 @@ return [ 'create_neg_reconcile_transaction' => 'Desmarque as transações selecionadas e, em seguida, crie uma correção removendo :amount para esta conta ativa.', 'reconcile_do_nothing' => 'Desmarcar as transações selecionadas, mas não corrigir.', 'reconcile_go_back' => 'Você sempre pode editar ou excluir uma correção mais tarde.', - 'must_be_asset_account' => 'Você só pode conciliar contas ativas', + 'must_be_asset_account' => 'Você só pode conciliar contas de ativos', 'reconciliation_stored' => 'Reconciliação armazenada', 'reconcilliation_transaction_title' => 'Reconciliação (:from a :to)', 'reconcile_this_account' => 'Concilie esta conta', @@ -772,9 +777,9 @@ return [ 'mass_deleted_transactions_success' => 'Excluído :amount de transação(ões).', 'mass_edited_transactions_success' => 'Atualizado :amount de transação(ões)', 'opt_group_no_account_type' => '(sem o tipo de conta)', - 'opt_group_defaultAsset' => 'Contas ativa padrão', + 'opt_group_defaultAsset' => 'Contas padrão', 'opt_group_savingAsset' => 'Contas de poupança', - 'opt_group_sharedAsset' => 'Contas ativas compartilhadas', + 'opt_group_sharedAsset' => 'Contas de ativos compartilhadas', 'opt_group_ccAsset' => 'Cartões de crédito', 'notes' => 'Notas', @@ -930,8 +935,8 @@ return [ 'description' => 'Descrição', 'sum_of_period' => 'Soma de período', 'average_in_period' => 'Média do período', - 'account_role_defaultAsset' => 'Conta ativa padrão', - 'account_role_sharedAsset' => 'Conta ativa compartilhadas', + 'account_role_defaultAsset' => 'Conta padrão', + 'account_role_sharedAsset' => 'Contas de ativos compartilhadas', 'account_role_savingAsset' => 'Conta poupança', 'account_role_ccAsset' => 'Cartão de crédito', 'budget_chart_click' => 'Clique no nome do orçamento na tabela acima para ver um gráfico.', @@ -1127,16 +1132,16 @@ return [ // import index page: 'import_index_title' => 'Importar dados para o Firefly III', 'import_index_sub_title' => 'Índice', - 'import_general_index_intro' => 'Bem-vindo à rotina de importação do Firefly. Existem algumas maneiras de importar dados no Firefly III, exibidos aqui como botões.', + 'import_general_index_intro' => 'Bem-vindo à rotina de importação do Firefly III. Existem algumas maneiras de importar dados no Firefly III, exibidos aqui como botões.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Esta função não está disponível quando você está usando o Firefly III dentro de um ambiente Sandstorm.io.', // empty lists? no objects? instructions: - 'no_accounts_title_asset' => 'Vamos criar uma conta ativa!', - 'no_accounts_intro_asset' => 'Ainda não possui contas ativas. As contas ativas são suas principais contas: sua conta corrente, conta poupança, conta compartilhada ou mesmo seu cartão de crédito.', - 'no_accounts_imperative_asset' => 'Para começar a usar o Firefly III, você deve criar pelo menos uma conta ativa. Vamos fazer agora:', - 'no_accounts_create_asset' => 'Criar uma conta ativa', + 'no_accounts_title_asset' => 'Vamos criar uma conta de ativos!', + 'no_accounts_intro_asset' => 'Ainda não possui contas de ativos. As contas de ativos são suas principais contas: sua conta corrente, conta poupança, conta compartilhada ou mesmo seu cartão de crédito.', + 'no_accounts_imperative_asset' => 'Para começar a usar o Firefly III, você deve criar pelo menos uma conta de ativos. Vamos fazer agora:', + 'no_accounts_create_asset' => 'Criar uma conta de ativo', 'no_accounts_title_expense' => 'Vamos criar uma conta de despesas!', 'no_accounts_intro_expense' => 'Você ainda não possui contas de despesas. As contas de despesas são os lugares onde você gasta dinheiro, como lojas e supermercados.', 'no_accounts_imperative_expense' => 'As contas de despesas são criadas automaticamente quando você cria transações, mas você também pode criar uma manualmente, se desejar. Vamos criar uma agora:', diff --git a/resources/lang/pt_BR/form.php b/resources/lang/pt_BR/form.php index 6dc6aab56d..ccd47f9f7d 100644 --- a/resources/lang/pt_BR/form.php +++ b/resources/lang/pt_BR/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Você tem certeza que quer apagar a tag ":tag"?', 'journal_link_areYouSure' => 'Tem certeza que deseja excluir a ligação entre :source e :destination?', 'linkType_areYouSure' => 'Tem certeza que deseja excluir o tipo de link ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Exclusão de dados do Firely são permanentes e não podem ser desfeitos.', + 'permDeleteWarning' => 'Exclusão de dados do Firefly III são permanentes e não podem ser desfeitos.', 'mass_make_selection' => 'Você ainda pode evitar que itens sejam excluídos, removendo a caixa de seleção.', 'delete_all_permanently' => 'Exclua os selecionados permanentemente', 'update_all_journals' => 'Atualizar essas transações', diff --git a/resources/lang/pt_BR/import.php b/resources/lang/pt_BR/import.php index f1ac8ca769..91cd87859a 100644 --- a/resources/lang/pt_BR/import.php +++ b/resources/lang/pt_BR/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Status de importação', 'config_sub_title' => 'Configurar a sua importação', 'status_finished_job' => 'As transações de :count importadas podem ser encontradas na tag :tag.', - 'status_finished_no_tag' => 'O Firefly III não coletou nenhum periódico do seu arquivo de importação.', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'import_with_key' => 'Importar com a chave \':key\'', // file, upload something @@ -73,7 +73,7 @@ return [ 'csv_initial_header_help' => 'Marque esta caixa se a primeira linha do seu arquivo CSV for os títulos das colunas.', 'csv_initial_date_help' => 'Formato de data e hora em seu CSV. Siga o formato como indica esta página. O valor padrão analisará datas que se parecem com isso: :dateExample.', 'csv_initial_delimiter_help' => 'Escolha o delimitador de campo que é usado em seu arquivo de entrada. Se não tiver certeza, a vírgula é a opção mais segura.', - 'csv_initial_import_account_help' => 'Se o seu arquivo CSV NÃO contém informações sobre sua(s) conta(s) ativa(s), use este combobox para selecionar para qual conta pertencem as transações no CSV.', + 'csv_initial_import_account_help' => 'Se o seu arquivo CSV NÃO contém informações sobre sua(s) conta(s) de ativo(s), use este combobox para selecionar para qual conta pertencem as transações no CSV.', 'csv_initial_submit' => 'Continue com o passo 3/4', // file, new options: @@ -108,9 +108,9 @@ return [ // map things. 'column__ignore' => '(ignorar esta coluna)', - 'column_account-iban' => 'Conta Ativa (IBAN)', - 'column_account-id' => 'ID da conta ativa (correspondência FF3)', - 'column_account-name' => 'Conta Ativa (nome)', + 'column_account-iban' => 'Conta de Ativo (IBAN)', + 'column_account-id' => 'ID da Conta de Ativo (correspondente FF3)', + 'column_account-name' => 'Conta de Ativo (nome)', 'column_amount' => 'Montante', 'column_amount_foreign' => 'Montante (em moeda estrangeira)', 'column_amount_debit' => 'Montante (coluna de débito)', @@ -143,7 +143,7 @@ return [ 'column_sepa-db' => 'Débito direto SEPA', 'column_tags-comma' => 'Tags (separadas por vírgula)', 'column_tags-space' => 'Tags (separadas por espaço)', - 'column_account-number' => 'Conta ativa (número da conta)', + 'column_account-number' => 'Conta de ativo (número da conta)', 'column_opposing-number' => 'Conta Contrária (número da conta)', 'column_note' => 'Nota(s)', @@ -160,7 +160,7 @@ return [ 'spectre_prerequisites_text' => 'Para importar dados usando a Spectre API, você deve fornecer ao Firefly III dois valores secretos. Eles podem ser encontrados na página de segredos.', 'spectre_enter_pub_key' => 'A importação só funcionará quando você inserir essa chave pública em sua página de segurança.', 'spectre_accounts_title' => 'Selecione as contas a serem importadas', - 'spectre_accounts_text' => 'Cada conta à esquerda abaixo foi encontrada pela Spectre e pode ser importada para Firefly III. Por favor selecione a conta ativa que deve armazenar as transações. Se você não deseja importar de qualquer conta específica, desmarque a caixa de seleção.', + 'spectre_accounts_text' => 'Cada conta à esquerda abaixo foi encontrada pela Spectre e pode ser importada para Firefly III. Por favor selecione a conta de ativo que deve armazenar as transações. Se você não deseja importar de qualquer conta específica, desmarque a caixa de seleção.', 'spectre_do_import' => 'Sim, importe a partir desta conta', // keys from "extra" array: diff --git a/resources/lang/pt_BR/intro.php b/resources/lang/pt_BR/intro.php index 4ccb1aa010..262f0a8015 100644 --- a/resources/lang/pt_BR/intro.php +++ b/resources/lang/pt_BR/intro.php @@ -71,8 +71,8 @@ return [ // create transaction 'transactions_create_switch_box' => 'Use esses botões para mudar rapidamente o tipo de transação que deseja salvar.', 'transactions_create_ffInput_category' => 'Você pode digitar livremente neste campo. As categorias criadas anteriormente serão sugeridas.', - 'transactions_create_withdrawal_ffInput_budget' => 'Vincule sua ;crwdn:gr:0:gr:crwdn; um orçamento para um melhor controle financeiro.', - 'transactions_create_withdrawal_currency_dropdown_amount' => 'Use este menu suspenso quando sua ;crwdn:gr:0:gr:crwdn; for em outra moeda.', + 'transactions_create_withdrawal_ffInput_budget' => 'Vincule sua retirada a um orçamento para um melhor controle financeiro.', + 'transactions_create_withdrawal_currency_dropdown_amount' => 'Use este menu suspenso quando seu depósito estiver em outra moeda.', 'transactions_create_deposit_currency_dropdown_amount' => 'Use este menu suspenso quando seu depósito estiver em outra moeda.', 'transactions_create_transfer_ffInput_piggy_bank_id' => 'Selecione um banco e vincule essa transferência às suas economias.', diff --git a/resources/lang/pt_BR/validation.php b/resources/lang/pt_BR/validation.php index 211422af55..3ebba5c6aa 100644 --- a/resources/lang/pt_BR/validation.php +++ b/resources/lang/pt_BR/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Este não é um válido IBAN.', 'unique_account_number_for_user' => 'Parece que este número de conta já está em uso.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', 'deleted_user' => 'Devido a restrições de segurança, você não pode registrar usando este endereço de e-mail.', 'rule_trigger_value' => 'Este valor é inválido para o disparo selecionado.', 'rule_action_value' => 'Este valor é inválido para a ação selecionada.', 'file_already_attached' => 'Arquivo ":name" carregado já está anexado para este objeto.', 'file_attached' => 'Arquivo carregado com sucesso ":name".', + 'must_exist' => 'O ID no campo :attribute não existe no banco de dados.', + 'all_accounts_equal' => 'Todas as contas neste campo devem ser iguais.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'Esse valor é inválido para este campo.', + 'at_least_one_transaction' => 'Precisa de ao menos uma transação.', + 'require_currency_info' => 'O conteúdo deste campo é inválido sem informações de moeda.', + 'equal_description' => 'Transaction description should not equal global description.', 'file_invalid_mime' => 'Arquivo ":name" é do tipo ":mime" que não é aceito como um novo upload.', 'file_too_large' => 'Arquivo ":name" é muito grande.', 'belongs_to_user' => 'O valor de :attribute é desconhecido', @@ -84,6 +92,7 @@ return [ 'required_without_all' => 'O campo :attribute é obrigatório quando nenhum dos :values está presente.', 'same' => 'Os campos :attribute e :other deverão conter valores iguais.', 'size.numeric' => 'O campo :attribute deverá conter o valor :size.', + 'amount_min_over_max' => 'O valor mínimo não pode ser maior do que o valor máximo.', 'size.file' => 'O campo :attribute deverá ter o tamanho de :size kilobytes.', 'size.string' => 'O campo :attribute deverá conter :size caracteres.', 'size.array' => 'O campo :attribute deve ter :size itens.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'A quantidade total não pode ser zero', 'secure_password' => 'Esta não é uma senha segura. Por favor, tente novamente. Para mais informações, visite https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => 'endereço de e-mail', - 'description' => 'descrição', - 'amount' => 'quantidade', - 'name' => 'nome', - 'targetamount' => 'quantidade alvo', - 'openingBalanceDate' => 'data do Saldo inicial', - 'openingBalance' => 'saldo inicial', - 'match' => 'coincidente', - 'amount_min' => 'valor mínimo', - 'amount_max' => 'valor máximo', - 'title' => 'título', - 'tag' => 'identificador', - 'rule-action-value.1' => 'valor de ação de regra #1', - 'rule-action-value.2' => 'valor de ação de regra #2', - 'rule-action-value.3' => 'valor de ação de regra #3', - 'rule-action-value.4' => 'valor de ação de regra #4', - 'rule-action-value.5' => 'valor de ação de regra #5', - 'rule-action.1' => 'regra de ação #1', - 'rule-action.2' => 'regra de ação #2', - 'rule-action.3' => 'regra de ação #3', - 'rule-action.4' => 'regra de ação #4', - 'rule-action.5' => 'regra de ação #5', - 'rule-trigger-value.1' => 'valor do disparador da regra #1', - 'rule-trigger-value.2' => 'valor do disparador da regra #2', - 'rule-trigger-value.3' => 'valor do disparador da regra #3', - 'rule-trigger-value.4' => 'valor do disparador da regra #4', - 'rule-trigger-value.5' => 'valor do disparador da regra #5', - 'rule-trigger.1' => 'disparador da regra #1', - 'rule-trigger.2' => 'disparador da regra #2', - 'rule-trigger.3' => 'disparador da regra #3', - 'rule-trigger.4' => 'disparador da regra #4', - 'rule-trigger.5' => 'disparador da regra #5', + 'email' => 'endereço de e-mail', + 'description' => 'descrição', + 'amount' => 'quantidade', + 'name' => 'nome', + 'piggy_bank_id' => 'ID do cofrinho', + 'targetamount' => 'quantidade alvo', + 'openingBalanceDate' => 'data do Saldo inicial', + 'openingBalance' => 'saldo inicial', + 'match' => 'coincidente', + 'amount_min' => 'valor mínimo', + 'amount_max' => 'valor máximo', + 'title' => 'título', + 'tag' => 'identificador', + 'transaction_description' => 'Descrição da transação', + 'rule-action-value.1' => 'valor de ação de regra #1', + 'rule-action-value.2' => 'valor de ação de regra #2', + 'rule-action-value.3' => 'valor de ação de regra #3', + 'rule-action-value.4' => 'valor de ação de regra #4', + 'rule-action-value.5' => 'valor de ação de regra #5', + 'rule-action.1' => 'regra de ação #1', + 'rule-action.2' => 'regra de ação #2', + 'rule-action.3' => 'regra de ação #3', + 'rule-action.4' => 'regra de ação #4', + 'rule-action.5' => 'regra de ação #5', + 'rule-trigger-value.1' => 'valor do disparador da regra #1', + 'rule-trigger-value.2' => 'valor do disparador da regra #2', + 'rule-trigger-value.3' => 'valor do disparador da regra #3', + 'rule-trigger-value.4' => 'valor do disparador da regra #4', + 'rule-trigger-value.5' => 'valor do disparador da regra #5', + 'rule-trigger.1' => 'disparador da regra #1', + 'rule-trigger.2' => 'disparador da regra #2', + 'rule-trigger.3' => 'disparador da regra #3', + 'rule-trigger.4' => 'disparador da regra #4', + 'rule-trigger.5' => 'disparador da regra #5', ], ]; diff --git a/resources/lang/ru_RU/components.php b/resources/lang/ru_RU/components.php new file mode 100644 index 0000000000..923d3c2aa5 --- /dev/null +++ b/resources/lang/ru_RU/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Персональный токен для доступа', + + // bills: + 'not_expected_period' => 'Не ожидается в данном периоде', + 'not_or_not_yet' => 'Пока нет', +]; \ No newline at end of file diff --git a/resources/lang/ru_RU/config.php b/resources/lang/ru_RU/config.php index 96f821b89b..a562e16b26 100644 --- a/resources/lang/ru_RU/config.php +++ b/resources/lang/ru_RU/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'ru', - 'locale' => 'ru, Russian, ru_RU, ru_RU.utf8, ru_RU.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%e %B %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => 'Неделя %W, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'ru', + 'locale' => 'ru, Russian, ru_RU, ru_RU.utf8, ru_RU.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%e %B %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => 'Неделя %W, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'Do MMMM YYYY', + 'date_time_js' => 'Do MMMM YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Неделя] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/ru_RU/firefly.php b/resources/lang/ru_RU/firefly.php index 436fb890ba..070c69a63c 100644 --- a/resources/lang/ru_RU/firefly.php +++ b/resources/lang/ru_RU/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Сбросить', 'want_to_login' => 'Я хочу войти', 'button_register' => 'Регистрация', + 'authorization' => 'Авторизация', + + // API access + 'authorization_request' => 'Запрос авторизации Firefly III v:version', + 'authorization_request_intro' => ':client запрашивает доступ к управлению вашими финансами. Вы хотите разрешить :client доступ к этой информации?', + 'scopes_will_be_able' => 'Это приложение будет иметь возможность:', + 'button_authorize' => 'Авторизация', // check for updates: 'update_check_title' => 'Проверить обновления', @@ -498,10 +505,10 @@ return [ 'secure_pw_should' => 'Должен ли я установить флажок?', 'secure_pw_long_password' => 'Если вы только что создали длинный одноразовый пароль для Firefly III с использованием какого-либо генератора паролей: нет.', 'secure_pw_short' => 'Если вы только что ввели пароль, который вы используете на нескольких сайтах: пожалуйста, да.', - 'personal_access_token' => 'Личный токен для доступа', - 'explain_access_token' => 'Этот токен необходим для выполнения операций из командной строки (таких как импорт или экспорт данных). Без него такие чувствительные команды не будут работать. Не показывайте никому свой токен. Никто не попросит у вас эту информацию, даже я. Если вы боитесь, что потеряли этот токен, или у вас паранойя, вы можете сгенерировать новый токен с помощью этой кнопки.', - 'regenerate_access_token' => 'Сгенерировать новый токен', - 'token_regenerated' => 'Новый токен был успешно сгенерирован', + 'command_line_token' => 'Токен командной строки', + 'explain_command_line_token' => 'Этот токен необходим для выполнения операций из командной строки (таких как импорт или экспорт данных). Без него такие чувствительные команды не будут работать. Не показывайте никому свой токен. Никто не попросит у вас эту информацию, даже я. Если вы боитесь, что потеряли этот токен, или у вас паранойя, вы можете сгенерировать новый токен с помощью этой кнопки.', + 'regenerate_command_line_token' => 'Сгенерировать новый токен командной строки', + 'token_regenerated' => 'Новый токен командной строки сгенерирован', 'change_your_email' => 'Изменить ваш адрес электронной почты', 'email_verification' => 'Письмо будет отправлено на ваши адреса электронной почты: старый и новый. В целях безопасности, вы не сможете войти в систему, пока не подтвердите новый адрес электронной почты. Если вы не уверены, что ваша установка Firefly III может отправлять электронную почту, не используйте эту функцию. Если вы являетесь администратором, вы можете проверить это на странице Администрирование.', 'email_changed_logout' => 'Пока вы не подтвердите свой адрес электронной почты, вы не сможете войти в систему.', @@ -634,8 +641,6 @@ return [ 'rescanned_bill' => 'Все счеты были перепроверены.', 'average_bill_amount_year' => 'Средняя сумма счёта на оплату (:year)', 'average_bill_amount_overall' => 'Средняя сумма счёта на оплату (за всё время)', - 'not_or_not_yet' => 'Нет (пока)', - 'not_expected_period' => 'Не ожидается в данном периоде', 'bill_is_active' => 'Счёт на оплату активен', 'bill_expected_between' => 'Ожидается между :start и :end', 'bill_will_automatch' => 'Счёт будет автоматически связан с подходящими транзакциями', @@ -1127,7 +1132,7 @@ return [ // import index page: 'import_index_title' => 'Импорт данных в Firefly III', 'import_index_sub_title' => 'Главная страница', - 'import_general_index_intro' => 'Добро пожаловать в инструмент импорта Firefly. Существует несколько способов импорта данных в Firefly III, отображаемых здесь в виде кнопок.', + 'import_general_index_intro' => 'Добро пожаловать в инструмент импорта Firefly III. Существует несколько способов импорта данных в Firefly III, отображаемых здесь в виде кнопок.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Эта функция недоступна, если вы используете Firefly III в среде Sandstorm.io.', diff --git a/resources/lang/ru_RU/form.php b/resources/lang/ru_RU/form.php index 0a87eefdc7..062a6dce69 100644 --- a/resources/lang/ru_RU/form.php +++ b/resources/lang/ru_RU/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => 'Вы действительно хотите удалить метку ":tag"?', 'journal_link_areYouSure' => 'Вы действительно хотите удалить связь между :source и :destination?', 'linkType_areYouSure' => 'Вы уверены, что хотите удалить тип ссылки ":name" (":inward" / ":outward")?', - 'permDeleteWarning' => 'Удаление информации из Firefly является постоянным и не может быть отменено.', + 'permDeleteWarning' => 'Удаление информации из Firefly III является постоянным и не может быть отменено.', 'mass_make_selection' => 'Вы все же можете предотвратить удаление элементов, сняв флажок.', 'delete_all_permanently' => 'Удалить выбранное навсегда', 'update_all_journals' => 'Обновить эти транзакции', diff --git a/resources/lang/ru_RU/import.php b/resources/lang/ru_RU/import.php index 09066983f7..18f1624e24 100644 --- a/resources/lang/ru_RU/import.php +++ b/resources/lang/ru_RU/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Статус импорта', 'config_sub_title' => 'Настройте свой импорт', 'status_finished_job' => 'Всего :count транзакций было импортировано. Они могу быть найдены по метке :tag.', - 'status_finished_no_tag' => 'Firefly III не собрал никаких журналов из вашего файла импорта.', + 'status_finished_no_tag' => 'Firefly III не собрал никаких транзакций из вашего файла импорта.', 'import_with_key' => 'Импорт с ключем \':key\'', // file, upload something diff --git a/resources/lang/ru_RU/validation.php b/resources/lang/ru_RU/validation.php index e75bf5546b..dc625fb7da 100644 --- a/resources/lang/ru_RU/validation.php +++ b/resources/lang/ru_RU/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Это некорректный IBAN.', 'unique_account_number_for_user' => 'Этот номер счёта уже используется.', + 'unique_iban_for_user' => 'Этот IBAN уже используется.', 'deleted_user' => 'По соображениям безопасности, вы не можете зарегистрироваться, используя этот адрес электронной почты.', 'rule_trigger_value' => 'Это значение является недопустимым для выбранного триггера.', 'rule_action_value' => 'Это значение является недопустимым для выбранного действия.', 'file_already_attached' => 'Загруженный файл ":name" уже прикреплён к этому объекту.', 'file_attached' => 'Файл ":name". успешно загружен.', + 'must_exist' => 'ID в поле field :attribute не существует в базе данных.', + 'all_accounts_equal' => 'Все счета в данном поле должны совпадать.', + 'invalid_selection' => 'Вы сделали неправильный выбор', + 'belongs_user' => 'Данное значение недопустимо для этого поля.', + 'at_least_one_transaction' => 'Необходима как минимум одна транзакция.', + 'require_currency_info' => 'Содержимое этого поля недействительно без информации о валюте.', + 'equal_description' => 'Описание транзакции не должно совпадать с глобальным описанием.', 'file_invalid_mime' => 'Файл ":name" имеет тип ":mime". Загрузка файлов такого типа невозможна.', 'file_too_large' => 'Файл ":name" слишком большой.', 'belongs_to_user' => 'Значение :attribute неизвестно', @@ -84,6 +92,7 @@ return [ 'required_without_all' => ':attribute поле обязательно для заполнения, так как ни одно из :values не существует.', 'same' => ':attribute и :other должны совпадать.', 'size.numeric' => ':attribute должен быть размером :size.', + 'amount_min_over_max' => 'Минимальная сумма не может быть больше максимальной суммы.', 'size.file' => ':attribute должен быть размером :size килобайт.', 'size.string' => ':attribute должен состоять из :size символов.', 'size.array' => ':attribute должен содержать :size элементов.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Общее количество не может быть равно нулю', 'secure_password' => 'Это не безопасный пароль. Попробуйте еще раз. Для получения справки посетите https://goo.gl/NCh2tN', 'attributes' => [ - 'email' => '"Адрес электронной почты"', - 'description' => '"Описание"', - 'amount' => 'Сумма', - 'name' => '"Название"', - 'targetamount' => '"Целевая сумма"', - 'openingBalanceDate' => '"Дата начального баланса"', - 'openingBalance' => '"Начальный баланс"', - 'match' => '"Ключи для связи"', - 'amount_min' => '"Минимальная сумма"', - 'amount_max' => '"Максимальная сумма"', - 'title' => '"Заголовок"', - 'tag' => '"Метка"', - 'rule-action-value.1' => '"Значение действия #1"', - 'rule-action-value.2' => '"Значение действия #2"', - 'rule-action-value.3' => '"Значение действия #3"', - 'rule-action-value.4' => '"Значение действия #4"', - 'rule-action-value.5' => '"Значение действия #5"', - 'rule-action.1' => '"Действие #1"', - 'rule-action.2' => '"Действие #2"', - 'rule-action.3' => '"Действие #3"', - 'rule-action.4' => '"Действие #4"', - 'rule-action.5' => '"Действие #5"', - 'rule-trigger-value.1' => '"Значение условия #1"', - 'rule-trigger-value.2' => '"Значение условия #2"', - 'rule-trigger-value.3' => '"Значение условия #3"', - 'rule-trigger-value.4' => '"Значение условия #4"', - 'rule-trigger-value.5' => '"Значение условия #5"', - 'rule-trigger.1' => '"Условие #1"', - 'rule-trigger.2' => '"Условие #2"', - 'rule-trigger.3' => '"Условие #3"', - 'rule-trigger.4' => '"Условие #4"', - 'rule-trigger.5' => '"Условие #5"', + 'email' => '"Адрес электронной почты"', + 'description' => '"Описание"', + 'amount' => 'Сумма', + 'name' => '"Название"', + 'piggy_bank_id' => 'ID копилки', + 'targetamount' => '"Целевая сумма"', + 'openingBalanceDate' => '"Дата начального баланса"', + 'openingBalance' => '"Начальный баланс"', + 'match' => '"Ключи для связи"', + 'amount_min' => '"Минимальная сумма"', + 'amount_max' => '"Максимальная сумма"', + 'title' => '"Заголовок"', + 'tag' => '"Метка"', + 'transaction_description' => 'описание транзакции', + 'rule-action-value.1' => '"Значение действия #1"', + 'rule-action-value.2' => '"Значение действия #2"', + 'rule-action-value.3' => '"Значение действия #3"', + 'rule-action-value.4' => '"Значение действия #4"', + 'rule-action-value.5' => '"Значение действия #5"', + 'rule-action.1' => '"Действие #1"', + 'rule-action.2' => '"Действие #2"', + 'rule-action.3' => '"Действие #3"', + 'rule-action.4' => '"Действие #4"', + 'rule-action.5' => '"Действие #5"', + 'rule-trigger-value.1' => '"Значение условия #1"', + 'rule-trigger-value.2' => '"Значение условия #2"', + 'rule-trigger-value.3' => '"Значение условия #3"', + 'rule-trigger-value.4' => '"Значение условия #4"', + 'rule-trigger-value.5' => '"Значение условия #5"', + 'rule-trigger.1' => '"Условие #1"', + 'rule-trigger.2' => '"Условие #2"', + 'rule-trigger.3' => '"Условие #3"', + 'rule-trigger.4' => '"Условие #4"', + 'rule-trigger.5' => '"Условие #5"', ], ]; diff --git a/resources/lang/tr_TR/components.php b/resources/lang/tr_TR/components.php new file mode 100644 index 0000000000..fae0f0f10b --- /dev/null +++ b/resources/lang/tr_TR/components.php @@ -0,0 +1,30 @@ +. + */ +declare(strict_types=1); + +return [ + // profile + 'personal_access_tokens' => 'Personal access tokens', + + // bills: + 'not_expected_period' => 'Not expected this period', + 'not_or_not_yet' => 'Not (yet)', +]; \ No newline at end of file diff --git a/resources/lang/tr_TR/config.php b/resources/lang/tr_TR/config.php index d3812f72e2..e58412cc0f 100644 --- a/resources/lang/tr_TR/config.php +++ b/resources/lang/tr_TR/config.php @@ -21,13 +21,20 @@ declare(strict_types=1); return [ - 'html_language' => 'tr', - 'locale' => 'tr, Turkish, tr_TR, tr_TR.utf8, tr_TR.S.UTF-8', - 'month' => '%B %Y', - 'month_and_day' => '%e %B %Y', - 'date_time' => '%e %B %Y, @ %T', - 'specific_day' => '%e %B %Y', - 'week_in_year' => '%W. hafta, %Y', - 'year' => '%Y', - 'half_year' => '%B %Y', + 'html_language' => 'tr', + 'locale' => 'tr, Turkish, tr_TR, tr_TR.utf8, tr_TR.S.UTF-8', + 'month' => '%B %Y', + 'month_and_day' => '%e %B %Y', + 'date_time' => '%e %B %Y, @ %T', + 'specific_day' => '%e %B %Y', + 'week_in_year' => '%W. hafta, %Y', + 'year' => '%Y', + 'half_year' => '%B %Y', + 'month_js' => 'MMMM YYYY', + 'month_and_day_js' => 'MMMM Do, YYYY', + 'date_time_js' => 'MMMM Do, YYYY, @ HH:mm:ss', + 'specific_day_js' => 'D MMMM YYYY', + 'week_in_year_js' => '[Week] w, YYYY', + 'year_js' => 'YYYY', + 'half_year_js' => 'Q YYYY', ]; diff --git a/resources/lang/tr_TR/firefly.php b/resources/lang/tr_TR/firefly.php index 8ee65ee103..da06325297 100644 --- a/resources/lang/tr_TR/firefly.php +++ b/resources/lang/tr_TR/firefly.php @@ -169,6 +169,13 @@ return [ 'reset_button' => 'Reset', 'want_to_login' => 'I want to login', 'button_register' => 'Register', + 'authorization' => 'Authorization', + + // API access + 'authorization_request' => 'Firefly III v:version Authorization Request', + 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', + 'scopes_will_be_able' => 'This application will be able to:', + 'button_authorize' => 'Authorize', // check for updates: 'update_check_title' => 'Check for updates', @@ -499,10 +506,10 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', 'secure_pw_should' => 'Kutuyu kontrol etmeli miyim?', 'secure_pw_long_password' => 'Firefly III için bir çeşit şifre üreticisi kullanarak uzun, tek kullanımlık bir şifre oluşturduysanız: hayır.', 'secure_pw_short' => 'Her zaman kullandığınız şifreyi kullandıysanız: Evet lütfen.', - 'personal_access_token' => 'Kişisel erişim simgesi', - 'explain_access_token' => 'Verileri içe veya dışa aktarmak gibi komut satır seçeneklerini gerçekleştirebilmek için bu token\'a ihtiyacınız var. O olmadan bu gibi hassas komutlar çalışmayacaktır. Erişim token\'ınınızı kimseyle paylaşmayın. Ben dahil kimse sizden bu token\'ı istemeyecek. Eğer kaybedeceğinizden korkuyorsanız ya da paranoyaklaştığınız zaman bu tuşu kullanarak token\'ı yeniden oluşturun.', - 'regenerate_access_token' => 'Erişim iznini yeniden oluştur', - 'token_regenerated' => 'Yeni bir belirteç oluşturuldu', + 'command_line_token' => 'Command line token', + 'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.', + 'regenerate_command_line_token' => 'Regenerate command line token', + 'token_regenerated' => 'A new command line token was generated', 'change_your_email' => 'E-posta adresini değiştir', 'email_verification' => 'ESKİ ve yeni e-posta adreslerinize bir e-posta gönderilecektir. Güvenlik nedenlerinden ötürü email adreslerinizi onaylayana kadar giriş yapamayacaksınız. Eğer Fİrefly III yüklemenizin e-posta gönderebileceğinden emin değilseniz lütfen bu özelliği kullanmayınız. Eğer bir yöneticiyseniz bunu Yönetim de test edebilirsiniz.', 'email_changed_logout' => 'E-posta adresinizi doğrulayana kadar giriş yapamazsınız.', @@ -635,8 +642,6 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', 'rescanned_bill' => 'Her şeyi yeniden araştırdım.', 'average_bill_amount_year' => 'Ortalama fatura tutarı (:year)', 'average_bill_amount_overall' => 'Ortalama fatura tutarı (genel)', - 'not_or_not_yet' => 'Henüz değil', - 'not_expected_period' => 'Bu periyotta beklenmiyor', 'bill_is_active' => 'Fatura aktif', 'bill_expected_between' => ':start ve :end arasında beklenen', 'bill_will_automatch' => 'Fatura uygun işlemlere otomatik olarak bağlandı', @@ -1128,7 +1133,7 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', // import index page: 'import_index_title' => 'Firefly III\'e veri aktarma', 'import_index_sub_title' => 'İndeks', - 'import_general_index_intro' => 'Firefly aktarım programına hoş geldiniz. Firefly III içine dosya aktarmanın burada bir kaç yolu var, burada butonlar olarak görüntülenmekte.', + 'import_general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Bir Sandstorm.io ortamında Firefly III kullanıyorsanız, bu işlev kullanılamaz.', diff --git a/resources/lang/tr_TR/form.php b/resources/lang/tr_TR/form.php index ff90c476bd..105fa170c7 100644 --- a/resources/lang/tr_TR/form.php +++ b/resources/lang/tr_TR/form.php @@ -158,7 +158,7 @@ return [ 'tag_areYouSure' => '":tag" etiketini silmek istediğinizden emin misiniz?', 'journal_link_areYouSure' => ':source and :destination arasındaki bağlantıyı silmek istediğinizden emin misiniz?', 'linkType_areYouSure' => '":name" (":inward" / ":outward") bağlantı türünü silmek istediğinizden emin misiniz?', - 'permDeleteWarning' => 'Firely\'den bir şeyler silmek kalıcıdır ve geri alınamaz.', + 'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.', 'mass_make_selection' => 'Onay kutusunu kaldırarak öğelerin silinmesini engelleyebilirsiniz.', 'delete_all_permanently' => 'Seçilenleri kalıcı olarak sil', 'update_all_journals' => 'Bu işlemleri güncelleyin', diff --git a/resources/lang/tr_TR/import.php b/resources/lang/tr_TR/import.php index efd498afd2..45997407f5 100644 --- a/resources/lang/tr_TR/import.php +++ b/resources/lang/tr_TR/import.php @@ -50,7 +50,7 @@ return [ 'status_sub_title' => 'Aktarma durumu', 'config_sub_title' => 'Hesabınızı oluşturunuz', 'status_finished_job' => 'The :count transactions imported can be found in tag :tag.', - 'status_finished_no_tag' => 'Firefly III has not collected any journals from your import file.', + 'status_finished_no_tag' => 'Firefly III has not collected any transactions from your import file.', 'import_with_key' => '\':key\' ile içe aktarın', // file, upload something diff --git a/resources/lang/tr_TR/validation.php b/resources/lang/tr_TR/validation.php index 7aac8e78db..0f6bee5597 100644 --- a/resources/lang/tr_TR/validation.php +++ b/resources/lang/tr_TR/validation.php @@ -23,11 +23,19 @@ declare(strict_types=1); return [ 'iban' => 'Bu IBAN geçerli değilrdir.', 'unique_account_number_for_user' => 'Bu hesap numarası zaten kullanılmaktadır.', + 'unique_iban_for_user' => 'It looks like this IBAN is already in use.', 'deleted_user' => 'Güvenlik kısıtlamaları nedeniyle, bu e-posta adresini kullanarak kayıt yapamazsınız.', 'rule_trigger_value' => 'Bu eylem, seçili işlem için geçersizdir.', 'rule_action_value' => 'Bu eylem seçili işlem için geçersizdir.', 'file_already_attached' => 'Yüklenen dosya ":name" zaten bu nesneye bağlı.', 'file_attached' => '":name" dosyası başarıyla yüklendi.', + 'must_exist' => 'The ID in field :attribute does not exist in the database.', + 'all_accounts_equal' => 'All accounts in this field must be equal.', + 'invalid_selection' => 'Your selection is invalid', + 'belongs_user' => 'This value is invalid for this field.', + 'at_least_one_transaction' => 'Need at least one transaction.', + 'require_currency_info' => 'The content of this field is invalid without currency information.', + 'equal_description' => 'Transaction description should not equal global description.', 'file_invalid_mime' => '":name" dosyası ":mime" türünde olup yeni bir yükleme olarak kabul edilemez.', 'file_too_large' => '":name" dosyası çok büyük.', 'belongs_to_user' => ':attribute\'nin değeri bilinmiyor', @@ -84,6 +92,7 @@ return [ 'required_without_all' => 'Hiçbir :values mevcut değilken :attribute alanı gereklidir.', 'same' => ':attribute ve :other eşleşmelidir.', 'size.numeric' => ':attribute :size olmalıdır.', + 'amount_min_over_max' => 'The minimum amount cannot be larger than the maximum amount.', 'size.file' => ':attribute :size kilobyte olmalıdır.', 'size.string' => ':attribute :size karakter olmalıdır.', 'size.array' => ':attribute :size öğeye sahip olmalıdır.', @@ -100,37 +109,39 @@ return [ 'amount_zero' => 'Toplam tutar sıfır olamaz', 'secure_password' => 'Güvenli bir şifre değildir. Lütfen tekrar deneyin. Daha fazla bilgi için https://goo.gl/NCh2tN adresini ziyaret edin', 'attributes' => [ - 'email' => 'email address', - 'description' => 'description', - 'amount' => 'amount', - 'name' => 'name', - 'targetamount' => 'target amount', - 'openingBalanceDate' => 'opening balance date', - 'openingBalance' => 'opening balance', - 'match' => 'match', - 'amount_min' => 'minimum amount', - 'amount_max' => 'maximum amount', - 'title' => 'title', - 'tag' => 'tag', - 'rule-action-value.1' => 'rule action value #1', - 'rule-action-value.2' => 'rule action value #2', - 'rule-action-value.3' => 'rule action value #3', - 'rule-action-value.4' => 'rule action value #4', - 'rule-action-value.5' => 'rule action value #5', - 'rule-action.1' => 'rule action #1', - 'rule-action.2' => 'rule action #2', - 'rule-action.3' => 'rule action #3', - 'rule-action.4' => 'rule action #4', - 'rule-action.5' => 'rule action #5', - 'rule-trigger-value.1' => 'rule trigger value #1', - 'rule-trigger-value.2' => 'rule trigger value #2', - 'rule-trigger-value.3' => 'rule trigger value #3', - 'rule-trigger-value.4' => 'rule trigger value #4', - 'rule-trigger-value.5' => 'rule trigger value #5', - 'rule-trigger.1' => 'rule trigger #1', - 'rule-trigger.2' => 'rule trigger #2', - 'rule-trigger.3' => 'rule trigger #3', - 'rule-trigger.4' => 'rule trigger #4', - 'rule-trigger.5' => 'rule trigger #5', + 'email' => 'email address', + 'description' => 'description', + 'amount' => 'amount', + 'name' => 'name', + 'piggy_bank_id' => 'piggy bank ID', + 'targetamount' => 'target amount', + 'openingBalanceDate' => 'opening balance date', + 'openingBalance' => 'opening balance', + 'match' => 'match', + 'amount_min' => 'minimum amount', + 'amount_max' => 'maximum amount', + 'title' => 'title', + 'tag' => 'tag', + 'transaction_description' => 'transaction description', + 'rule-action-value.1' => 'rule action value #1', + 'rule-action-value.2' => 'rule action value #2', + 'rule-action-value.3' => 'rule action value #3', + 'rule-action-value.4' => 'rule action value #4', + 'rule-action-value.5' => 'rule action value #5', + 'rule-action.1' => 'rule action #1', + 'rule-action.2' => 'rule action #2', + 'rule-action.3' => 'rule action #3', + 'rule-action.4' => 'rule action #4', + 'rule-action.5' => 'rule action #5', + 'rule-trigger-value.1' => 'rule trigger value #1', + 'rule-trigger-value.2' => 'rule trigger value #2', + 'rule-trigger-value.3' => 'rule trigger value #3', + 'rule-trigger-value.4' => 'rule trigger value #4', + 'rule-trigger-value.5' => 'rule trigger value #5', + 'rule-trigger.1' => 'rule trigger #1', + 'rule-trigger.2' => 'rule trigger #2', + 'rule-trigger.3' => 'rule trigger #3', + 'rule-trigger.4' => 'rule trigger #4', + 'rule-trigger.5' => 'rule trigger #5', ], ]; diff --git a/resources/views/accounts/edit.twig b/resources/views/accounts/edit.twig index b793c6b9d7..d1a14908cb 100644 --- a/resources/views/accounts/edit.twig +++ b/resources/views/accounts/edit.twig @@ -49,7 +49,7 @@ {% endif %} {{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }} - {{ ExpandedForm.checkbox('active','1') }} + {{ ExpandedForm.checkbox('active','1', preFilled.active) }} diff --git a/resources/views/accounts/show.twig b/resources/views/accounts/show.twig index 79b34d6243..c137e6e45f 100644 --- a/resources/views/accounts/show.twig +++ b/resources/views/accounts/show.twig @@ -1,7 +1,7 @@ {% extends "./layout/default" %} {% block breadcrumbs %} - {{ Breadcrumbs.render(Route.getCurrentRoute.getName, account, moment, start, end) }} + {{ Breadcrumbs.render(Route.getCurrentRoute.getName, account, start, end) }} {% endblock %} {% block content %} @@ -10,11 +10,7 @@

- {% if moment == 'all' %} - {{ trans('firefly.chart_all_journals_for_account', {name:account.name}) }} - {% else %} - {{ trans('firefly.chart_account_in_period', {name: account.name, start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat) }) }} - {% endif %} + {{ trans('firefly.chart_account_in_period', {name: account.name, start: start.formatLocalized(monthAndDayFormat), end: end.formatLocalized(monthAndDayFormat) }) }}

@@ -83,14 +79,6 @@
{% endif %} - {% if periods.count > 0 %} - - {% endif %} -
@@ -104,21 +92,12 @@ {% set showReconcile = false %} {% endif %} {% include 'list.journals' with {sorting:true, hideBills:true, hideBudgets: true, hideCategories: true, showReconcile: showReconcile} %} - {% if periods.count > 0 %} -

- - - {{ 'show_all_no_filter'|_ }} - -

- {% else %} -

- - - {{ 'show_the_current_period_and_overview'|_ }} - -

- {% endif %} +

+ + + {{ 'show_the_current_period_and_overview'|_ }} + +

@@ -128,7 +107,7 @@ {% if (period.spent != 0 or period.earned != 0) %}
@@ -150,7 +129,6 @@
{% endif %} {% endfor %} -

{{ 'showEverything'|_ }}

{% endif %}
@@ -166,22 +144,12 @@ // uri's for charts: var chartUri = '{{ chartUri }}'; {% if start and end %} - var incomeCategoryUri = '{{ route('chart.account.income-category', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; - var expenseCategoryUri = '{{ route('chart.account.expense-category', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; - var expenseBudgetUri = '{{ route('chart.account.expense-budget', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; - {% else %} - var incomeCategoryUri = '{{ route('chart.account.income-category', [account.id, 'all', 'all']) }}'; - var expenseCategoryUri = '{{ route('chart.account.expense-category', [account.id, 'all', 'all']) }}'; - var expenseBudgetUri = '{{ route('chart.account.expense-budget', [account.id, 'all', 'all']) }}'; + var incomeCategoryUri = '{{ route('chart.account.income-category', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; + var expenseCategoryUri = '{{ route('chart.account.expense-category', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; + var expenseBudgetUri = '{{ route('chart.account.expense-budget', [account.id, start.format('Ymd'), end.format('Ymd')]) }}'; {% endif %} - - - diff --git a/resources/views/auth/login.twig b/resources/views/auth/login.twig index 8d0ee18c90..094375048e 100644 --- a/resources/views/auth/login.twig +++ b/resources/views/auth/login.twig @@ -54,10 +54,10 @@
- +
- +
diff --git a/resources/views/bills/index.twig b/resources/views/bills/index.twig index 1fa5e633a7..ae637245ac 100644 --- a/resources/views/bills/index.twig +++ b/resources/views/bills/index.twig @@ -42,5 +42,9 @@ {% endblock %} {% block scripts %} + {% endblock %} diff --git a/resources/views/bills/show.twig b/resources/views/bills/show.twig index 1742fd3a6c..83148c7f0d 100644 --- a/resources/views/bills/show.twig +++ b/resources/views/bills/show.twig @@ -10,14 +10,14 @@
-

{{ bill.name }}

+

{{ object.data.name }}

@@ -28,18 +28,18 @@ {{ 'matching_on'|_ }} - {% for word in bill.match|split(',') %} + {% for word in object.data.match %} {{ word }} {% endfor %} - {{ trans('firefly.between_amounts', {low: bill.amount_min|formatAmount, high: bill.amount_max|formatAmount })|raw }} + {{ trans('firefly.between_amounts', {low: object.data.amount_min|formatAmount, high: object.data.amount_max|formatAmount })|raw }} {{ 'repeats'|_ }} - {{ trans('firefly.repeat_freq_' ~bill.repeat_freq) }}. + {{ trans('firefly.repeat_freq_' ~object.data.repeat_freq) }}. {{ 'bill_is_active'|_ }} - {% if bill.active %} + {% if object.data.active %} {{ 'yes'|_ }} {% else %} {{ 'no'|_ }} @@ -49,21 +49,20 @@ {{ 'bill_will_automatch'|_ }} - {% if bill.automatch %} + {% if object.data.automatch %} {{ 'yes'|_ }} {% else %} {{ 'no'|_ }} {% endif %} - {{ 'next_expected_match'|_ }} - {% if bill.nextExpectedMatch %} - {{ bill.nextExpectedMatch.formatLocalized(monthAndDayFormat) }} - {% else %} - {{ 'unknown'|_ }} + {% if object.data.next_expected_match|length > 0 %} + {{ formatDate(object.data.next_expected_match, monthAndDayFormat) }} + {% else %} + {{ 'unknown'|_ }} {% endif %} @@ -85,52 +84,52 @@

{{ 'more'|_ }}

- {% if bill.notes.count == 1 %} + {% if object.notes|length > 0 %} - +
{{ trans('list.notes') }}{{ bill.notes.first.text|markdown }}{{ object.notes.data[0].markdown }}
{% endif %}
- {% if bill.attachments|length > 0 %} + {% if object.data.attachments_count > 0 %}

{{ 'attachments'|_ }}

- {% for att in bill.attachments %} + {% for att in bill.data.attachments.data %} {% endfor %} @@ -171,7 +170,7 @@ {% block scripts %} diff --git a/resources/views/budgets/income.twig b/resources/views/budgets/income.twig index 201e2f2a3c..09a919b3da 100644 --- a/resources/views/budgets/income.twig +++ b/resources/views/budgets/income.twig @@ -14,6 +14,7 @@ +
{{ getCurrencySymbol()|raw }}
diff --git a/resources/views/budgets/index.twig b/resources/views/budgets/index.twig index 6dff1b45c3..627bdf2efd 100644 --- a/resources/views/budgets/index.twig +++ b/resources/views/budgets/index.twig @@ -108,9 +108,9 @@
@@ -237,13 +237,13 @@ - + + + - +
- - + +
- - - {% if att.title %} - {{ att.title }} + + + {% if att.data.title %} + {{ att.data.title }} {% else %} - {{ att.filename }} + {{ att.data.filename }} {% endif %} - ({{ att.size|filesize }}) - {% if att.description %} + ({{ att.data.size|filesize }}) + {% if att.data.description %}
- {{ att.description }} + {{ att.data.description }} {% endif %}
- +